[mutter] Use utility functions to convert between frame and client rectangles



commit 4ee9f3563bb8315af71bebe31d06bd08b121d827
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Fri Nov 15 16:11:20 2013 -0500

    Use utility functions to convert between frame and client rectangles
    
    There are extensive places in the code where we convert between the client
    rectangle and the frame rectangle. Instead of manually doing it use
    new helper functions on MetaWindow and the existing meta_window_get_outer_rect().
    
    This fixes a number of bugs where the computation was being done incorrectly,
    most of these bugs are with the recently added custom frame extents, but
    some relate to invisible borders or even simply to confusion between the
    window and frame rectangle.
    
    Switch the placement code to place the frame rectangle rather
    than the client window - this simplifies things considerably.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=707194

 doc/reference/meta-sections.txt |    2 +
 src/core/constraints.c          |   50 ++++-----
 src/core/display.c              |   18 ++--
 src/core/place.c                |  214 +++++++++++++++------------------------
 src/core/window.c               |  142 ++++++++++++++++++--------
 src/meta/window.h               |    8 ++
 6 files changed, 222 insertions(+), 212 deletions(-)
---
diff --git a/doc/reference/meta-sections.txt b/doc/reference/meta-sections.txt
index 08e8f7c..b87cbfe 100644
--- a/doc/reference/meta-sections.txt
+++ b/doc/reference/meta-sections.txt
@@ -542,6 +542,8 @@ meta_window_is_skip_taskbar
 meta_window_get_rect
 meta_window_get_input_rect
 meta_window_get_outer_rect
+meta_window_client_rect_to_frame_rect
+meta_window_frame_rect_to_client_rect
 meta_window_get_screen
 meta_window_get_display
 meta_window_get_xwindow
diff --git a/src/core/constraints.c b/src/core/constraints.c
index bc23a72..a60595f 100644
--- a/src/core/constraints.c
+++ b/src/core/constraints.c
@@ -204,10 +204,10 @@ static void place_window_if_needed       (MetaWindow     *window,
                                           ConstraintInfo *info);
 static void update_onscreen_requirements (MetaWindow     *window,
                                           ConstraintInfo *info);
