emacs-diffs
[Top][All Lists]
Advanced

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

master e9ad64ef92: Rewrite Haiku frame geometry code to handle decorator


From: Po Lu
Subject: master e9ad64ef92: Rewrite Haiku frame geometry code to handle decorator frames
Date: Tue, 17 May 2022 05:59:33 -0400 (EDT)

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

    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'.
---
 doc/lispref/frames.texi |   4 +-
 src/haiku_support.cc    | 122 +++++++++++++++++++++++++++++---------------
 src/haiku_support.h     |   3 ++
 src/haikufns.c          | 132 +++++++++++++++++++++++++++++++++---------------
 src/haikuterm.c         |  42 ++++++++-------
 src/haikuterm.h         |   5 ++
 6 files changed, 205 insertions(+), 103 deletions(-)

diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 3bbeef005b..5853c45b79 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 c883d86534..299b37c1cc 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 bccef2628b..cdeb40f67c 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 d55cdac44d..e8e303fd27 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 ed8040edc9..d46228d02e 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 4b124a6ba3..068be82687 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



reply via email to

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