Implement a generic "size change" mechanism

A much less hacky version of maximize / unmaximize is reimplemented
in terms of this, but it could also eventually be used for fullscreen /
unfullscreen, and tile / untile.
This commit is contained in:
Jasper St. Pierre 2015-07-05 21:08:08 -07:00
parent 7de1f3a7be
commit 9f04c58ffe
10 changed files with 99 additions and 240 deletions

View File

@ -37,11 +37,6 @@
* compositor needs to delay hiding the windows until the switch
* workspace animation completes.
*
* meta_compositor_maximize_window() and meta_compositor_unmaximize_window()
* are transitions within the visible state. The window is resized __before__
* the call, so it may be necessary to readjust the display based on the
* old_rect to start the animation.
*
* # Containers #
*
* There's two containers in the stage that are used to place window actors, here
@ -769,23 +764,14 @@ meta_compositor_hide_window (MetaCompositor *compositor,
}
void
meta_compositor_maximize_window (MetaCompositor *compositor,
meta_compositor_size_change_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_maximize (window_actor, old_rect, new_rect);
}
void
meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
meta_window_actor_size_change (window_actor, META_SIZE_CHANGE_MAXIMIZE, old_frame_rect, old_buffer_rect);
}
void

View File

@ -202,61 +202,26 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
return retval;
}
/*
* The public method that the compositor hooks into for maximize and unmaximize
* events.
*
* Returns TRUE if the plugin handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out.
*/
gboolean
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
meta_plugin_manager_event_size_change (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor,
MetaPluginEffect event,
gint target_x,
gint target_y,
gint target_width,
gint target_height)
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = plugin_mgr->compositor->display;
gboolean retval = FALSE;
if (display->display_opening)
return FALSE;
switch (event)
{
case META_PLUGIN_MAXIMIZE:
if (klass->maximize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
klass->maximize (plugin, actor,
target_x, target_y,
target_width, target_height);
}
break;
case META_PLUGIN_UNMAXIMIZE:
if (klass->unmaximize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
klass->unmaximize (plugin, actor,
target_x, target_y,
target_width, target_height);
}
break;
default:
g_warning ("Incorrect handler called for event %d", event);
}
if (!klass->size_change)
return FALSE;
return retval;
meta_plugin_manager_kill_window_effects (plugin_mgr, actor);
klass->size_change (plugin, actor, which_change, old_frame_rect, old_buffer_rect);
return TRUE;
}
/*

View File

@ -27,13 +27,13 @@
#include <meta/meta-plugin.h>
typedef enum {
META_PLUGIN_NONE,
META_PLUGIN_MINIMIZE,
META_PLUGIN_MAXIMIZE,
META_PLUGIN_UNMAXIMIZE,
META_PLUGIN_MAP,
META_PLUGIN_DESTROY,
META_PLUGIN_SWITCH_WORKSPACE,
META_PLUGIN_UNMINIMIZE,
META_PLUGIN_SIZE_CHANGE,
} MetaPluginEffect;
/**
@ -50,13 +50,11 @@ gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
MetaWindowActor *actor,
MetaPluginEffect event);
gboolean meta_plugin_manager_event_maximize (MetaPluginManager *mgr,
gboolean meta_plugin_manager_event_size_change (MetaPluginManager *mgr,
MetaWindowActor *actor,
MetaPluginEffect event,
gint target_x,
gint target_y,
gint target_width,
gint target_height);
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
gboolean meta_plugin_manager_switch_workspace (MetaPluginManager *mgr,
gint from,

View File

@ -118,17 +118,10 @@ meta_plugin_unminimize_completed (MetaPlugin *plugin,
}
void
meta_plugin_maximize_completed (MetaPlugin *plugin,
meta_plugin_size_change_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAXIMIZE);
}
void
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMAXIMIZE);
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_SIZE_CHANGE);
}
void

View File

@ -19,12 +19,10 @@ void meta_window_actor_show (MetaWindowActor *self,
void meta_window_actor_hide (MetaWindowActor *self,
MetaCompEffect effect);
void meta_window_actor_maximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_size_change (MetaWindowActor *self,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
void meta_window_actor_process_x11_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);

View File

@ -87,8 +87,7 @@ struct _MetaWindowActorPrivate
*/
gint minimize_in_progress;
gint unminimize_in_progress;
gint maximize_in_progress;
gint unmaximize_in_progress;
gint size_change_in_progress;
gint map_in_progress;
gint destroy_in_progress;
@ -1036,8 +1035,7 @@ gboolean
meta_window_actor_effect_in_progress (MetaWindowActor *self)
{
return (self->priv->minimize_in_progress ||
self->priv->maximize_in_progress ||
self->priv->unmaximize_in_progress ||
self->priv->size_change_in_progress ||
self->priv->map_in_progress ||
self->priv->destroy_in_progress);
}
@ -1048,8 +1046,7 @@ is_freeze_thaw_effect (MetaPluginEffect event)
switch (event)
{
case META_PLUGIN_DESTROY:
case META_PLUGIN_MAXIMIZE:
case META_PLUGIN_UNMAXIMIZE:
case META_PLUGIN_SIZE_CHANGE:
return TRUE;
break;
default:
@ -1068,6 +1065,8 @@ start_simple_effect (MetaWindowActor *self,
switch (event)
{
case META_PLUGIN_NONE:
return FALSE;
case META_PLUGIN_MINIMIZE:
counter = &priv->minimize_in_progress;
break;
@ -1080,8 +1079,7 @@ start_simple_effect (MetaWindowActor *self,
case META_PLUGIN_DESTROY:
counter = &priv->destroy_in_progress;
break;
case META_PLUGIN_UNMAXIMIZE:
case META_PLUGIN_MAXIMIZE:
case META_PLUGIN_SIZE_CHANGE:
case META_PLUGIN_SWITCH_WORKSPACE:
g_assert_not_reached ();
break;
@ -1134,6 +1132,8 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
switch (event)
{
case META_PLUGIN_NONE:
break;
case META_PLUGIN_MINIMIZE:
{
priv->minimize_in_progress--;
@ -1176,20 +1176,12 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
priv->destroy_in_progress = 0;
}
break;
case META_PLUGIN_UNMAXIMIZE:
priv->unmaximize_in_progress--;
if (priv->unmaximize_in_progress < 0)
case META_PLUGIN_SIZE_CHANGE:
priv->size_change_in_progress--;
if (priv->size_change_in_progress < 0)
{
g_warning ("Error in unmaximize accounting.");
priv->unmaximize_in_progress = 0;
}
break;
case META_PLUGIN_MAXIMIZE:
priv->maximize_in_progress--;
if (priv->maximize_in_progress < 0)
{
g_warning ("Error in maximize accounting.");
priv->maximize_in_progress = 0;
g_warning ("Error in size change accounting.");
priv->size_change_in_progress = 0;
}
break;
case META_PLUGIN_SWITCH_WORKSPACE:
@ -1315,14 +1307,13 @@ meta_window_actor_show (MetaWindowActor *self,
event = META_PLUGIN_UNMINIMIZE;
break;
case META_COMP_EFFECT_NONE:
event = META_PLUGIN_NONE;
break;
case META_COMP_EFFECT_DESTROY:
case META_COMP_EFFECT_MINIMIZE:
default:
g_assert_not_reached();
}
if (compositor->switch_workspace_in_progress ||
event == 0 ||
!start_simple_effect (self, event))
{
clutter_actor_show (CLUTTER_ACTOR (self));
@ -1335,7 +1326,7 @@ meta_window_actor_hide (MetaWindowActor *self,
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
MetaPluginEffect event = 0;
MetaPluginEffect event;
g_return_if_fail (priv->visible);
@ -1357,70 +1348,32 @@ meta_window_actor_hide (MetaWindowActor *self,
event = META_PLUGIN_MINIMIZE;
break;
case META_COMP_EFFECT_NONE:
event = META_PLUGIN_NONE;
break;
case META_COMP_EFFECT_UNMINIMIZE:
case META_COMP_EFFECT_CREATE:
default:
g_assert_not_reached();
}
if (event == 0 ||
!start_simple_effect (self, event))
if (!start_simple_effect (self, event))
clutter_actor_hide (CLUTTER_ACTOR (self));
}
void
meta_window_actor_maximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
meta_window_actor_size_change (MetaWindowActor *self,
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect)
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
/* The window has already been resized (in order to compute new_rect),
* which by side effect caused the actor to be resized. Restore it to the
* old size and position */
clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
self->priv->maximize_in_progress++;
self->priv->size_change_in_progress++;
meta_window_actor_freeze (self);
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
self,
META_PLUGIN_MAXIMIZE,
new_rect->x, new_rect->y,
new_rect->width, new_rect->height))
if (!meta_plugin_manager_event_size_change (compositor->plugin_mgr, self,
which_change, old_frame_rect, old_buffer_rect))
{
self->priv->maximize_in_progress--;
meta_window_actor_thaw (self);
}
}
void
meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
/* The window has already been resized (in order to compute new_rect),
* which by side effect caused the actor to be resized. Restore it to the
* old size and position */
clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
self->priv->unmaximize_in_progress++;
meta_window_actor_freeze (self);
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
self,
META_PLUGIN_UNMAXIMIZE,
new_rect->x, new_rect->y,
new_rect->width, new_rect->height))
{
self->priv->unmaximize_in_progress--;
self->priv->size_change_in_progress--;
meta_window_actor_thaw (self);
}
}

