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
This commit is contained in:
Owen W. Taylor 2013-11-15 16:11:20 -05:00
parent a1087c3f30
commit f36a627330
6 changed files with 222 additions and 211 deletions

View File

@ -542,6 +542,8 @@ meta_window_is_skip_taskbar
meta_window_get_rect meta_window_get_rect
meta_window_get_input_rect meta_window_get_input_rect
meta_window_get_outer_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_screen
meta_window_get_display meta_window_get_display
meta_window_get_xwindow meta_window_get_xwindow

View File

@ -204,10 +204,10 @@ static void place_window_if_needed (MetaWindow *window,
ConstraintInfo *info); ConstraintInfo *info);
static void update_onscreen_requirements (MetaWindow *window, static void update_onscreen_requirements (MetaWindow *window,
ConstraintInfo *info); ConstraintInfo *info);
static void extend_by_frame (MetaRectangle *rect, static void extend_by_frame (MetaWindow *window,
const MetaFrameBorders *borders); MetaRectangle *rect);
static void unextend_by_frame (MetaRectangle *rect, static void unextend_by_frame (MetaWindow *window,
const MetaFrameBorders *borders); MetaRectangle *rect);
static inline void get_size_limits (const MetaWindow *window, static inline void get_size_limits (const MetaWindow *window,
const MetaFrameBorders *borders, const MetaFrameBorders *borders,
gboolean include_frame, gboolean include_frame,
@ -519,10 +519,11 @@ place_window_if_needed(MetaWindow *window,
!window->minimized && !window->minimized &&
!window->fullscreen) !window->fullscreen)
{ {
MetaRectangle placed_rect = info->orig; MetaRectangle placed_rect;
MetaWorkspace *cur_workspace; MetaWorkspace *cur_workspace;
const MetaMonitorInfo *monitor_info; const MetaMonitorInfo *monitor_info;
meta_window_get_outer_rect (window, &placed_rect);
meta_window_place (window, info->borders, info->orig.x, info->orig.y, meta_window_place (window, info->borders, info->orig.x, info->orig.y,
&placed_rect.x, &placed_rect.y); &placed_rect.x, &placed_rect.y);
did_placement = TRUE; did_placement = TRUE;
@ -541,6 +542,7 @@ place_window_if_needed(MetaWindow *window,
meta_workspace_get_onmonitor_region (cur_workspace, meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number); monitor_info->number);
meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect);
info->current.x = placed_rect.x; info->current.x = placed_rect.x;
info->current.y = placed_rect.y; info->current.y = placed_rect.y;
@ -649,7 +651,7 @@ update_onscreen_requirements (MetaWindow *window,
/* The require onscreen/on-single-monitor and titlebar_visible /* The require onscreen/on-single-monitor and titlebar_visible
* stuff is relative to the outer window, not the inner * 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 /* Update whether we want future constraint runs to require the
* window to be on fully onscreen. * 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 */ /* 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 static void
extend_by_frame (MetaRectangle *rect, extend_by_frame (MetaWindow *window,
const MetaFrameBorders *borders) MetaRectangle *rect)
{ {
rect->x -= borders->visible.left; meta_window_client_rect_to_frame_rect (window, rect, rect);
rect->y -= borders->visible.top;
rect->width += borders->visible.left + borders->visible.right;
rect->height += borders->visible.top + borders->visible.bottom;
} }
static void static void
unextend_by_frame (MetaRectangle *rect, unextend_by_frame (MetaWindow *window,
const MetaFrameBorders *borders) MetaRectangle *rect)
{ {
rect->x += borders->visible.left; meta_window_frame_rect_to_client_rect (window, rect, rect);
rect->y += borders->visible.top;
rect->width -= borders->visible.left + borders->visible.right;
rect->height -= borders->visible.top + borders->visible.bottom;
} }
static inline void static inline void
@ -778,13 +774,13 @@ constrain_modal_dialog (MetaWindow *window,
*/ */
child_rect = info->current; 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); meta_window_get_outer_rect (parent, &parent_rect);
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2); 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); 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; x = child_rect.x;
y = child_rect.y; y = child_rect.y;
@ -851,14 +847,14 @@ constrain_maximization (MetaWindow *window,
active_workspace_struts = window->screen->active_workspace->all_struts; active_workspace_struts = window->screen->active_workspace->all_struts;
target_size = info->current; 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, meta_rectangle_expand_to_avoiding_struts (&target_size,
&info->entire_monitor, &info->entire_monitor,
direction, direction,
active_workspace_struts); active_workspace_struts);
} }
/* Now make target_size = maximized size of client window */ /* 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 /* Check min size constraints; max size constraints are ignored for maximized
* windows, as per bug 327543. * windows, as per bug 327543.
@ -917,7 +913,7 @@ constrain_tiling (MetaWindow *window,
* use an external function for the actual calculation * use an external function for the actual calculation
*/ */
meta_window_get_current_tile_area (window, &target_size); 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 /* Check min size constraints; max size constraints are ignored as for
* maximized windows. * maximized windows.
@ -1267,7 +1263,7 @@ do_screen_and_monitor_relative_constraints (
/* Determine whether constraint applies; exit if it doesn't */ /* Determine whether constraint applies; exit if it doesn't */
how_far_it_can_be_smushed = info->current; how_far_it_can_be_smushed = info->current;
get_size_limits (window, info->borders, TRUE, &min_size, &max_size); 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) if (info->action_type != ACTION_MOVE)
{ {
@ -1287,7 +1283,7 @@ do_screen_and_monitor_relative_constraints (
&info->current); &info->current);
if (exit_early || constraint_satisfied || check_only) if (exit_early || constraint_satisfied || check_only)
{ {
unextend_by_frame (&info->current, info->borders); unextend_by_frame (window, &info->current);
return constraint_satisfied; return constraint_satisfied;
} }
@ -1311,7 +1307,7 @@ do_screen_and_monitor_relative_constraints (
info->fixed_directions, info->fixed_directions,
&info->current); &info->current);
unextend_by_frame (&info->current, info->borders); unextend_by_frame (window, &info->current);
return TRUE; return TRUE;
} }

