diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a22fde97eb64188872a6d3b9f24ac944fd8801ce..0ba09cc4fe422c0a1a12b40c03e8fd836f5eecdc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -106,7 +106,7 @@ variables: - .skip-git-clone variables: FDO_DISTRIBUTION_VERSION: 42 - BASE_TAG: '2025-04-08.0' + BASE_TAG: '2025-04-29.0' MUTTER_USER: 'meta-user' FDO_DISTRIBUTION_PACKAGES: accountsservice-devel diff --git a/.gitlab-ci/install-common-dependencies.sh b/.gitlab-ci/install-common-dependencies.sh index 83bb07bfec313513b83b39fc2dc649101005f3fa..7a90881c5ea62db37f553fb05b67992a3153ce5e 100755 --- a/.gitlab-ci/install-common-dependencies.sh +++ b/.gitlab-ci/install-common-dependencies.sh @@ -131,3 +131,8 @@ then https://gitlab.freedesktop.org/wayland/wayland-protocols.git \ 1.43 fi + +./$SCRIPTS_DIR/install-meson-project.sh \ + "${OPTIONS[@]}" \ + https://gitlab.gnome.org/GNOME/glib.git \ + main c22642589b5f999d6b89379c852c199919da6ae5 diff --git a/mtk/mtk/mtk-rectangle.c b/mtk/mtk/mtk-rectangle.c index 25a88bb6f8889e527fc2653df6a1067b680a071d..63be7ab07131120088cec6ba0559c9c7cf03aeb6 100644 --- a/mtk/mtk/mtk-rectangle.c +++ b/mtk/mtk/mtk-rectangle.c @@ -445,6 +445,12 @@ mtk_rectangle_is_adjacent_to (const MtkRectangle *rect, return FALSE; } +gboolean +mtk_rectangle_is_empty (const MtkRectangle *rect) +{ + return rect->width == 0 || rect->height == 0; +} + /** * mtk_rectangle_transform: * @rect: the #MtkRectangle to be transformed diff --git a/mtk/mtk/mtk-rectangle.h b/mtk/mtk/mtk-rectangle.h index a5b641bf88a5da0f2846a0d14b9536642888745b..9d5f86fcf7e19bd129a4d208f05400992fce6043 100644 --- a/mtk/mtk/mtk-rectangle.h +++ b/mtk/mtk/mtk-rectangle.h @@ -162,7 +162,8 @@ MTK_EXPORT gboolean mtk_rectangle_is_adjacent_to (const MtkRectangle *rect, const MtkRectangle *other); - +MTK_EXPORT +gboolean mtk_rectangle_is_empty (const MtkRectangle *rect); MTK_EXPORT void mtk_rectangle_transform (const MtkRectangle *rect, diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h index 75dcf48fb9d78e10be2bf9070026c1693c85de4e..73975d20933a404e9aed2d299fdc2b36be0d5563 100644 --- a/src/compositor/compositor-private.h +++ b/src/compositor/compositor-private.h @@ -107,6 +107,7 @@ gboolean meta_compositor_drag_window (MetaCompositor *compositor, graphene_point_t *pos_hint, ClutterActor *grab_actor); +META_EXPORT_TEST MetaWindowDrag * meta_compositor_get_current_window_drag (MetaCompositor *compositor); void meta_compositor_grab_begin (MetaCompositor *compositor); diff --git a/src/compositor/meta-window-drag.c b/src/compositor/meta-window-drag.c index c8a4c335abf3b8e9e9494492154f1a5fce0690d3..20ba53c706ea5ee73e986f4066a9d31fa34d9da1 100644 --- a/src/compositor/meta-window-drag.c +++ b/src/compositor/meta-window-drag.c @@ -23,6 +23,7 @@ #include "compositor/compositor-private.h" #include "compositor/edge-resistance.h" +#include "core/meta-window-config-private.h" #include "core/window-private.h" #include "meta/meta-enum-types.h" @@ -567,7 +568,8 @@ process_mouse_move_resize_grab (MetaWindowDrag *window_drag, /* Restore the original tile mode */ tile_mode = window_drag->tile_mode; - window->tile_monitor_number = window_drag->tile_monitor_number; + meta_window_config_set_tile_monitor_number (window->config, + window_drag->tile_monitor_number); /* End move or resize and restore to original state. If the * window was a maximized window that had been "shaken loose" we @@ -1184,7 +1186,10 @@ update_move_maybe_tile (MetaWindowDrag *window_drag, window_drag->preview_tile_mode = META_TILE_NONE; if (window_drag->preview_tile_mode != META_TILE_NONE) - window->tile_monitor_number = logical_monitor->number; + { + meta_window_config_set_tile_monitor_number (window->config, + logical_monitor->number); + } } static void @@ -1244,7 +1249,7 @@ update_move (MetaWindowDrag *window_drag, /* We don't want to tile while snapping. Also, clear any previous tile request. */ window_drag->preview_tile_mode = META_TILE_NONE; - window->tile_monitor_number = -1; + meta_window_config_set_tile_monitor_number (window->config, -1); } else if (meta_prefs_get_edge_tiling () && !meta_window_is_maximized (window) && @@ -1269,7 +1274,7 @@ update_move (MetaWindowDrag *window_drag, * is enabled, as top edge tiling can be used in that case */ window_drag->shaken_loose = !meta_prefs_get_edge_tiling (); - window->tile_mode = META_TILE_NONE; + meta_window_config_set_tile_mode (window->config, META_TILE_NONE); /* move the unmaximized window to the cursor */ prop = @@ -1296,7 +1301,8 @@ update_move (MetaWindowDrag *window_drag, * loose or it is still maximized (then move straight) */ else if ((window_drag->shaken_loose || meta_window_is_maximized (window)) && - window->tile_mode != META_TILE_LEFT && window->tile_mode != META_TILE_RIGHT) + meta_window_config_get_tile_mode (window->config) != META_TILE_LEFT && + meta_window_config_get_tile_mode (window->config) != META_TILE_RIGHT) { MetaDisplay *display = meta_window_get_display (window); MetaContext *context = meta_display_get_context (display); @@ -1311,7 +1317,7 @@ update_move (MetaWindowDrag *window_drag, MetaFrame *frame; #endif - window->tile_mode = META_TILE_NONE; + meta_window_config_set_tile_mode (window->config, META_TILE_NONE); wmonitor = window->monitor; n_logical_monitors = meta_monitor_manager_get_num_logical_monitors (monitor_manager); @@ -1364,14 +1370,17 @@ update_move (MetaWindowDrag *window_drag, * trigger it unwittingly, e.g. when shaking loose the window or moving * it to another monitor. */ - update_tile_preview (window_drag, window->tile_mode != META_TILE_NONE); + update_tile_preview (window_drag, + meta_window_config_get_tile_mode (window->config) != + META_TILE_NONE); meta_window_get_frame_rect (window, &old); /* Don't allow movement in the maximized directions or while tiled */ - if (window->maximized_horizontally || meta_window_is_tiled_side_by_side (window)) + if (meta_window_config_is_maximized_horizontally (window->config) || + meta_window_is_tiled_side_by_side (window)) new_x = old.x; - if (window->maximized_vertically) + if (meta_window_config_is_maximized_vertically (window->config)) new_y = old.y; window_drag->last_edge_resistance_flags = @@ -1598,6 +1607,7 @@ maybe_maximize_tiled_window (MetaWindow *window) { MtkRectangle work_area; gint shake_threshold; + int tile_monitor_number; int width; if (!meta_window_is_tiled_side_by_side (window)) @@ -1605,8 +1615,10 @@ maybe_maximize_tiled_window (MetaWindow *window) shake_threshold = meta_prefs_get_drag_threshold (); + tile_monitor_number = + meta_window_config_get_tile_monitor_number (window->config); meta_window_get_work_area_for_monitor (window, - window->tile_monitor_number, + tile_monitor_number, &work_area); meta_window_config_get_size (window->config, &width, NULL); if (width >= work_area.width - shake_threshold) @@ -1671,7 +1683,7 @@ end_grab_op (MetaWindowDrag *window_drag, } else if (meta_grab_op_is_resizing (window_drag->grab_op)) { - if (window->tile_match != NULL) + if (meta_window_config_get_tile_match (window->config)) flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS); update_resize (window_drag, flags, (int) x, (int) y); @@ -1746,7 +1758,7 @@ process_pointer_event (MetaWindowDrag *window_drag, } else if (meta_grab_op_is_resizing (window_drag->grab_op)) { - if (window->tile_match != NULL) + if (meta_window_config_get_tile_match (window->config)) flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS); queue_update_resize (window_drag, flags, (int) x, (int) y); @@ -1889,8 +1901,10 @@ meta_window_drag_begin (MetaWindowDrag *window_drag, window_drag->leading_device = device; window_drag->leading_touch_sequence = sequence; - window_drag->tile_mode = grab_window->tile_mode; - window_drag->tile_monitor_number = grab_window->tile_monitor_number; + window_drag->tile_mode = + meta_window_config_get_tile_mode (grab_window->config); + window_drag->tile_monitor_number = + meta_window_config_get_tile_monitor_number (grab_window->config); window_drag->anchor_root_x = root_x; window_drag->anchor_root_y = root_y; window_drag->latest_motion_x = root_x; diff --git a/src/compositor/meta-window-drag.h b/src/compositor/meta-window-drag.h index c6b51f808164559a11925eab59d5c3c6f02d4b6e..e5f5c316910f157010637b15561c1464c4ed0001 100644 --- a/src/compositor/meta-window-drag.h +++ b/src/compositor/meta-window-drag.h @@ -19,6 +19,7 @@ #pragma once +#include "core/util-private.h" #include "meta/common.h" #include "meta/window.h" @@ -35,10 +36,12 @@ gboolean meta_window_drag_begin (MetaWindowDrag *drag, uint32_t timestamp, ClutterActor *grab_actor); +META_EXPORT_TEST void meta_window_drag_end (MetaWindowDrag *drag); void meta_window_drag_update_resize (MetaWindowDrag *drag); +META_EXPORT_TEST MetaWindow * meta_window_drag_get_window (MetaWindowDrag *window_drag); MetaGrabOp meta_window_drag_get_grab_op (MetaWindowDrag *window_drag); diff --git a/src/core/constraints.c b/src/core/constraints.c index 9c287c668d4e6e854c085e2d44686590c423b911..efa8c4cafe79cb953b8768058739d867dc5b18dd 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -33,6 +33,7 @@ #include "backends/meta-monitor-manager-private.h" #include "compositor/compositor-private.h" #include "core/boxes-private.h" +#include "core/meta-window-config-private.h" #include "core/meta-workspace-manager-private.h" #include "core/place.h" #include "core/workspace-private.h" @@ -362,7 +363,7 @@ setup_constraint_info (MetaBackend *backend, { MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; + MetaLogicalMonitor *logical_monitor = NULL; MetaWorkspace *cur_workspace; MetaPlacementRule *placement_rule; @@ -445,9 +446,20 @@ setup_constraint_info (MetaBackend *backend, } else { - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, - &info->current); + if (!(flags & META_MOVE_RESIZE_RECT_INVALID)) + { + meta_topic (META_DEBUG_GEOMETRY, + "Constraining using monitor from new rectangle"); + logical_monitor = + meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, + &info->current); + } + + if (!logical_monitor) + { + meta_topic (META_DEBUG_GEOMETRY, "Constraining using window monitor"); + logical_monitor = window->monitor; + } } if (!logical_monitor) @@ -548,9 +560,8 @@ place_window_if_needed (MetaWindow *window, */ did_placement = FALSE; if (!window->placed && - window->calc_placement && - !(window->maximized_horizontally || - window->maximized_vertically) && + place_flags & META_PLACE_FLAG_CALCULATE && + !meta_window_config_is_any_maximized (window->config) && !window->minimized && !meta_window_is_fullscreen (window)) { @@ -584,6 +595,7 @@ place_window_if_needed (MetaWindow *window, { meta_window_place (window, place_flags, orig_rect.x, orig_rect.y, + info->current.width, info->current.height, &placed_rect.x, &placed_rect.y); /* placing the window may have changed the monitor. Find the @@ -636,6 +648,7 @@ place_window_if_needed (MetaWindow *window, * uses the placed coordinates (bug #556696). */ window->unconstrained_rect = info->current; + window->unconstrained_rect_valid = TRUE; meta_window_maximize_internal (window, (window->maximize_horizontally_after_placement ? @@ -1211,25 +1224,33 @@ constrain_maximization (MetaWindow *window, gboolean check_only) { MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; + gboolean is_maximized_horizontally, is_maximized_vertically; MtkRectangle target_size; MtkRectangle min_size, max_size; gboolean hminbad, vminbad; gboolean horiz_equal, vert_equal; gboolean constraint_already_satisfied; + MetaTileMode tile_mode; if (priority > PRIORITY_MAXIMIZATION) return TRUE; /* Determine whether constraint applies; exit if it doesn't */ - if ((!window->maximized_horizontally && !window->maximized_vertically) || + if (!meta_window_config_is_any_maximized (window->config) || meta_window_is_tiled_side_by_side (window)) return TRUE; + is_maximized_horizontally = + meta_window_config_is_maximized_horizontally (window->config); + is_maximized_vertically = + meta_window_config_is_maximized_vertically (window->config); + /* Calculate target_size = maximized size of (window + frame) */ + tile_mode = meta_window_config_get_tile_mode (window->config); if (meta_window_is_maximized (window) && - window->tile_mode == META_TILE_MAXIMIZED) + tile_mode == META_TILE_MAXIMIZED) { - meta_window_get_tile_area (window, window->tile_mode, &target_size); + meta_window_get_tile_area (window, tile_mode, &target_size); } else if (meta_window_is_maximized (window)) { @@ -1247,7 +1268,7 @@ constrain_maximization (MetaWindow *window, MetaDirection direction; GSList *active_workspace_struts; - if (window->maximized_horizontally) + if (is_maximized_horizontally) direction = META_DIRECTION_HORIZONTAL; else direction = META_DIRECTION_VERTICAL; @@ -1264,8 +1285,8 @@ constrain_maximization (MetaWindow *window, * windows, as per bug 327543. */ get_size_limits (window, &min_size, &max_size); - hminbad = target_size.width < min_size.width && window->maximized_horizontally; - vminbad = target_size.height < min_size.height && window->maximized_vertically; + hminbad = target_size.width < min_size.width && is_maximized_horizontally; + vminbad = target_size.height < min_size.height && is_maximized_vertically; if (hminbad || vminbad) return TRUE; @@ -1275,18 +1296,18 @@ constrain_maximization (MetaWindow *window, vert_equal = target_size.y == info->current.y && target_size.height == info->current.height; constraint_already_satisfied = - (horiz_equal || !window->maximized_horizontally) && - (vert_equal || !window->maximized_vertically); + (horiz_equal || !is_maximized_horizontally) && + (vert_equal || !is_maximized_vertically); if (check_only || constraint_already_satisfied) return constraint_already_satisfied; /*** Enforce constraint ***/ - if (window->maximized_horizontally) + if (is_maximized_horizontally) { info->current.x = target_size.x; info->current.width = target_size.width; } - if (window->maximized_vertically) + if (is_maximized_vertically) { info->current.y = target_size.y; info->current.height = target_size.height; @@ -1300,6 +1321,7 @@ constrain_tiling (MetaWindow *window, ConstraintPriority priority, gboolean check_only) { + MetaTileMode tile_mode; MtkRectangle target_size; MtkRectangle min_size, max_size; gboolean hminbad, vminbad; @@ -1316,7 +1338,8 @@ constrain_tiling (MetaWindow *window, /* Calculate target_size - as the tile previews need this as well, we * use an external function for the actual calculation */ - meta_window_get_tile_area (window, window->tile_mode, &target_size); + tile_mode = meta_window_config_get_tile_mode (window->config); + meta_window_get_tile_area (window, tile_mode, &target_size); /* Check min size constraints; max size constraints are ignored as for * maximized windows. @@ -1413,9 +1436,9 @@ constrain_size_increments (MetaWindow *window, extra_height = (client_rect.height - bh) % hi; extra_width = (client_rect.width - bw) % wi; /* ignore size increments for maximized windows */ - if (window->maximized_horizontally) + if (meta_window_config_is_maximized_horizontally (window->config)) extra_width *= 0; - if (window->maximized_vertically) + if (meta_window_config_is_maximized_vertically (window->config)) extra_height *= 0; /* constraint is satisfied iff there is no extra height or width */ constraint_already_satisfied = @@ -1481,9 +1504,9 @@ constrain_size_limits (MetaWindow *window, /* Determine whether constraint is already satisfied; exit if it is */ get_size_limits (window, &min_size, &max_size); /* We ignore max-size limits for maximized windows; see #327543 */ - if (window->maximized_horizontally) + if (meta_window_config_is_maximized_horizontally (window->config)) max_size.width = MAX (max_size.width, info->current.width); - if (window->maximized_vertically) + if (meta_window_config_is_maximized_vertically (window->config)) max_size.height = MAX (max_size.height, info->current.height); too_small = !mtk_rectangle_could_fit_rect (&info->current, &min_size); too_big = !mtk_rectangle_could_fit_rect (&max_size, &info->current); diff --git a/src/core/display-private.h b/src/core/display-private.h index bcfee4918a1dff0f84c4d92a3843bd16006101ce..4881088947bc2289ae3b2704802e008ff002569b 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -58,14 +58,6 @@ typedef enum #define _NET_WM_STATE_ADD 1 /* add/set property */ #define _NET_WM_STATE_TOGGLE 2 /* toggle property */ -typedef enum -{ - META_TILE_NONE, - META_TILE_LEFT, - META_TILE_RIGHT, - META_TILE_MAXIMIZED -} MetaTileMode; - typedef void (* MetaDisplayWindowFunc) (MetaWindow *window, gpointer user_data); diff --git a/src/core/display.c b/src/core/display.c index c2600ec753d87db0d9408a53f13e7e4a25d5078a..4cadf007c698eefa94e8d2120602b1789e145c21 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -3101,8 +3101,7 @@ check_fullscreen_func (gpointer data) if (meta_window_is_monitor_sized (window)) covers_monitors = TRUE; } - else if (window->maximized_horizontally && - window->maximized_vertically) + else if (meta_window_is_maximized (window)) { MetaLogicalMonitor *logical_monitor; @@ -3549,7 +3548,7 @@ static void move_resize (MetaDisplay *display, GList *windows) { - g_list_foreach (windows, (GFunc) meta_window_update_layout, NULL); + g_list_foreach (windows, (GFunc) meta_window_idle_move_resize, NULL); g_list_foreach (windows, (GFunc) warn_on_incorrectly_unmanaged_window, NULL); } diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 32b143b70d8dfca066967c979dbb492c344dda5e..5af53703c0b86c2fd5c114abea4d9fa29b7d2324 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -36,6 +36,7 @@ #include "compositor/compositor-private.h" #include "core/keybindings-private.h" #include "core/meta-accel-parse.h" +#include "core/meta-window-config-private.h" #include "core/meta-workspace-manager-private.h" #include "core/workspace-private.h" #include "meta/compositor.h" @@ -1790,7 +1791,7 @@ handle_maximize_vertically (MetaDisplay *display, { if (window->has_resize_func) { - if (window->maximized_vertically) + if (meta_window_config_is_maximized_vertically (window->config)) meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL); else meta_window_maximize (window, META_MAXIMIZE_VERTICAL); @@ -1806,7 +1807,7 @@ handle_maximize_horizontally (MetaDisplay *display, { if (window->has_resize_func) { - if (window->maximized_horizontally) + if (meta_window_config_is_maximized_horizontally (window->config)) meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL); else meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL); @@ -2125,14 +2126,21 @@ handle_toggle_tiled (MetaDisplay *display, } else if (meta_window_can_tile_side_by_side (window, window->monitor->number)) { - window->tile_monitor_number = window->monitor->number; + gboolean is_maximized_vertically; + + meta_window_config_set_tile_monitor_number (window->config, + window->monitor->number); /* Maximization constraints beat tiling constraints, so if the window * is maximized, tiling won't have any effect unless we unmaximize it * horizontally first; rather than calling meta_window_unmaximize(), * we just set the flag and rely on meta_window_tile() syncing it to * save an additional roundtrip. */ - window->maximized_horizontally = FALSE; + is_maximized_vertically = + meta_window_config_is_maximized_vertically (window->config); + meta_window_config_set_maximized_directions (window->config, + FALSE, + is_maximized_vertically); meta_window_tile (window, mode); } } @@ -2168,7 +2176,7 @@ handle_unmaximize (MetaDisplay *display, MetaKeyBinding *binding, gpointer user_data) { - if (window->maximized_vertically || window->maximized_horizontally) + if (meta_window_config_is_any_maximized (window->config)) meta_window_unmaximize (window, META_MAXIMIZE_BOTH); } diff --git a/src/core/meta-window-config-private.h b/src/core/meta-window-config-private.h index ea34b69998db363644fc3e1481b4a11cf97c6f6c..d950da5cd402cd36db9566be19de443a85072952 100644 --- a/src/core/meta-window-config-private.h +++ b/src/core/meta-window-config-private.h @@ -19,5 +19,48 @@ #pragma once #include "meta/meta-window-config.h" +#include "meta/types.h" + +typedef enum +{ + META_TILE_NONE, + META_TILE_LEFT, + META_TILE_RIGHT, + META_TILE_MAXIMIZED +} MetaTileMode; MetaWindowConfig * meta_window_config_initial_new (void); + +gboolean meta_window_config_is_maximized (MetaWindowConfig *config); + +gboolean meta_window_config_is_any_maximized (MetaWindowConfig *config); + +gboolean meta_window_config_is_maximized_horizontally (MetaWindowConfig *config); + +gboolean meta_window_config_is_maximized_vertically (MetaWindowConfig *config); + +void meta_window_config_set_maximized_directions (MetaWindowConfig *window_config, + gboolean horizontally, + gboolean vertically); + +MetaTileMode meta_window_config_get_tile_mode (MetaWindowConfig *config); + +int meta_window_config_get_tile_monitor_number (MetaWindowConfig *config); + +double meta_window_config_get_tile_hfraction (MetaWindowConfig *config); + +MetaWindow * meta_window_config_get_tile_match (MetaWindowConfig *config); + +void meta_window_config_set_tile_mode (MetaWindowConfig *config, + MetaTileMode tile_mode); + +void meta_window_config_set_tile_monitor_number (MetaWindowConfig *config, + int tile_monitor_number); + +void meta_window_config_set_tile_hfraction (MetaWindowConfig *config, + double hfraction); + +void meta_window_config_set_tile_match (MetaWindowConfig *config, + MetaWindow *tile_match); + +gboolean meta_window_config_is_floating (MetaWindowConfig *config); diff --git a/src/core/meta-window-config.c b/src/core/meta-window-config.c index 74f5aa81f4c784301387444838ece50fe1bee923..6d5fb4c2d905c5ae5330f0224563190e6055f734 100644 --- a/src/core/meta-window-config.c +++ b/src/core/meta-window-config.c @@ -37,6 +37,14 @@ struct _MetaWindowConfig MtkRectangle rect; gboolean is_fullscreen; + + gboolean maximized_horizontally; + gboolean maximized_vertically; + + MetaTileMode tile_mode; + int tile_monitor_number; + double tile_hfraction; + MetaWindow *tile_match; }; G_DEFINE_FINAL_TYPE (MetaWindowConfig, meta_window_config, G_TYPE_OBJECT) @@ -126,6 +134,8 @@ static void meta_window_config_init (MetaWindowConfig *window_config) { window_config->rect = MTK_RECTANGLE_INIT (0, 0, 0, 0); + window_config->tile_monitor_number = -1; + window_config->tile_hfraction = -1.0; } gboolean @@ -200,6 +210,98 @@ meta_window_config_get_is_fullscreen (MetaWindowConfig *window_config) return window_config->is_fullscreen; } +gboolean +meta_window_config_is_maximized (MetaWindowConfig *config) +{ + return config->maximized_horizontally && config->maximized_vertically; +} + +gboolean +meta_window_config_is_any_maximized (MetaWindowConfig *config) +{ + return config->maximized_horizontally || config->maximized_vertically; +} + +gboolean +meta_window_config_is_maximized_horizontally (MetaWindowConfig *config) +{ + return config->maximized_horizontally; +} + +gboolean +meta_window_config_is_maximized_vertically (MetaWindowConfig *config) +{ + return config->maximized_vertically; +} + +void +meta_window_config_set_maximized_directions (MetaWindowConfig *config, + gboolean horizontally, + gboolean vertically) +{ + config->maximized_horizontally = horizontally; + config->maximized_vertically = vertically; +} + +MetaTileMode +meta_window_config_get_tile_mode (MetaWindowConfig *config) +{ + return config->tile_mode; +} + +int +meta_window_config_get_tile_monitor_number (MetaWindowConfig *config) +{ + return config->tile_monitor_number; +} + +double +meta_window_config_get_tile_hfraction (MetaWindowConfig *config) +{ + return config->tile_hfraction; +} + +MetaWindow * +meta_window_config_get_tile_match (MetaWindowConfig *config) +{ + return config->tile_match; +} + +void +meta_window_config_set_tile_mode (MetaWindowConfig *config, + MetaTileMode tile_mode) +{ + config->tile_mode = tile_mode; +} + +void +meta_window_config_set_tile_monitor_number (MetaWindowConfig *config, + int tile_monitor_number) +{ + config->tile_monitor_number = tile_monitor_number; +} + +void +meta_window_config_set_tile_hfraction (MetaWindowConfig *config, + double hfraction) +{ + config->tile_hfraction = hfraction; +} + +void +meta_window_config_set_tile_match (MetaWindowConfig *config, + MetaWindow *tile_match) +{ + config->tile_match = tile_match; +} + +gboolean +meta_window_config_is_floating (MetaWindowConfig *config) +{ + return (!config->is_fullscreen && + !meta_window_config_is_any_maximized (config)); +} + MetaWindowConfig * meta_window_config_new (void) { diff --git a/src/core/place.c b/src/core/place.c index aefa246c5e5d377874c9232b937c48318ae9d935..2718c5f525fdb06782097024b3167af403687c58 100644 --- a/src/core/place.c +++ b/src/core/place.c @@ -164,16 +164,16 @@ northeast_cmp (gconstpointer a, } static void -find_next_cascade (MetaWindow *window, +find_next_cascade (MetaWindow *window, + MtkRectangle work_area, /* visible windows on relevant workspaces */ - GList *windows, - int *new_x, - int *new_y, - gboolean place_centered) + GList *windows, + int width, + int height, + int *new_x, + int *new_y, + gboolean place_centered) { - MetaDisplay *display = meta_window_get_display (window); - MetaContext *context = meta_display_get_context (display); - MetaBackend *backend = meta_context_get_backend (context); GList *tmp; GList *sorted; int adjusted_center_x, adjusted_center_y; @@ -182,8 +182,6 @@ find_next_cascade (MetaWindow *window, MtkRectangle frame_rect; int window_width, window_height; int cascade_stage; - MtkRectangle work_area; - MetaLogicalMonitor *current; gboolean ltr = clutter_get_text_direction () == CLUTTER_TEXT_DIRECTION_LTR; /* This is a "fuzzy" cascade algorithm. @@ -200,19 +198,17 @@ find_next_cascade (MetaWindow *window, * of NW corner of window frame. */ - current = meta_backend_get_current_logical_monitor (backend); - meta_window_get_work_area_for_logical_monitor (window, current, &work_area); - meta_window_get_frame_rect (window, &frame_rect); - window_width = frame_rect.width; - window_height = frame_rect.height; + window_width = width; + window_height = height; sorted = g_list_copy (windows); if (place_centered) { WindowDistanceComparisonData window_distance_data = { .area = work_area, - .window = frame_rect, + .window = MTK_RECTANGLE_INIT (frame_rect.x, frame_rect.y, + width, height), .ltr = ltr, }; @@ -637,6 +633,8 @@ find_first_fit (MetaWindow *window, /* visible windows on relevant workspaces */ GList *windows, MetaLogicalMonitor *logical_monitor, + int width, + int height, int *new_x, int *new_y) { @@ -651,7 +649,7 @@ find_first_fit (MetaWindow *window, GList *below_sorted; GList *end_sorted; GList *tmp; - MtkRectangle rect; + MtkRectangle rect = MTK_RECTANGLE_INIT (0, 0, width, height); MtkRectangle work_area; gboolean ltr = clutter_get_text_direction () == CLUTTER_TEXT_DIRECTION_LTR; @@ -667,8 +665,6 @@ find_first_fit (MetaWindow *window, end_sorted = g_list_sort (end_sorted, topmost_cmp); end_sorted = g_list_sort (end_sorted, ltr ? leftmost_cmp : rightmost_cmp); - meta_window_get_frame_rect (window, &rect); - #ifdef WITH_VERBOSE_MODE { char monitor_location_string[RECT_LENGTH]; @@ -844,6 +840,8 @@ meta_window_place (MetaWindow *window, MetaPlaceFlag flags, int x, int y, + int new_width, + int new_height, int *new_x, int *new_y) { @@ -853,6 +851,7 @@ meta_window_place (MetaWindow *window, g_autoptr (GList) windows = NULL; MetaLogicalMonitor *logical_monitor = NULL; gboolean place_centered = FALSE; + MtkRectangle work_area; meta_topic (META_DEBUG_PLACEMENT, "Placing window %s", window->desc); @@ -957,9 +956,8 @@ meta_window_place (MetaWindow *window, if (parent) { - MtkRectangle frame_rect, parent_frame_rect; + MtkRectangle parent_frame_rect; - meta_window_get_frame_rect (window, &frame_rect); meta_window_get_frame_rect (parent, &parent_frame_rect); y = parent_frame_rect.y; @@ -967,12 +965,12 @@ meta_window_place (MetaWindow *window, /* center of parent */ x = parent_frame_rect.x + parent_frame_rect.width / 2; /* center of child over center of parent */ - x -= frame_rect.width / 2; + x -= new_width / 2; /* "visually" center window over parent, leaving twice as * much space below as on top. */ - y += (parent_frame_rect.height - frame_rect.height) / 3; + y += (parent_frame_rect.height - new_height) / 3; meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent", @@ -989,27 +987,28 @@ meta_window_place (MetaWindow *window, */ windows = find_windows_relevant_for_placement (window); - logical_monitor = meta_backend_get_current_logical_monitor (backend); + + if (!window->showing_for_first_time) + logical_monitor = meta_window_get_main_logical_monitor (window); + else + logical_monitor = meta_backend_get_current_logical_monitor (backend); + + meta_window_get_work_area_for_logical_monitor (window, + logical_monitor, + &work_area); + place_centered = window_place_centered (window); if (place_centered) { - /* Center on current monitor */ - MtkRectangle work_area; - MtkRectangle frame_rect; - - meta_window_get_work_area_for_logical_monitor (window, - logical_monitor, - &work_area); - meta_window_get_frame_rect (window, &frame_rect); - - x = work_area.x + (work_area.width - frame_rect.width) / 2; - y = work_area.y + (work_area.height - frame_rect.height) / 2; + x = work_area.x + (work_area.width - new_width) / 2; + y = work_area.y + (work_area.height - new_height) / 2; meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on monitor %d", window->desc, logical_monitor->number); - find_next_cascade (window, windows, &x, &y, place_centered); + find_next_cascade (window, work_area, windows, new_width, new_height, + &x, &y, place_centered); } else { @@ -1018,9 +1017,13 @@ meta_window_place (MetaWindow *window, y = logical_monitor->rect.y; /* No good fit? Fall back to cascading... */ - if (!find_first_fit (window, windows, logical_monitor, + if (!find_first_fit (window, windows, + logical_monitor, new_width, new_height, &x, &y)) - find_next_cascade (window, windows, &x, &y, place_centered); + { + find_next_cascade (window, work_area, windows, new_width, new_height, + &x, &y, place_centered); + } } /* Maximize windows if they are too big for their work area (bit of @@ -1031,17 +1034,15 @@ meta_window_place (MetaWindow *window, !meta_window_is_fullscreen (window)) { MtkRectangle workarea; - MtkRectangle frame_rect; meta_window_get_work_area_for_logical_monitor (window, logical_monitor, &workarea); - meta_window_get_frame_rect (window, &frame_rect); /* If the window is bigger than the screen, then automaximize. Do NOT * auto-maximize the directions independently. See #419810. */ - if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height) + if (new_width >= workarea.width && new_height >= workarea.height) { window->maximize_horizontally_after_placement = TRUE; window->maximize_vertically_after_placement = TRUE; @@ -1077,7 +1078,8 @@ meta_window_place (MetaWindow *window, y = logical_monitor->rect.y; found_fit = find_first_fit (window, focus_window_list, - logical_monitor, &x, &y); + logical_monitor, new_width, new_height, + &x, &y); g_list_free (focus_window_list); } diff --git a/src/core/place.h b/src/core/place.h index d29e711057a99bde872296ea3915b68128968fd1..b51b2528b985b980e50261d4b928c13bb39c53e6 100644 --- a/src/core/place.h +++ b/src/core/place.h @@ -32,5 +32,7 @@ void meta_window_place (MetaWindow *window, MetaPlaceFlag place_flags, int x, int y, + int new_width, + int new_height, int *new_x, int *new_y); diff --git a/src/core/window-private.h b/src/core/window-private.h index c48a60aacc7eef868457df897ab33dc48e7d7ed1..a116fbe8352bca7cb0bf1eb183718c939f52908d 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -33,6 +33,7 @@ #include "backends/meta-logical-monitor.h" #include "clutter/clutter.h" +#include "core/meta-window-config-private.h" #include "core/stack.h" #include "meta/meta-window-config.h" #include "meta/compositor.h" @@ -72,6 +73,7 @@ typedef enum META_MOVE_RESIZE_PLACEMENT_CHANGED = 1 << 11, META_MOVE_RESIZE_WAYLAND_CLIENT_RESIZE = 1 << 12, META_MOVE_RESIZE_CONSTRAIN = 1 << 13, + META_MOVE_RESIZE_RECT_INVALID = 1 << 14, } MetaMoveResizeFlags; typedef enum _MetaPlaceFlag @@ -79,13 +81,15 @@ typedef enum _MetaPlaceFlag META_PLACE_FLAG_NONE = 0, META_PLACE_FLAG_FORCE_MOVE = 1 << 0, META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT = 1 << 1, + META_PLACE_FLAG_CALCULATE = 1 << 2, } MetaPlaceFlag; typedef enum { - META_MOVE_RESIZE_RESULT_MOVED = 1 << 0, - META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1, - META_MOVE_RESIZE_RESULT_STATE_CHANGED = 1 << 3, + META_MOVE_RESIZE_RESULT_MOVED = 1 << 0, + META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1, + META_MOVE_RESIZE_RESULT_STATE_CHANGED = 1 << 3, + META_MOVE_RESIZE_RESULT_UPDATE_UNCONSTRAINED = 1 << 4, } MetaMoveResizeResultFlags; typedef enum @@ -259,11 +263,6 @@ struct _MetaWindow /* Initial timestamp property */ guint32 initial_timestamp; - /* The current tile mode */ - MetaTileMode tile_mode; - - int tile_monitor_number; - struct { MetaEdgeConstraint top; MetaEdgeConstraint right; @@ -271,8 +270,6 @@ struct _MetaWindow MetaEdgeConstraint left; } edge_constraints; - double tile_hfraction; - MetaLogicalMonitorId *preferred_logical_monitor; /* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has @@ -360,9 +357,6 @@ struct _MetaWindow /* Focused window that is (directly or indirectly) attached to this one */ MetaWindow *attached_focus_window; - /* The currently complementary tiled window, if any */ - MetaWindow *tile_match; - struct { MetaPlacementRule *rule; MetaPlacementState state; @@ -392,10 +386,6 @@ struct _MetaWindow /* Whether this is an override redirect window or not */ guint override_redirect : 1; - /* Whether we're maximized */ - guint maximized_horizontally : 1; - guint maximized_vertically : 1; - /* Whether we have to maximize/minimize after placement */ guint maximize_horizontally_after_placement : 1; guint maximize_vertically_after_placement : 1; @@ -520,9 +510,13 @@ struct _MetaWindow /* TRUE if window appears focused at the moment */ guint appears_focused : 1; - /* Have we placed this window? */ + /* Have we placed this window according to the floating window placement + * algorithm? */ guint placed : 1; + /* Have this window been positioned? */ + uint unconstrained_rect_valid : 1; + /* Has this window not ever been shown yet? */ guint showing_for_first_time : 1; @@ -537,11 +531,6 @@ struct _MetaWindow */ guint withdrawn : 1; - /* TRUE if constrain_position should calc placement. - * only relevant if !window->placed - */ - guint calc_placement : 1; - /* if TRUE, window is attached to its parent */ guint attached : 1; @@ -798,6 +787,11 @@ void meta_window_move_resize (MetaWindow *window, MetaMoveResizeFlags flags, MtkRectangle frame_rect); +void meta_window_move_resize_internal (MetaWindow *window, + MetaMoveResizeFlags flags, + MetaPlaceFlag place_flags, + MtkRectangle frame_rect); + void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op); void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op); @@ -837,7 +831,7 @@ void meta_window_update_visibility (MetaWindow *window); void meta_window_clear_queued (MetaWindow *window); -void meta_window_update_layout (MetaWindow *window); +void meta_window_idle_move_resize (MetaWindow *window); gboolean meta_window_calculate_bounds (MetaWindow *window, int *bounds_width, diff --git a/src/core/window.c b/src/core/window.c index a463ddbbc0cc0a9d5f44121117b6f0adee4d529c..776f08f288c78d166ab1073088563f85ab38e1a3 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -177,11 +177,6 @@ static void set_hidden_suspended_state (MetaWindow *window); static void initable_iface_init (GInitableIface *initable_iface); -static void meta_window_move_resize_internal (MetaWindow *window, - MetaMoveResizeFlags flags, - MetaPlaceFlag place_flags, - MtkRectangle frame_rect); - typedef struct _MetaWindowPrivate { MetaQueueType queued_types; @@ -382,105 +377,108 @@ meta_window_finalize (GObject *object) } static void -meta_window_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +meta_window_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - MetaWindow *win = META_WINDOW (object); - MetaWindowPrivate *priv = meta_window_get_instance_private (win); + MetaWindow *window = META_WINDOW (object); + MetaWindowPrivate *priv = meta_window_get_instance_private (window); + MetaWindowConfig *config = window->config; switch (prop_id) { case PROP_TITLE: - g_value_set_string (value, win->title); + g_value_set_string (value, window->title); break; case PROP_DECORATED: - g_value_set_boolean (value, win->decorated); + g_value_set_boolean (value, window->decorated); break; case PROP_FULLSCREEN: - g_value_set_boolean (value, meta_window_is_fullscreen (win)); + g_value_set_boolean (value, meta_window_is_fullscreen (window)); break; case PROP_MAXIMIZED_HORIZONTALLY: - g_value_set_boolean (value, win->maximized_horizontally); + g_value_set_boolean (value, + meta_window_config_is_maximized_horizontally (config)); break; case PROP_MAXIMIZED_VERTICALLY: - g_value_set_boolean (value, win->maximized_vertically); + g_value_set_boolean (value, + meta_window_config_is_maximized_vertically (config)); break; case PROP_MINIMIZED: - g_value_set_boolean (value, win->minimized); + g_value_set_boolean (value, window->minimized); break; case PROP_WINDOW_TYPE: - g_value_set_enum (value, win->type); + g_value_set_enum (value, window->type); break; case PROP_USER_TIME: - g_value_set_uint (value, win->net_wm_user_time); + g_value_set_uint (value, window->net_wm_user_time); break; case PROP_DEMANDS_ATTENTION: - g_value_set_boolean (value, win->wm_state_demands_attention); + g_value_set_boolean (value, window->wm_state_demands_attention); break; case PROP_URGENT: - g_value_set_boolean (value, win->urgent); + g_value_set_boolean (value, window->urgent); break; case PROP_SKIP_TASKBAR: - g_value_set_boolean (value, win->skip_taskbar); + g_value_set_boolean (value, window->skip_taskbar); break; case PROP_MUTTER_HINTS: - g_value_set_string (value, win->mutter_hints); + g_value_set_string (value, window->mutter_hints); break; case PROP_APPEARS_FOCUSED: - g_value_set_boolean (value, win->appears_focused); + g_value_set_boolean (value, window->appears_focused); break; case PROP_WM_CLASS: - g_value_set_string (value, win->res_class); + g_value_set_string (value, window->res_class); break; case PROP_RESIZEABLE: - g_value_set_boolean (value, win->has_resize_func); + g_value_set_boolean (value, window->has_resize_func); break; case PROP_ABOVE: - g_value_set_boolean (value, win->wm_state_above); + g_value_set_boolean (value, window->wm_state_above); break; case PROP_GTK_APPLICATION_ID: - g_value_set_string (value, win->gtk_application_id); + g_value_set_string (value, window->gtk_application_id); break; case PROP_GTK_UNIQUE_BUS_NAME: - g_value_set_string (value, win->gtk_unique_bus_name); + g_value_set_string (value, window->gtk_unique_bus_name); break; case PROP_GTK_APPLICATION_OBJECT_PATH: - g_value_set_string (value, win->gtk_application_object_path); + g_value_set_string (value, window->gtk_application_object_path); break; case PROP_GTK_WINDOW_OBJECT_PATH: - g_value_set_string (value, win->gtk_window_object_path); + g_value_set_string (value, window->gtk_window_object_path); break; case PROP_GTK_APP_MENU_OBJECT_PATH: - g_value_set_string (value, win->gtk_app_menu_object_path); + g_value_set_string (value, window->gtk_app_menu_object_path); break; case PROP_GTK_MENUBAR_OBJECT_PATH: - g_value_set_string (value, win->gtk_menubar_object_path); + g_value_set_string (value, window->gtk_menubar_object_path); break; case PROP_ON_ALL_WORKSPACES: - g_value_set_boolean (value, win->on_all_workspaces); + g_value_set_boolean (value, window->on_all_workspaces); break; case PROP_IS_ALIVE: - g_value_set_boolean (value, win->is_alive); + g_value_set_boolean (value, window->is_alive); break; case PROP_DISPLAY: - g_value_set_object (value, win->display); + g_value_set_object (value, window->display); break; case PROP_EFFECT: - g_value_set_int (value, win->pending_compositor_effect); + g_value_set_int (value, window->pending_compositor_effect); break; case PROP_SUSPEND_STATE: g_value_set_enum (value, priv->suspend_state); break; case PROP_MAPPED: - g_value_set_boolean (value, win->mapped); + g_value_set_boolean (value, window->mapped); break; case PROP_MAIN_MONITOR: - g_value_set_object (value, win->monitor); + g_value_set_object (value, window->monitor); break; case PROP_TAG: - g_value_set_string (value, win->tag); + g_value_set_string (value, window->tag); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -489,20 +487,20 @@ meta_window_get_property(GObject *object, } static void -meta_window_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +meta_window_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - MetaWindow *win = META_WINDOW (object); + MetaWindow *window = META_WINDOW (object); switch (prop_id) { case PROP_DISPLAY: - win->display = g_value_get_object (value); + window->display = g_value_get_object (value); break; case PROP_EFFECT: - win->pending_compositor_effect = g_value_get_int (value); + window->pending_compositor_effect = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1100,10 +1098,7 @@ meta_window_constructed (GObject *object) /* initialize the remaining size_hints as if size_hints.flags were zero */ meta_window_set_normal_hints (window, NULL); - /* And this is our unmaximized size */ frame_rect = meta_window_config_get_rect (window->config); - window->saved_rect = frame_rect; - window->saved_rect_fullscreen = frame_rect; window->unconstrained_rect = frame_rect; window->title = NULL; @@ -1111,8 +1106,6 @@ meta_window_constructed (GObject *object) window->has_focus = FALSE; window->attached_focus_window = NULL; - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; window->maximize_horizontally_after_placement = FALSE; window->maximize_vertically_after_placement = FALSE; window->minimize_after_placement = FALSE; @@ -1122,9 +1115,6 @@ meta_window_constructed (GObject *object) window->require_titlebar_visible = TRUE; window->on_all_workspaces = FALSE; window->on_all_workspaces_requested = FALSE; - window->tile_mode = META_TILE_NONE; - window->tile_monitor_number = -1; - window->tile_hfraction = -1.; window->initially_iconic = FALSE; window->minimized = FALSE; window->iconic = FALSE; @@ -1141,7 +1131,6 @@ meta_window_constructed (GObject *object) window->initial_timestamp_set = FALSE; window->net_wm_user_time_set = FALSE; window->input = TRUE; - window->calc_placement = FALSE; window->unmaps_pending = 0; window->reparents_pending = 0; @@ -1193,7 +1182,8 @@ meta_window_constructed (GObject *object) window->compositor_private = NULL; - if (frame_rect.width > 0 && frame_rect.height > 0) + if (frame_rect.width > 0 && frame_rect.height > 0 && + (window->size_hints.flags & META_SIZE_HINTS_USER_POSITION)) { window->monitor = meta_window_find_monitor_from_frame_rect (window); window->highest_scale_monitor = @@ -1211,8 +1201,6 @@ meta_window_constructed (GObject *object) meta_logical_monitor_dup_id (window->monitor); } - window->tile_match = NULL; - /* Assign this #MetaWindow a sequence number which can be used * for sorting. */ @@ -1595,7 +1583,7 @@ meta_window_unmanage (MetaWindow *window, invalidate_work_areas (window); } - if (window->maximized_horizontally || window->maximized_vertically) + if (meta_window_config_is_any_maximized (window->config)) unmaximize_window_before_freeing (window); meta_window_unqueue (window, @@ -2189,12 +2177,6 @@ meta_window_force_placement (MetaWindow *window, * have been mapped/placed since we last did constrain_position */ - /* calc_placement is an efficiency hack to avoid - * multiple placement calculations before we finally - * show the window. - */ - window->calc_placement = TRUE; - flags = (META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_CONSTRAIN); @@ -2203,9 +2185,8 @@ meta_window_force_placement (MetaWindow *window, meta_window_move_resize_internal (window, flags, - place_flags, + place_flags | META_PLACE_FLAG_CALCULATE, window->unconstrained_rect); - window->calc_placement = FALSE; /* don't ever do the initial position constraint thing again. * This is toggled here so that initially-iconified windows @@ -2405,7 +2386,8 @@ meta_window_show (MetaWindow *window) place_flags |= META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT; } - if (!window->placed) + if (!window->placed && + meta_window_config_is_floating (window->config)) { if (window->monitor && meta_prefs_get_auto_maximize () && @@ -2791,12 +2773,12 @@ meta_window_save_rect (MetaWindow *window) frame_rect = meta_window_config_get_rect (window->config); /* save size/pos as appropriate args for move_resize */ - if (!window->maximized_horizontally) + if (!meta_window_config_is_maximized_horizontally (window->config)) { window->saved_rect.x = frame_rect.x; window->saved_rect.width = frame_rect.width; } - if (!window->maximized_vertically) + if (!meta_window_config_is_maximized_vertically (window->config)) { window->saved_rect.y = frame_rect.y; window->saved_rect.height = frame_rect.height; @@ -2811,8 +2793,11 @@ meta_window_maximize_internal (MetaWindow *window, { /* At least one of the two directions ought to be set */ gboolean maximize_horizontally, maximize_vertically; + gboolean was_maximized_horizontally, was_maximized_vertically; + maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; - maximize_vertically = directions & META_MAXIMIZE_VERTICAL; + maximize_vertically = directions & META_MAXIMIZE_VERTICAL; + g_assert (maximize_horizontally || maximize_vertically); meta_topic (META_DEBUG_WINDOW_OPS, @@ -2822,6 +2807,11 @@ meta_window_maximize_internal (MetaWindow *window, maximize_horizontally ? " horizontally" : maximize_vertically ? " vertically" : "BUGGGGG"); + was_maximized_horizontally = + meta_window_config_is_maximized_horizontally (window->config); + was_maximized_vertically = + meta_window_config_is_maximized_vertically (window->config); + if (saved_rect != NULL) window->saved_rect = *saved_rect; else @@ -2830,10 +2820,10 @@ meta_window_maximize_internal (MetaWindow *window, if (maximize_horizontally && maximize_vertically) window->saved_maximize = TRUE; - window->maximized_horizontally = - window->maximized_horizontally || maximize_horizontally; - window->maximized_vertically = - window->maximized_vertically || maximize_vertically; + meta_window_config_set_maximized_directions ( + window->config, + was_maximized_horizontally || maximize_horizontally, + was_maximized_vertically || maximize_vertically); /* Update the edge constraints */ update_edge_constraints (window); @@ -2856,6 +2846,7 @@ meta_window_maximize (MetaWindow *window, { MtkRectangle *saved_rect = NULL; gboolean maximize_horizontally, maximize_vertically; + gboolean was_maximized_horizontally, was_maximized_vertically; g_return_if_fail (META_IS_WINDOW (window)); g_return_if_fail (!window->override_redirect); @@ -2865,31 +2856,27 @@ meta_window_maximize (MetaWindow *window, maximize_vertically = directions & META_MAXIMIZE_VERTICAL; g_assert (maximize_horizontally || maximize_vertically); + was_maximized_horizontally = + meta_window_config_is_maximized_horizontally (window->config); + was_maximized_vertically = + meta_window_config_is_maximized_vertically (window->config); + /* Only do something if the window isn't already maximized in the * given direction(s). */ - if ((maximize_horizontally && !window->maximized_horizontally) || - (maximize_vertically && !window->maximized_vertically)) + if ((maximize_horizontally && !was_maximized_horizontally) || + (maximize_vertically && !was_maximized_vertically)) { - /* if the window hasn't been placed yet, we'll maximize it then - */ - if (!window->placed) - { - window->maximize_horizontally_after_placement = - window->maximize_horizontally_after_placement || - maximize_horizontally; - window->maximize_vertically_after_placement = - window->maximize_vertically_after_placement || - maximize_vertically; - return; - } + MetaMoveResizeFlags flags; - if (window->tile_mode != META_TILE_NONE) + if (meta_window_config_get_tile_mode (window->config) != META_TILE_NONE) { saved_rect = &window->saved_rect; - window->maximized_vertically = FALSE; - window->tile_mode = META_TILE_NONE; + meta_window_config_set_maximized_directions (window->config, + was_maximized_horizontally, + FALSE); + meta_window_config_set_tile_mode (window->config, META_TILE_NONE); } meta_window_maximize_internal (window, @@ -2905,12 +2892,14 @@ meta_window_maximize (MetaWindow *window, META_SIZE_CHANGE_MAXIMIZE, &old_frame_rect, &old_buffer_rect); - meta_window_move_resize (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED | - META_MOVE_RESIZE_CONSTRAIN), - window->unconstrained_rect); + flags = (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_STATE_CHANGED | + META_MOVE_RESIZE_CONSTRAIN); + if (!window->unconstrained_rect_valid) + flags |= META_MOVE_RESIZE_RECT_INVALID; + + meta_window_move_resize (window, flags, window->unconstrained_rect); } } @@ -2926,8 +2915,14 @@ meta_window_maximize (MetaWindow *window, MetaMaximizeFlags meta_window_get_maximized (MetaWindow *window) { - return ((window->maximized_horizontally ? META_MAXIMIZE_HORIZONTAL : 0) | - (window->maximized_vertically ? META_MAXIMIZE_VERTICAL : 0)); + MetaMaximizeFlags flags = 0; + + if (meta_window_config_is_maximized_horizontally (window->config)) + flags |= META_MAXIMIZE_HORIZONTAL; + if (meta_window_config_is_maximized_vertically (window->config)) + flags |= META_MAXIMIZE_VERTICAL; + + return flags; } /** @@ -2939,7 +2934,7 @@ meta_window_get_maximized (MetaWindow *window) gboolean meta_window_is_maximized (MetaWindow *window) { - return (window->maximized_horizontally && window->maximized_vertically); + return meta_window_config_is_maximized (window->config); } /** @@ -3030,6 +3025,8 @@ meta_window_get_tile_fraction (MetaWindow *window, MetaTileMode tile_mode, double *fraction) { + double tile_hfraction = + meta_window_config_get_tile_hfraction (window->config); MetaWindow *tile_match; /* Make sure the tile match is up-to-date and matches the @@ -3042,13 +3039,13 @@ meta_window_get_tile_fraction (MetaWindow *window, else if (tile_mode == META_TILE_MAXIMIZED) *fraction = 1.; else if (tile_match) - *fraction = 1. - tile_match->tile_hfraction; + *fraction = 1. - meta_window_config_get_tile_hfraction (tile_match->config); else if (meta_window_is_tiled_side_by_side (window)) { - if (window->tile_mode != tile_mode) - *fraction = 1. - window->tile_hfraction; + if (meta_window_config_get_tile_mode (window->config) != tile_mode) + *fraction = 1. - tile_hfraction; else - *fraction = window->tile_hfraction; + *fraction = tile_hfraction; } else *fraction = .5; @@ -3059,17 +3056,21 @@ meta_window_update_tile_fraction (MetaWindow *window, int new_w, int new_h) { - MetaWindow *tile_match = window->tile_match; + MetaWindow *tile_match = meta_window_config_get_tile_match (window->config); + int tile_monitor_number; MtkRectangle work_area; MetaWindowDrag *window_drag; if (!meta_window_is_tiled_side_by_side (window)) return; + tile_monitor_number = + meta_window_config_get_tile_monitor_number (window->config); meta_window_get_work_area_for_monitor (window, - window->tile_monitor_number, + tile_monitor_number, &work_area); - window->tile_hfraction = (double)new_w / work_area.width; + meta_window_config_set_tile_hfraction (window->config, + (double) new_w / work_area.width); window_drag = meta_compositor_get_current_window_drag (window->display->compositor); @@ -3077,13 +3078,18 @@ meta_window_update_tile_fraction (MetaWindow *window, if (tile_match && window_drag && meta_window_drag_get_window (window_drag) == window) - meta_window_tile (tile_match, tile_match->tile_mode); + { + MetaTileMode tile_match_tile_mode = + meta_window_config_get_tile_mode (tile_match->config); + + meta_window_tile (tile_match, tile_match_tile_mode); + } } static void update_edge_constraints (MetaWindow *window) { - switch (window->tile_mode) + switch (meta_window_config_get_tile_mode (window->config)) { case META_TILE_NONE: window->edge_constraints.top = META_EDGE_CONSTRAINT_NONE; @@ -3102,7 +3108,7 @@ update_edge_constraints (MetaWindow *window) case META_TILE_LEFT: window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR; - if (window->tile_match) + if (meta_window_config_get_tile_match (window->config)) window->edge_constraints.right = META_EDGE_CONSTRAINT_WINDOW; else window->edge_constraints.right = META_EDGE_CONSTRAINT_NONE; @@ -3116,7 +3122,7 @@ update_edge_constraints (MetaWindow *window) window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR; window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR; - if (window->tile_match) + if (meta_window_config_get_tile_match (window->config)) window->edge_constraints.left = META_EDGE_CONSTRAINT_WINDOW; else window->edge_constraints.left = META_EDGE_CONSTRAINT_NONE; @@ -3124,13 +3130,13 @@ update_edge_constraints (MetaWindow *window) } /* h/vmaximize also modify the edge constraints */ - if (window->maximized_vertically) + if (meta_window_config_is_maximized_vertically (window->config)) { window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR; window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR; } - if (window->maximized_horizontally) + if (meta_window_config_is_maximized_horizontally (window->config)) { window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR; window->edge_constraints.left = META_EDGE_CONSTRAINT_MONITOR; @@ -3140,36 +3146,44 @@ update_edge_constraints (MetaWindow *window) gboolean meta_window_is_tiled_side_by_side (MetaWindow *window) { - return window->maximized_vertically && - !window->maximized_horizontally && - window->tile_mode != META_TILE_NONE; + MetaWindowConfig *config = window->config; + + return (meta_window_config_is_maximized_vertically (config) && + !meta_window_config_is_maximized_horizontally (config) && + meta_window_config_get_tile_mode (config) != META_TILE_NONE); } gboolean meta_window_is_tiled_left (MetaWindow *window) { - return window->tile_mode == META_TILE_LEFT && + return meta_window_config_get_tile_mode (window->config) == META_TILE_LEFT && meta_window_is_tiled_side_by_side (window); } gboolean meta_window_is_tiled_right (MetaWindow *window) { - return window->tile_mode == META_TILE_RIGHT && + return meta_window_config_get_tile_mode (window->config) == META_TILE_RIGHT && meta_window_is_tiled_side_by_side (window); } void meta_window_untile (MetaWindow *window) { + int tile_monitor_number; + MetaTileMode tile_mode; + g_return_if_fail (META_IS_WINDOW (window)); - window->tile_monitor_number = - window->saved_maximize ? window->monitor->number - : -1; - window->tile_mode = + tile_monitor_number = window->saved_maximize ? window->monitor->number + : -1; + meta_window_config_set_tile_monitor_number (window->config, + tile_monitor_number); + + tile_mode = window->saved_maximize ? META_TILE_MAXIMIZED : META_TILE_NONE; + meta_window_config_set_tile_mode (window->config, tile_mode); if (window->saved_maximize) meta_window_maximize (window, META_MAXIMIZE_BOTH); @@ -3183,24 +3197,28 @@ meta_window_tile (MetaWindow *window, { MetaMaximizeFlags directions; MetaWindowDrag *window_drag; + MetaWindow *tile_match; + double tile_hfraction; g_return_if_fail (META_IS_WINDOW (window)); - meta_window_get_tile_fraction (window, tile_mode, &window->tile_hfraction); - window->tile_mode = tile_mode; + meta_window_get_tile_fraction (window, tile_mode, &tile_hfraction); + meta_window_config_set_tile_hfraction (window->config, tile_hfraction); + meta_window_config_set_tile_mode (window->config, tile_mode); /* Don't do anything if no tiling is requested */ - if (window->tile_mode == META_TILE_NONE) + if (tile_mode == META_TILE_NONE) { - window->tile_monitor_number = -1; + meta_window_config_set_tile_monitor_number (window->config, -1); return; } - else if (window->tile_monitor_number < 0) + else if (meta_window_config_get_tile_monitor_number (window->config) < 0) { - window->tile_monitor_number = window->monitor->number; + meta_window_config_set_tile_monitor_number (window->config, + window->monitor->number); } - if (window->tile_mode == META_TILE_MAXIMIZED) + if (tile_mode == META_TILE_MAXIMIZED) directions = META_MAXIMIZE_BOTH; else directions = META_MAXIMIZE_VERTICAL; @@ -3210,9 +3228,10 @@ meta_window_tile (MetaWindow *window, window_drag = meta_compositor_get_current_window_drag (window->display->compositor); - if (!window->tile_match || + tile_match = meta_window_config_get_tile_match (window->config); + if (!tile_match || !window_drag || - window->tile_match != meta_window_drag_get_window (window_drag)) + tile_match != meta_window_drag_get_window (window_drag)) { MtkRectangle old_frame_rect, old_buffer_rect; @@ -3279,8 +3298,7 @@ unmaximize_window_before_freeing (MetaWindow *window) "Unmaximizing %s just before freeing", window->desc); - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; + meta_window_config_set_maximized_directions (window->config, FALSE, FALSE); if (window->withdrawn) /* See bug #137185 */ { @@ -3320,6 +3338,7 @@ meta_window_unmaximize (MetaWindow *window, MetaMaximizeFlags directions) { gboolean unmaximize_horizontally, unmaximize_vertically; + gboolean was_maximized_horizontally, was_maximized_vertically; g_return_if_fail (META_IS_WINDOW (window)); g_return_if_fail (!window->override_redirect); @@ -3332,24 +3351,35 @@ meta_window_unmaximize (MetaWindow *window, if (unmaximize_horizontally && unmaximize_vertically) window->saved_maximize = FALSE; + was_maximized_horizontally = + meta_window_config_is_maximized_horizontally (window->config); + was_maximized_vertically = + meta_window_config_is_maximized_vertically (window->config); + /* Only do something if the window isn't already maximized in the * given direction(s). */ - if ((unmaximize_horizontally && window->maximized_horizontally) || - (unmaximize_vertically && window->maximized_vertically)) + if ((unmaximize_horizontally && was_maximized_horizontally) || + (unmaximize_vertically && was_maximized_vertically)) { - MtkRectangle *desired_rect; + MtkRectangle desired_rect; + gboolean has_desired_rect = FALSE; MtkRectangle target_rect; MtkRectangle work_area; MtkRectangle old_frame_rect, old_buffer_rect; gboolean has_target_size; + MetaPlaceFlag place_flags = META_PLACE_FLAG_NONE; + MetaMoveResizeFlags flags = (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_STATE_CHANGED | + META_MOVE_RESIZE_UNMAXIMIZE); meta_window_get_work_area_current_monitor (window, &work_area); meta_window_get_frame_rect (window, &old_frame_rect); meta_window_get_buffer_rect (window, &old_buffer_rect); if (unmaximize_vertically) - window->tile_mode = META_TILE_NONE; + meta_window_config_set_tile_mode (window->config, META_TILE_NONE); meta_topic (META_DEBUG_WINDOW_OPS, "Unmaximizing %s%s", @@ -3358,10 +3388,10 @@ meta_window_unmaximize (MetaWindow *window, unmaximize_horizontally ? " horizontally" : unmaximize_vertically ? " vertically" : "BUGGGGG"); - window->maximized_horizontally = - window->maximized_horizontally && !unmaximize_horizontally; - window->maximized_vertically = - window->maximized_vertically && !unmaximize_vertically; + meta_window_config_set_maximized_directions ( + window->config, + was_maximized_horizontally && !unmaximize_horizontally, + was_maximized_vertically && !unmaximize_vertically); /* Update the edge constraints */ update_edge_constraints (window); @@ -3372,56 +3402,75 @@ meta_window_unmaximize (MetaWindow *window, */ meta_window_frame_size_changed (window); - desired_rect = &window->saved_rect; + if (!window->placed && + !mtk_rectangle_is_empty (&window->unconstrained_rect)) + { + place_flags |= META_PLACE_FLAG_CALCULATE; + flags |= META_MOVE_RESIZE_CONSTRAIN; - /* Unmaximize to the saved_rect position in the direction(s) - * being unmaximized. - */ - target_rect = old_frame_rect; + if (!window->unconstrained_rect_valid) + flags |= META_MOVE_RESIZE_RECT_INVALID; + + target_rect = window->unconstrained_rect; + } + else + { + desired_rect = window->saved_rect; + has_desired_rect = TRUE; + + /* Unmaximize to the saved_rect position in the direction(s) + * being unmaximized. + */ + target_rect = old_frame_rect; + } /* Avoid unmaximizing to "almost maximized" size when the previous size * is greater then 80% of the work area use MAX_UNMAXIMIZED_WINDOW_AREA of * the work area as upper limit while maintaining the aspect ratio. */ if (unmaximize_horizontally && unmaximize_vertically && - desired_rect->width * desired_rect->height > + has_desired_rect && + desired_rect.width * desired_rect.height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA) { - if (desired_rect->width > desired_rect->height) + if (desired_rect.width > desired_rect.height) { float aspect; - aspect = (float) desired_rect->height / (float) desired_rect->width; - desired_rect->width = + aspect = (float) desired_rect.height / (float) desired_rect.width; + desired_rect.width = (int) MAX (work_area.width * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_width); - desired_rect->height = - (int) MAX (desired_rect->width * aspect, + desired_rect.height = + (int) MAX (desired_rect.width * aspect, window->size_hints.min_height); } else { float aspect; - aspect = (float) desired_rect->width / (float) desired_rect->height; - desired_rect->height = + aspect = (float) desired_rect.width / (float) desired_rect.height; + desired_rect.height = (int) MAX (work_area.height * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_height); - desired_rect->width = - (int) MAX (desired_rect->height * aspect, + desired_rect.width = + (int) MAX (desired_rect.height * aspect, window->size_hints.min_width); } } - if (unmaximize_horizontally) + if (has_desired_rect) { - target_rect.x = desired_rect->x; - target_rect.width = desired_rect->width; - } - if (unmaximize_vertically) - { - target_rect.y = desired_rect->y; - target_rect.height = desired_rect->height; + if (unmaximize_horizontally) + { + target_rect.x = desired_rect.x; + target_rect.width = desired_rect.width; + } + if (unmaximize_vertically) + { + target_rect.y = desired_rect.y; + target_rect.height = desired_rect.height; + } } /* Window's size hints may have changed while maximized, making @@ -3436,12 +3485,8 @@ meta_window_unmaximize (MetaWindow *window, META_SIZE_CHANGE_UNMAXIMIZE, &old_frame_rect, &old_buffer_rect); - meta_window_move_resize (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED | - META_MOVE_RESIZE_UNMAXIMIZE), - target_rect); + meta_window_move_resize_internal (window, flags, place_flags, + target_rect); meta_window_recalc_features (window); set_net_wm_state (window); @@ -3524,6 +3569,7 @@ meta_window_make_fullscreen (MetaWindow *window) if (!meta_window_is_fullscreen (window)) { MtkRectangle old_frame_rect, old_buffer_rect; + MetaMoveResizeFlags flags; meta_window_get_frame_rect (window, &old_frame_rect); meta_window_get_buffer_rect (window, &old_buffer_rect); @@ -3533,12 +3579,14 @@ meta_window_make_fullscreen (MetaWindow *window) &old_frame_rect, &old_buffer_rect); meta_window_make_fullscreen_internal (window); - meta_window_move_resize (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED | - META_MOVE_RESIZE_CONSTRAIN), - window->unconstrained_rect); + + flags = (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_STATE_CHANGED | + META_MOVE_RESIZE_CONSTRAIN); + if (!window->unconstrained_rect_valid) + flags |= META_MOVE_RESIZE_RECT_INVALID; + meta_window_move_resize (window, flags, window->unconstrained_rect); } } @@ -3552,12 +3600,32 @@ meta_window_unmake_fullscreen (MetaWindow *window) { MtkRectangle old_frame_rect, old_buffer_rect, target_rect; gboolean has_target_size; + MetaPlaceFlag place_flags = META_PLACE_FLAG_NONE; + MetaMoveResizeFlags flags = (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_STATE_CHANGED | + META_MOVE_RESIZE_UNFULLSCREEN); meta_topic (META_DEBUG_WINDOW_OPS, "Unfullscreening %s", window->desc); meta_window_config_set_is_fullscreen (window->config, FALSE); - target_rect = window->saved_rect_fullscreen; + + + if (!window->placed && + !mtk_rectangle_is_empty (&window->unconstrained_rect)) + { + place_flags |= META_PLACE_FLAG_CALCULATE; + flags |= META_MOVE_RESIZE_CONSTRAIN; + if (!window->unconstrained_rect_valid) + flags |= META_MOVE_RESIZE_RECT_INVALID; + + target_rect = window->unconstrained_rect; + } + else + { + target_rect = window->saved_rect_fullscreen; + } meta_window_frame_size_changed (window); meta_window_get_frame_rect (window, &old_frame_rect); @@ -3580,12 +3648,8 @@ meta_window_unmake_fullscreen (MetaWindow *window) window, META_SIZE_CHANGE_UNFULLSCREEN, &old_frame_rect, &old_buffer_rect); - meta_window_move_resize (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED | - META_MOVE_RESIZE_UNFULLSCREEN), - target_rect); + meta_window_move_resize_internal (window, flags, place_flags, + target_rect); meta_display_queue_check_fullscreen (window->display); @@ -3920,12 +3984,17 @@ meta_window_update_for_monitors_changed (MetaWindow *window) old = window->monitor; new = meta_window_find_monitor_from_id (window); - if (window->tile_mode != META_TILE_NONE) + if (meta_window_config_get_tile_mode (window->config) != META_TILE_NONE) { + int new_monitor_number; + if (new) - window->tile_monitor_number = new->number; + new_monitor_number = new->number; else - window->tile_monitor_number = -1; + new_monitor_number = -1; + + meta_window_config_set_tile_monitor_number (window->config, + new_monitor_number); } if (new && old) @@ -4003,7 +4072,7 @@ meta_window_update_monitor (MetaWindow *window, g_signal_emit (window, window_signals[HIGHEST_SCALE_MONITOR_CHANGED], 0); } -static void +void meta_window_move_resize_internal (MetaWindow *window, MetaMoveResizeFlags flags, MetaPlaceFlag place_flags, @@ -4050,7 +4119,7 @@ meta_window_move_resize_internal (MetaWindow *window, META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE)); - did_placement = !window->placed && window->calc_placement; + did_placement = !window->placed && (place_flags & META_PLACE_FLAG_CALCULATE); gravity = meta_window_get_gravity (window); @@ -4120,7 +4189,7 @@ meta_window_move_resize_internal (MetaWindow *window, } /* If we did placement, then we need to save the position that the window - * was placed at to make sure that meta_window_update_layout() places the + * was placed at to make sure that meta_window_idle_move_resize() places the * window correctly. */ if (did_placement) @@ -4150,12 +4219,10 @@ meta_window_move_resize_internal (MetaWindow *window, g_signal_emit (window, window_signals[SIZE_CHANGED], 0); } - /* Only update the stored size when requested but not when a - * (potentially outdated) request completes */ - if (!(flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE) || - flags & META_MOVE_RESIZE_WAYLAND_CLIENT_RESIZE) + if (result & META_MOVE_RESIZE_RESULT_UPDATE_UNCONSTRAINED) { window->unconstrained_rect = unconstrained_rect; + window->unconstrained_rect_valid = TRUE; } if ((moved_or_resized || @@ -4201,14 +4268,6 @@ meta_window_move_resize_internal (MetaWindow *window, meta_stack_update_window_tile_matches (window->display->stack, workspace_manager->active_workspace); - - /* This is a workaround for #1627. We still don't have any tests that can - * reproduce this issue reliably and this is not a proper fix! */ - if (flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE && - (result & META_MOVE_RESIZE_RESULT_MOVED || - result & META_MOVE_RESIZE_RESULT_RESIZED) && - (window->maximized_horizontally || window->maximized_vertically)) - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); } void @@ -4303,6 +4362,7 @@ meta_window_move_between_rects (MetaWindow *window, window->unconstrained_rect.x = new_x; window->unconstrained_rect.y = new_y; + window->unconstrained_rect_valid = TRUE; meta_window_move_resize (window, (move_resize_flags | @@ -4359,8 +4419,8 @@ meta_window_move_to_monitor (MetaWindow *window, { MtkRectangle old_area, new_area; - if (window->tile_mode != META_TILE_NONE) - window->tile_monitor_number = monitor; + if (meta_window_config_get_tile_mode (window->config) != META_TILE_NONE) + meta_window_config_set_tile_monitor_number (window->config, monitor); meta_window_get_work_area_for_monitor (window, window->monitor->number, @@ -4407,12 +4467,15 @@ adjust_size_for_tile_match (MetaWindow *window, int *new_h) { MtkRectangle work_area, rect; - MetaWindow *tile_match = window->tile_match; + MetaWindow *tile_match = meta_window_config_get_tile_match (window->config); + int tile_monitor_number; if (!meta_window_is_tiled_side_by_side (window) || !tile_match) return; - meta_window_get_work_area_for_monitor (window, window->tile_monitor_number, + tile_monitor_number = + meta_window_config_get_tile_monitor_number (window->config); + meta_window_get_work_area_for_monitor (window, tile_monitor_number, &work_area); /* Make sure the resize does not break minimum sizes */ @@ -4468,13 +4531,24 @@ meta_window_resize_frame (MetaWindow *window, } void -meta_window_update_layout (MetaWindow *window) +meta_window_idle_move_resize (MetaWindow *window) { - meta_window_move_resize_frame (window, FALSE, - window->unconstrained_rect.x, - window->unconstrained_rect.y, - window->unconstrained_rect.width, - window->unconstrained_rect.height); + MetaMoveResizeFlags flags; + + if (!meta_window_is_showable (window)) + return; + + flags = (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_CONSTRAIN); + if (!window->unconstrained_rect_valid) + flags |= META_MOVE_RESIZE_RECT_INVALID; + meta_window_move_resize (window, + META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_CONSTRAIN | + META_MOVE_RESIZE_RECT_INVALID, + window->unconstrained_rect); } gboolean @@ -5997,7 +6071,8 @@ meta_window_get_work_area_all_monitors (MetaWindow *window, int meta_window_get_current_tile_monitor_number (MetaWindow *window) { - int tile_monitor_number = window->tile_monitor_number; + int tile_monitor_number = + meta_window_config_get_tile_monitor_number (window->config); if (tile_monitor_number < 0) { @@ -7133,20 +7208,26 @@ meta_window_has_modals (MetaWindow *window) MetaWindow * meta_window_get_tile_match (MetaWindow *window) { - return window->tile_match; + return meta_window_config_get_tile_match (window->config); } void meta_window_compute_tile_match (MetaWindow *window) { - window->tile_match = meta_window_find_tile_match (window, window->tile_mode); + MetaTileMode tile_mode = meta_window_config_get_tile_mode (window->config); + MetaWindow *tile_match; + + tile_match = meta_window_find_tile_match (window, tile_mode); + meta_window_config_set_tile_match (window->config, tile_match); } static MetaWindow * meta_window_find_tile_match (MetaWindow *window, MetaTileMode current_mode) { - MetaWindow *match; + int tile_monitor_number; + MetaWindow *other_window; + MetaWindow *match = NULL; MetaStack *stack; MetaTileMode match_tile_mode = META_TILE_NONE; @@ -7162,15 +7243,34 @@ meta_window_find_tile_match (MetaWindow *window, stack = window->display->stack; - for (match = meta_stack_get_top (stack); - match; - match = meta_stack_get_below (stack, match, FALSE)) + tile_monitor_number = + meta_window_config_get_tile_monitor_number (window->config); + + for (other_window = meta_stack_get_top (stack); + other_window; + other_window = meta_stack_get_below (stack, other_window, FALSE)) { - if (!match->minimized && - match->tile_mode == match_tile_mode && - match->tile_monitor_number == window->tile_monitor_number && - meta_window_get_workspace (match) == meta_window_get_workspace (window)) - break; + MetaTileMode other_tile_mode; + int other_tile_monitor_number; + + if (other_window->minimized) + continue; + + other_tile_mode = meta_window_config_get_tile_mode (other_window->config); + if (other_tile_mode != match_tile_mode) + continue; + + other_tile_monitor_number = + meta_window_config_get_tile_monitor_number (other_window->config); + + if (other_tile_monitor_number != tile_monitor_number) + continue; + + if (meta_window_get_workspace (other_window) == meta_window_get_workspace (window)) + { + match = other_window; + break; + } } if (match) @@ -7201,11 +7301,11 @@ meta_window_find_tile_match (MetaWindow *window, * rather than a match for a potential tile mode, then discard * windows with too much gap or overlap */ - if (window->tile_mode == current_mode && + if (meta_window_config_get_tile_mode (window->config) == current_mode && !(window_drag && meta_grab_op_is_resizing (meta_window_drag_get_grab_op (window_drag)) && meta_window_drag_get_window (window_drag) == window && - window->tile_match != NULL)) + meta_window_config_get_tile_match (window->config))) { int threshold = meta_prefs_get_drag_threshold (); if (ABS (topmost_rect.x - bottommost_rect.x - bottommost_rect.width) > threshold && diff --git a/src/tests/meson.build b/src/tests/meson.build index d342b20d080bc2acd074cab69ed6d380667ba74b..ea6962c2c42dfdf64388f34ed8c8d123a80d1cea 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -966,6 +966,12 @@ stacking_tests = [ 'sticky-transients', 'strut-monitor-changes', 'window-placement', + 'x11-move', + 'map-maximized', + 'map-fullscreen', + 'tiling', + 'interactive-move', + 'map-on-monitor', ] foreach stacking_test: stacking_tests diff --git a/src/tests/stacking/interactive-move.metatest b/src/tests/stacking/interactive-move.metatest new file mode 100644 index 0000000000000000000000000000000000000000..1eb8ffbe24922c660d18d92730997c7a6c834851 --- /dev/null +++ b/src/tests/stacking/interactive-move.metatest @@ -0,0 +1,26 @@ +new_client w wayland + +# +# This test case ensures that window state configuration changes after an +# interactive move doesn't cause unexpected window movement. +# + +create w/1 +show w/1 +wait +move w/1 0 10 +maximize w/1 +unmaximize w/1 +wait_reconfigure w/1 +assert_position w/1 0 10 + +move w/1 20 20 +assert_position w/1 20 20 + +create w/2 +show w/2 +wait + +assert_focused w/2 + +assert_position w/1 20 20 diff --git a/src/tests/stacking/map-fullscreen.metatest b/src/tests/stacking/map-fullscreen.metatest new file mode 100644 index 0000000000000000000000000000000000000000..da920babbc4690cbef2ae1bc34842b1bffa89a1d --- /dev/null +++ b/src/tests/stacking/map-fullscreen.metatest @@ -0,0 +1,52 @@ +set_pref center-new-windows false +resize_monitor default 400 400 +new_client w wayland +new_client x x11 + +# Map a Wayland window fullscreen, and make sure it gets placed according to its +# nonfullscreen size: +# +# ------------ +# | ---- | +# | |w | | +# | ---- | +# | | +# | | +# ------------ + +create w/1 csd +resize_ignore_titlebar w/1 120 120 +fullscreen w/1 +show w/1 +wait_reconfigure w/1 +assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT +assert_position w/1 0 0 + +unfullscreen w/1 +wait_reconfigure w/1 +assert_size w/1 120 120 +assert_position w/1 18 12 + +# Map a X11 window fullscreen, and make sure it gets placed according to it's +# nonfullscreen size +# +# ------------ +# | ---- | +# | |w | | +# | ---- | +# | |x | | +# | ---- | +# ------------ + +create x/1 csd +resize_ignore_titlebar x/1 120 120 +fullscreen x/1 +show x/1 +wait_reconfigure x/1 +assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT +assert_position x/1 0 0 + +unfullscreen x/1 +wait_reconfigure x/1 +assert_size x/1 120 120 +assert_position x/1 18 132 diff --git a/src/tests/stacking/map-maximized.metatest b/src/tests/stacking/map-maximized.metatest new file mode 100644 index 0000000000000000000000000000000000000000..11ecac07cede32c616436d941f47646fced8c7c4 --- /dev/null +++ b/src/tests/stacking/map-maximized.metatest @@ -0,0 +1,52 @@ +set_pref center-new-windows false +resize_monitor default 400 400 +new_client w wayland +new_client x x11 + +# Map a Wayland window maximized, and make sure it gets placed according to its +# unmaximized size: +# +# ------------ +# | ---- | +# | |w | | +# | ---- | +# | | +# | | +# ------------ + +create w/1 csd +resize w/1 120 120 +maximize w/1 +show w/1 +wait_reconfigure w/1 +assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT +assert_position w/1 0 0 + +unmaximize w/1 +wait_reconfigure w/1 +assert_size w/1 120 120 +assert_position w/1 18 12 + +# Map a X11 window maximized, and make sure it gets placed according to it's +# unmaximized size +# +# ------------ +# | ---- | +# | |w | | +# | ---- | +# | |x | | +# | ---- | +# ------------ + +create x/1 csd +resize x/1 120 120 +maximize x/1 +show x/1 +wait_reconfigure x/1 +assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT +assert_position x/1 0 0 + +unmaximize x/1 +wait_reconfigure x/1 +assert_size x/1 120 120 +assert_position x/1 18 132 diff --git a/src/tests/stacking/map-on-monitor.metatest b/src/tests/stacking/map-on-monitor.metatest new file mode 100644 index 0000000000000000000000000000000000000000..7c048193aff21d7c00c3c0e5ebe18bff8b47785b --- /dev/null +++ b/src/tests/stacking/map-on-monitor.metatest @@ -0,0 +1,109 @@ +resize_monitor default 640 480 +add_monitor secondary 800 600 + +move_cursor_to 700 200 + +new_client w wayland +new_client x x11 + +# +# Wayland +# + +# Map floating on secondary monitor + +create w/1 csd +resize w/1 100 100 +show w/1 +assert_position w/1 990 250 +assert_size w/1 100 100 +destroy w/1 + +# Map maximized on secondary monitor, move cursor, then unmaximize + +create w/2 csd +resize w/2 100 100 +maximize w/2 +show w/2 +assert_position w/2 640 0 +assert_size w/2 800 600 + +move_cursor_to 10 10 + +unmaximize w/2 +wait_reconfigure w/2 +assert_position w/2 990 250 +assert_size w/2 100 100 +destroy w/2 + +# Map fullscreen on secondary monitor, then unfullscreen + +move_cursor_to 700 200 + +create w/3 csd +resize_ignore_titlebar w/3 100 100 +fullscreen w/3 +show w/3 +assert_position w/3 640 0 +assert_size w/3 800 600 + +move_cursor_to 10 10 + +unfullscreen w/3 +wait_reconfigure w/3 +assert_position w/3 990 250 +assert_size w/3 100 100 +destroy w/3 + +# +# X11 +# + +# Map floating on secondary monitor + +move_cursor_to 700 200 + +create x/1 csd +resize x/1 100 100 +show x/1 +assert_position x/1 990 250 +assert_size x/1 100 100 +destroy x/1 + +# Map maximized on secondary monitor, then unmaximize + +move_cursor_to 700 200 + +create x/2 csd +resize x/2 100 100 +maximize x/2 +show x/2 +assert_position x/2 640 0 +assert_size x/2 800 600 + +move_cursor_to 10 10 + +unmaximize x/2 +wait_reconfigure x/2 +assert_position x/2 990 250 +assert_size x/2 100 100 +destroy x/2 + +# Map fullscreen on secondary monitor, then unfullscreen + +move_cursor_to 700 200 + +create x/3 csd +resize_ignore_titlebar x/3 100 100 +fullscreen x/3 +show x/3 +assert_position x/3 640 0 +assert_size x/3 800 600 + +move_cursor_to 10 10 + +unfullscreen x/3 +wait_reconfigure x/3 +assert_position x/3 990 250 +assert_size x/3 100 100 +destroy x/3 diff --git a/src/tests/stacking/tiling.metatest b/src/tests/stacking/tiling.metatest new file mode 100644 index 0000000000000000000000000000000000000000..c91c2efdf4daab6e1c4f9d154564c59917853701 --- /dev/null +++ b/src/tests/stacking/tiling.metatest @@ -0,0 +1,50 @@ +new_client w wayland + +create w/1 csd +show w/1 + +create w/2 csd +show w/2 + +tile w/1 left +tile w/2 right + +wait_reconfigure w/1 +wait_reconfigure w/2 + +assert_position w/1 0 0 +assert_size w/1 MONITOR_WIDTH/2 MONITOR_HEIGHT + +assert_position w/2 MONITOR_WIDTH/2 0 +assert_size w/2 MONITOR_WIDTH/2 MONITOR_HEIGHT + +# Resize both -40 pixels horizontally + +begin_resize w/1 right +update_resize w/1 -35 0 +end_resize w/1 +wait_reconfigure w/1 +wait_reconfigure w/2 + +assert_position w/1 0 0 +assert_size w/1 MONITOR_WIDTH/2-35 MONITOR_HEIGHT + +assert_position w/2 MONITOR_WIDTH/2-35 0 +assert_size w/2 MONITOR_WIDTH/2+35 MONITOR_HEIGHT + +# Resize both +80 pixels horizontally + +begin_resize w/1 right +update_resize w/1 5 0 +update_resize w/1 10 0 +update_resize w/1 15 0 +update_resize w/1 20 0 +end_resize w/1 +wait_reconfigure w/1 +wait_reconfigure w/2 + +assert_position w/1 0 0 +assert_size w/1 MONITOR_WIDTH/2-15 MONITOR_HEIGHT + +assert_position w/2 MONITOR_WIDTH/2-15 0 +assert_size w/2 MONITOR_WIDTH/2+15 MONITOR_HEIGHT diff --git a/src/tests/stacking/x11-move.metatest b/src/tests/stacking/x11-move.metatest new file mode 100644 index 0000000000000000000000000000000000000000..552298be6a40e29fef29c00b39856757ad4e6391 --- /dev/null +++ b/src/tests/stacking/x11-move.metatest @@ -0,0 +1,9 @@ +resize_monitor default 640 480 +add_monitor secondary 800 600 + +new_client x x11 +create x/1 +x11_geometry x/1 100x100+700+10 +show x/1 + +assert_position x/1 700 10 diff --git a/src/tests/test-client.c b/src/tests/test-client.c index 7aa3b9306fd77216029b318edc14e72281119f27..d5b1dbc46791a0573e27bedee431d7daaf479f5f 100644 --- a/src/tests/test-client.c +++ b/src/tests/test-client.c @@ -33,6 +33,7 @@ const char *client_id = "0"; static gboolean wayland; +static gboolean dont_exit_on_eof; GHashTable *windows; GQuark event_source_quark; GQuark event_handlers_quark; @@ -592,11 +593,14 @@ process_line (const char *line) gtk_window_present (GTK_WINDOW (window)); } - else if (strcmp (argv[0], "resize") == 0) + else if (strcmp (argv[0], "resize") == 0 || + strcmp (argv[0], "resize_ignore_titlebar") == 0) { + int titlebar_height; + if (argc != 4) { - g_print ("usage: resize \n"); + g_print ("usage: %s \n", argv[0]); goto out; } @@ -606,11 +610,28 @@ process_line (const char *line) int width = atoi (argv[2]); int height = atoi (argv[3]); - int titlebar_height = calculate_titlebar_height (GTK_WINDOW (window)); + + if (strcmp (argv[0], "resize_ignore_titlebar") == 0) + titlebar_height = 0; + else + titlebar_height = calculate_titlebar_height (GTK_WINDOW (window)); + gtk_window_resize (GTK_WINDOW (window), width, height - titlebar_height); } + else if (strcmp (argv[0], "x11_geometry") == 0) + { + GtkWidget *window; + + window = lookup_window (argv[1]); + if (!window) + goto out; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_window_parse_geometry (GTK_WINDOW (window), argv[2]); + G_GNUC_END_IGNORE_DEPRECATIONS + } else if (strcmp (argv[0], "raise") == 0) { if (argc != 2) @@ -1019,7 +1040,8 @@ on_line_received (GObject *source, { if (error != NULL) g_printerr ("Error reading from stdin: %s\n", error->message); - gtk_main_quit (); + if (!dont_exit_on_eof) + gtk_main_quit (); return; } @@ -1045,7 +1067,8 @@ read_next_line (GDataInputStream *in) { if (error) g_printerr ("Error reading from stdin: %s\n", error->message); - gtk_main_quit (); + if (!dont_exit_on_eof) + gtk_main_quit (); return; } @@ -1066,6 +1089,12 @@ const GOptionEntry options[] = { "Create a wayland client, not an X11 one", NULL }, + { + "dont-exit-on-eof", 0, 0, G_OPTION_ARG_NONE, + &dont_exit_on_eof, + "Don't terminate client when reaching end of file", + NULL + }, { "client-id", 0, 0, G_OPTION_ARG_STRING, &client_id, diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c index 24e7788985a2af00b2322004d634ab6bda74ce30..10a32c1b7e138ee26d42ee54b76797b438232e20 100644 --- a/src/tests/test-runner.c +++ b/src/tests/test-runner.c @@ -25,14 +25,17 @@ #include #include "backends/meta-virtual-monitor.h" +#include "clutter/clutter.h" +#include "compositor/compositor-private.h" #include "compositor/meta-window-actor-private.h" +#include "compositor/meta-window-drag.h" +#include "core/meta-workspace-manager-private.h" #include "core/meta-workspace-manager-private.h" #include "core/window-private.h" +#include "core/workspace-private.h" #include "meta-test/meta-context-test.h" #include "meta/util.h" #include "meta/window.h" -#include "core/meta-workspace-manager-private.h" -#include "core/workspace-private.h" #include "tests/meta-test-utils.h" #include "wayland/meta-wayland.h" #include "wayland/meta-window-wayland.h" @@ -510,6 +513,46 @@ maybe_divide (const char *str, return value; } +static int +maybe_add (const char *str, + int value, + const char **out_str) +{ + *out_str = str; + + if (str[0] == '+') + { + double term; + + str += 1; + term = g_strtod (str, (char **) out_str); + + value = (int) round (value + term); + } + + return value; +} + +static int +maybe_subtract (const char *str, + int value, + const char **out_str) +{ + *out_str = str; + + if (str[0] == '-') + { + double term; + + str += 1; + term = g_strtod (str, (char **) out_str); + + value = (int) round (value - term); + } + + return value; +} + static int maybe_do_math (const char *str, int value, @@ -523,6 +566,12 @@ maybe_do_math (const char *str, case '/': value = maybe_divide (str, value, &str); break; + case '+': + value = maybe_add (str, value, &str); + break; + case '-': + value = maybe_subtract (str, value, &str); + break; default: *out_str = str; return value; @@ -855,6 +904,23 @@ test_case_parse_signal (TestCase *test, return TRUE; } +static MetaGrabOp +grab_op_from_edge (const char *edge) +{ + MetaGrabOp op = META_GRAB_OP_WINDOW_BASE; + + if (strcmp (edge, "top") == 0) + op |= META_GRAB_OP_WINDOW_DIR_NORTH; + else if (strcmp (edge, "bottom") == 0) + op |= META_GRAB_OP_WINDOW_DIR_SOUTH; + else if (strcmp (edge, "left") == 0) + op |= META_GRAB_OP_WINDOW_DIR_WEST; + else if (strcmp (edge, "right") == 0) + op |= META_GRAB_OP_WINDOW_DIR_EAST; + + return op; +} + static gboolean test_case_do (TestCase *test, const char *filename, @@ -1044,7 +1110,8 @@ test_case_do (TestCase *test, meta_wait_for_window_shown (window); } - else if (strcmp (argv[0], "resize") == 0) + else if (strcmp (argv[0], "resize") == 0 || + strcmp (argv[0], "resize_ignore_titlebar") == 0) { if (argc != 4) BAD_COMMAND("usage: %s / width height", argv[0]); @@ -1058,6 +1125,107 @@ test_case_do (TestCase *test, argv[2], argv[3], NULL)) return FALSE; } + else if (strcmp (argv[0], "x11_geometry") == 0) + { + MetaTestClient *client; + const char *window_id; + + if (argc != 3) + BAD_COMMAND ("usage: %s / ", argv[0]); + + if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) + return FALSE; + + if (!meta_test_client_do (client, error, argv[0], window_id, + argv[2], NULL)) + return FALSE; + } + else if (strcmp (argv[0], "begin_resize") == 0) + { + MetaBackend *backend = meta_context_get_backend (test->context); + ClutterSeat *seat = meta_backend_get_default_seat (backend); + ClutterInputDevice *pointer = clutter_seat_get_pointer (seat); + MetaTestClient *client; + const char *window_id; + MetaWindow *window; + MetaGrabOp grab_op; + MtkRectangle rect; + gboolean ret; + MetaWindowDrag *window_drag; + + if (argc != 3) + BAD_COMMAND("usage: %s / [top|bottom|left|right]", argv[0]); + + if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) + return FALSE; + + window = meta_test_client_find_window (client, window_id, error); + + grab_op = grab_op_from_edge (argv[2]); + + meta_window_get_frame_rect (window, &rect); + graphene_point_t grab_origin; + + grab_origin = GRAPHENE_POINT_INIT (rect.x + rect.width / 2.0f, + rect.y + rect.height / 2.0f); + + window_drag = + meta_compositor_get_current_window_drag (window->display->compositor); + g_assert_null (window_drag); + ret = meta_window_begin_grab_op (window, + grab_op, + pointer, NULL, + meta_display_get_current_time_roundtrip (window->display), + &grab_origin); + g_assert_true (ret); + } + else if (strcmp (argv[0], "update_resize") == 0) + { + MetaTestClient *client; + const char *window_id; + MetaWindow *window; + MtkRectangle rect; + int delta_x, delta_y; + + if (argc != 4) + BAD_COMMAND("usage: %s / ", argv[0]); + + if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) + return FALSE; + + window = meta_test_client_find_window (client, window_id, error); + + meta_window_get_frame_rect (window, &rect); + delta_x = atoi (argv[2]); + delta_y = atoi (argv[3]); + + meta_window_resize_frame (window, + TRUE, + rect.width + delta_x, + rect.height + delta_y); + } + else if (strcmp (argv[0], "end_resize") == 0) + { + MetaTestClient *client; + const char *window_id; + MetaWindow *window; + MetaWindowDrag *window_drag; + + if (argc != 2) + BAD_COMMAND("usage: %s /", argv[0]); + + if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) + return FALSE; + + window = meta_test_client_find_window (client, window_id, error); + + window_drag = + meta_compositor_get_current_window_drag (window->display->compositor); + g_assert_nonnull (window_drag); + g_assert_true (meta_window_drag_get_window (window_drag) == window); + + meta_window_drag_end (window_drag); + } else if (strcmp (argv[0], "move") == 0) { MetaWindow *window; @@ -2204,14 +2372,16 @@ run_test (MetaContext *context, int line_no = 0; while (error == NULL) { - char *line = g_data_input_stream_read_line_utf8 (in, NULL, NULL, &error); + g_autofree char *line = NULL; + int argc; + g_auto (GStrv) argv = NULL; + + line = g_data_input_stream_read_line_utf8 (in, NULL, NULL, &error); if (line == NULL) break; line_no++; - int argc; - char **argv = NULL; if (!g_shell_parse_argv (line, &argc, &argv, &error)) { if (g_error_matches (error, G_SHELL_ERROR, G_SHELL_ERROR_EMPTY_STRING)) @@ -2228,9 +2398,6 @@ run_test (MetaContext *context, next: if (error) g_prefix_error (&error, "%d: ", line_no); - - g_free (line); - g_strfreev (argv); } { diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c index 8d8842c32dd197830f2599317661defb79ceccf1..db5b7ac744474dfd6f969a7e95257243c5ee9448 100644 --- a/src/tests/wayland-unit-tests.c +++ b/src/tests/wayland-unit-tests.c @@ -627,7 +627,7 @@ toplevel_reuse_surface (void) } static void -toplevel_sessions (void) +toplevel_sessions_basic (void) { MetaWaylandTestClient *wayland_test_client; @@ -1554,11 +1554,11 @@ init_tests (void) toplevel_apply_limits); g_test_add_func ("/wayland/toplevel/activation", toplevel_activation); - g_test_add_func ("/wayland/toplevel/sessions", - toplevel_sessions); - g_test_add_func ("/wayland/toplevel/sessions-replace", + g_test_add_func ("/wayland/toplevel/sessions/basic", + toplevel_sessions_basic); + g_test_add_func ("/wayland/toplevel/sessions/replace", toplevel_sessions_replace); - g_test_add_func ("/wayland/toplevel/sessions-restore", + g_test_add_func ("/wayland/toplevel/sessions/restore", toplevel_sessions_restore); #ifdef MUTTER_PRIVILEGED_TEST (void)(toplevel_sessions_restore_maximized); @@ -1568,13 +1568,13 @@ init_tests (void) (void)(toplevel_bounds_struts); (void)(toplevel_bounds_monitors); #else - g_test_add_func ("/wayland/toplevel/sessions-restore-maximized", + g_test_add_func ("/wayland/toplevel/sessions/restore-maximized", toplevel_sessions_restore_maximized); - g_test_add_func ("/wayland/toplevel/sessions-restore-tiled", + g_test_add_func ("/wayland/toplevel/sessions/restore-tiled", toplevel_sessions_restore_tiled); - g_test_add_func ("/wayland/toplevel/sessions-restore-fullscreen", + g_test_add_func ("/wayland/toplevel/sessions/restore-fullscreen", toplevel_sessions_restore_fullscreen); - g_test_add_func ("/wayland/toplevel/sessions-restore-fullscreen-monitor-removed", + g_test_add_func ("/wayland/toplevel/sessions/restore-fullscreen-monitor-removed", toplevel_sessions_restore_fullscreen_monitor_removed); g_test_add_func ("/wayland/toplevel/bounds/struts", toplevel_bounds_struts); diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c index 8a82d3507a83659f39ff87d2f67fa4139b611753..992839a6ab15be3e9f493a31cbb1955ef176baa4 100644 --- a/src/wayland/meta-wayland-gtk-shell.c +++ b/src/wayland/meta-wayland-gtk-shell.c @@ -395,13 +395,14 @@ fill_states (struct wl_array *states, MetaWindow *window, struct wl_resource *resource) { + MetaTileMode tile_mode = meta_window_config_get_tile_mode (window->config); int version; version = wl_resource_get_version (resource); if (version < GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION && - (window->tile_mode == META_TILE_LEFT || - window->tile_mode == META_TILE_RIGHT)) + (tile_mode == META_TILE_LEFT || + tile_mode == META_TILE_RIGHT)) add_state_value (states, GTK_SURFACE1_STATE_TILED); if (version >= GTK_SURFACE1_STATE_TILED_TOP_SINCE_VERSION && diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c index f92c1b34a7d5d6f0535a611279d4a8c31a8bbfed..f9175a9af83e8a5fc54b1044b64807205c35305e 100644 --- a/src/wayland/meta-wayland-window-configuration.c +++ b/src/wayland/meta-wayland-window-configuration.c @@ -40,6 +40,8 @@ meta_wayland_window_configuration_new (MetaWindow *window, configuration = g_new0 (MetaWaylandWindowConfiguration, 1); *configuration = (MetaWaylandWindowConfiguration) { + .ref_count = G_REF_COUNT_INIT, + .serial = ++global_serial_counter, .bounds_width = bounds_width, @@ -50,13 +52,15 @@ meta_wayland_window_configuration_new (MetaWindow *window, .flags = flags, .is_fullscreen = meta_window_is_fullscreen (window), + .is_floating = meta_window_config_is_floating (window->config), .is_suspended = meta_window_is_suspended (window), }; meta_window_config_get_position (window->config, &x, &y); if (flags & META_MOVE_RESIZE_MOVE_ACTION || x != rect.x || - y != rect.y) + y != rect.y || + !configuration->is_floating) { configuration->has_position = TRUE; configuration->x = rect.x; @@ -85,6 +89,8 @@ meta_wayland_window_configuration_new_relative (MetaWindow *window, configuration = g_new0 (MetaWaylandWindowConfiguration, 1); *configuration = (MetaWaylandWindowConfiguration) { + .ref_count = G_REF_COUNT_INIT, + .serial = ++global_serial_counter, .has_relative_position = TRUE, @@ -111,6 +117,7 @@ meta_wayland_window_configuration_new_empty (int bounds_width, configuration = g_new0 (MetaWaylandWindowConfiguration, 1); *configuration = (MetaWaylandWindowConfiguration) { + .ref_count = G_REF_COUNT_INIT, .serial = ++global_serial_counter, .scale = scale, .bounds_width = bounds_width, @@ -120,10 +127,51 @@ meta_wayland_window_configuration_new_empty (int bounds_width, return configuration; } +MetaWaylandWindowConfiguration * +meta_wayland_window_configuration_new_from_other (MetaWaylandWindowConfiguration *other) +{ + MetaWaylandWindowConfiguration *configuration; + + configuration = g_new0 (MetaWaylandWindowConfiguration, 1); + *configuration = (MetaWaylandWindowConfiguration) { + .ref_count = G_REF_COUNT_INIT, + .serial = ++global_serial_counter, + + .has_position = other->has_position, + .x = other->x, + .y = other->y, + .has_relative_position = other->has_relative_position, + .rel_x = other->rel_x, + .rel_y = other->rel_y, + .has_size = other->has_size, + .is_resizing = other->is_resizing, + .width = other->width, + .height = other->height, + .scale = other->scale, + .gravity = other->gravity, + .flags = other->flags, + .bounds_width = other->bounds_width, + .bounds_height = other->bounds_height, + .is_fullscreen = other->is_fullscreen, + .is_floating = other->is_floating, + .is_suspended = other->is_suspended, + }; + + return configuration; +} + +MetaWaylandWindowConfiguration * +meta_wayland_window_configuration_ref (MetaWaylandWindowConfiguration *configuration) +{ + g_ref_count_inc (&configuration->ref_count); + return configuration; +} + void -meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration) +meta_wayland_window_configuration_unref (MetaWaylandWindowConfiguration *configuration) { - g_free (configuration); + if (g_ref_count_dec (&configuration->ref_count)) + g_free (configuration); } MetaWindowConfig * @@ -176,6 +224,10 @@ meta_wayland_window_configuration_apply_window_config (MetaWindow meta_window_config_set_is_fullscreen (window->config, is_fullscreen); configuration->is_fullscreen = is_fullscreen; + configuration->is_floating = + (!meta_window_config_get_is_fullscreen (window_config) && + !meta_window_config_is_any_maximized (window_config)); + if (prev_x != configuration->x || prev_y != configuration->y) { configuration->has_position = TRUE; @@ -192,3 +244,32 @@ meta_wayland_window_configuration_apply_window_config (MetaWindow return configuration; } + +gboolean +meta_wayland_window_configuration_is_equivalent (MetaWaylandWindowConfiguration *configuration, + MetaWaylandWindowConfiguration *other) +{ + g_return_val_if_fail (configuration, FALSE); + + if (!other) + return FALSE; + + return (configuration->has_position == other->has_position && + configuration->x == other->x && + configuration->y == other->y && + configuration->has_relative_position == other->has_relative_position && + configuration->rel_x == other->rel_x && + configuration->rel_y == other->rel_y && + configuration->has_size == other->has_size && + configuration->is_resizing == other->is_resizing && + configuration->width == other->width && + configuration->height == other->height && + configuration->scale == other->scale && + configuration->gravity == other->gravity && + configuration->flags == other->flags && + configuration->bounds_width == other->bounds_width && + configuration->bounds_height == other->bounds_height && + configuration->is_fullscreen == other->is_fullscreen && + configuration->is_floating == other->is_floating && + configuration->is_suspended == other->is_suspended); +} diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h index 762816e5ac05b3d95a5ad6a6057dec3a7da7bc62..fa7f664a50381d6e7cf042744a6c37bfda425ff2 100644 --- a/src/wayland/meta-wayland-window-configuration.h +++ b/src/wayland/meta-wayland-window-configuration.h @@ -27,6 +27,8 @@ struct _MetaWaylandWindowConfiguration { + grefcount ref_count; + uint32_t serial; gboolean has_position; @@ -50,6 +52,7 @@ struct _MetaWaylandWindowConfiguration int bounds_height; gboolean is_fullscreen; + gboolean is_floating; gboolean is_suspended; }; @@ -72,7 +75,14 @@ MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (in int bounds_height, int scale); -void meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration); +MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_from_other (MetaWaylandWindowConfiguration *other); + +MetaWaylandWindowConfiguration * meta_wayland_window_configuration_ref (MetaWaylandWindowConfiguration *configuration); + +void meta_wayland_window_configuration_unref (MetaWaylandWindowConfiguration *configuration); + +gboolean meta_wayland_window_configuration_is_equivalent (MetaWaylandWindowConfiguration *configuration, + MetaWaylandWindowConfiguration *other); MetaWindowConfig * meta_window_config_new_from_wayland_window_configuration (MetaWindow *window, MetaWaylandWindowConfiguration *configuration); @@ -80,3 +90,6 @@ MetaWindowConfig * meta_window_config_new_from_wayland_window_configuration (Met MetaWaylandWindowConfiguration * meta_wayland_window_configuration_apply_window_config (MetaWindow *window, MetaWaylandWindowConfiguration *configuration, MetaWindowConfig *window_config); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaWaylandWindowConfiguration, + meta_wayland_window_configuration_unref) diff --git a/src/wayland/meta-wayland-xdg-session-state.c b/src/wayland/meta-wayland-xdg-session-state.c index f63923d30297a88e69ecbfd7f0b887871e421a58..d37ad7b03f6ebef1095b1bd70a15db7d1e3a0b7e 100644 --- a/src/wayland/meta-wayland-xdg-session-state.c +++ b/src/wayland/meta-wayland-xdg-session-state.c @@ -321,6 +321,7 @@ meta_wayland_xdg_session_state_save_window (MetaSessionState *state, META_WAYLAND_XDG_SESSION_STATE (state); MetaWaylandXdgToplevelState *toplevel_state; MtkRectangle rect; + MetaTileMode tile_mode; toplevel_state = meta_wayland_xdg_session_state_ensure_toplevel (xdg_session_state, @@ -331,6 +332,8 @@ meta_wayland_xdg_session_state_save_window (MetaSessionState *state, "minimized", &toplevel_state->is_minimized, NULL); + tile_mode = meta_window_config_get_tile_mode (window->config); + if (meta_window_get_maximized (window) == (META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL)) { @@ -338,12 +341,12 @@ meta_wayland_xdg_session_state_save_window (MetaSessionState *state, toplevel_state->tiled.rect = rect; } - else if (window->tile_mode == META_TILE_LEFT || - window->tile_mode == META_TILE_RIGHT) + else if (tile_mode == META_TILE_LEFT || + tile_mode == META_TILE_RIGHT) { - if (window->tile_mode == META_TILE_LEFT) + if (tile_mode == META_TILE_LEFT) toplevel_state->window_state = WINDOW_STATE_TILED_LEFT; - else if (window->tile_mode == META_TILE_RIGHT) + else if (tile_mode == META_TILE_RIGHT) toplevel_state->window_state = WINDOW_STATE_TILED_RIGHT; toplevel_state->tiled.rect = rect; @@ -413,7 +416,10 @@ meta_wayland_xdg_session_state_restore_window (MetaSessionState *state, rect = &toplevel_state->tiled.rect; target_monitor = determine_monitor_for_rect (window, rect); if (target_monitor) - window->tile_monitor_number = target_monitor->number; + { + meta_window_config_set_tile_monitor_number (window->config, + target_monitor->number); + } break; } @@ -439,6 +445,7 @@ meta_wayland_xdg_session_state_restore_window (MetaSessionState *state, { case WINDOW_STATE_NONE: case WINDOW_STATE_FLOATING: + window->placed = TRUE; break; case WINDOW_STATE_TILED_LEFT: meta_window_tile (window, META_TILE_LEFT); @@ -455,7 +462,6 @@ meta_wayland_xdg_session_state_restore_window (MetaSessionState *state, if (toplevel_state->is_minimized) meta_window_minimize (window); - window->placed = TRUE; if (meta_is_topic_enabled (META_DEBUG_SESSION_MANAGEMENT)) { diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index bed32b3fa4b5da2d8224be38fbec03522eccd0ac..f1b33c0e29c21c691ee814e277c227fdb538ff3b 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -470,7 +470,6 @@ xdg_toplevel_set_maximized (struct wl_client *client, if (!window) return; - meta_window_force_placement (window, META_PLACE_FLAG_FORCE_MOVE); meta_window_maximize (window, META_MAXIMIZE_BOTH); } @@ -887,7 +886,8 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, if (!xdg_surface_priv->configure_sent) { - MetaWaylandWindowConfiguration *configuration; + MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + g_autoptr (MetaWaylandWindowConfiguration) configuration = NULL; g_autoptr (MetaWindowConfig) window_config = NULL; int bounds_width, bounds_height, geometry_scale; MtkRectangle rect; @@ -928,9 +928,7 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, configuration, window_config); - meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); - meta_wayland_window_configuration_free (configuration); - return; + meta_window_wayland_configure (wl_window, configuration); } } diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 10e82e6b9fec70cdd4ffd5db8239b16025911933..4cf4d9f4d304eba03e93df118b165b45b3bfe8d7 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -66,13 +66,7 @@ struct _MetaWindowWayland GList *pending_configurations; gboolean has_pending_state_change; - gboolean has_last_sent_configuration; - MtkRectangle last_sent_rect; - int last_sent_rel_x; - int last_sent_rel_y; - int last_sent_geometry_scale; - MetaGravity last_sent_gravity; - + MetaWaylandWindowConfiguration *last_sent_configuration; MetaWaylandWindowConfiguration *last_acked_configuration; gboolean has_been_shown; @@ -190,44 +184,52 @@ meta_window_wayland_focus (MetaWindow *window, } } -static void +void meta_window_wayland_configure (MetaWindowWayland *wl_window, MetaWaylandWindowConfiguration *configuration) { meta_wayland_surface_configure_notify (wl_window->surface, configuration); wl_window->pending_configurations = - g_list_prepend (wl_window->pending_configurations, configuration); + g_list_prepend (wl_window->pending_configurations, + meta_wayland_window_configuration_ref (configuration)); + + g_clear_pointer (&wl_window->last_sent_configuration, + meta_wayland_window_configuration_unref); + wl_window->last_sent_configuration = + meta_wayland_window_configuration_ref (configuration); } static void surface_state_changed (MetaWindow *window) { MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - MetaWaylandWindowConfiguration *configuration; - int bounds_width; - int bounds_height; + MetaWaylandWindowConfiguration *last_sent_configuration = + wl_window->last_sent_configuration; + MetaWaylandWindowConfiguration *last_acked_configuration = + wl_window->last_acked_configuration; + g_autoptr (MetaWaylandWindowConfiguration) configuration = NULL; /* don't send notify when the window is being unmanaged */ if (window->unmanaging) return; - g_return_if_fail (wl_window->has_last_sent_configuration); + g_return_if_fail (last_sent_configuration); + + configuration = + meta_wayland_window_configuration_new_from_other (last_sent_configuration); + configuration->flags = META_MOVE_RESIZE_STATE_CHANGED; + configuration->is_suspended = wl_window->is_suspended; - if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height)) + if (last_acked_configuration && + last_acked_configuration->serial == last_sent_configuration->serial && + last_sent_configuration->is_floating) { - bounds_width = 0; - bounds_height = 0; + configuration->has_position = FALSE; + configuration->x = 0; + configuration->y = 0; } - configuration = - meta_wayland_window_configuration_new (window, - wl_window->last_sent_rect, - bounds_width, bounds_height, - wl_window->last_sent_geometry_scale, - META_MOVE_RESIZE_STATE_CHANGED, - wl_window->last_sent_gravity); - meta_window_wayland_configure (wl_window, configuration); } @@ -251,6 +253,43 @@ meta_window_wayland_grab_op_ended (MetaWindow *window, META_WINDOW_CLASS (meta_window_wayland_parent_class)->grab_op_ended (window, op); } +static gboolean +should_configure (MetaWindow *window, + MtkRectangle constrained_rect, + MetaMoveResizeFlags flags) +{ + MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + MetaWaylandWindowConfiguration *last_sent_configuration = + wl_window->last_sent_configuration; + MtkRectangle frame_rect; + + frame_rect = meta_window_config_get_rect (window->config); + + /* Initial configuration, always need to configure. */ + if (!last_sent_configuration) + return TRUE; + + /* The constrained size changed from last time, also explicit, thus need to + * configure the new size. */ + if (last_sent_configuration->has_size && + (constrained_rect.width != last_sent_configuration->width || + constrained_rect.height != last_sent_configuration->height)) + return TRUE; + + /* Something wants to resize our mapped window. */ + if (meta_wayland_surface_get_buffer (wl_window->surface) && + (constrained_rect.width != frame_rect.width || + constrained_rect.height != frame_rect.height)) + return TRUE; + + /* The state was changed, or the change was explicitly marked as a configure + * request. */ + if (flags & META_MOVE_RESIZE_STATE_CHANGED) + return TRUE; + + return FALSE; +} + static void meta_window_wayland_move_resize_internal (MetaWindow *window, MtkRectangle unconstrained_rect, @@ -262,6 +301,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, MetaMoveResizeResultFlags *result) { MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + MetaWaylandWindowConfiguration *last_sent_configuration = + wl_window->last_sent_configuration; gboolean can_move_now = FALSE; MtkRectangle configured_rect; MtkRectangle frame_rect; @@ -358,12 +399,13 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, case META_PLACEMENT_STATE_CONSTRAINED_PENDING: { if (flags & META_MOVE_RESIZE_PLACEMENT_CHANGED || - rel_x != wl_window->last_sent_rel_x || - rel_y != wl_window->last_sent_rel_y || + !last_sent_configuration || + rel_x != last_sent_configuration->rel_x || + rel_y != last_sent_configuration->rel_y || constrained_rect.width != frame_rect.width || constrained_rect.height != frame_rect.height) { - MetaWaylandWindowConfiguration *configuration; + g_autoptr (MetaWaylandWindowConfiguration) configuration = NULL; configuration = meta_wayland_window_configuration_new_relative (window, @@ -372,14 +414,18 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, configured_rect.width, configured_rect.height, geometry_scale); - meta_window_wayland_configure (wl_window, configuration); - - wl_window->last_sent_rel_x = rel_x; - wl_window->last_sent_rel_y = rel_y; - - window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED; - - can_move_now = FALSE; + if (!meta_wayland_window_configuration_is_equivalent ( + configuration, + wl_window->last_sent_configuration)) + { + meta_window_wayland_configure (wl_window, + configuration); + + window->placement.state = + META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED; + + can_move_now = FALSE; + } } else { @@ -395,20 +441,12 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, break; } } - else if (constrained_rect.width != frame_rect.width || - constrained_rect.height != frame_rect.height || - flags & META_MOVE_RESIZE_STATE_CHANGED) + else if (should_configure (window, unconstrained_rect, flags)) { - MetaWaylandWindowConfiguration *configuration; + g_autoptr (MetaWaylandWindowConfiguration) configuration = NULL; int bounds_width; int bounds_height; - if (!meta_wayland_surface_get_buffer (wl_window->surface) && - !meta_window_is_maximized (window) && - window->tile_mode == META_TILE_NONE && - !meta_window_is_fullscreen (window)) - return; - if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height)) @@ -424,8 +462,13 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, geometry_scale, flags, gravity); - meta_window_wayland_configure (wl_window, configuration); - can_move_now = FALSE; + if (!meta_wayland_window_configuration_is_equivalent ( + configuration, + wl_window->last_sent_configuration)) + { + meta_window_wayland_configure (wl_window, configuration); + can_move_now = FALSE; + } } else { @@ -433,11 +476,6 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, } } - wl_window->has_last_sent_configuration = TRUE; - wl_window->last_sent_rect = configured_rect; - wl_window->last_sent_geometry_scale = geometry_scale; - wl_window->last_sent_gravity = gravity; - if (can_move_now) { new_x = constrained_rect.x; @@ -479,6 +517,10 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, if (can_move_now && flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED) *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED; + + if (flags & META_MOVE_RESIZE_WAYLAND_CLIENT_RESIZE || + !(flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE)) + *result |= META_MOVE_RESIZE_RESULT_UPDATE_UNCONSTRAINED; } static void @@ -924,9 +966,11 @@ meta_window_wayland_finalize (GObject *object) MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (object); g_clear_pointer (&wl_window->last_acked_configuration, - meta_wayland_window_configuration_free); + meta_wayland_window_configuration_unref); + g_clear_pointer (&wl_window->last_sent_configuration, + meta_wayland_window_configuration_unref); g_list_free_full (wl_window->pending_configurations, - (GDestroyNotify) meta_wayland_window_configuration_free); + (GDestroyNotify) meta_wayland_window_configuration_unref); G_OBJECT_CLASS (meta_window_wayland_parent_class)->finalize (object); } @@ -1116,7 +1160,7 @@ acquire_acked_configuration (MetaWindowWayland *wl_window, if (is_matching_configuration) tail = g_list_delete_link (tail, l); g_list_free_full (tail, - (GDestroyNotify) meta_wayland_window_configuration_free); + (GDestroyNotify) meta_wayland_window_configuration_unref); if (is_matching_configuration) return configuration; @@ -1132,13 +1176,15 @@ meta_window_wayland_is_resize (MetaWindowWayland *wl_window, int width, int height) { + MetaWaylandWindowConfiguration *last_sent_configuration = + wl_window->last_sent_configuration; int old_width; int old_height; if (wl_window->pending_configurations) { - old_width = wl_window->last_sent_rect.width; - old_height = wl_window->last_sent_rect.height; + old_width = last_sent_configuration->width; + old_height = last_sent_configuration->height; } else { @@ -1146,7 +1192,7 @@ meta_window_wayland_is_resize (MetaWindowWayland *wl_window, meta_window_config_get_size (window->config, &old_width, &old_height); } - return !wl_window->has_last_sent_configuration || + return !last_sent_configuration || old_width != width || old_height != height; } @@ -1203,6 +1249,7 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, MetaWaylandSurfaceState *pending) { MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + gboolean has_position = FALSE; MetaDisplay *display = window->display; MetaWaylandSurface *surface = wl_window->surface; int dx, dy; @@ -1216,6 +1263,7 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, MtkRectangle frame_rect; MetaWindowActor *window_actor; MetaWaylandToplevelDrag *toplevel_drag; + MetaPlaceFlag place_flags = META_PLACE_FLAG_NONE; /* new_geom is in the logical pixel coordinate space, but MetaWindow wants its * rects to represent what in turn will end up on the stage, i.e. we need to @@ -1261,7 +1309,9 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, is_window_being_resized = (window_drag && meta_grab_op_is_resizing (meta_window_drag_get_grab_op (window_drag)) && - meta_window_drag_get_window (window_drag) == window); + (meta_window_drag_get_window (window_drag) == window || + meta_window_drag_get_window (window_drag) == + meta_window_config_get_tile_match (window->config))); frame_rect = meta_window_config_get_rect (window->config); rect = (MtkRectangle) { @@ -1287,11 +1337,34 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, } else { - if (acked_configuration->is_fullscreen) - flags |= META_MOVE_RESIZE_CONSTRAIN; + if (!acked_configuration->is_floating) + { + flags |= META_MOVE_RESIZE_CONSTRAIN; + } + else if (!window->placed) + { + place_flags |= META_PLACE_FLAG_CALCULATE; + flags |= META_MOVE_RESIZE_CONSTRAIN; + } + if (acked_configuration->has_position) - calculate_position (acked_configuration, &new_geom, &rect); + { + has_position = TRUE; + calculate_position (acked_configuration, &new_geom, &rect); + } + } + } + else + { + if (!window->placed && + meta_window_config_is_floating (window->config)) + { + place_flags |= META_PLACE_FLAG_CALCULATE; + flags |= META_MOVE_RESIZE_CONSTRAIN; } + + if (window->placed) + has_position = TRUE; } } else @@ -1300,6 +1373,9 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, calculate_position (acked_configuration, &new_geom, &rect); } + if (!has_position) + flags |= META_MOVE_RESIZE_RECT_INVALID; + toplevel_drag = get_toplevel_drag (window); if (toplevel_drag && !is_window_being_resized && !window->mapped && rect.width > 0 && rect.height > 0) @@ -1332,7 +1408,7 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, } g_clear_pointer (&wl_window->last_acked_configuration, - meta_wayland_window_configuration_free); + meta_wayland_window_configuration_unref); wl_window->last_acked_configuration = g_steal_pointer (&acked_configuration); /* Force unconstrained move when running toplevel drags */ @@ -1342,7 +1418,10 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, meta_window_actor_set_tied_to_drag (window_actor, TRUE); } - meta_window_move_resize (window, flags, rect); + meta_window_move_resize_internal (window, flags, place_flags, rect); + + if (place_flags & META_PLACE_FLAG_CALCULATE) + window->placed = TRUE; } void @@ -1350,6 +1429,7 @@ meta_window_place_with_placement_rule (MetaWindow *window, MetaPlacementRule *placement_rule) { gboolean first_placement; + MetaPlaceFlag place_flags = META_PLACE_FLAG_NONE; first_placement = !window->placement.rule; @@ -1363,14 +1443,16 @@ meta_window_place_with_placement_rule (MetaWindow *window, window->unconstrained_rect.width = placement_rule->width; window->unconstrained_rect.height = placement_rule->height; - window->calc_placement = first_placement; - meta_window_move_resize (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_PLACEMENT_CHANGED | - META_MOVE_RESIZE_CONSTRAIN), - window->unconstrained_rect); - window->calc_placement = FALSE; + if (first_placement) + place_flags |= META_PLACE_FLAG_CALCULATE; + + meta_window_move_resize_internal (window, + (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_PLACEMENT_CHANGED | + META_MOVE_RESIZE_CONSTRAIN), + place_flags, + window->unconstrained_rect); } void diff --git a/src/wayland/meta-window-wayland.h b/src/wayland/meta-window-wayland.h index cfba8905b0cf55da0a5883ca13aa9be7d68b3e9f..2e22ec4f893befcd3daf4b3c9e91f5c9df4c7cc0 100644 --- a/src/wayland/meta-window-wayland.h +++ b/src/wayland/meta-window-wayland.h @@ -54,6 +54,9 @@ MetaWaylandWindowConfiguration * meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window, uint32_t serial); +void meta_window_wayland_configure (MetaWindowWayland *wl_window, + MetaWaylandWindowConfiguration *configuration); + void meta_window_wayland_set_min_size (MetaWindow *window, int width, int height); diff --git a/src/x11/events.c b/src/x11/events.c index 4a9a43cbdedf480ff242346ac1a89f36d8ddb508..5b01ffadf92c807480a6d14332b93c7d1767b8c1 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -1537,7 +1537,11 @@ handle_other_xevent (MetaX11Display *x11_display, case ReparentNotify: { if (window && window->reparents_pending > 0) - window->reparents_pending -= 1; + { + window->reparents_pending -= 1; + if (window->reparents_pending == 0) + meta_window_queue (window, META_QUEUE_MOVE_RESIZE); + } if (event->xreparent.event == x11_display->xroot) meta_stack_tracker_reparent_event (display->stack_tracker, &event->xreparent); diff --git a/src/x11/window-props.c b/src/x11/window-props.c index af6506d6b20bb3ac18fc63b15de20a60e2d9dbdc..f83625fdad275c960ffb54076f345a28ba605fbc 100644 --- a/src/x11/window-props.c +++ b/src/x11/window-props.c @@ -44,6 +44,7 @@ #include #include "compositor/compositor-private.h" +#include "core/meta-window-config-private.h" #include "core/meta-workspace-manager-private.h" #include "core/util-private.h" #include "meta/meta-x11-group.h" @@ -794,6 +795,8 @@ reload_net_wm_state (MetaWindow *window, MetaX11Display *x11_display = window->display->x11_display; MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); + gboolean maximize_horizontally = FALSE; + gboolean maximize_vertically = FALSE; int i; if (!initial) @@ -804,8 +807,7 @@ reload_net_wm_state (MetaWindow *window, return; } - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; + meta_window_config_set_maximized_directions (window->config, FALSE, FALSE); meta_window_config_set_is_fullscreen (window->config, FALSE); priv->wm_state_modal = FALSE; priv->wm_state_skip_taskbar = FALSE; @@ -821,9 +823,9 @@ reload_net_wm_state (MetaWindow *window, while (i < value->v.atom_list.n_atoms) { if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ) - window->maximize_horizontally_after_placement = TRUE; + maximize_horizontally = TRUE; else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT) - window->maximize_vertically_after_placement = TRUE; + maximize_vertically = TRUE; else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_HIDDEN) window->minimize_after_placement = TRUE; else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_MODAL) @@ -849,6 +851,10 @@ reload_net_wm_state (MetaWindow *window, ++i; } + meta_window_config_set_maximized_directions (window->config, + maximize_horizontally, + maximize_vertically); + meta_topic (META_DEBUG_X11, "Reloaded _NET_WM_STATE for %s", window->desc); diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index ebcb97c2cc5abe4d290c370fbf7e8acdfaa943db..2f04533d317d47be929bc167ac2e73cc9c611f0a 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -688,6 +688,7 @@ meta_window_x11_initialize_state (MetaWindow *window) MtkRectangle rect; MetaMoveResizeFlags flags; MetaGravity gravity = window->size_hints.win_gravity; + MetaPlaceFlag place_flags = META_PLACE_FLAG_NONE; rect.x = window->size_hints.x; rect.y = window->size_hints.y; @@ -699,9 +700,13 @@ meta_window_x11_initialize_state (MetaWindow *window) META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_CONSTRAIN); + if (!(window->size_hints.flags & META_SIZE_HINTS_USER_POSITION)) + flags |= META_MOVE_RESIZE_RECT_INVALID; + adjust_for_gravity (window, TRUE, gravity, &rect); meta_window_client_rect_to_frame_rect (window, &rect, &rect); - meta_window_move_resize (window, flags, rect); + + meta_window_move_resize_internal (window, flags, place_flags, rect); } meta_window_x11_update_shape_region (window); @@ -1632,6 +1637,7 @@ meta_window_x11_move_resize_internal (MetaWindow *window, *result |= META_MOVE_RESIZE_RESULT_RESIZED; if (flags & META_MOVE_RESIZE_STATE_CHANGED) *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED; + *result |= META_MOVE_RESIZE_RESULT_UPDATE_UNCONSTRAINED; update_gtk_edge_constraints (window); } @@ -2369,12 +2375,12 @@ meta_window_x11_set_net_wm_state (MetaWindow *window) data[i] = x11_display->atom__NET_WM_STATE_SKIP_TASKBAR; ++i; } - if (window->maximized_horizontally) + if (meta_window_config_is_maximized_horizontally (window->config)) { data[i] = x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ; ++i; } - if (window->maximized_vertically) + if (meta_window_config_is_maximized_vertically (window->config)) { data[i] = x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT; ++i; @@ -3461,9 +3467,10 @@ meta_window_x11_client_message (MetaWindow *window, gboolean max; MetaMaximizeFlags directions = 0; - max = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && - !window->maximized_horizontally)); + max = + (action == _NET_WM_STATE_ADD || + (action == _NET_WM_STATE_TOGGLE && + !meta_window_config_is_maximized_horizontally (window->config))); if (first == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ || second == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ)