From: Po Lu Date: Tue, 17 May 2022 09:40:57 +0000 (+0000) Subject: Rewrite Haiku frame geometry code to handle decorator frames X-Git-Tag: emacs-29.0.90~1910^2~632 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=e9ad64ef92e7e8292ba596a97e114cbc91c6faa3;p=emacs.git Rewrite Haiku frame geometry code to handle decorator frames * doc/lispref/frames.texi (Frame Layout): Document changes to Haiku frame layout. * src/haiku_support.cc (class EmacsWindow, MoveToIncludingFrame) (EmacsMoveTo, MakeFullscreen): Move to an offset including the decorator frames. (be_get_window_decorator_dimensions): (be_get_window_decorator_frame): New functions. * src/haiku_support.h: Update prototypes. * src/haikufns.c (haiku_update_after_decoration_change): New function. (haiku_create_frame, haiku_set_undecorated) (haiku_set_override_redirect): Call that function. (frame_geometry): Actually calculate frame geometry based on decorator and frame sizes. * src/haikuterm.c (haiku_coords_from_parent): Use frame width instead. (haiku_read_socket): Set left and top positions based on decorator width and height. * src/haikuterm.h (struct haiku_output): New field `frame_x' and `frame_y'. --- diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 3bbeef005bd..5853c45b79e 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -683,9 +683,9 @@ The position of the top left corner of the native frame specifies the indicate that position for the various builds: @itemize @w{} -@item (1) non-toolkit and terminal frames +@item (1) non-toolkit, Haiku, and terminal frames -@item (2) Lucid, Motif, MS-Windows, and Haiku frames +@item (2) Lucid, Motif, and MS-Windows frames @item (3) GTK+ and NS frames @end itemize diff --git a/src/haiku_support.cc b/src/haiku_support.cc index c883d865343..299b37c1cc9 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -795,12 +795,24 @@ public: subset_windows = f; } + void + MoveToIncludingFrame (int x, int y) + { + BRect decorator, frame; + + decorator = DecoratorFrame (); + frame = Frame (); + + MoveTo (x + frame.left - decorator.left, + y + frame.top - decorator.top); + } + void DoMove (struct child_frame *f) { BRect frame = this->Frame (); - f->window->MoveTo (frame.left + f->xoff, - frame.top + f->yoff); + f->window->MoveToIncludingFrame (frame.left + f->xoff, + frame.top + f->yoff); } void @@ -1062,7 +1074,7 @@ public: gui_abort ("Failed to lock child frame state lock"); if (!this->parent) - this->MoveTo (x, y); + this->MoveToIncludingFrame (x, y); else this->parent->MoveChild (this, x, y, 0); child_frame_lock.Unlock (); @@ -1172,30 +1184,6 @@ public: BWindow::Zoom (); } - void - GetParentWidthHeight (int *width, int *height) - { - if (!child_frame_lock.Lock ()) - gui_abort ("Failed to lock child frame state lock"); - - if (parent) - { - BRect frame = parent->Frame (); - *width = BE_RECT_WIDTH (frame); - *height = BE_RECT_HEIGHT (frame); - } - else - { - BScreen s (this); - BRect frame = s.Frame (); - - *width = BE_RECT_WIDTH (frame); - *height = BE_RECT_HEIGHT (frame); - } - - child_frame_lock.Unlock (); - } - void OffsetChildRect (BRect *r, EmacsWindow *c) { @@ -1221,17 +1209,21 @@ public: 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; - uint32 flags = Flags (); + flags = Flags (); + if (fullscreen_p) { if (zoomed_p) @@ -1240,24 +1232,18 @@ public: flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE; pre_fullscreen_rect = Frame (); - if (!child_frame_lock.Lock ()) - gui_abort ("Failed to lock child frame state lock"); - - if (parent) - parent->OffsetChildRect (&pre_fullscreen_rect, this); - - child_frame_lock.Unlock (); - - int w, h; - EmacsMoveTo (0, 0); - GetParentWidthHeight (&w, &h); - ResizeTo (w - 1, h - 1); + MoveTo (0, 0); + ResizeTo (BE_RECT_WIDTH (screen_frame) - 1, + BE_RECT_HEIGHT (screen_frame) - 1); } else { flags &= ~(B_NOT_MOVABLE | B_NOT_ZOOMABLE); - EmacsMoveTo (pre_fullscreen_rect.left, - pre_fullscreen_rect.top); + + /* 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); } @@ -5097,3 +5083,55 @@ be_create_pixmap_cursor (void *bitmap, int x, int y) return cursor; } + +void +be_get_window_decorator_dimensions (void *window, int *left, int *top, + int *right, int *bottom) +{ + BWindow *wnd; + BRect frame, window_frame; + + wnd = (BWindow *) window; + + if (!wnd->LockLooper ()) + gui_abort ("Failed to lock window looper frame"); + + frame = wnd->DecoratorFrame (); + window_frame = wnd->Frame (); + + if (left) + *left = window_frame.left - frame.left; + + if (top) + *top = window_frame.top - frame.top; + + if (right) + *right = frame.right - window_frame.right; + + if (bottom) + *bottom = frame.bottom - window_frame.bottom; + + wnd->UnlockLooper (); +} + +void +be_get_window_decorator_frame (void *window, int *left, int *top, + int *width, int *height) +{ + BWindow *wnd; + BRect frame; + + wnd = (BWindow *) window; + + if (!wnd->LockLooper ()) + gui_abort ("Failed to lock window looper frame"); + + frame = wnd->DecoratorFrame (); + + *left = frame.left; + *top = frame.top; + *width = BE_RECT_WIDTH (frame); + *height = BE_RECT_HEIGHT (frame); + + wnd->UnlockLooper (); +} diff --git a/src/haiku_support.h b/src/haiku_support.h index bccef2628b1..cdeb40f67c4 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -686,6 +686,9 @@ extern bool be_select_font (void (*) (void), bool (*) (void), extern int be_find_font_indices (struct haiku_font_pattern *, int *, int *); 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 *); + #ifdef __cplusplus } diff --git a/src/haikufns.c b/src/haikufns.c index d55cdac44dd..e8e303fd279 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -104,6 +104,29 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo, return parms; } +/* Update the left and top offsets of F after its decorators + change. */ +static void +haiku_update_after_decoration_change (struct frame *f) +{ + int x, y, width, height; + struct frame *parent; + + 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; + } + + f->left_pos = x; + f->top_pos = y; +} + void haiku_change_tool_bar_height (struct frame *f, int height) { @@ -827,10 +850,7 @@ haiku_create_frame (Lisp_Object parms) f->terminal->reference_count++; - block_input (); - FRAME_OUTPUT_DATA (f)->window - = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); - unblock_input (); + FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); if (!FRAME_OUTPUT_DATA (f)->window) xsignal1 (Qerror, build_unibyte_string ("Could not create window")); @@ -842,7 +862,8 @@ haiku_create_frame (Lisp_Object parms) Vframe_list = Fcons (frame, Vframe_list); - Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, + Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms, + Qparent_frame, NULL, NULL, RES_TYPE_SYMBOL); if (EQ (parent_frame, Qunbound) @@ -1315,6 +1336,8 @@ haiku_set_undecorated (struct frame *f, Lisp_Object new_value, FRAME_UNDECORATED (f) = !NILP (new_value); BWindow_change_decoration (FRAME_HAIKU_WINDOW (f), NILP (new_value)); unblock_input (); + + haiku_update_after_decoration_change (f); } static void @@ -1329,6 +1352,8 @@ haiku_set_override_redirect (struct frame *f, Lisp_Object new_value, !NILP (new_value)); FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value); unblock_input (); + + haiku_update_after_decoration_change (f); } static void @@ -1375,47 +1400,74 @@ haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval static Lisp_Object frame_geometry (Lisp_Object frame, Lisp_Object attribute) { - struct frame *f = decode_live_frame (frame); - check_window_system (f); + struct frame *f, *parent; + int outer_x, outer_y, outer_width, outer_height; + int right_off, bottom_off, top_off; + int native_x, native_y; + + f = decode_window_system_frame (frame); + parent = FRAME_PARENT_FRAME (f); + + be_get_window_decorator_frame (FRAME_HAIKU_WINDOW (f), &outer_x, + &outer_y, &outer_width, &outer_height); + be_get_window_decorator_dimensions (FRAME_HAIKU_WINDOW (f), NULL, + &top_off, &right_off, &bottom_off); + native_x = FRAME_OUTPUT_DATA (f)->frame_x; + native_y = FRAME_OUTPUT_DATA (f)->frame_y; + + if (parent) + { + /* Adjust all the coordinates by the coordinates of the parent + frame. */ + outer_x -= FRAME_OUTPUT_DATA (parent)->frame_x; + outer_y -= FRAME_OUTPUT_DATA (parent)->frame_y; + native_x -= FRAME_OUTPUT_DATA (parent)->frame_x; + native_y -= FRAME_OUTPUT_DATA (parent)->frame_y; + } if (EQ (attribute, Qouter_edges)) - return list4i (f->left_pos, f->top_pos, - f->left_pos, f->top_pos); + return list4i (outer_x, outer_y, + outer_x + outer_width, + outer_y + outer_height); else if (EQ (attribute, Qnative_edges)) - return list4i (f->left_pos, f->top_pos, - f->left_pos + FRAME_PIXEL_WIDTH (f), - f->top_pos + FRAME_PIXEL_HEIGHT (f)); + return list4i (native_x, native_y, + native_x + FRAME_PIXEL_WIDTH (f), + native_y + FRAME_PIXEL_HEIGHT (f)); else if (EQ (attribute, Qinner_edges)) - return list4i (f->left_pos + FRAME_INTERNAL_BORDER_WIDTH (f), - f->top_pos + FRAME_INTERNAL_BORDER_WIDTH (f) + - FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f), - f->left_pos - FRAME_INTERNAL_BORDER_WIDTH (f) + - FRAME_PIXEL_WIDTH (f), - f->top_pos + FRAME_PIXEL_HEIGHT (f) - - FRAME_INTERNAL_BORDER_WIDTH (f)); + return list4i (native_x + FRAME_INTERNAL_BORDER_WIDTH (f), + native_y + FRAME_INTERNAL_BORDER_WIDTH (f) + + FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f), + native_x - FRAME_INTERNAL_BORDER_WIDTH (f) + + FRAME_PIXEL_WIDTH (f), + native_y + FRAME_PIXEL_HEIGHT (f) + - FRAME_INTERNAL_BORDER_WIDTH (f)); else - return - list (Fcons (Qouter_position, - Fcons (make_fixnum (f->left_pos), - make_fixnum (f->top_pos))), - Fcons (Qouter_size, - Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)), - make_fixnum (FRAME_PIXEL_HEIGHT (f)))), - Fcons (Qexternal_border_size, - Fcons (make_fixnum (0), make_fixnum (0))), - Fcons (Qtitle_bar_size, - Fcons (make_fixnum (0), make_fixnum (0))), - Fcons (Qmenu_bar_external, Qnil), - Fcons (Qmenu_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) - - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), - make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))), - Fcons (Qtool_bar_external, Qnil), - Fcons (Qtool_bar_position, Qtop), - Fcons (Qtool_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) - - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), - make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))), - Fcons (Qinternal_border_width, make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f)))); + return list (Fcons (Qouter_position, + Fcons (make_fixnum (outer_x), + make_fixnum (outer_y))), + Fcons (Qouter_size, + Fcons (make_fixnum (outer_width), + make_fixnum (outer_height))), + Fcons (Qexternal_border_size, + Fcons (make_fixnum (right_off), + make_fixnum (bottom_off))), + Fcons (Qtitle_bar_size, + Fcons (make_fixnum (outer_width), + make_fixnum (top_off))), + Fcons (Qmenu_bar_external, Qnil), + Fcons (Qmenu_bar_size, + Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) + - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), + make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))), + Fcons (Qtool_bar_external, Qnil), + Fcons (Qtool_bar_position, Qtop), + Fcons (Qtool_bar_size, + Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) + - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)), + make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))), + Fcons (Qinternal_border_width, + make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f)))); } void diff --git a/src/haikuterm.c b/src/haikuterm.c index ed8040edc91..d46228d02ef 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -96,14 +96,9 @@ static void haiku_coords_from_parent (struct frame *f, int *x, int *y) { struct frame *p = FRAME_PARENT_FRAME (f); - eassert (p); - for (struct frame *parent = p; parent; - parent = FRAME_PARENT_FRAME (parent)) - { - *x -= parent->left_pos; - *y -= parent->top_pos; - } + *x -= FRAME_OUTPUT_DATA (p)->frame_x; + *y -= FRAME_OUTPUT_DATA (p)->frame_y; } static void @@ -3535,7 +3530,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) SET_FRAME_ICONIFIED (f, 0); inev.kind = DEICONIFY_EVENT; - /* Haiku doesn't expose frames on deiconification, but if we are double-buffered, the previous screen contents should have been preserved. */ @@ -3559,30 +3553,40 @@ 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; + struct frame *p; if (!f) continue; + FRAME_OUTPUT_DATA (f)->frame_x = b->x; + FRAME_OUTPUT_DATA (f)->frame_y = b->y; + if (FRAME_PARENT_FRAME (f)) haiku_coords_from_parent (f, &b->x, &b->y); - if (b->x != f->left_pos || b->y != f->top_pos) + be_get_window_decorator_dimensions (b->window, &decorator_width, + &decorator_height, NULL, + NULL); + + left = b->x - decorator_width; + top = b->y - decorator_height; + + if (left != f->left_pos || top != f->top_pos) { inev.kind = MOVE_FRAME_EVENT; - XSETINT (inev.x, b->x); - XSETINT (inev.y, b->y); + XSETINT (inev.x, left); + XSETINT (inev.y, top); - f->left_pos = b->x; - f->top_pos = b->y; + f->left_pos = left; + f->top_pos = top; - struct frame *p; + p = FRAME_PARENT_FRAME (f); - if ((p = FRAME_PARENT_FRAME (f))) - { - void *window = FRAME_HAIKU_WINDOW (p); - EmacsWindow_move_weak_child (window, b->window, b->x, b->y); - } + if (p) + EmacsWindow_move_weak_child (FRAME_HAIKU_WINDOW (p), + b->window, left, top); XSETFRAME (inev.frame_or_window, f); } diff --git a/src/haikuterm.h b/src/haikuterm.h index 4b124a6ba30..068be826871 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -196,6 +196,11 @@ struct haiku_output They are changed only when a different background is involved. -1 means no color has been computed. */ long relief_background; + + /* The absolute position of this frame. This differs from left_pos + and top_pos in that the decorator and parent frames are not taken + into account. */ + int frame_x, frame_y; }; struct x_output