]> git.eshelyaron.com Git - emacs.git/commitdiff
Rewrite Haiku frame geometry code to handle decorator frames
authorPo Lu <luangruo@yahoo.com>
Tue, 17 May 2022 09:40:57 +0000 (09:40 +0000)
committerPo Lu <luangruo@yahoo.com>
Tue, 17 May 2022 09:59:20 +0000 (09:59 +0000)
* 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'.

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

index 3bbeef005bde99f419aa4c1e96ec4819169926b8..5853c45b79ea4a7bdb63c1b0dfea5b3ec082e5e4 100644 (file)
@@ -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
index c883d865343a8d5e2af032836143ff2ecef9e376..299b37c1cc926b0f90d873f0ddc2b42fc4fffe52 100644 (file)
@@ -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 ();
+}
index bccef2628b14bf6b47e320cc09e04204277b7773..cdeb40f67c47df46c3d0e1aff6b44db0a5cdffca 100644 (file)
@@ -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
 }
 
index d55cdac44dd675eb14ea3a565963e42d963c4f8d..e8e303fd2798cdcf308ff3c1ff3b970ff10d0b20 100644 (file)
@@ -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
index ed8040edc9125178415c145d8275f498909af884..d46228d02efdb08e5a0e8abf3a015e9576c09c13 100644 (file)
@@ -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);
              }
index 4b124a6ba30d2ff3645dfe8e5a848bf5416b2106..068be8268718f60c19346f595f1e70c66c1e3a5d 100644 (file)
@@ -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