]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix race conditions processing frame fullscreen state on Haiku
authorPo Lu <luangruo@yahoo.com>
Thu, 19 May 2022 03:43:39 +0000 (03:43 +0000)
committerPo Lu <luangruo@yahoo.com>
Thu, 19 May 2022 03:43:39 +0000 (03:43 +0000)
* doc/lispref/frames.texi (Size Parameters): Remove note saying
Haiku doesn't support `fullwidth' and `fullboth'.

* src/haiku_support.cc (subset_windows, class EmacsWindow)
(Unparent, ParentTo): Stop calling old fullscreen functions.
(ClearFullscreen, FullscreenRectForMode, SetFullscreen): New
functions.  Completely rewrite old zoom and fullscreen handling
code.
(Zoom): Send a ZOOM_EVENT and don't actually zoom.
(BWindow_zoom, EmacsWindow_make_fullscreen, EmacsWindow_unzoom):
Delete functions.
(be_set_window_fullscreen_mode): New function.

* src/haiku_support.h (struct haiku_zoom_event): Remove
`zoomed_p' parameter.
(enum haiku_fullscreen_mode): New enum.  Update prototypes.

* src/haikufns.c (Fx_display_pixel_height): Return height
instead of width.

* src/haikuterm.c (haiku_make_fullscreen_consistent)
(haiku_read_socket, haiku_fullscreen): Adjust to always set zoom
and fullscreen in the main thread instead of the UI threads.

* src/haikuterm.h (struct haiku_output): Remove flag `zoomed_p'
and add field `fullscreen_mode'.

doc/lispref/frames.texi
src/haiku_support.cc
src/haiku_support.h
src/haikufns.c
src/haikuterm.c
src/haikuterm.h

index 5853c45b79ea4a7bdb63c1b0dfea5b3ec082e5e4..5ea060871f4173e690d9f9367847c70ee67041c5 100644 (file)
@@ -1734,16 +1734,14 @@ fit will be clipped by the window manager.
 @item fullscreen
 This parameter specifies whether to maximize the frame's width, height
 or both.  Its value can be @code{fullwidth}, @code{fullheight},
-@code{fullboth}, or @code{maximized}.@footnote{On Haiku, setting
-@code{fullscreen} to @code{fullwidth} or @code{fullheight} has no
-effect.}  A @dfn{fullwidth} frame is as
+@code{fullboth}, or @code{maximized}.  A @dfn{fullwidth} frame is as
 wide as possible, a @dfn{fullheight} frame is as tall as possible, and
 a @dfn{fullboth} frame is both as wide and as tall as possible.  A
-@dfn{maximized} frame is like a ``fullboth'' frame, except that it usually
-keeps its title bar and the buttons for resizing
-and closing the frame.  Also, maximized frames typically avoid hiding
-any task bar or panels displayed on the desktop.  A ``fullboth'' frame,
-on the other hand, usually omits the title bar and occupies the entire
+@dfn{maximized} frame is like a ``fullboth'' frame, except that it
+usually keeps its title bar and the buttons for resizing and closing
+the frame.  Also, maximized frames typically avoid hiding any task bar
+or panels displayed on the desktop.  A ``fullboth'' frame, on the
+other hand, usually omits the title bar and occupies the entire
 available screen space.
 
 Full-height and full-width frames are more similar to maximized
index 0c126dab3d6da6cacd1d2bf831be553ff42b1058..0b3ab4cf4ae06195600bcae1b4c89fcb2c16eff7 100644 (file)
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
 #include <config.h>
+#include <attribute.h>
 
 #include <app/Application.h>
 #include <app/Cursor.h>
@@ -518,33 +519,42 @@ public:
     struct child_frame *next;
     int xoff, yoff;
     EmacsWindow *window;
-  } *subset_windows = NULL;
+  } *subset_windows;
 
-  EmacsWindow *parent = NULL;
+  EmacsWindow *parent;
   BRect pre_fullscreen_rect;
   BRect pre_zoom_rect;
-  int x_before_zoom = INT_MIN;
-  int y_before_zoom = INT_MIN;
-  bool fullscreen_p = false;
-  bool zoomed_p = false;
-  bool shown_flag = false;
-  volatile int was_shown_p = 0;
-  bool menu_bar_active_p = false;
-  bool override_redirect_p = false;
+  int x_before_zoom;
+  int y_before_zoom;
+  bool shown_flag;
+  volatile bool was_shown_p;
+  bool menu_bar_active_p;
+  bool override_redirect_p;
   window_look pre_override_redirect_look;
   window_feel pre_override_redirect_feel;
   uint32 pre_override_redirect_workspaces;
   int window_id;
-  bool *menus_begun = NULL;
+  bool *menus_begun;
   enum haiku_z_group z_group;
-  bool tooltip_p = false;
+  bool tooltip_p;
+  enum haiku_fullscreen_mode fullscreen_mode;
 
   EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK,
-                           B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS)
+                           B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS),
+                  subset_windows (NULL),
+                  parent (NULL),
+                  x_before_zoom (INT_MIN),
+                  y_before_zoom (INT_MIN),
+                  shown_flag (false),
+                  was_shown_p (false),
+                  menu_bar_active_p (false),
+                  override_redirect_p (false),
+                  window_id (current_window_id),
+                  menus_begun (NULL),
+                  z_group (Z_GROUP_NONE),
+                  tooltip_p (false),
+                  fullscreen_mode (FULLSCREEN_MODE_NONE)
   {
-    window_id = current_window_id++;
-    z_group = Z_GROUP_NONE;
-
     /* This pulse rate is used by scroll bars for repeating a button
        action while a button is held down.  */
     SetPulseRate (30000);
@@ -711,12 +721,6 @@ public:
     RecomputeFeel ();
     UpwardsUnSubsetChildren (parent);
     this->RemoveFromSubset (this);
-
-    if (fullscreen_p)
-      {
-       fullscreen_p = 0;
-       MakeFullscreen (1);
-      }
     child_frame_lock.Unlock ();
   }
 
@@ -766,11 +770,6 @@ public:
     this->AddToSubset (this);
     if (!IsHidden () && this->parent)
       UpwardsSubsetChildren (parent);
-    if (fullscreen_p)
-      {
-       fullscreen_p = 0;
-       MakeFullscreen (1);
-      }
     window->LinkChild (this);
 
     child_frame_lock.Unlock ();
@@ -1161,41 +1160,103 @@ public:
   }
 
   void
-  Zoom (BPoint o, float w, float h)
+  ClearFullscreen (void)
   {
-    struct haiku_zoom_event rq;
-    BRect rect;
-    rq.window = this;
+    switch (fullscreen_mode)
+      {
+      case FULLSCREEN_MODE_MAXIMIZED:
+       BWindow::Zoom (pre_zoom_rect.LeftTop (),
+                      BE_RECT_WIDTH (pre_zoom_rect) - 1,
+                      BE_RECT_HEIGHT (pre_zoom_rect) - 1);
+       break;
 
-    if (fullscreen_p)
-      MakeFullscreen (0);
+      case FULLSCREEN_MODE_BOTH:
+      case FULLSCREEN_MODE_HEIGHT:
+      case FULLSCREEN_MODE_WIDTH:
+       MoveTo (pre_fullscreen_rect.LeftTop ());
+       ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect) - 1,
+                 BE_RECT_HEIGHT (pre_fullscreen_rect) - 1);
 
-    if (!zoomed_p)
-      {
-       pre_zoom_rect = Frame ();
-       zoomed_p = true;
-       rect = CalculateZoomRect ();
-      }
-    else
-      {
-       zoomed_p = false;
-       rect = pre_zoom_rect;
+       SetFlags (Flags () & ~(B_NOT_MOVABLE
+                              | B_NOT_ZOOMABLE
+                              | B_NOT_RESIZABLE));
+       break;
+
+      case FULLSCREEN_MODE_NONE:
+       break;
       }
 
-    rq.zoomed = zoomed_p;
-    haiku_write (ZOOM_EVENT, &rq);
+    fullscreen_mode = FULLSCREEN_MODE_NONE;
+  }
 