-static void extend_by_frame              (MetaRectangle           *rect,
-                                          const MetaFrameBorders  *borders);
-static void unextend_by_frame            (MetaRectangle           *rect,
-                                          const MetaFrameBorders  *borders);
+static void extend_by_frame              (MetaWindow     *window,
+                                          MetaRectangle  *rect);
+static void unextend_by_frame            (MetaWindow     *window,
+                                          MetaRectangle  *rect);
 static inline void get_size_limits       (const MetaWindow        *window,
                                           const MetaFrameBorders  *borders,
                                           gboolean include_frame,
@@ -519,10 +519,11 @@ place_window_if_needed(MetaWindow     *window,
       !window->minimized &&
       !window->fullscreen)
     {
-      MetaRectangle placed_rect = info->orig;
+      MetaRectangle placed_rect;
       MetaWorkspace *cur_workspace;
       const MetaMonitorInfo *monitor_info;
 
+      meta_window_get_outer_rect (window, &placed_rect);
       meta_window_place (window, info->borders, info->orig.x, info->orig.y,
                          &placed_rect.x, &placed_rect.y);
       did_placement = TRUE;
@@ -541,6 +542,7 @@ place_window_if_needed(MetaWindow     *window,
         meta_workspace_get_onmonitor_region (cur_workspace, 
                                              monitor_info->number);
 
+      meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect);
 
       info->current.x = placed_rect.x;
       info->current.y = placed_rect.y;
@@ -649,7 +651,7 @@ update_onscreen_requirements (MetaWindow     *window,
   /* The require onscreen/on-single-monitor and titlebar_visible
    * stuff is relative to the outer window, not the inner
    */
-  extend_by_frame (&info->current, info->borders);
+  extend_by_frame (window, &info->current);
 
   /* Update whether we want future constraint runs to require the
    * window to be on fully onscreen.
@@ -698,27 +700,21 @@ update_onscreen_requirements (MetaWindow     *window,
     }
 
   /* Don't forget to restore the position of the window */
-  unextend_by_frame (&info->current, info->borders);
+  unextend_by_frame (window, &info->current);
 }
 
 static void
-extend_by_frame (MetaRectangle           *rect,
-                 const MetaFrameBorders *borders)
+extend_by_frame (MetaWindow    *window,
+                 MetaRectangle *rect)
 {
-  rect->x -= borders->visible.left;
-  rect->y -= borders->visible.top;
-  rect->width  += borders->visible.left + borders->visible.right;
-  rect->height += borders->visible.top + borders->visible.bottom;
+  meta_window_client_rect_to_frame_rect (window, rect, rect);
 }
 
 static void
-unextend_by_frame (MetaRectangle           *rect,
-                   const MetaFrameBorders *borders)
+unextend_by_frame (MetaWindow    *window,
+                   MetaRectangle *rect)
 {
-  rect->x += borders->visible.left;
-  rect->y += borders->visible.top;
-  rect->width  -= borders->visible.left + borders->visible.right;
-  rect->height -= borders->visible.top + borders->visible.bottom;
+  meta_window_frame_rect_to_client_rect (window, rect, rect);
 }
 
 static inline void
@@ -778,13 +774,13 @@ constrain_modal_dialog (MetaWindow         *window,
   */
 
   child_rect = info->current;
-  extend_by_frame (&child_rect, info->borders);
+  extend_by_frame (window, &child_rect);
 
   meta_window_get_outer_rect (parent, &parent_rect);
 
   child_rect.x = parent_rect.x + (parent_rect.width / 2  - child_rect.width / 2);
   child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
-  unextend_by_frame (&child_rect, info->borders);
+  unextend_by_frame (window, &child_rect);
   x = child_rect.x;
   y = child_rect.y;
 
@@ -851,14 +847,14 @@ constrain_maximization (MetaWindow         *window,
       active_workspace_struts = window->screen->active_workspace->all_struts;
 
       target_size = info->current;
-      extend_by_frame (&target_size, info->borders);
+      extend_by_frame (window, &target_size);
       meta_rectangle_expand_to_avoiding_struts (&target_size,
                                                 &info->entire_monitor,
                                                 direction,
                                                 active_workspace_struts);
    }
   /* Now make target_size = maximized size of client window */
-  unextend_by_frame (&target_size, info->borders);
+  unextend_by_frame (window, &target_size);
 
   /* Check min size constraints; max size constraints are ignored for maximized
    * windows, as per bug 327543.
@@ -917,7 +913,7 @@ constrain_tiling (MetaWindow         *window,
    * use an external function for the actual calculation
    */
   meta_window_get_current_tile_area (window, &target_size);
-  unextend_by_frame (&target_size, info->borders);
+  unextend_by_frame (window, &target_size);
 
   /* Check min size constraints; max size constraints are ignored as for
    * maximized windows.
@@ -1267,7 +1263,7 @@ do_screen_and_monitor_relative_constraints (
   /* Determine whether constraint applies; exit if it doesn't */
   how_far_it_can_be_smushed = info->current;
   get_size_limits (window, info->borders, TRUE, &min_size, &max_size);
-  extend_by_frame (&info->current, info->borders);
+  extend_by_frame (window, &info->current);
 
   if (info->action_type != ACTION_MOVE)
     {
@@ -1287,7 +1283,7 @@ do_screen_and_monitor_relative_constraints (
                                         &info->current);
   if (exit_early || constraint_satisfied || check_only)
     {
-      unextend_by_frame (&info->current, info->borders);
+      unextend_by_frame (window, &info->current);
       return constraint_satisfied;
     }
 
@@ -1311,7 +1307,7 @@ do_screen_and_monitor_relative_constraints (
                                       info->fixed_directions,
                                       &info->current);
 
-  unextend_by_frame (&info->current, info->borders);
+  unextend_by_frame (window, &info->current);
   return TRUE;
 }
 
diff --git a/src/core/display.c b/src/core/display.c
index c6620ac..d94f136 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1610,6 +1610,7 @@ window_raise_with_delay_callback (void *data)
     {
       int x, y, root_x, root_y;
       Window root, child;
+      MetaRectangle frame_rect;
       unsigned int mask;
       gboolean same_screen;
       gboolean point_in_window;
@@ -1621,9 +1622,8 @@ window_raise_with_delay_callback (void *data)
                                   &root_x, &root_y, &x, &y, &mask);
       meta_error_trap_pop (window->display);
 
-      point_in_window = 
-        (window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
-        (window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect));
+      meta_window_get_outer_rect (window, &frame_rect);
+      point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
       if (same_screen && point_in_window)
        meta_window_raise (window);
       else
@@ -2437,15 +2437,15 @@ event_callback (XEvent   *event,
                     {
                       gboolean north, south;
                       gboolean west, east;
-                      int root_x, root_y;
+                      MetaRectangle frame_rect;
                       MetaGrabOp op;
 
-                      meta_window_get_position (window, &root_x, &root_y);
+                      meta_window_get_outer_rect (window, &frame_rect);
 
-                      west = device_event->root_x <  (root_x + 1 * window->rect.width  / 3);
-                      east = device_event->root_x >  (root_x + 2 * window->rect.width  / 3);
-                      north = device_event->root_y < (root_y + 1 * window->rect.height / 3);
-                      south = device_event->root_y > (root_y + 2 * window->rect.height / 3);
+                      west = device_event->root_x <  (frame_rect.x + 1 * frame_rect.width  / 3);
+                      east = device_event->root_x >  (frame_rect.x + 2 * frame_rect.width  / 3);
+                      north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3);
+                      south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3);
 
                       if (north && west)
                         op = META_GRAB_OP_RESIZING_NW;
diff --git a/src/core/place.c b/src/core/place.c
index 70171cb..7835dee 100644
--- a/src/core/place.c
+++ b/src/core/place.c
@@ -47,34 +47,18 @@ northwestcmp (gconstpointer a, gconstpointer b)
 {
   MetaWindow *aw = (gpointer) a;
   MetaWindow *bw = (gpointer) b;
+  MetaRectangle a_frame;
+  MetaRectangle b_frame;
   int from_origin_a;
   int from_origin_b;
   int ax, ay, bx, by;
 
-  /* we're interested in the frame position for cascading,
-   * not meta_window_get_position()
-   */
-  if (aw->frame)
-    {
-      ax = aw->frame->rect.x;
-      ay = aw->frame->rect.y;
-    }
-  else
-    {
-      ax = aw->rect.x;
-      ay = aw->rect.y;
-    }
-
-  if (bw->frame)
-    {
-      bx = bw->frame->rect.x;
-      by = bw->frame->rect.y;
-    }
-  else
-    {
-      bx = bw->rect.x;
-      by = bw->rect.y;
-    }
+  meta_window_get_outer_rect (aw, &a_frame);
+  meta_window_get_outer_rect (bw, &b_frame);
+  ax = a_frame.x;
+  ay = a_frame.y;
+  bx = b_frame.x;
+  by = b_frame.y;
   
   /* probably there's a fast good-enough-guess we could use here. */
   from_origin_a = sqrt (ax * ax + ay * ay);
@@ -102,6 +86,7 @@ find_next_cascade (MetaWindow *window,
   GList *sorted;
   int cascade_x, cascade_y;
   int x_threshold, y_threshold;
+  MetaRectangle frame_rect;
   int window_width, window_height;
   int cascade_stage;
   MetaRectangle work_area;
@@ -143,30 +128,25 @@ find_next_cascade (MetaWindow *window,
   cascade_y = MAX (0, work_area.y);
   
   /* Find first cascade position that's not used. */
-  
-  window_width = window->frame ? window->frame->rect.width : window->rect.width;
-  window_height = window->frame ? window->frame->rect.height : window->rect.height;
+
+  meta_window_get_outer_rect (window, &frame_rect);
+  window_width = frame_rect.width;
+  window_height = frame_rect.height;
   
   cascade_stage = 0;
   tmp = sorted;
   while (tmp != NULL)
     {
       MetaWindow *w;
+      MetaRectangle w_frame_rect;
       int wx, wy;
       
       w = tmp->data;
 
       /* we want frame position, not window position */
-      if (w->frame)
-        {
-          wx = w->frame->rect.x;
-          wy = w->frame->rect.y;
-        }
-      else
-        {
-          wx = w->rect.x;
-          wy = w->rect.y;
-        }
+      meta_window_get_outer_rect (w, &w_frame_rect);
+      wx = w_frame_rect.x;
+      wy = w_frame_rect.y;
       
       if (ABS (wx - cascade_x) < x_threshold &&
           ABS (wy - cascade_y) < y_threshold)
@@ -223,17 +203,8 @@ find_next_cascade (MetaWindow *window,
   
   g_list_free (sorted);
 
-  /* Convert coords to position of window, not position of frame. */
-  if (borders == NULL)
-    {
-      *new_x = cascade_x;
-      *new_y = cascade_y;
-    }
-  else
-    {
-      *new_x = cascade_x + borders->visible.left;
-      *new_y = cascade_y + borders->visible.top;
-    }
+  *new_x = cascade_x;
+  *new_y = cascade_y;
 }
 
 static void
@@ -250,14 +221,10 @@ find_most_freespace (MetaWindow *window,
   int max_area;
   int max_width, max_height, left, right, top, bottom;
   int left_space, right_space, top_space, bottom_space;
-  int frame_size_left, frame_size_top;
   MetaRectangle work_area;
   MetaRectangle avoid;
   MetaRectangle outer;
 
-  frame_size_left = borders ? borders->visible.left : 0;
-  frame_size_top  = borders ? borders->visible.top : 0;
-
   meta_window_get_work_area_current_monitor (focus_window, &work_area);
   meta_window_get_outer_rect (focus_window, &avoid);
   meta_window_get_outer_rect (window, &outer);
@@ -304,36 +271,54 @@ find_most_freespace (MetaWindow *window,
   switch (side)
     {
     case META_LEFT:
-      *new_y = avoid.y + frame_size_top;
+      *new_y = avoid.y;
       if (left_space > outer.width)
-        *new_x = avoid.x - outer.width + frame_size_left;
+        *new_x = avoid.x - outer.width;
       else
-        *new_x = work_area.x + frame_size_left;
+        *new_x = work_area.x;
       break;
     case META_RIGHT:
-      *new_y = avoid.y + frame_size_top;
+      *new_y = avoid.y;
       if (right_space > outer.width)
-        *new_x = avoid.x + avoid.width + frame_size_left;
+        *new_x = avoid.x + avoid.width;
       else
-        *new_x = work_area.x + work_area.width - outer.width + frame_size_left;
+        *new_x = work_area.x + work_area.width - outer.width;
       break;
     case META_TOP:
-      *new_x = avoid.x + frame_size_left;
+      *new_x = avoid.x;
       if (top_space > outer.height)
-        *new_y = avoid.y - outer.height + frame_size_top;
+        *new_y = avoid.y - outer.height;
       else
-        *new_y = work_area.y + frame_size_top;
+        *new_y = work_area.y;
       break;
     case META_BOTTOM:
-      *new_x = avoid.x + frame_size_left;
+      *new_x = avoid.x;
       if (bottom_space > outer.height)
-        *new_y = avoid.y + avoid.height + frame_size_top;
+        *new_y = avoid.y + avoid.height;
       else
-        *new_y = work_area.y + work_area.height - outer.height + frame_size_top;
+        *new_y = work_area.y + work_area.height - outer.height;
       break;
     }
 }
 
+static gboolean
+window_overlaps_focus_window (MetaWindow *window)
+{
+  MetaWindow *focus_window;
+  MetaRectangle window_frame, focus_frame, overlap;
+
+  focus_window = window->display->focus_window;
+  if (focus_window == NULL)
+    return FALSE;
+
+  meta_window_get_outer_rect (window, &window_frame);
+  meta_window_get_outer_rect (focus_window, &focus_frame);
+
+  return meta_rectangle_intersect (&window_frame,
+                                   &focus_frame,
+                                   &overlap);
+}
+
 static void
 avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
                                              MetaFrameBorders *borders,
@@ -355,16 +340,15 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
    */
 
   MetaWindow *focus_window;
-  MetaRectangle overlap;
 
   focus_window = window->display->focus_window;
 
+  /* denied_focus_and_not_transient is only set when focus_window != NULL */
+
   if (window->denied_focus_and_not_transient &&
       window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
       meta_window_same_application (window, focus_window) &&
-      meta_rectangle_intersect (&window->rect,
-                                &focus_window->rect,
-                                &overlap))
+      window_overlaps_focus_window (window))
     {
       find_most_freespace (window, borders, focus_window, *x, *y, x, y);
       meta_topic (META_DEBUG_PLACEMENT,
@@ -427,20 +411,14 @@ leftmost_cmp (gconstpointer a, gconstpointer b)
 {
   MetaWindow *aw = (gpointer) a;
   MetaWindow *bw = (gpointer) b;
+  MetaRectangle a_frame;
+  MetaRectangle b_frame;
   int ax, bx;
 
-  /* we're interested in the frame position for cascading,
-   * not meta_window_get_position()
-   */
-  if (aw->frame)
-    ax = aw->frame->rect.x;
-  else
-    ax = aw->rect.x;
-
-  if (bw->frame)
-    bx = bw->frame->rect.x;
-  else
-    bx = bw->rect.x;
+  meta_window_get_outer_rect (aw, &a_frame);
+  meta_window_get_outer_rect (bw, &b_frame);
+  ax = a_frame.x;
+  bx = b_frame.x;
 
   if (ax < bx)
     return -1;
@@ -455,20 +433,14 @@ topmost_cmp (gconstpointer a, gconstpointer b)
 {
   MetaWindow *aw = (gpointer) a;
   MetaWindow *bw = (gpointer) b;
+  MetaRectangle a_frame;
+  MetaRectangle b_frame;
   int ay, by;
 
-  /* we're interested in the frame position for cascading,
-   * not meta_window_get_position()
-   */
-  if (aw->frame)
-    ay = aw->frame->rect.y;
-  else
-    ay = aw->rect.y;
-
-  if (bw->frame)
-    by = bw->frame->rect.y;
-  else
-    by = bw->rect.y;
+  meta_window_get_outer_rect (aw, &a_frame);
+  meta_window_get_outer_rect (bw, &b_frame);
+  ay = a_frame.y;
+  by = b_frame.y;
 
   if (ay < by)
     return -1;
@@ -540,15 +512,8 @@ find_first_fit (MetaWindow *window,
   right_sorted = g_list_copy (windows);
   right_sorted = g_list_sort (right_sorted, topmost_cmp);
   right_sorted = g_list_sort (right_sorted, leftmost_cmp);
-  
-  rect.width = window->rect.width;
-  rect.height = window->rect.height;
-  
-  if (borders)
-    {
-      rect.width += borders->visible.left + borders->visible.right;
-      rect.height += borders->visible.top + borders->visible.bottom;
-    }
+
+  meta_window_get_outer_rect (window, &rect);
 
 #ifdef WITH_VERBOSE_MODE
     {
@@ -570,11 +535,6 @@ find_first_fit (MetaWindow *window,
       {
         *new_x = rect.x;
         *new_y = rect.y;
-        if (borders)
-          {
-            *new_x += borders->visible.left;
-            *new_y += borders->visible.top;
-          }
     
         retval = TRUE;
        
@@ -598,11 +558,6 @@ find_first_fit (MetaWindow *window,
           {
             *new_x = rect.x;
             *new_y = rect.y;
-            if (borders)
-              {
-                *new_x += borders->visible.left;
-                *new_y += borders->visible.top;
-              }
           
             retval = TRUE;
           
@@ -629,11 +584,6 @@ find_first_fit (MetaWindow *window,
           {
             *new_x = rect.x;
             *new_y = rect.y;
-            if (borders)
-              {
-                *new_x += borders->visible.left;
-                *new_y += borders->visible.top;
-              }
         
             retval = TRUE;
        
@@ -775,24 +725,22 @@ meta_window_place (MetaWindow        *window,
 
       if (parent)
         {
-          int w;
+          MetaRectangle frame_rect, parent_frame_rect;
 
-          meta_window_get_position (parent, &x, &y);
-          w = parent->rect.width;
+          meta_window_get_outer_rect (window, &frame_rect);
+          meta_window_get_outer_rect (parent, &parent_frame_rect);
+
+          y = parent_frame_rect.y;
 
           /* center of parent */
-          x = x + w / 2;
+          x = parent_frame_rect.x + parent_frame_rect.width / 2;
           /* center of child over center of parent */
-          x -= window->rect.width / 2;
+          x -= frame_rect.width / 2;
 
           /* "visually" center window over parent, leaving twice as
            * much space below as on top.
            */
-          y += (parent->rect.height - window->rect.height)/3;
-
-          /* put top of child's frame, not top of child's client */
-          if (borders)
-            y += borders->visible.top;
+          y += (parent_frame_rect.height - frame_rect.height)/3;
 
           meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
                       window->desc);
@@ -813,6 +761,9 @@ meta_window_place (MetaWindow        *window,
     {
       /* Center on current monitor */
       int w, h;
+      MetaRectangle frame_rect;
+
+      meta_window_get_outer_rect (window, &frame_rect);
 
       /* Warning, this function is a round trip! */
       xi = meta_screen_get_current_monitor_info (window->screen);
@@ -820,8 +771,8 @@ meta_window_place (MetaWindow        *window,
       w = xi->rect.width;
       h = xi->rect.height;
 
-      x = (w - window->rect.width) / 2;
-      y = (h - window->rect.height) / 2;
+      x = (w - frame_rect.width) / 2;
+      y = (h - frame_rect.height) / 2;
 
       x += xi->rect.x;
       y += xi->rect.y;
@@ -909,17 +860,14 @@ meta_window_place (MetaWindow        *window,
    */
   if (window->denied_focus_and_not_transient)
     {
-      gboolean       found_fit;
       MetaWindow    *focus_window;
-      MetaRectangle  overlap;
+      gboolean       found_fit;
 
       focus_window = window->display->focus_window;
       g_assert (focus_window != NULL);
 
       /* No need to do anything if the window doesn't overlap at all */
-      found_fit = !meta_rectangle_intersect (&window->rect,
-                                             &focus_window->rect,
-                                             &overlap);
+      found_fit = !window_overlaps_focus_window (window);
 
       /* Try to do a first fit again, this time only taking into account the
        * focus window.
diff --git a/src/core/window.c b/src/core/window.c
index a75fd6f..69094d3 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -3820,7 +3820,7 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
 {
   int monitor;
   MetaRectangle tile_area;
-  MetaFrameBorders borders;
+  MetaRectangle client_rect;
 
   if (!meta_window_can_tile_maximized (window))
     return FALSE;
@@ -3834,13 +3834,10 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
 
   tile_area.width /= 2;
 
-  meta_frame_calc_borders (window->frame, &borders);
-
-  tile_area.width  -= (borders.visible.left + borders.visible.right);
-  tile_area.height -= (borders.visible.top + borders.visible.bottom);
+  meta_window_frame_rect_to_client_rect (window, &tile_area, &client_rect);
 
-  return tile_area.width >= window->size_hints.min_width &&
-         tile_area.height >= window->size_hints.min_height;
+  return client_rect.width >= window->size_hints.min_width &&
+         client_rect.height >= window->size_hints.min_height;
 }
 
 static void
@@ -5397,23 +5394,10 @@ meta_window_move_frame (MetaWindow  *window,
                   int          root_x_nw,
                   int          root_y_nw)
 {
-  int x = root_x_nw;
-  int y = root_y_nw;
+  MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
 
-  if (window->frame)
-    {
-      MetaFrameBorders borders;
-      meta_frame_calc_borders (window->frame, &borders);
-
-      /* root_x_nw and root_y_nw correspond to where the top of
-       * the visible frame should be. Offset by the distance between
-       * the origin of the window and the origin of the enclosing
-       * window decorations.
-       */
-      x += window->frame->child_x - borders.invisible.left;
-      y += window->frame->child_y - borders.invisible.top;
-    }
-  meta_window_move (window, user_op, x, y);
+  meta_window_frame_rect_to_client_rect (window, &rect, &rect);
+  meta_window_move (window, user_op, rect.x, rect.y);
 }
 
 static void
@@ -5461,18 +5445,10 @@ meta_window_move_resize_frame (MetaWindow  *window,
                                int          w,
                                int          h)
 {
-  MetaFrameBorders borders;
-
-  meta_frame_calc_borders (window->frame, &borders);
-  /* offset by the distance between the origin of the window
-   * and the origin of the enclosing window decorations ( + border)
-   */
-  root_x_nw += borders.visible.left;
-  root_y_nw += borders.visible.top;
-  w -= borders.visible.left + borders.visible.right;
-  h -= borders.visible.top + borders.visible.bottom;
+  MetaRectangle rect = { root_x_nw, root_y_nw, w, h };
+  meta_window_frame_rect_to_client_rect (window, &rect, &rect);
 
-  meta_window_move_resize (window, user_op, root_x_nw, root_y_nw, w, h);
+  meta_window_move_resize (window, user_op, rect.x, rect.y, rect.width, rect.height);
 }
 
 /**
@@ -5785,6 +5761,91 @@ meta_window_get_input_rect (const MetaWindow *window,
 }
 
 /**
+ * meta_window_client_rect_to_frame_rect:
+ * @window: a #MetaWindow
+ * @frame_rect: client rectangle in root coordinates
+ * @client_rect: (out): location to store the computed corresponding frame bounds.
+ *
+ * Converts a desired bounds of the client window - what is passed to meta_window_move_resize() -
+ * into the corresponding bounds of the window frame (excluding invisible borders
+ * and client side shadows.)
+ */
+void
+meta_window_client_rect_to_frame_rect (MetaWindow    *window,
+                                       MetaRectangle *frame_rect,
+                                       MetaRectangle *client_rect)
+{
+  if (!client_rect)
+    return;
+
+  *client_rect = *frame_rect;
+
+  if (window->frame)
+    {
+      MetaFrameBorders borders;
+      meta_frame_calc_borders (window->frame, &borders);
+
+      client_rect->x -= borders.visible.left;
+      client_rect->y -= borders.visible.top;
+      client_rect->width  += borders.visible.left + borders.visible.right;
+      client_rect->height += borders.visible.top  + borders.visible.bottom;
+    }
+  else
+    {
+      if (window->has_custom_frame_extents)
+        {
+          const GtkBorder *extents = &window->custom_frame_extents;
+          client_rect->x += extents->left;
+          client_rect->y += extents->top;
+          client_rect->width -= extents->left + extents->right;
+          client_rect->height -= extents->top + extents->bottom;
+        }
+    }
+}
+
+/**
+ * meta_window_frame_rect_to_client_rect:
+ * @window: a #MetaWindow
+ * @frame_rect: desired frame bounds for the window
+ * @client_rect: (out): location to store the computed corresponding client rectangle.
+ *
+ * Converts a desired frame bounds for a window into the bounds of the client
+ * window - what is passed to meta_window_move_resize().
+ */
+void
+meta_window_frame_rect_to_client_rect (MetaWindow    *window,
+                                       MetaRectangle *frame_rect,
+                                       MetaRectangle *client_rect)
+{
+  if (!client_rect)
+    return;
+
+  *client_rect = *frame_rect;
+
+  if (window->frame)
+    {
+      MetaFrameBorders borders;
+      meta_frame_calc_borders (window->frame, &borders);
+
+      client_rect->x += borders.visible.left;
+      client_rect->y += borders.visible.top;
+      client_rect->width  -= borders.visible.left + borders.visible.right;
+      client_rect->height -= borders.visible.top  + borders.visible.bottom;
+    }
+  else
+    {
+      if (window->has_custom_frame_extents)
+        {
+          const GtkBorder *extents = &window->custom_frame_extents;
+          client_rect->x -= extents->left;
+          client_rect->y -= extents->top;
+          client_rect->width += extents->left + extents->right;
+          client_rect->height += extents->top + extents->bottom;
+        }
+    }
+}
+
+/**
  * meta_window_get_outer_rect:
  * @window: a #MetaWindow
  * @rect: (out): pointer to an allocated #MetaRectangle
@@ -8504,18 +8565,13 @@ recalc_window_features (MetaWindow *window)
 
   if (window->has_maximize_func)
     {
-      MetaRectangle work_area;
-      MetaFrameBorders borders;
-      int min_frame_width, min_frame_height;
+      MetaRectangle work_area, client_rect;
 
       meta_window_get_work_area_current_monitor (window, &work_area);
-      meta_frame_calc_borders (window->frame, &borders);
-
-      min_frame_width = window->size_hints.min_width + borders.visible.left + borders.visible.right;
-      min_frame_height = window->size_hints.min_height + borders.visible.top + borders.visible.bottom;
+      meta_window_frame_rect_to_client_rect (window, &work_area, &client_rect);
 
-      if (min_frame_width >= work_area.width ||
-          min_frame_height >= work_area.height)
+      if (window->size_hints.min_width >= client_rect.width ||
+          window->size_hints.min_height >= client_rect.height)
         window->has_maximize_func = FALSE;
     }
 
diff --git a/src/meta/window.h b/src/meta/window.h
index 424d537..3efd261 100644
--- a/src/meta/window.h
+++ b/src/meta/window.h
@@ -101,6 +101,14 @@ gboolean meta_window_is_skip_taskbar (MetaWindow *window);
 MetaRectangle *meta_window_get_rect (MetaWindow *window);
 void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect);
 void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect);
+
+void meta_window_client_rect_to_frame_rect (MetaWindow    *window,
+                                            MetaRectangle *frame_rect,
+                                            MetaRectangle *client_rect);
+void meta_window_frame_rect_to_client_rect (MetaWindow    *window,
+                                            MetaRectangle *frame_rect,
+                                            MetaRectangle *client_rect);
+
 MetaScreen *meta_window_get_screen (MetaWindow *window);
 MetaDisplay *meta_window_get_display (MetaWindow *window);
 Window meta_window_get_xwindow (MetaWindow *window);


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