emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 4dfaefcffc: Fix race conditions processing frame fullscreen state


From: Po Lu
Subject: master 4dfaefcffc: Fix race conditions processing frame fullscreen state on Haiku
Date: Wed, 18 May 2022 23:44:03 -0400 (EDT)

branch: master
commit 4dfaefcffc987400a317b5ccf0c9bf00f7c84134
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix race conditions processing frame fullscreen state on Haiku
    
    * 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 |  14 ++-
 src/haiku_support.cc    | 242 ++++++++++++++++++++++++------------------------
 src/haiku_support.h     |  14 ++-
 src/haikufns.c          |   2 +-
 src/haikuterm.c         |  47 +++++++---
 src/haikuterm.h         |  11 ++-
 6 files changed, 183 insertions(+), 147 deletions(-)

diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 5853c45b79..5ea060871f 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -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
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 0c126dab3d..0b3ab4cf4a 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -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 ();
+}
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 14dd36e275..0bfd027c0d 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -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 *);
diff --git a/src/haikufns.c b/src/haikufns.c
index 76a8569970..314152008b 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -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,
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 2db1e352ff..731afd9d39 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -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 *
diff --git a/src/haikuterm.h b/src/haikuterm.h
index 068be82687..41b1a85b00 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]