-    BWindow::Zoom (rect.LeftTop (), BE_RECT_WIDTH (rect) - 1,
-                  BE_RECT_HEIGHT (rect) - 1);
+  BRect
+  FullscreenRectForMode (enum haiku_fullscreen_mode mode)
+  {
+    BScreen screen (this);
+    BRect frame;
+
+    if (!screen.IsValid ())
+      return BRect (0, 0, 0, 0);
+
+    frame = screen.Frame ();
+
+    if (mode == FULLSCREEN_MODE_HEIGHT)
+      frame.right -= BE_RECT_WIDTH (frame) / 2;
+    else if (mode == FULLSCREEN_MODE_WIDTH)
+      frame.bottom -= BE_RECT_HEIGHT (frame) / 2;
+
+    return frame;
   }
 
   void
-  UnZoom (void)
+  SetFullscreen (enum haiku_fullscreen_mode mode)
   {
-    if (!zoomed_p)
+    BRect zoom_rect;
+
+    if (fullscreen_mode == mode)
       return;
 
-    BWindow::Zoom ();
+    ClearFullscreen ();
+
+    switch (mode)
+      {
+      case FULLSCREEN_MODE_MAXIMIZED:
+       pre_zoom_rect = Frame ();
+       zoom_rect = CalculateZoomRect ();
+       BWindow::Zoom (zoom_rect.LeftTop (),
+                      BE_RECT_WIDTH (zoom_rect) - 1,
+                      BE_RECT_HEIGHT (zoom_rect) - 1);
+       break;
+
+      case FULLSCREEN_MODE_BOTH:
+       SetFlags (Flags () | B_NOT_MOVABLE);
+       FALLTHROUGH;
+
+      case FULLSCREEN_MODE_HEIGHT:
+      case FULLSCREEN_MODE_WIDTH:
+       SetFlags (Flags () | B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
+       pre_fullscreen_rect = Frame ();
+       zoom_rect = FullscreenRectForMode (mode);
+       ResizeTo (BE_RECT_WIDTH (zoom_rect) - 1,
+                 BE_RECT_HEIGHT (zoom_rect) - 1);
+       MoveTo (zoom_rect.left, zoom_rect.top);
+
+       break;
+
+      case FULLSCREEN_MODE_NONE:
+       break;
+      }
+
+    fullscreen_mode = mode;
+  }
+
+  void
+  Zoom (BPoint o, float w, float h)
+  {
+    struct haiku_zoom_event rq;
+
+    rq.window = this;
+    haiku_write (ZOOM_EVENT, &rq);
   }
 
   void
@@ -1218,51 +1279,6 @@ public:
     child_frame_lock.Lock ();
     gui_abort ("Trying to calculate offsets for a child frame that doesn't exist");
   }
-
-  void
-  MakeFullscreen (int make_fullscreen_p)
-  {
-    BScreen screen (this);
-    uint32 flags;
-    BRect screen_frame;
-
-    if (!screen.IsValid ())
-      gui_abort ("Trying to make a window fullscreen without a screen");
-
-    screen_frame = screen.Frame ();
-    UnZoom ();
-
-    if (make_fullscreen_p == fullscreen_p)
-      return;
-
-    fullscreen_p = make_fullscreen_p;
-    flags = Flags ();
-
-    if (fullscreen_p)
-      {
-       if (zoomed_p)
-         UnZoom ();
-
-       flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE;
-       pre_fullscreen_rect = Frame ();
-
-       MoveTo (0, 0);
-       ResizeTo (BE_RECT_WIDTH (screen_frame) - 1,
-                 BE_RECT_HEIGHT (screen_frame) - 1);
-      }
-    else
-      {
-       flags &= ~(B_NOT_MOVABLE | B_NOT_ZOOMABLE);
-
-       /* Use MoveTo directly since pre_fullscreen_rect isn't
-          adjusted for decorator sizes.  */
-       MoveTo (pre_fullscreen_rect.left,
-               pre_fullscreen_rect.top);
-       ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect) - 1,
-                 BE_RECT_HEIGHT (pre_fullscreen_rect) - 1);
-      }
-    SetFlags (flags);
-  }
 };
 
 class EmacsMenuBar : public BMenuBar
@@ -4486,30 +4502,6 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p,
   return file_name;
 }
 