View File

@ -78,6 +78,7 @@ typedef enum
META_MOVE_RESIZE_RESIZE_ACTION = 1 << 3,
META_MOVE_RESIZE_WAYLAND_RESIZE = 1 << 4,
META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR = 1 << 6,
} MetaMoveResizeFlags;
typedef enum

View File

@ -2664,8 +2664,6 @@ meta_window_maximize (MetaWindow *window,
{
MetaRectangle *saved_rect = NULL;
gboolean maximize_horizontally, maximize_vertically;
MetaRectangle old_rect;
MetaRectangle new_rect;
g_return_if_fail (!window->override_redirect);
@ -2715,18 +2713,23 @@ meta_window_maximize (MetaWindow *window,
directions,
saved_rect);
meta_window_get_frame_rect (window, &old_rect);
MetaRectangle old_frame_rect, old_buffer_rect, new_rect;
meta_window_get_frame_rect (window, &old_frame_rect);
meta_window_get_buffer_rect (window, &old_buffer_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_MOVE_ACTION |
META_MOVE_RESIZE_RESIZE_ACTION |
META_MOVE_RESIZE_STATE_CHANGED |
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
NorthWestGravity,
window->unconstrained_rect);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_maximize_window (window->display->compositor,
window,
&old_rect,
&new_rect);
meta_compositor_size_change_window (window->display->compositor, window,
META_SIZE_CHANGE_MAXIMIZE,
&old_frame_rect, &old_buffer_rect);
}
}
@ -2886,8 +2889,6 @@ void
meta_window_tile (MetaWindow *window)
{
MetaMaximizeFlags directions;
MetaRectangle old_rect;
MetaRectangle new_rect;
/* Don't do anything if no tiling is requested */
if (window->tile_mode == META_TILE_NONE)
@ -2901,16 +2902,8 @@ meta_window_tile (MetaWindow *window)
meta_window_maximize_internal (window, directions, NULL);
meta_screen_update_tile_preview (window->screen, FALSE);
meta_window_get_frame_rect (window, &old_rect);
meta_window_move_resize_now (window);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_maximize_window (window->display->compositor,
window,
&old_rect,
&new_rect);
if (window->frame)
meta_frame_queue_draw (window->frame);
}
@ -3004,10 +2997,11 @@ meta_window_unmaximize (MetaWindow *window,
MetaRectangle *desired_rect;
MetaRectangle target_rect;
MetaRectangle work_area;
MetaRectangle old_rect;
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_rect);
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",
@ -3032,7 +3026,7 @@ meta_window_unmaximize (MetaWindow *window,
/* Unmaximize to the saved_rect position in the direction(s)
* being unmaximized.
*/
target_rect = old_rect;
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
@ -3074,15 +3068,17 @@ meta_window_unmaximize (MetaWindow *window,
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_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_unmaximize_window (window->display->compositor,
window,
&old_rect,
&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
@ -3691,7 +3687,7 @@ meta_window_move_resize_internal (MetaWindow *window,
{
window->unconstrained_rect = unconstrained_rect;
if (window->known_to_compositor)
if (window->known_to_compositor && !(flags & META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR))
meta_compositor_sync_window_geometry (window->display->compositor,
window,
did_placement);

View File

@ -54,6 +54,11 @@ typedef enum
META_COMP_EFFECT_NONE
} MetaCompEffect;
typedef enum {
META_SIZE_CHANGE_MAXIMIZE,
META_SIZE_CHANGE_UNMAXIMIZE,
} MetaSizeChange;
MetaCompositor *meta_compositor_new (MetaDisplay *display);
void meta_compositor_destroy (MetaCompositor *compositor);
@ -89,14 +94,11 @@ void meta_compositor_switch_workspace (MetaCompositor *compositor,
MetaWorkspace *to,
MetaMotionDirection direction);
void meta_compositor_maximize_window (MetaCompositor *compositor,
void meta_compositor_size_change_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaWindow *window,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,

View File

@ -55,8 +55,7 @@ struct _MetaPlugin
* MetaPluginClass:
* @start: virtual function called when the compositor starts managing a screen
* @minimize: virtual function called when a window is minimized
* @maximize: virtual function called when a window is maximized
* @unmaximize: virtual function called when a window is unmaximized
* @size_change: virtual function called when a window changes size to/from constraints
* @map: virtual function called when a window is mapped
* @destroy: virtual function called when a window is destroyed
* @switch_workspace: virtual function called when the user switches to another
@ -103,39 +102,11 @@ struct _MetaPluginClass
void (*unminimize) (MetaPlugin *plugin,
MetaWindowActor *actor);
/**
* MetaPluginClass::maximize:
* @actor: a #MetaWindowActor
* @x: target X coordinate
* @y: target Y coordinate
* @width: target width
* @height: target height
*
* Virtual function called when the window represented by @actor is maximized.
*/
void (*maximize) (MetaPlugin *plugin,
void (*size_change) (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
/**
* MetaPluginClass::unmaximize:
* @actor: a #MetaWindowActor
* @x: target X coordinate
* @y: target Y coordinate
* @width: target width
* @height: target height
*
* Virtual function called when the window represented by @actor is unmaximized.
*/
void (*unmaximize) (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
MetaSizeChange which_change,
MetaRectangle *old_frame_rect,
MetaRectangle *old_buffer_rect);
/**
* MetaPluginClass::map:
@ -386,11 +357,7 @@ meta_plugin_unminimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_maximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
meta_plugin_size_change_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void