mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
Move window repair and reshape to a paint function
Add a paint function that checks all windows for repair and shape updates; this: - simplifies the logic for when a window needs to be repaired - avoids duplicate work when we get multiple damage effects - avoids the need to look ahead in the event queue Instead of relying on repair to implicitly resize the MutterWindow actor, set the size explicitly when the core code updates the geometry. (This is needed because we haven't repaired yet when we start an animation, and the animation may depend on the size to, e.g., rescale from the center.) Because the core geometry update happens before we start maximize/unmaximize effects we need to work around this by passing both the old and new geometry to the compositor. http://bugzilla.gnome.org/show_bug.cgi?id=587251
This commit is contained in:
parent
bc9a2cc92a
commit
9244f0f113
@ -19,6 +19,7 @@ struct _MetaCompositor
|
||||
Atom atom_x_root_pixmap;
|
||||
Atom atom_x_set_root;
|
||||
Atom atom_net_wm_window_opacity;
|
||||
guint repaint_func_id;
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
|
@ -142,6 +142,7 @@ mutter_switch_workspace_completed (MetaScreen *screen)
|
||||
void
|
||||
meta_compositor_destroy (MetaCompositor *compositor)
|
||||
{
|
||||
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -704,27 +705,29 @@ meta_compositor_unminimize_window (MetaCompositor *compositor,
|
||||
void
|
||||
meta_compositor_maximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect)
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_maximize_window\n");
|
||||
if (!cw)
|
||||
return;
|
||||
|
||||
mutter_window_maximize (cw, window_rect);
|
||||
mutter_window_maximize (cw, old_rect, new_rect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect)
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
|
||||
if (!cw)
|
||||
return;
|
||||
|
||||
mutter_window_unmaximize (cw, window_rect);
|
||||
mutter_window_unmaximize (cw, old_rect, new_rect);
|
||||
}
|
||||
|
||||
void
|
||||
@ -976,6 +979,35 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
pre_paint_windows (MetaCompScreen *info)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = info->windows; l; l = l->next)
|
||||
mutter_window_pre_paint (l->data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mutter_repaint_func (gpointer data)
|
||||
{
|
||||
MetaCompositor *compositor = data;
|
||||
GSList *screens = meta_display_get_screens (compositor->display);
|
||||
GSList *l;
|
||||
|
||||
for (l = screens; l; l = l->next)
|
||||
{
|
||||
MetaScreen *screen = l->data;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
if (!info)
|
||||
continue;
|
||||
|
||||
pre_paint_windows (info);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MetaCompositor *
|
||||
meta_compositor_new (MetaDisplay *display)
|
||||
{
|
||||
@ -1006,6 +1038,10 @@ meta_compositor_new (MetaDisplay *display)
|
||||
compositor->atom_x_set_root = atoms[1];
|
||||
compositor->atom_net_wm_window_opacity = atoms[2];
|
||||
|
||||
compositor->repaint_func_id = clutter_threads_add_repaint_func (mutter_repaint_func,
|
||||
compositor,
|
||||
NULL);
|
||||
|
||||
return compositor;
|
||||
}
|
||||
|
||||
|
@ -14,12 +14,16 @@ void mutter_window_minimize (MutterWindow *cw);
|
||||
void mutter_window_destroy (MutterWindow *cw);
|
||||
|
||||
void mutter_window_maximize (MutterWindow *cw,
|
||||
MetaRectangle *window_rect);
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void mutter_window_unmaximize (MutterWindow *cw,
|
||||
MetaRectangle *window_rect);
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void mutter_window_process_damage (MutterWindow *cw,
|
||||
XDamageNotifyEvent *event);
|
||||
void mutter_window_pre_paint (MutterWindow *self);
|
||||
|
||||
gboolean mutter_window_effect_in_progress (MutterWindow *cw,
|
||||
gboolean include_destroy);
|
||||
void mutter_window_sync_actor_position (MutterWindow *cw);
|
||||
|
@ -61,6 +61,8 @@ struct _MutterWindowPrivate
|
||||
guint needs_map : 1;
|
||||
guint needs_unmap : 1;
|
||||
guint needs_repair : 1;
|
||||
guint needs_reshape : 1;
|
||||
guint size_changed : 1;
|
||||
|
||||
guint needs_destroy : 1;
|
||||
|
||||
@ -94,7 +96,6 @@ static void mutter_window_detach (MutterWindow *self);
|
||||
static gboolean mutter_window_has_shadow (MutterWindow *self);
|
||||
|
||||
|
||||
static void repair_win (MutterWindow *self);
|
||||
static gboolean is_shaped (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
/*
|
||||
@ -739,6 +740,27 @@ mutter_window_effect_in_progress (MutterWindow *self,
|
||||
(include_destroy && self->priv->destroy_in_progress));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_window_mark_for_repair (MutterWindow *self)
|
||||
{
|
||||
MutterWindowPrivate *priv = self->priv;
|
||||
|
||||
priv->needs_repair = TRUE;
|
||||
|
||||
if (priv->attrs.map_state == IsUnmapped)
|
||||
return;
|
||||
|
||||
/* This will cause the compositor paint function to be run
|
||||
* if the actor is visible or a clone of the actor is visible.
|
||||
* if the actor isn't visible in any way, then we don't
|
||||
* need to repair the window anyways, and can wait until
|
||||
* the stage is redrawn for some other reason
|
||||
*
|
||||
* The compositor paint function repairs all windows.
|
||||
*/
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
void
|
||||
mutter_window_effect_completed (MutterWindow *self,
|
||||
gulong event)
|
||||
@ -839,8 +861,7 @@ mutter_window_effect_completed (MutterWindow *self,
|
||||
MetaRectangle rect;
|
||||
meta_window_get_outer_rect (priv->window, &rect);
|
||||
clutter_actor_set_position (actor, rect.x, rect.y);
|
||||
mutter_window_detach (self);
|
||||
repair_win (self);
|
||||
clutter_actor_set_size (actor, rect.width,rect.height);
|
||||
effect_done = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -857,8 +878,7 @@ mutter_window_effect_completed (MutterWindow *self,
|
||||
MetaRectangle rect;
|
||||
meta_window_get_outer_rect (priv->window, &rect);
|
||||
clutter_actor_set_position (actor, rect.x, rect.y);
|
||||
mutter_window_detach (self);
|
||||
repair_win (self);
|
||||
clutter_actor_set_size (actor, rect.width, rect.height);
|
||||
effect_done = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -895,11 +915,22 @@ mutter_window_effect_completed (MutterWindow *self,
|
||||
return;
|
||||
}
|
||||
|
||||
if (effect_done &&
|
||||
(priv->needs_repair || priv->needs_reshape))
|
||||
{
|
||||
/* Make sure that pre_paint function gets called */
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called to drop our reference to a window backing pixmap that we
|
||||
* previously obtained with XCompositeNameWindowPixmap. We do this
|
||||
* when the window is unmapped or when we want to update to a new
|
||||
* pixmap for a new size.
|
||||
*/
|
||||
static void
|
||||
mutter_window_detach (MutterWindow *self)
|
||||
{
|
||||
@ -913,6 +944,7 @@ mutter_window_detach (MutterWindow *self)
|
||||
|
||||
XFreePixmap (xdisplay, priv->back_pixmap);
|
||||
priv->back_pixmap = None;
|
||||
mutter_window_mark_for_repair (self);
|
||||
}
|
||||
|
||||
void
|
||||
@ -990,7 +1022,10 @@ mutter_window_sync_actor_position (MutterWindow *self)
|
||||
|
||||
if (priv->attrs.width != window_rect.width ||
|
||||
priv->attrs.height != window_rect.height)
|
||||
mutter_window_detach (self);
|
||||
{
|
||||
priv->size_changed = TRUE;
|
||||
mutter_window_mark_for_repair (self);
|
||||
}
|
||||
|
||||
/* XXX deprecated: please use meta_window_get_outer_rect instead */
|
||||
priv->attrs.width = window_rect.width;
|
||||
@ -1002,7 +1037,9 @@ mutter_window_sync_actor_position (MutterWindow *self)
|
||||
return;
|
||||
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (self),
|
||||
window_rect.x, window_rect.y);
|
||||
window_rect.x, window_rect.y);
|
||||
clutter_actor_set_size (CLUTTER_ACTOR (self),
|
||||
window_rect.width, window_rect.height);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1022,13 +1059,7 @@ mutter_window_map (MutterWindow *self)
|
||||
|
||||
priv->attrs.map_state = IsViewable;
|
||||
|
||||
/*
|
||||
* Now repair the window; this ensures that the actor is correctly sized
|
||||
* before we run any effects on it.
|
||||
*/
|
||||
priv->needs_map = FALSE;
|
||||
mutter_window_detach (self);
|
||||
repair_win (self);
|
||||
mutter_window_mark_for_repair (self);
|
||||
|
||||
/*
|
||||
* Make sure the position is set correctly (we might have got moved while
|
||||
@ -1131,18 +1162,25 @@ mutter_window_minimize (MutterWindow *self)
|
||||
|
||||
void
|
||||
mutter_window_maximize (MutterWindow *self,
|
||||
MetaRectangle *window_rect)
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
|
||||
|
||||
/* 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++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!mutter_plugin_manager_event_maximize (info->plugin_mgr,
|
||||
self,
|
||||
MUTTER_PLUGIN_MAXIMIZE,
|
||||
window_rect->x, window_rect->y,
|
||||
window_rect->width, window_rect->height))
|
||||
new_rect->x, new_rect->y,
|
||||
new_rect->width, new_rect->height))
|
||||
|
||||
{
|
||||
self->priv->maximize_in_progress--;
|
||||
@ -1151,18 +1189,25 @@ mutter_window_maximize (MutterWindow *self,
|
||||
|
||||
void
|
||||
mutter_window_unmaximize (MutterWindow *self,
|
||||
MetaRectangle *window_rect)
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
|
||||
|
||||
/* 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++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!mutter_plugin_manager_event_maximize (info->plugin_mgr,
|
||||
self,
|
||||
MUTTER_PLUGIN_UNMAXIMIZE,
|
||||
window_rect->x, window_rect->y,
|
||||
window_rect->width, window_rect->height))
|
||||
new_rect->x, new_rect->y,
|
||||
new_rect->width, new_rect->height))
|
||||
{
|
||||
self->priv->unmaximize_in_progress--;
|
||||
}
|
||||
@ -1202,8 +1247,7 @@ mutter_window_new (MetaWindow *window)
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (self),
|
||||
priv->attrs.x, priv->attrs.y);
|
||||
mutter_window_sync_actor_position (self);
|
||||
|
||||
/* Hang our compositor window state off the MetaWindow for fast retrieval */
|
||||
meta_window_set_compositor_private (window, G_OBJECT (self));
|
||||
@ -1230,7 +1274,7 @@ mutter_window_new (MetaWindow *window)
|
||||
}
|
||||
|
||||
static void
|
||||
repair_win (MutterWindow *self)
|
||||
check_needs_repair (MutterWindow *self)
|
||||
{
|
||||
MutterWindowPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
@ -1241,12 +1285,24 @@ repair_win (MutterWindow *self)
|
||||
Window xwindow = priv->xwindow;
|
||||
gboolean full = FALSE;
|
||||
|
||||
if (!priv->needs_repair)
|
||||
return;
|
||||
|
||||
if (priv->attrs.map_state == IsUnmapped)
|
||||
return;
|
||||
|
||||
if (xwindow == meta_screen_get_xroot (screen) ||
|
||||
xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
|
||||
return;
|
||||
|
||||
compositor = meta_display_get_compositor (display);
|
||||
|
||||
if (priv->size_changed)
|
||||
{
|
||||
mutter_window_detach (self);
|
||||
priv->size_changed = FALSE;
|
||||
}
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
if (priv->back_pixmap == None)
|
||||
@ -1367,33 +1423,7 @@ void
|
||||
mutter_window_process_damage (MutterWindow *self,
|
||||
XDamageNotifyEvent *event)
|
||||
{
|
||||
MutterWindowPrivate *priv = self->priv;
|
||||
Display *dpy = event->display;
|
||||
Drawable drawable = event->drawable;
|
||||
XEvent next;
|
||||
|
||||
if (priv->destroy_pending ||
|
||||
priv->maximize_in_progress ||
|
||||
priv->unmaximize_in_progress)
|
||||
{
|
||||
priv->needs_repair = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the event queue does not already contain DetstroyNotify for this
|
||||
* window -- if it does, we need to stop updating the pixmap (to avoid damage
|
||||
* notifications that come from the window teardown), and process the destroy
|
||||
* immediately.
|
||||
*/
|
||||
if (XCheckTypedWindowEvent (dpy, drawable, DestroyNotify, &next))
|
||||
{
|
||||
priv->destroy_pending = TRUE;
|
||||
mutter_window_destroy (self);
|
||||
return;
|
||||
}
|
||||
|
||||
repair_win (self);
|
||||
mutter_window_mark_for_repair (self);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1412,13 +1442,13 @@ mutter_window_finish_workspace_switch (MutterWindow *self)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mutter_window_update_shape (MutterWindow *self,
|
||||
gboolean shaped)
|
||||
static void
|
||||
check_needs_reshape (MutterWindow *self)
|
||||
{
|
||||
MutterWindowPrivate *priv = self->priv;
|
||||
|
||||
priv->shaped = shaped;
|
||||
if (!priv->needs_reshape)
|
||||
return;
|
||||
|
||||
mutter_shaped_texture_clear_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor));
|
||||
|
||||
@ -1444,6 +1474,36 @@ mutter_window_update_shape (MutterWindow *self,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->needs_reshape = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_window_update_shape (MutterWindow *self,
|
||||
gboolean shaped)
|
||||
{
|
||||
MutterWindowPrivate *priv = self->priv;
|
||||
|
||||
priv->shaped = shaped;
|
||||
priv->needs_reshape = TRUE;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
void
|
||||
mutter_window_pre_paint (MutterWindow *self)
|
||||
{
|
||||
MutterWindowPrivate *priv = self->priv;
|
||||
|
||||
/* The window is frozen due to a pending animation: we'll wait until
|
||||
* the animation finishes to reshape and repair the window */
|
||||
if (priv->destroy_in_progress ||
|
||||
priv->maximize_in_progress ||
|
||||
priv->unmaximize_in_progress)
|
||||
return;
|
||||
|
||||
check_needs_reshape (self);
|
||||
check_needs_repair (self);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2919,14 +2919,18 @@ meta_window_maximize (MetaWindow *window,
|
||||
|
||||
if (window->display->compositor)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
MetaRectangle old_rect;
|
||||
MetaRectangle new_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_rect);
|
||||
|
||||
meta_window_move_resize_now (window);
|
||||
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
meta_window_get_outer_rect (window, &new_rect);
|
||||
meta_compositor_maximize_window (window->display->compositor,
|
||||
window,
|
||||
&window_rect);
|
||||
&old_rect,
|
||||
&new_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3035,7 +3039,9 @@ meta_window_unmaximize (MetaWindow *window,
|
||||
|
||||
if (window->display->compositor)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
MetaRectangle old_rect, new_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_rect);
|
||||
|
||||
meta_window_move_resize (window,
|
||||
FALSE,
|
||||
@ -3043,13 +3049,12 @@ meta_window_unmaximize (MetaWindow *window,
|
||||
target_rect.y,
|
||||
target_rect.width,
|
||||
target_rect.height);
|
||||
meta_window_move_resize_now (window);
|
||||
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
|
||||
meta_window_get_outer_rect (window, &new_rect);
|
||||
meta_compositor_unmaximize_window (window->display->compositor,
|
||||
window,
|
||||
&window_rect);
|
||||
&old_rect,
|
||||
&new_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -84,10 +84,12 @@ void meta_compositor_unminimize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *icon_rect);
|
||||
void meta_compositor_maximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect);
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect);
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *from,
|
||||
|
Loading…
Reference in New Issue
Block a user