-/* Zoom WINDOW.  */
-void
-BWindow_zoom (void *window)
-{
-  BWindow *w = (BWindow *) window;
-  w->Zoom ();
-}
-
-/* Make WINDOW fullscreen if FULLSCREEN_P.  */
-void
-EmacsWindow_make_fullscreen (void *window, int fullscreen_p)
-{
-  EmacsWindow *w = (EmacsWindow *) window;
-  w->MakeFullscreen (fullscreen_p);
-}
-
-/* Unzoom (maximize) WINDOW.  */
-void
-EmacsWindow_unzoom (void *window)
-{
-  EmacsWindow *w = (EmacsWindow *) window;
-  w->UnZoom ();
-}
-
 /* Move the pointer into MBAR and start tracking.  Return whether the
    menu bar was opened correctly.  */
 bool
@@ -5180,3 +5172,15 @@ be_unlock_window (void *window)
 
   wnd->UnlockLooper ();
 }
+
+void
+be_set_window_fullscreen_mode (void *window, enum haiku_fullscreen_mode mode)
+{
+  EmacsWindow *w = (EmacsWindow *) window;
+
+  if (!w->LockLooper ())
+    gui_abort ("Failed to lock window to set fullscreen mode");
+
+  w->SetFullscreen (mode);
+  w->UnlockLooper ();
+}
index 14dd36e275a72b39b66222fe8a50babf1c5dc8e5..0bfd027c0d3f8f1564ee68c725e9b03d4d8a6c35 100644 (file)
@@ -249,7 +249,6 @@ struct haiku_menu_bar_help_event
 struct haiku_zoom_event
 {
   void *window;
-  bool zoomed;
 };
 
 enum haiku_font_specification
@@ -316,6 +315,15 @@ enum haiku_font_weight
     HAIKU_MEDIUM      = 2000,
   };
 
