]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid race conditions when computing real frame positions on Haiku
authorPo Lu <luangruo@yahoo.com>
Tue, 17 May 2022 13:13:18 +0000 (13:13 +0000)
committerPo Lu <luangruo@yahoo.com>
Tue, 17 May 2022 13:13:41 +0000 (13:13 +0000)
* src/haiku_support.cc (DispatchMessage): Accept
SEND_MOVE_FRAME_EVENT.
(class EmacsWindow, FrameMoved): Include decorator frame in
MOVE_EVENT events.
(be_send_move_frame_event): New function.
* src/haiku_support.h (struct haiku_move_event): Include
decorator dimensions.  Update prototypes.

* src/haikufns.c (haiku_update_after_decoration_change): Ask for
a move frame event and don't do anything if configury is not yet
complete.

* src/haikuterm.c (haiku_read_socket): Adjust accordingly.

src/haiku_support.cc
src/haiku_support.h
src/haikufns.c
src/haikuterm.c

index 299b37c1cc926b0f90d873f0ddc2b42fc4fffe52..28c86085847d9b9db9cf11da8cdb9b2103224efd 100644 (file)
@@ -106,6 +106,7 @@ enum
     SET_FONT_INDICES     = 3012,
     SET_PREVIEW_DIALOG   = 3013,
     UPDATE_PREVIEW_DIALOG = 3014,
+    SEND_MOVE_FRAME_EVENT = 3015,
   };
 
 /* X11 keysyms that we use.  */
@@ -993,6 +994,8 @@ public:
            haiku_write (WHEEL_MOVE_EVENT, &rq);
          };
       }
+    else if (msg->what == SEND_MOVE_FRAME_EVENT)
+      FrameMoved (Frame ().LeftTop ());
     else
       BWindow::DispatchMessage (msg, handler);
   }
@@ -1034,33 +1037,44 @@ public:
   }
 
   void
-  FrameMoved (BPoint newPosition)
+  FrameMoved (BPoint new_position)
   {
     struct haiku_move_event rq;
+    BRect frame, decorator_frame;
+    struct child_frame *f;
+
     rq.window = this;
-    rq.x = std::lrint (newPosition.x);
-    rq.y = std::lrint (newPosition.y);
+    rq.x = std::lrint (new_position.x);
+    rq.y = std::lrint (new_position.y);
+
+    frame = Frame ();
+    decorator_frame = DecoratorFrame ();
+
+    rq.decorator_width
+      = std::lrint (frame.left - decorator_frame.left);
+    rq.decorator_height
+      = std::lrint (frame.top - decorator_frame.top);
 
     haiku_write (MOVE_EVENT, &rq);
 
     CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
       {
-       for (struct child_frame *f = subset_windows;
-            f; f = f->next)
+       for (f = subset_windows; f; f = f->next)
          DoMove (f);
        child_frame_lock.Unlock ();
 
-       BWindow::FrameMoved (newPosition);
+       BWindow::FrameMoved (new_position);
       }
   }
 
   void
   WorkspacesChanged (uint32_t old, uint32_t n)
   {
+    struct child_frame *f;
+
     CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
       {
-       for (struct child_frame *f = subset_windows;
-            f; f = f->next)
+       for (f = subset_windows; f; f = f->next)
          DoUpdateWorkspace (f);
 
        child_frame_lock.Unlock ();
@@ -5135,3 +5149,17 @@ be_get_window_decorator_frame (void *window, int *left, int *top,
 
   wnd->UnlockLooper ();
 }
+
+/* Request that a MOVE_EVENT be sent for WINDOW.  This is so that
+   frame offsets can be updated after a frame parameter affecting
+   decorators changes.  Sending an event instead of updating the
+   offsets directly avoids race conditions where events with older
+   information are received after the update happens.  */
+void
+be_send_move_frame_event (void *window)
+{
+  BWindow *wnd = (BWindow *) window;
+  BMessenger msg (wnd);
+
+  msg.SendMessage (SEND_MOVE_FRAME_EVENT);
+}
index cdeb40f67c47df46c3d0e1aff6b44db0a5cdffca..22f13c1ee67ca17712976c23e69a980c1429680b 100644 (file)
@@ -219,8 +219,9 @@ struct haiku_iconification_event
 struct haiku_move_event
 {
   void *window;
-  int x;
-  int y;
+  int x, y;
+  int decorator_width;
+  int decorator_height;
 };
 
 struct haiku_wheel_move_event
@@ -688,6 +689,7 @@ extern status_t be_roster_launch (const char *, const char *, char **,
                                  ptrdiff_t, void *, team_id *);
 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 *);
 
 #ifdef __cplusplus
 }
index e8e303fd2798cdcf308ff3c1ff3b970ff10d0b20..fa47da73d2c1573993afb1639206df4f73150636 100644 (file)
@@ -109,22 +109,15 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo,
 static void
 haiku_update_after_decoration_change (struct frame *f)
 {
-  int x, y, width, height;
-  struct frame *parent;
+  /* Don't reset offsets during initial frame creation, since the
+     contents of f->left_pos and f->top_pos won't be applied to the
+     window until `x-create-frame' finishes, so setting them here will
+     overwrite the offsets that the window should be moved to.  */
 
-  be_get_window_decorator_frame (FRAME_HAIKU_WINDOW (f),
-                                &x, &y, &width, &height);
-
-  parent = FRAME_PARENT_FRAME (f);
-
-  if (parent)
-    {
-      x = x - FRAME_OUTPUT_DATA (f)->frame_x;
-      y = y - FRAME_OUTPUT_DATA (f)->frame_x;
-    }
+  if (!FRAME_OUTPUT_DATA (f)->configury_done)
+    return;
 
-  f->left_pos = x;
-  f->top_pos = y;
+  be_send_move_frame_event (FRAME_HAIKU_WINDOW (f));
 }
 
 void
index d46228d02efdb08e5a0e8abf3a015e9576c09c13..0952392210882fc3599dabf5aa2bb9880fd1fd0e 100644 (file)
@@ -3553,7 +3553,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
          {
            struct haiku_move_event *b = buf;
            struct frame *f = haiku_window_to_frame (b->window);
-           int decorator_width, decorator_height, top, left;
+           int top, left;
            struct frame *p;
 
            if (!f)
@@ -3565,12 +3565,8 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
            if (FRAME_PARENT_FRAME (f))
              haiku_coords_from_parent (f, &b->x, &b->y);
 
-           be_get_window_decorator_dimensions (b->window, &decorator_width,
-                                               &decorator_height, NULL,
-                                               NULL);
-
-           left = b->x - decorator_width;
-           top = b->y - decorator_height;
+           left = b->x - b->decorator_width;
+           top = b->y - b->decorator_height;
 
            if (left != f->left_pos || top != f->top_pos)
              {