summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2015-06-30 22:36:23 -0700
committerJasper St. Pierre <jstpierre@mecheye.net>2016-04-04 14:50:56 -0700
commit8e587e2e42a6ff2ab5f538baf4db75918d9647f9 (patch)
tree72709e7aba4507484acd08e2c9809c84b1b17d1a
parent93901dc32f23f573afc9224d5620496d74bfa3f9 (diff)
downloadmutter-8e587e2e42a6ff2ab5f538baf4db75918d9647f9.tar.gz
Add "size states" which save window size information
https://bugzilla.gnome.org/show_bug.cgi?id=751857
-rw-r--r--src/core/window-private.h23
-rw-r--r--src/core/window.c269
-rw-r--r--src/wayland/meta-window-wayland.c4
-rw-r--r--src/x11/session.c8
-rw-r--r--src/x11/window-x11.c8
5 files changed, 174 insertions, 138 deletions
diff --git a/src/core/window-private.h b/src/core/window-private.h
index d76aed897..7a2e5d890 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -88,6 +88,20 @@ typedef enum
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
} MetaMoveResizeResultFlags;
+/* This contains all the "state" needed for a certain size configuration.
+ * We have three of these size configurations: normal, tiled, and
+ * maximized. The idea here is that if the user tiles a normal window,
+ * then maximizes it, we should, upon unmaximizing and untiling the window,
+ * return to a normal state. We need a way of storing this information
+ * while maximized, so we use this structure. */
+struct _MetaWindowSizeState
+{
+ guint maximized_horizontally : 1;
+ guint maximized_vertically : 1;
+ MetaRectangle rect;
+};
+typedef struct _MetaWindowSizeState MetaWindowSizeState;
+
struct _MetaWindow
{
GObject parent_instance;
@@ -393,9 +407,6 @@ struct _MetaWindow
/* The current window geometry of the window. */
MetaRectangle rect;
- /* The geometry to restore when we unmaximize. */
- MetaRectangle saved_rect;
-
/* This is the geometry the window will have if no constraints have
* applied. We use this whenever we are moving implicitly (for example,
* if we move to avoid a panel, we can snap back to this position if
@@ -435,6 +446,12 @@ struct _MetaWindow
/* Bypass compositor hints */
guint bypass_compositor;
+
+ /* This is where we store data while in another state. The information
+ * above in MetaWindow is always the current state of the window. */
+ struct {
+ MetaWindowSizeState normal, maximized;
+ } size_states;
};
struct _MetaWindowClass
diff --git a/src/core/window.c b/src/core/window.c
index 0edf2abf0..429b0795d 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -89,8 +89,6 @@ static void meta_window_force_placement (MetaWindow *window);
static void meta_window_show (MetaWindow *window);
static void meta_window_hide (MetaWindow *window);
-static void meta_window_save_rect (MetaWindow *window);
-
static void ensure_mru_position_after (MetaWindow *window,
MetaWindow *after_this_one);
@@ -872,7 +870,7 @@ _meta_window_shared_new (MetaDisplay *display,
meta_set_normal_hints (window, NULL);
/* And this is our unmaximized size */
- window->saved_rect = window->rect;
+ window->size_states.normal.rect = window->rect;
window->unconstrained_rect = window->rect;
window->depth = attrs->depth;
@@ -2606,23 +2604,23 @@ ensure_size_hints_satisfied (MetaRectangle *rect,
rect->height += ((minh - rect->height)/hinc + 1)*hinc;
}
+static inline MetaWindowSizeState *
+get_current_size_state (MetaWindow *window)
+{
+ if (META_WINDOW_MAXIMIZED (window))
+ return &window->size_states.maximized;
+ else
+ return &window->size_states.normal;
+}
+
static void
-meta_window_save_rect (MetaWindow *window)
+save_size_state (MetaWindow *window,
+ MetaWindowSizeState *size_state,
+ MetaRectangle *saved_rect)
{
- if (!(META_WINDOW_MAXIMIZED (window) || window->fullscreen))
- {
- /* save size/pos as appropriate args for move_resize */
- if (!window->maximized_horizontally)
- {
- window->saved_rect.x = window->rect.x;
- window->saved_rect.width = window->rect.width;
- }
- if (!window->maximized_vertically)
- {
- window->saved_rect.y = window->rect.y;
- window->saved_rect.height = window->rect.height;
- }
- }
+ size_state->rect = *saved_rect;
+ size_state->maximized_horizontally = window->maximized_horizontally;
+ size_state->maximized_vertically = window->maximized_vertically;
}
void
@@ -2643,10 +2641,11 @@ meta_window_maximize_internal (MetaWindow *window,
maximize_horizontally ? " horizontally" :
maximize_vertically ? " vertically" : "BUGGGGG");
- if (saved_rect != NULL)
- window->saved_rect = *saved_rect;
- else
- meta_window_save_rect (window);
+ if (!saved_rect)
+ saved_rect = &window->rect;
+
+ MetaWindowSizeState *size_state = get_current_size_state (window);
+ save_size_state (window, size_state, saved_rect);
window->maximized_horizontally =
window->maximized_horizontally || maximize_horizontally;
@@ -2924,7 +2923,7 @@ unmaximize_window_before_freeing (MetaWindow *window)
if (window->withdrawn) /* See bug #137185 */
{
- window->rect = window->saved_rect;
+ window->rect = window->size_states.normal.rect;
set_net_wm_state (window);
}
else if (window->screen->closing) /* See bug #358042 */
@@ -2937,19 +2936,83 @@ unmaximize_window_before_freeing (MetaWindow *window)
* before closing it. */
meta_window_move_resize_frame (window,
FALSE,
- window->saved_rect.x,
- window->saved_rect.y,
- window->saved_rect.width,
- window->saved_rect.height);
+ window->size_states.normal.rect.x,
+ window->size_states.normal.rect.y,
+ window->size_states.normal.rect.width,
+ window->size_states.normal.rect.height);
}
}
+static void
+meta_window_unmaximize_internal (MetaWindow *window,
+ MetaWindowSizeState *size_state)
+{
+ MetaRectangle old_frame_rect, old_buffer_rect, target_rect;
+
+ g_return_if_fail (!window->override_redirect);
+
+ meta_window_get_frame_rect (window, &old_frame_rect);
+ meta_window_get_buffer_rect (window, &old_buffer_rect);
+
+ window->maximized_horizontally = size_state->maximized_horizontally;
+ window->maximized_vertically = size_state->maximized_vertically;
+
+ /* recalc_features() will eventually clear the cached frame
+ * extents, but we need the correct frame extents in the code below,
+ * so invalidate the old frame extents manually up front.
+ */
+ meta_window_frame_size_changed (window);
+
+ target_rect = size_state->rect;
+
+ /* Window's size hints may have changed while maximized, making
+ * saved_rect invalid. #329152
+ */
+ meta_window_frame_rect_to_client_rect (window, &target_rect, &target_rect);
+ ensure_size_hints_satisfied (&target_rect, &window->size_hints);
+ meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect);
+
+ meta_window_move_resize_internal (window,
+ (META_MOVE_RESIZE_MOVE_ACTION |
+ META_MOVE_RESIZE_RESIZE_ACTION |
+ META_MOVE_RESIZE_STATE_CHANGED |
+ META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
+ NorthWestGravity,
+ target_rect);
+
+ meta_compositor_size_change_window (window->display->compositor, window,
+ META_SIZE_CHANGE_UNMAXIMIZE,
+ &old_frame_rect, &old_buffer_rect);
+
+ /* When we unmaximize, if we're doing a mouse move also we could
+ * get the window suddenly jumping to the upper left corner of
+ * the workspace, since that's where it was when the grab op
+ * started. So we need to update the grab state. We have to do
+ * it after the actual operation, as the window may have been moved
+ * by constraints.
+ */
+ if (meta_grab_op_is_moving (window->display->grab_op) &&
+ window->display->grab_window == window)
+ {
+ window->display->grab_anchor_window_pos = window->unconstrained_rect;
+ }
+
+ meta_window_recalc_features (window);
+ set_net_wm_state (window);
+ if (!window->monitor->in_fullscreen)
+ meta_screen_queue_check_fullscreen (window->screen);
+
+ g_object_freeze_notify (G_OBJECT (window));
+ g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]);
+ g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]);
+ g_object_thaw_notify (G_OBJECT (window));
+}
+
void
meta_window_unmaximize (MetaWindow *window,
MetaMaximizeFlags directions)
{
gboolean unmaximize_horizontally, unmaximize_vertically;
- MetaRectangle new_rect;
g_return_if_fail (!window->override_redirect);
@@ -2958,45 +3021,46 @@ meta_window_unmaximize (MetaWindow *window,
unmaximize_vertically = directions & META_MAXIMIZE_VERTICAL;
g_assert (unmaximize_horizontally || unmaximize_vertically);
- /* 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))
+ MetaWindowSizeState *size_state;
+ size_state = &window->size_states.normal;
+
+ /* Special-case unmaximizing both directions to restoring the
+ * last state. This makes the unmaximize buttons go back to the
+ * tiled state... */
+ if (META_WINDOW_MAXIMIZED (window) && directions == META_MAXIMIZE_BOTH)
{
+ meta_window_unmaximize_internal (window, size_state);
+ }
+ else if ((unmaximize_horizontally && window->maximized_horizontally) ||
+ (unmaximize_vertically && window->maximized_vertically))
+ {
+ MetaWindowSizeState new_size_state;
MetaRectangle *desired_rect;
MetaRectangle target_rect;
MetaRectangle work_area;
- MetaRectangle old_frame_rect, old_buffer_rect;
meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area);
- meta_window_get_frame_rect (window, &old_frame_rect);
- meta_window_get_buffer_rect (window, &old_buffer_rect);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Unmaximizing %s%s\n",
- window->desc,
- unmaximize_horizontally && unmaximize_vertically ? "" :
- unmaximize_horizontally ? " horizontally" :
- unmaximize_vertically ? " vertically" : "BUGGGGG");
-
- window->maximized_horizontally =
- window->maximized_horizontally && !unmaximize_horizontally;
- window->maximized_vertically =
- window->maximized_vertically && !unmaximize_vertically;
-
- /* recalc_features() will eventually clear the cached frame
- * extents, but we need the correct frame extents in the code below,
- * so invalidate the old frame extents manually up front.
- */
- meta_window_frame_size_changed (window);
- desired_rect = &window->saved_rect;
+ new_size_state.maximized_horizontally = window->maximized_horizontally && !unmaximize_horizontally;
+ new_size_state.maximized_vertically = window->maximized_vertically && !unmaximize_vertically;
/* Unmaximize to the saved_rect position in the direction(s)
* being unmaximized.
*/
- target_rect = old_frame_rect;
+ target_rect = window->rect;
+
+ desired_rect = &size_state->rect;
+
+ 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;
+ }
/* 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
@@ -3008,71 +3072,21 @@ meta_window_unmaximize (MetaWindow *window,
if (desired_rect->width > desired_rect->height)
{
float aspect = (float)desired_rect->height / (float)desired_rect->width;
- desired_rect->width = MAX (work_area.width * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_width);
- desired_rect->height = MAX (desired_rect->width * aspect, window->size_hints.min_height);
+ target_rect.width = MAX (work_area.width * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_width);
+ target_rect.height = MAX (desired_rect->width * aspect, window->size_hints.min_height);
}
else
{
float aspect = (float)desired_rect->width / (float)desired_rect->height;
- desired_rect->height = MAX (work_area.height * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_height);
- desired_rect->width = MAX (desired_rect->height * aspect, window->size_hints.min_width);
+ target_rect.height = MAX (work_area.height * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_height);
+ target_rect.width = MAX (desired_rect->height * aspect, window->size_hints.min_width);
}
}
- 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;
- }
+ new_size_state.rect = target_rect;
- /* Window's size hints may have changed while maximized, making
- * saved_rect invalid. #329152
- */
- meta_window_frame_rect_to_client_rect (window, &target_rect, &target_rect);
- ensure_size_hints_satisfied (&target_rect, &window->size_hints);
- meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect);
-
- meta_window_move_resize_internal (window,
- (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION |
- META_MOVE_RESIZE_STATE_CHANGED |
- META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
- NorthWestGravity,
- target_rect);
-
- meta_window_get_frame_rect (window, &new_rect);
- meta_compositor_size_change_window (window->display->compositor, window,
- META_SIZE_CHANGE_UNMAXIMIZE,
- &old_frame_rect, &old_buffer_rect);
-
- /* When we unmaximize, if we're doing a mouse move also we could
- * get the window suddenly jumping to the upper left corner of
- * the workspace, since that's where it was when the grab op
- * started. So we need to update the grab state. We have to do
- * it after the actual operation, as the window may have been moved
- * by constraints.
- */
- if (meta_grab_op_is_moving (window->display->grab_op) &&
- window->display->grab_window == window)
- {
- window->display->grab_anchor_window_pos = window->unconstrained_rect;
- }
-
- meta_window_recalc_features (window);
- set_net_wm_state (window);
- if (!window->monitor->in_fullscreen)
- meta_screen_queue_check_fullscreen (window->screen);
+ meta_window_unmaximize_internal (window, &new_size_state);
}
-
- g_object_freeze_notify (G_OBJECT (window));
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]);
- g_object_thaw_notify (G_OBJECT (window));
}
void
@@ -3126,7 +3140,8 @@ meta_window_make_fullscreen_internal (MetaWindow *window)
meta_window_unshade (window, timestamp);
}
- meta_window_save_rect (window);
+ MetaWindowSizeState *size_state = get_current_size_state (window);
+ save_size_state (window, size_state, &window->rect);
window->fullscreen = TRUE;
@@ -3186,7 +3201,9 @@ meta_window_unmake_fullscreen (MetaWindow *window)
"Unfullscreening %s\n", window->desc);
window->fullscreen = FALSE;
- target_rect = window->saved_rect;
+
+ MetaWindowSizeState *size_state = get_current_size_state (window);
+ target_rect = size_state->rect;
meta_window_frame_size_changed (window);
meta_window_get_frame_rect (window, &old_frame_rect);
@@ -3736,8 +3753,8 @@ meta_window_move_between_rects (MetaWindow *window,
window->unconstrained_rect.x = new_area->x + rel_x * scale_x;
window->unconstrained_rect.y = new_area->y + rel_y * scale_y;
- window->saved_rect.x = window->unconstrained_rect.x;
- window->saved_rect.y = window->unconstrained_rect.y;
+ window->size_states.normal.rect.x = window->unconstrained_rect.x;
+ window->size_states.normal.rect.y = window->unconstrained_rect.y;
meta_window_move_resize_now (window);
}
@@ -5532,7 +5549,7 @@ update_move (MetaWindow *window,
((double)(x - display->grab_initial_window_pos.x)) /
((double)display->grab_initial_window_pos.width);
- display->grab_initial_window_pos.x = x - window->saved_rect.width * prop;
+ display->grab_initial_window_pos.x = x - window->size_states.normal.rect.width * prop;
/* If we started dragging the window from above the top of the window,
* pretend like we started dragging from the middle of the titlebar
@@ -5544,10 +5561,10 @@ update_move (MetaWindow *window,
display->grab_anchor_root_y = display->grab_initial_window_pos.y + titlebar_rect.height / 2;
}
- window->saved_rect.x = display->grab_initial_window_pos.x;
- window->saved_rect.y = display->grab_initial_window_pos.y;
+ window->size_states.normal.rect.x = display->grab_initial_window_pos.x;
+ window->size_states.normal.rect.y = display->grab_initial_window_pos.y;
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
+ meta_window_unmaximize_internal (window, &window->size_states.normal);
return;
}
@@ -5577,17 +5594,17 @@ update_move (MetaWindow *window,
*/
if (wmonitor->number != monitor)
{
- window->saved_rect.x = work_area.x;
- window->saved_rect.y = work_area.y;
+ window->size_states.normal.rect.x = work_area.x;
+ window->size_states.normal.rect.y = work_area.y;
if (window->frame)
{
- window->saved_rect.x += window->frame->child_x;
- window->saved_rect.y += window->frame->child_y;
+ window->size_states.normal.rect.x += window->frame->child_x;
+ window->size_states.normal.rect.y += window->frame->child_y;
}
- window->unconstrained_rect.x = window->saved_rect.x;
- window->unconstrained_rect.y = window->saved_rect.y;
+ window->unconstrained_rect.x = window->size_states.normal.rect.x;
+ window->unconstrained_rect.y = window->size_states.normal.rect.y;
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index f38e4b984..e103b50de 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -363,7 +363,9 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
/* Window size. */
scale_rect_size (&window->rect, scale_factor);
scale_rect_size (&window->unconstrained_rect, scale_factor);
- scale_rect_size (&window->saved_rect, scale_factor);
+ scale_rect_size (&window->size_states.normal.rect, scale_factor);
+ scale_rect_size (&window->size_states.tiled.rect, scale_factor);
+ scale_rect_size (&window->size_states.maximized.rect, scale_factor);
/* Window geometry offset (XXX: Need a better place, see
* meta_window_wayland_move_resize). */
diff --git a/src/x11/session.c b/src/x11/session.c
index 13cf76429..f4e80b27d 100644
--- a/src/x11/session.c
+++ b/src/x11/session.c
@@ -965,10 +965,10 @@ save_state (void)
{
fprintf (outfile,
" <maximized saved_x=\"%d\" saved_y=\"%d\" saved_width=\"%d\" saved_height=\"%d\"/>\n",
- window->saved_rect.x,
- window->saved_rect.y,
- window->saved_rect.width,
- window->saved_rect.height);
+ window->size_states.normal.rect.x,
+ window->size_states.normal.rect.y,
+ window->size_states.normal.rect.width,
+ window->size_states.normal.rect.height);
}
/* Gravity */
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index 3d47f0d4e..1bdb5d5eb 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -413,10 +413,10 @@ meta_window_apply_session_info (MetaWindow *window,
info->saved_rect.height,
window->desc);
- window->saved_rect.x = info->saved_rect.x;
- window->saved_rect.y = info->saved_rect.y;
- window->saved_rect.width = info->saved_rect.width;
- window->saved_rect.height = info->saved_rect.height;
+ window->size_states.normal.rect.x = info->saved_rect.x;
+ window->size_states.normal.rect.y = info->saved_rect.y;
+ window->size_states.normal.rect.width = info->saved_rect.width;
+ window->size_states.normal.rect.height = info->saved_rect.height;
}
}
}