From f36a62733098d8ef416d627c20f50c64bc7f0a4b Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Fri, 15 Nov 2013 16:11:20 -0500 Subject: [PATCH] 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 | 17 +-- src/core/place.c | 214 ++++++++++++-------------------- src/core/window.c | 142 ++++++++++++++------- src/meta/window.h | 8 ++ 6 files changed, 222 insertions(+), 211 deletions(-) diff --git a/doc/reference/meta-sections.txt b/doc/reference/meta-sections.txt index 08e8f7c16..b87cbfed1 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 bc23a7220..a60595fb4 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 5649f9a5a..525f9bd04 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -1607,6 +1607,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; @@ -1618,9 +1619,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 @@ -2173,15 +2173,16 @@ meta_display_handle_event (MetaDisplay *display, { gboolean north, south; gboolean west, east; + MetaRectangle frame_rect; int root_x, root_y; 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); - east = event->button.x > (root_x + 2 * window->rect.width / 3); - north = event->button.y < (root_y + 1 * window->rect.height / 3); - south = event->button.y > (root_y + 2 * window->rect.height / 3); + west = event->button.x < (frame_rect.x + 1 * frame_rect.width / 3); + east = event->button.x > (frame_rect.x + 2 * frame_rect.width / 3); + north = event->button.y < (frame_rect.y + 1 * frame_rect.height / 3); + south = event->button.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 70171cb05..7835deeef 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 e92932aa4..c993d2df2 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -3959,7 +3959,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; @@ -3973,13 +3973,10 @@ meta_window_can_tile_side_by_side (MetaWindow *window) 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); - tile_area.height -= (borders.visible.top + borders.visible.bottom); - - 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 @@ -5670,23 +5667,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 @@ -5734,18 +5718,10 @@ meta_window_move_resize_frame (MetaWindow *window, int w, 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); - /* 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); + meta_window_move_resize (window, user_op, rect.x, rect.y, rect.width, rect.height); } /** @@ -6057,6 +6033,91 @@ meta_window_get_input_rect (const MetaWindow *window, *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: * @window: a #MetaWindow @@ -8784,18 +8845,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); + 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; - min_frame_height = window->size_hints.min_height + borders.visible.top + borders.visible.bottom; - - 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 bc03cf055..da4448923 100644 --- a/src/meta/window.h +++ b/src/meta/window.h @@ -111,6 +111,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);