View File

@ -1607,6 +1607,7 @@ window_raise_with_delay_callback (void *data)
{ {
int x, y, root_x, root_y; int x, y, root_x, root_y;
Window root, child; Window root, child;
MetaRectangle frame_rect;
unsigned int mask; unsigned int mask;
gboolean same_screen; gboolean same_screen;
gboolean point_in_window; gboolean point_in_window;
@ -1618,9 +1619,8 @@ window_raise_with_delay_callback (void *data)
&root_x, &root_y, &x, &y, &mask); &root_x, &root_y, &x, &y, &mask);
meta_error_trap_pop (window->display); meta_error_trap_pop (window->display);
point_in_window = meta_window_get_outer_rect (window, &frame_rect);
(window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) || point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
(window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect));
if (same_screen && point_in_window) if (same_screen && point_in_window)
meta_window_raise (window); meta_window_raise (window);
else else
@ -2173,15 +2173,16 @@ meta_display_handle_event (MetaDisplay *display,
{ {
gboolean north, south; gboolean north, south;
gboolean west, east; gboolean west, east;
MetaRectangle frame_rect;
int root_x, root_y; int root_x, root_y;
MetaGrabOp op; MetaGrabOp op;
meta_window_get_position (window, &root_x, &root_y); meta_window_get_outer_rect (window, &frame_rect);
west = event->button.x < (root_x + 1 * window->rect.width / 3); west = event->button.x < (frame_rect.x + 1 * frame_rect.width / 3);
east = event->button.x > (root_x + 2 * window->rect.width / 3); east = event->button.x > (frame_rect.x + 2 * frame_rect.width / 3);
north = event->button.y < (root_y + 1 * window->rect.height / 3); north = event->button.y < (frame_rect.y + 1 * frame_rect.height / 3);
south = event->button.y > (root_y + 2 * window->rect.height / 3); south = event->button.y > (frame_rect.y + 2 * frame_rect.height / 3);
if (north && west) if (north && west)
op = META_GRAB_OP_RESIZING_NW; op = META_GRAB_OP_RESIZING_NW;

View File

@ -47,34 +47,18 @@ northwestcmp (gconstpointer a, gconstpointer b)
{ {
MetaWindow *aw = (gpointer) a; MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b; MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int from_origin_a; int from_origin_a;
int from_origin_b; int from_origin_b;
int ax, ay, bx, by; int ax, ay, bx, by;
/* we're interested in the frame position for cascading, meta_window_get_outer_rect (aw, &a_frame);
* not meta_window_get_position() meta_window_get_outer_rect (bw, &b_frame);
*/ ax = a_frame.x;
if (aw->frame) ay = a_frame.y;
{ bx = b_frame.x;
ax = aw->frame->rect.x; by = b_frame.y;
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;
}
/* probably there's a fast good-enough-guess we could use here. */ /* probably there's a fast good-enough-guess we could use here. */
from_origin_a = sqrt (ax * ax + ay * ay); from_origin_a = sqrt (ax * ax + ay * ay);
@ -102,6 +86,7 @@ find_next_cascade (MetaWindow *window,
GList *sorted; GList *sorted;
int cascade_x, cascade_y; int cascade_x, cascade_y;
int x_threshold, y_threshold; int x_threshold, y_threshold;
MetaRectangle frame_rect;
int window_width, window_height; int window_width, window_height;
int cascade_stage; int cascade_stage;
MetaRectangle work_area; MetaRectangle work_area;
@ -144,29 +129,24 @@ find_next_cascade (MetaWindow *window,
/* Find first cascade position that's not used. */ /* Find first cascade position that's not used. */
window_width = window->frame ? window->frame->rect.width : window->rect.width; meta_window_get_outer_rect (window, &frame_rect);
window_height = window->frame ? window->frame->rect.height : window->rect.height; window_width = frame_rect.width;
window_height = frame_rect.height;
cascade_stage = 0; cascade_stage = 0;
tmp = sorted; tmp = sorted;
while (tmp != NULL) while (tmp != NULL)
{ {
MetaWindow *w; MetaWindow *w;
MetaRectangle w_frame_rect;
int wx, wy; int wx, wy;
w = tmp->data; w = tmp->data;
/* we want frame position, not window position */ /* we want frame position, not window position */
if (w->frame) meta_window_get_outer_rect (w, &w_frame_rect);
{ wx = w_frame_rect.x;
wx = w->frame->rect.x; wy = w_frame_rect.y;
wy = w->frame->rect.y;
}
else
{
wx = w->rect.x;
wy = w->rect.y;
}
if (ABS (wx - cascade_x) < x_threshold && if (ABS (wx - cascade_x) < x_threshold &&
ABS (wy - cascade_y) < y_threshold) ABS (wy - cascade_y) < y_threshold)
@ -223,18 +203,9 @@ find_next_cascade (MetaWindow *window,
g_list_free (sorted); g_list_free (sorted);
/* Convert coords to position of window, not position of frame. */
if (borders == NULL)
{
*new_x = cascade_x; *new_x = cascade_x;
*new_y = cascade_y; *new_y = cascade_y;
} }
else
{
*new_x = cascade_x + borders->visible.left;
*new_y = cascade_y + borders->visible.top;
}
}
static void static void
find_most_freespace (MetaWindow *window, find_most_freespace (MetaWindow *window,
@ -250,14 +221,10 @@ find_most_freespace (MetaWindow *window,
int max_area; int max_area;
int max_width, max_height, left, right, top, bottom; int max_width, max_height, left, right, top, bottom;
int left_space, right_space, top_space, bottom_space; int left_space, right_space, top_space, bottom_space;
int frame_size_left, frame_size_top;
MetaRectangle work_area; MetaRectangle work_area;
MetaRectangle avoid; MetaRectangle avoid;
MetaRectangle outer; 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_work_area_current_monitor (focus_window, &work_area);
meta_window_get_outer_rect (focus_window, &avoid); meta_window_get_outer_rect (focus_window, &avoid);
meta_window_get_outer_rect (window, &outer); meta_window_get_outer_rect (window, &outer);
@ -304,36 +271,54 @@ find_most_freespace (MetaWindow *window,
switch (side) switch (side)
{ {
case META_LEFT: case META_LEFT:
*new_y = avoid.y + frame_size_top; *new_y = avoid.y;
if (left_space > outer.width) if (left_space > outer.width)
*new_x = avoid.x - outer.width + frame_size_left; *new_x = avoid.x - outer.width;
else else
*new_x = work_area.x + frame_size_left; *new_x = work_area.x;
break; break;
case META_RIGHT: case META_RIGHT:
*new_y = avoid.y + frame_size_top; *new_y = avoid.y;
if (right_space > outer.width) if (right_space > outer.width)
*new_x = avoid.x + avoid.width + frame_size_left; *new_x = avoid.x + avoid.width;
else 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; break;
case META_TOP: case META_TOP:
*new_x = avoid.x + frame_size_left; *new_x = avoid.x;
if (top_space > outer.height) if (top_space > outer.height)
*new_y = avoid.y - outer.height + frame_size_top; *new_y = avoid.y - outer.height;
else else
*new_y = work_area.y + frame_size_top; *new_y = work_area.y;
break; break;
case META_BOTTOM: case META_BOTTOM:
*new_x = avoid.x + frame_size_left; *new_x = avoid.x;
if (bottom_space > outer.height) if (bottom_space > outer.height)
*new_y = avoid.y + avoid.height + frame_size_top; *new_y = avoid.y + avoid.height;
else 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; 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 static void
avoid_being_obscured_as_second_modal_dialog (MetaWindow *window, avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
MetaFrameBorders *borders, MetaFrameBorders *borders,
@ -355,16 +340,15 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
*/ */
MetaWindow *focus_window; MetaWindow *focus_window;
MetaRectangle overlap;
focus_window = window->display->focus_window; 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 && if (window->denied_focus_and_not_transient &&
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */ window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
meta_window_same_application (window, focus_window) && meta_window_same_application (window, focus_window) &&
meta_rectangle_intersect (&window->rect, window_overlaps_focus_window (window))
&focus_window->rect,
&overlap))
{ {
find_most_freespace (window, borders, focus_window, *x, *y, x, y); find_most_freespace (window, borders, focus_window, *x, *y, x, y);
meta_topic (META_DEBUG_PLACEMENT, meta_topic (META_DEBUG_PLACEMENT,
@ -427,20 +411,14 @@ leftmost_cmp (gconstpointer a, gconstpointer b)
{ {
MetaWindow *aw = (gpointer) a; MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b; MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int ax, bx; int ax, bx;
/* we're interested in the frame position for cascading, meta_window_get_outer_rect (aw, &a_frame);
* not meta_window_get_position() meta_window_get_outer_rect (bw, &b_frame);
*/ ax = a_frame.x;
if (aw->frame) bx = b_frame.x;
ax = aw->frame->rect.x;
else
ax = aw->rect.x;
if (bw->frame)
bx = bw->frame->rect.x;
else
bx = bw->rect.x;
if (ax < bx) if (ax < bx)
return -1; return -1;
@ -455,20 +433,14 @@ topmost_cmp (gconstpointer a, gconstpointer b)
{ {
MetaWindow *aw = (gpointer) a; MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b; MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int ay, by; int ay, by;
/* we're interested in the frame position for cascading, meta_window_get_outer_rect (aw, &a_frame);
* not meta_window_get_position() meta_window_get_outer_rect (bw, &b_frame);
*/ ay = a_frame.y;
if (aw->frame) by = b_frame.y;
ay = aw->frame->rect.y;
else
ay = aw->rect.y;
if (bw->frame)
by = bw->frame->rect.y;
else
by = bw->rect.y;
if (ay < by) if (ay < by)
return -1; return -1;
@ -541,14 +513,7 @@ find_first_fit (MetaWindow *window,
right_sorted = g_list_sort (right_sorted, topmost_cmp); right_sorted = g_list_sort (right_sorted, topmost_cmp);
right_sorted = g_list_sort (right_sorted, leftmost_cmp); right_sorted = g_list_sort (right_sorted, leftmost_cmp);
rect.width = window->rect.width; meta_window_get_outer_rect (window, &rect);
rect.height = window->rect.height;
if (borders)
{
rect.width += borders->visible.left + borders->visible.right;
rect.height += borders->visible.top + borders->visible.bottom;
}
#ifdef WITH_VERBOSE_MODE #ifdef WITH_VERBOSE_MODE
{ {
@ -570,11 +535,6 @@ find_first_fit (MetaWindow *window,
{ {
*new_x = rect.x; *new_x = rect.x;
*new_y = rect.y; *new_y = rect.y;
if (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE; retval = TRUE;
@ -598,11 +558,6 @@ find_first_fit (MetaWindow *window,
{ {
*new_x = rect.x; *new_x = rect.x;
*new_y = rect.y; *new_y = rect.y;
if (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE; retval = TRUE;
@ -629,11 +584,6 @@ find_first_fit (MetaWindow *window,
{ {
*new_x = rect.x; *new_x = rect.x;
*new_y = rect.y; *new_y = rect.y;
if (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE; retval = TRUE;
@ -775,24 +725,22 @@ meta_window_place (MetaWindow *window,
if (parent) if (parent)
{ {
int w; MetaRectangle frame_rect, parent_frame_rect;
meta_window_get_position (parent, &x, &y); meta_window_get_outer_rect (window, &frame_rect);
w = parent->rect.width; meta_window_get_outer_rect (parent, &parent_frame_rect);
y = parent_frame_rect.y;
/* center of parent */ /* center of parent */
x = x + w / 2; x = parent_frame_rect.x + parent_frame_rect.width / 2;
/* center of child over center of parent */ /* 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 /* "visually" center window over parent, leaving twice as
* much space below as on top. * much space below as on top.
*/ */
y += (parent->rect.height - window->rect.height)/3; y += (parent_frame_rect.height - frame_rect.height)/3;
/* put top of child's frame, not top of child's client */
if (borders)
y += borders->visible.top;
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n", meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
window->desc); window->desc);
@ -813,6 +761,9 @@ meta_window_place (MetaWindow *window,
{ {
/* Center on current monitor */ /* Center on current monitor */
int w, h; int w, h;
MetaRectangle frame_rect;
meta_window_get_outer_rect (window, &frame_rect);
/* Warning, this function is a round trip! */ /* Warning, this function is a round trip! */
xi = meta_screen_get_current_monitor_info (window->screen); xi = meta_screen_get_current_monitor_info (window->screen);
@ -820,8 +771,8 @@ meta_window_place (MetaWindow *window,
w = xi->rect.width; w = xi->rect.width;
h = xi->rect.height; h = xi->rect.height;
x = (w - window->rect.width) / 2; x = (w - frame_rect.width) / 2;
y = (h - window->rect.height) / 2; y = (h - frame_rect.height) / 2;
x += xi->rect.x; x += xi->rect.x;
y += xi->rect.y; y += xi->rect.y;
@ -909,17 +860,14 @@ meta_window_place (MetaWindow *window,
*/ */
if (window->denied_focus_and_not_transient) if (window->denied_focus_and_not_transient)
{ {
gboolean found_fit;
MetaWindow *focus_window; MetaWindow *focus_window;
MetaRectangle overlap; gboolean found_fit;
focus_window = window->display->focus_window; focus_window = window->display->focus_window;
g_assert (focus_window != NULL); g_assert (focus_window != NULL);
/* No need to do anything if the window doesn't overlap at all */ /* No need to do anything if the window doesn't overlap at all */
found_fit = !meta_rectangle_intersect (&window->rect, found_fit = !window_overlaps_focus_window (window);
&focus_window->rect,
&overlap);
/* Try to do a first fit again, this time only taking into account the /* Try to do a first fit again, this time only taking into account the
* focus window. * focus window.

View File

@ -3959,7 +3959,7 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
{ {
int monitor; int monitor;
MetaRectangle tile_area; MetaRectangle tile_area;
MetaFrameBorders borders; MetaRectangle client_rect;
if (!meta_window_can_tile_maximized (window)) if (!meta_window_can_tile_maximized (window))
return FALSE; return FALSE;
@ -3973,13 +3973,10 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
tile_area.width /= 2; tile_area.width /= 2;
meta_frame_calc_borders (window->frame, &borders); meta_window_frame_rect_to_client_rect (window, &tile_area, &client_rect);
tile_area.width -= (borders.visible.left + borders.visible.right); return client_rect.width >= window->size_hints.min_width &&
tile_area.height -= (borders.visible.top + borders.visible.bottom); client_rect.height >= window->size_hints.min_height;
return tile_area.width >= window->size_hints.min_width &&
tile_area.height >= window->size_hints.min_height;
} }
static void static void
@ -5670,23 +5667,10 @@ meta_window_move_frame (MetaWindow *window,
int root_x_nw, int root_x_nw,
int root_y_nw) int root_y_nw)
{ {
int x = root_x_nw; MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
int y = root_y_nw;
if (window->frame) meta_window_frame_rect_to_client_rect (window, &rect, &rect);
{ meta_window_move (window, user_op, rect.x, rect.y);
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);
} }
static void static void
@ -5734,18 +5718,10 @@ meta_window_move_resize_frame (MetaWindow *window,
int w, int w,
int h) int h)
{ {
MetaFrameBorders borders; MetaRectangle rect = { root_x_nw, root_y_nw, w, h };
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
meta_frame_calc_borders (window->frame, &borders); meta_window_move_resize (window, user_op, rect.x, rect.y, rect.width, rect.height);
/* 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;
meta_window_move_resize (window, user_op, root_x_nw, root_y_nw, w, h);
} }
/** /**
@ -6057,6 +6033,91 @@ meta_window_get_input_rect (const MetaWindow *window,
*rect = window->rect; *rect = window->rect;
} }
/**
* 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: * meta_window_get_outer_rect:
* @window: a #MetaWindow * @window: a #MetaWindow
@ -8784,18 +8845,13 @@ recalc_window_features (MetaWindow *window)
if (window->has_maximize_func) if (window->has_maximize_func)
{ {
MetaRectangle work_area; MetaRectangle work_area, client_rect;
MetaFrameBorders borders;
int min_frame_width, min_frame_height;
meta_window_get_work_area_current_monitor (window, &work_area); meta_window_get_work_area_current_monitor (window, &work_area);
meta_frame_calc_borders (window->frame, &borders); meta_window_frame_rect_to_client_rect (window, &work_area, &client_rect);
min_frame_width = window->size_hints.min_width + borders.visible.left + borders.visible.right; if (window->size_hints.min_width >= client_rect.width ||
min_frame_height = window->size_hints.min_height + borders.visible.top + borders.visible.bottom; window->size_hints.min_height >= client_rect.height)
if (min_frame_width >= work_area.width ||
min_frame_height >= work_area.height)
window->has_maximize_func = FALSE; window->has_maximize_func = FALSE;
} }

View File

@ -111,6 +111,14 @@ gboolean meta_window_is_skip_taskbar (MetaWindow *window);
MetaRectangle *meta_window_get_rect (MetaWindow *window); MetaRectangle *meta_window_get_rect (MetaWindow *window);
void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect); 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_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); MetaScreen *meta_window_get_screen (MetaWindow *window);
MetaDisplay *meta_window_get_display (MetaWindow *window); MetaDisplay *meta_window_get_display (MetaWindow *window);
Window meta_window_get_xwindow (MetaWindow *window); Window meta_window_get_xwindow (MetaWindow *window);