diff options
Diffstat (limited to 'src/core/window.c')
| -rw-r--r-- | src/core/window.c | 192 |
1 files changed, 186 insertions, 6 deletions
diff --git a/src/core/window.c b/src/core/window.c index cdf7ab3b..4c8a3914 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -2158,6 +2158,14 @@ meta_window_show (MetaWindow *window) if (!window->placed) window->denied_focus_and_not_transient = TRUE; } + else if (window->type == META_WINDOW_MODAL_DIALOG) + { + /* Keep the non-modal transient behavior from 6ea23df for GTK + * popups and VLC controls, but focus modal dialogs that block + * the focused ancestor. + */ + takes_focus_on_map = TRUE; + } } if (!window->placed) @@ -4238,14 +4246,17 @@ meta_window_get_xor_rect (MetaWindow *window, { if (window->frame) { - xor_rect->x = grab_wireframe_rect->x - window->frame->child_x; - xor_rect->y = grab_wireframe_rect->y - window->frame->child_y; - xor_rect->width = grab_wireframe_rect->width + window->frame->child_x + window->frame->right_width; + MetaFrameBorders borders; + meta_frame_calc_borders (window->frame, &borders); + + xor_rect->x = grab_wireframe_rect->x - window->frame->child_x + borders.invisible.left; + xor_rect->y = grab_wireframe_rect->y - window->frame->child_y + borders.invisible.top; + xor_rect->width = grab_wireframe_rect->width + window->frame->child_x + window->frame->right_width - borders.invisible.left - borders.invisible.right; if (window->shaded) - xor_rect->height = window->frame->child_y; + xor_rect->height = window->frame->child_y - borders.invisible.top; else - xor_rect->height = grab_wireframe_rect->height + window->frame->child_y + window->frame->bottom_height; + xor_rect->height = grab_wireframe_rect->height + window->frame->child_y + window->frame->bottom_height - borders.invisible.top - borders.invisible.bottom; } else *xor_rect = *grab_wireframe_rect; @@ -4991,7 +5002,7 @@ meta_window_move_resize_request (MetaWindow *window, * workarea smaller than the monitor. */ if (meta_prefs_get_force_fullscreen() && - (window->decorated || !meta_window_is_client_decorated (window)) && + (!window->decorated && !meta_window_is_client_decorated (window)) && meta_rectangle_equal (&rect, &xinerama_info->rect) && window->has_fullscreen_func && !window->fullscreen) @@ -7872,6 +7883,34 @@ update_resize (MetaWindow *window, gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); g_assert (gravity >= 0); + /* Clamp resize to respect the minimum size of the matched window */ + if (window->display->grab_tile_match != NULL) + { + MetaWindow *match = window->display->grab_tile_match; + MetaRectangle work_area; + MetaFrameBorders borders; + int max_primary_width; + int primary_borders_w = 0; + int match_borders_w = 0; + + meta_window_get_work_area_for_xinerama (window, + window->tile_monitor_number, + &work_area); + + /* Use visible borders only since invisible borders overlap between + * adjacent tiled windows and don't consume work area space */ + meta_frame_calc_borders (window->frame, &borders); + primary_borders_w = borders.visible.left + borders.visible.right; + + meta_frame_calc_borders (match->frame, &borders); + match_borders_w = borders.visible.left + borders.visible.right; + + max_primary_width = work_area.width - primary_borders_w - + match->size_hints.min_width - match_borders_w; + if (new_w > max_primary_width) + new_w = max_primary_width; + } + /* Do any edge resistance/snapping */ meta_window_edge_resistance_for_resize (window, old.width, @@ -7906,6 +7945,61 @@ update_resize (MetaWindow *window, meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); } + /* Resize matching tiled window */ + if (window->display->grab_tile_match != NULL && !window->display->grab_wireframe_active) + { + MetaWindow *match = window->display->grab_tile_match; + + /* Validate match is still valid */ + if (!match->tiled || match->minimized || match->workspace != window->workspace) + { + window->display->grab_tile_match = NULL; + } + else + { + MetaRectangle work_area; + MetaFrameBorders borders; + int match_gravity; + int match_width; + int primary_borders_w = 0; + int match_borders_w = 0; + + meta_window_get_work_area_for_xinerama (window, + window->tile_monitor_number, + &work_area); + + /* Use visible borders only since invisible borders overlap between + * adjacent tiled windows and don't consume work area space */ + meta_frame_calc_borders (window->frame, &borders); + primary_borders_w = borders.visible.left + borders.visible.right; + + meta_frame_calc_borders (match->frame, &borders); + match_borders_w = borders.visible.left + borders.visible.right; + + /* Match client width */ + match_width = work_area.width - window->rect.width - primary_borders_w - match_borders_w; + + /* Determine what gravity to use regardless of + * whether it's corner tiled or edge tiled. */ + if (match->tile_mode == META_TILE_LEFT || + match->tile_mode == META_TILE_TOP_LEFT || + match->tile_mode == META_TILE_BOTTOM_LEFT) + match_gravity = WestGravity; + else + match_gravity = EastGravity; + + /* Do the actual resize of the matching window */ + if (match_width >= match->size_hints.min_width) + { + match->tile_resized = TRUE; + meta_window_resize_with_gravity (match, TRUE, + match_width, + match->rect.height, /* keep original height */ + match_gravity); + } + } + } + /* Store the latest resize time, if we actually resized. */ if (window->rect.width != old.width || window->rect.height != old.height) window->display->grab_last_moveresize_time = g_get_real_time (); @@ -8324,6 +8418,92 @@ meta_window_get_current_tile_area (MetaWindow *window, tile_area->width = width; } +MetaWindow* +meta_window_find_tile_match (MetaWindow *window) +{ + MetaTileMode opposite_mode; + GList *windows, *l; + + if (!window->tiled || !window->frame) + return NULL; + + switch (window->tile_mode) + { + case META_TILE_LEFT: + opposite_mode = META_TILE_RIGHT; + break; + case META_TILE_RIGHT: + opposite_mode = META_TILE_LEFT; + break; + case META_TILE_TOP_LEFT: + opposite_mode = META_TILE_TOP_RIGHT; + break; + case META_TILE_TOP_RIGHT: + opposite_mode = META_TILE_TOP_LEFT; + break; + case META_TILE_BOTTOM_LEFT: + opposite_mode = META_TILE_BOTTOM_RIGHT; + break; + case META_TILE_BOTTOM_RIGHT: + opposite_mode = META_TILE_BOTTOM_LEFT; + break; + default: + return NULL; + } + + /* Use stack list and iterate backwards since meta_stack_list_windows returns + * bottom-to-top order. We want to match the most likely visible window */ + windows = meta_stack_list_windows (window->screen->stack, window->workspace); + + for (l = g_list_last (windows); l != NULL; l = l->prev) + { + MetaWindow *candidate = l->data; + + /* Skip itself, non-tiled windows, and windows without frames (e.g. docks, etc.) */ + if (candidate == window || !candidate->tiled || !candidate->frame) + continue; + + /* Skip windows that don't match the opposite tile mode */ + if (candidate->tile_mode != opposite_mode) + continue; + + /* Skip windows on different monitors */ + if (candidate->tile_monitor_number != window->tile_monitor_number) + continue; + + /* Skip windows not visible in the current workspace (e.g. minimized) */ + if (!meta_window_showing_on_its_workspace (candidate)) + continue; + + /* Since windows can be tiled at different sizes, we verify that their + * edges touch (or at least are close enough) */ + MetaRectangle win_rect, cand_rect; + int tolerance = 8; /* pixels */ + + meta_window_get_outer_rect (window, &win_rect); + meta_window_get_outer_rect (candidate, &cand_rect); + + if (window->tile_mode == META_TILE_LEFT || + window->tile_mode == META_TILE_TOP_LEFT || + window->tile_mode == META_TILE_BOTTOM_LEFT) + { + if (ABS (win_rect.x + win_rect.width - cand_rect.x) > tolerance) + continue; + } + else + { + if (ABS (cand_rect.x + cand_rect.width - win_rect.x) > tolerance) + continue; + } + + g_list_free (windows); + return candidate; + } + + g_list_free (windows); + return NULL; +} + gboolean meta_window_same_application (MetaWindow *window, MetaWindow *other_window) |