+enum haiku_fullscreen_mode
+  {
+    FULLSCREEN_MODE_NONE,
+    FULLSCREEN_MODE_WIDTH,
+    FULLSCREEN_MODE_HEIGHT,
+    FULLSCREEN_MODE_BOTH,
+    FULLSCREEN_MODE_MAXIMIZED,
+  };
+
 struct haiku_font_pattern
 {
   /* Bitmask indicating which fields are set.  */
@@ -495,7 +503,6 @@ extern void BWindow_center_on_screen (void *);
 extern void BWindow_change_decoration (void *, int);
 extern void BWindow_set_tooltip_decoration (void *);
 extern void BWindow_set_avoid_focus (void *, int);
-extern void BWindow_zoom (void *);
 extern void BWindow_set_size_alignment (void *, int, int);
 extern void BWindow_sync (void *);
 extern void BWindow_send_behind (void *, void *);
@@ -623,8 +630,6 @@ extern void BAlert_delete (void *);
 extern void EmacsWindow_parent_to (void *, void *);
 extern void EmacsWindow_unparent (void *);
 extern void EmacsWindow_move_weak_child (void *, void *, int, int);
-extern void EmacsWindow_make_fullscreen (void *, int);
-extern void EmacsWindow_unzoom (void *);
 
 extern void be_get_version_string (char *, int);
 extern int be_get_display_planes (void);
@@ -690,6 +695,7 @@ extern status_t be_roster_launch (const char *, const char *, char **,
 extern void be_get_window_decorator_dimensions (void *, int *, int *, int *, int *);
 extern void be_get_window_decorator_frame (void *, int *, int *, int *, int *);
 extern void be_send_move_frame_event (void *);
+extern void be_set_window_fullscreen_mode (void *, enum haiku_fullscreen_mode);
 
 extern void be_lock_window (void *);
 extern void be_unlock_window (void *);
index 76a8569970a85d606896bbe7576e17784409c5be..314152008b0812b75bfe90bc11c0868a6659940b 100644 (file)
@@ -2281,7 +2281,7 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_heigh
   check_haiku_display_info (terminal);
 
   be_get_screen_dimensions (&width, &height);
-  return make_fixnum (width);
+  return make_fixnum (height);
 }
 
 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
index 2db1e352ffba323ee38f44195c9a9492a78a4e87..731afd9d39470316f7d48d667f1f85586cb1317f 100644 (file)
@@ -3018,11 +3018,20 @@ static struct redisplay_interface haiku_redisplay_interface =
 static void
 haiku_make_fullscreen_consistent (struct frame *f)
 {
-  Lisp_Object lval = get_frame_param (f, Qfullscreen);
-
-  if (!EQ (lval, Qmaximized) && FRAME_OUTPUT_DATA (f)->zoomed_p)
+  Lisp_Object lval;
+  struct haiku_output *output;
+
+  output = FRAME_OUTPUT_DATA (f);
+
+  if (output->fullscreen_mode == FULLSCREEN_MODE_BOTH)
+    lval = Qfullboth;
+  else if (output->fullscreen_mode == FULLSCREEN_MODE_WIDTH)
+    lval = Qfullwidth;
+  else if (output->fullscreen_mode == FULLSCREEN_MODE_HEIGHT)
+    lval = Qfullheight;
+  else if (output->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
     lval = Qmaximized;
-  else if (EQ (lval, Qmaximized) && !FRAME_OUTPUT_DATA (f)->zoomed_p)
+  else
     lval = Qnil;
 
   store_frame_param (f, Qfullscreen, lval);
@@ -3857,14 +3866,20 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
        case ZOOM_EVENT:
          {
            struct haiku_zoom_event *b = buf;
-
            struct frame *f = haiku_window_to_frame (b->window);
+           struct haiku_output *output;
 
            if (!f)
              continue;
 
-           FRAME_OUTPUT_DATA (f)->zoomed_p = b->zoomed;
-           haiku_make_fullscreen_consistent (f);
+           output = FRAME_OUTPUT_DATA (f);
+
+           if (output->fullscreen_mode == FULLSCREEN_MAXIMIZED)
+             f->want_fullscreen = FULLSCREEN_NONE;
+           else
+             f->want_fullscreen = FULLSCREEN_MAXIMIZED;
+
+           FRAME_TERMINAL (f)->fullscreen_hook (f);
            break;
          }
        case DRAG_AND_DROP_EVENT:
@@ -4096,6 +4111,8 @@ haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
 static void
 haiku_fullscreen (struct frame *f)
 {
+  enum haiku_fullscreen_mode mode;
+
   /* When FRAME_OUTPUT_DATA (f)->configury_done is false, the frame is
      being created, and its regular width and height have not yet been
      set.  This function will be called again by haiku_create_frame,
@@ -4104,18 +4121,22 @@ haiku_fullscreen (struct frame *f)
     return;
 
   if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
-    BWindow_zoom (FRAME_HAIKU_WINDOW (f));
+    mode = FULLSCREEN_MODE_MAXIMIZED;
   else if (f->want_fullscreen == FULLSCREEN_BOTH)
-    EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 1);
+    mode = FULLSCREEN_MODE_BOTH;
+  else if (f->want_fullscreen == FULLSCREEN_WIDTH)
+    mode = FULLSCREEN_MODE_WIDTH;
+  else if (f->want_fullscreen == FULLSCREEN_HEIGHT)
+    mode = FULLSCREEN_MODE_HEIGHT;
   else
-    {
-      EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
-      EmacsWindow_unzoom (FRAME_HAIKU_WINDOW (f));
-    }
+    mode = FULLSCREEN_MODE_NONE;
 
   f->want_fullscreen = FULLSCREEN_NONE;
+  be_set_window_fullscreen_mode (FRAME_HAIKU_WINDOW (f), mode);
+  FRAME_OUTPUT_DATA (f)->fullscreen_mode = mode;
 
   haiku_update_size_hints (f);
+  haiku_make_fullscreen_consistent (f);
 }
 
 static struct terminal *
index 068be8268718f60c19346f595f1e70c66c1e3a5d..41b1a85b000649ecea4bc306478f3f9d0f545093 100644 (file)
@@ -160,13 +160,16 @@ struct haiku_output
   int fontset;
   int baseline_offset;
 
-  bool_bf zoomed_p : 1;
+  /* Whether or not the hourglass cursor is currently being
+     displayed.  */
   bool_bf hourglass_p : 1;
+
+  /* Whether or not the menu bar is open.  */
   bool_bf menu_bar_open_p : 1;
 
   /* Whether or not there is data in a back buffer that hasn't been
      displayed yet.  */
-  bool dirty_p;
+  bool_bf dirty_p : 1;
 
   struct font *font;
 
@@ -201,6 +204,10 @@ struct haiku_output
      and top_pos in that the decorator and parent frames are not taken
      into account.  */
   int frame_x, frame_y;
+
+  /* The current fullscreen mode of this frame.  This should be `enum
+     haiku_fullscreen_mode', but that isn't available here.  */
+  int fullscreen_mode;
 };
 
 struct x_output