From: Po Lu Date: Tue, 17 May 2022 13:13:18 +0000 (+0000) Subject: Avoid race conditions when computing real frame positions on Haiku X-Git-Tag: emacs-29.0.90~1910^2~626 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=5c656182ce30372873ea2e3f1ffb555f52df9d95;p=emacs.git Avoid race conditions when computing real frame positions on Haiku * 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. --- diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 299b37c1cc9..28c86085847 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -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); +} diff --git a/src/haiku_support.h b/src/haiku_support.h index cdeb40f67c4..22f13c1ee67 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -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 } diff --git a/src/haikufns.c b/src/haikufns.c index e8e303fd279..fa47da73d2c 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -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 diff --git a/src/haikuterm.c b/src/haikuterm.c index d46228d02ef..09523922108 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -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) {