Compare commits

...

4 Commits

Author SHA1 Message Date
a3a2109c0c Fix input and bounding shapes
1) We need to select for shape events
2) For decorated windows, we don't want to apply any input
   shape, because the frame is always rectangular and eats
   all the input
3) For undecorated windows, the "has input shape" check is
   wrong if the window has a bounding shape but not an input
   shape
2014-02-25 01:16:13 +01:00
bdbeafc222 MetaWindowActor: replace MetaSurfaceActorEmpty with no MSA at all
Have MetaWindowActor cope with having a NULL surface actor, and
drop the Empty class.
2014-02-24 22:40:43 +01:00
89ca36818a MetaSurfaceActor: move freeze accounting to MetaWindowActor
Turns out we only ever need to freeze/thaw whole windows, not
surfaces or subsurfaces.
This will allow removing the surface actor without losing
the count.
2014-02-24 22:00:12 +01:00
fe1a58b459 compositor: Add a new MetaSurfaceActorEmpty
This will be used in the interim before MetaSurfaceActorWayland
we set_window_id is called. This is somewhat expensive and hacky,
but all other attempts to prevent either MetaWindowActor or
MetaWindow from created prematurely, e.g. before we have a
set_window_id have failed.
2014-02-24 14:46:19 -05:00
8 changed files with 151 additions and 78 deletions

View File

@ -940,6 +940,18 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
meta_window_actor_update_opacity (window_actor);
}
void
meta_compositor_window_surface_changed (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
meta_window_actor_update_surface (window_actor);
}
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent

View File

@ -26,8 +26,8 @@ struct _MetaSurfaceActorPrivate
cairo_region_t *input_region;
/* Freeze/thaw accounting */
guint freeze_count;
guint needs_damage_all : 1;
guint frozen : 1;
};
static void cullable_iface_init (MetaCullableInterface *iface);
@ -223,7 +223,7 @@ static gboolean
is_frozen (MetaSurfaceActor *self)
{
MetaSurfaceActorPrivate *priv = self->priv;
return (priv->freeze_count > 0);
return priv->frozen;
}
void
@ -274,31 +274,19 @@ meta_surface_actor_is_visible (MetaSurfaceActor *self)
}
void
meta_surface_actor_freeze (MetaSurfaceActor *self)
meta_surface_actor_set_frozen (MetaSurfaceActor *self,
gboolean frozen)
{
MetaSurfaceActorPrivate *priv = self->priv;
priv->freeze_count ++;
}
priv->frozen = frozen;
void
meta_surface_actor_thaw (MetaSurfaceActor *self)
{
MetaSurfaceActorPrivate *priv = self->priv;
if (priv->freeze_count == 0)
if (!frozen && priv->needs_damage_all)
{
g_critical ("Error in freeze/thaw accounting.");
return;
}
/* Since we ignore damage events while a window is frozen for certain effects
* we may need to issue an update_area() covering the whole pixmap if we
* don't know what real damage has happened. */
priv->freeze_count --;
/* Since we ignore damage events while a window is frozen for certain effects
* we may need to issue an update_area() covering the whole pixmap if we
* don't know what real damage has happened. */
if (priv->needs_damage_all)
{
meta_surface_actor_process_damage (self, 0, 0,
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
@ -306,12 +294,6 @@ meta_surface_actor_thaw (MetaSurfaceActor *self)
}
}
gboolean
meta_surface_actor_is_frozen (MetaSurfaceActor *self)
{
return is_frozen (self);
}
gboolean
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
{

View File

@ -69,9 +69,8 @@ void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
void meta_surface_actor_freeze (MetaSurfaceActor *actor);
void meta_surface_actor_thaw (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor);
void meta_surface_actor_set_frozen (MetaSurfaceActor *actor,
gboolean frozen);
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,

View File

@ -63,5 +63,6 @@ void meta_window_actor_effect_completed (MetaWindowActor *actor,
gulong event);
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
void meta_window_actor_update_surface (MetaWindowActor *self);
#endif /* META_WINDOW_ACTOR_PRIVATE_H */

View File

@ -84,6 +84,7 @@ struct _MetaWindowActorPrivate
/* List of FrameData for recent frames */
GList *frames;
guint freeze_count;
guint visible : 1;
guint disposed : 1;
@ -253,7 +254,15 @@ static gboolean
is_argb32 (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
return meta_surface_actor_is_argb32 (priv->surface);
/* assume we're argb until we get the window (because
in practice we're drawing nothing, so we're fully
transparent)
*/
if (priv->surface)
return meta_surface_actor_is_argb32 (priv->surface);
else
return TRUE;
}
static gboolean
@ -269,14 +278,19 @@ static gboolean
is_frozen (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
return meta_surface_actor_is_frozen (priv->surface);
return priv->surface == NULL || priv->freeze_count > 0;
}
static void
meta_window_actor_freeze (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
meta_surface_actor_freeze (priv->surface);
if (priv->freeze_count == 0 && priv->surface)
meta_surface_actor_set_frozen (priv->surface, TRUE);
priv->freeze_count ++;
}
static void
@ -284,11 +298,16 @@ meta_window_actor_thaw (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
meta_surface_actor_thaw (priv->surface);
if (priv->freeze_count <= 0)
g_error ("Error in freeze/thaw accounting");
if (is_frozen (self))
priv->freeze_count--;
if (priv->freeze_count > 0)
return;
if (priv->surface)
meta_surface_actor_set_frozen (priv->surface, FALSE);
/* We sometimes ignore moves and resizes on frozen windows */
meta_window_actor_sync_actor_geometry (self, FALSE);
@ -326,14 +345,13 @@ set_surface (MetaWindowActor *self,
/* If the previous surface actor was frozen, start out
* frozen as well... */
if (priv->updates_frozen)
meta_surface_actor_freeze (priv->surface);
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
meta_window_actor_update_shape (self);
}
}
static void
void
meta_window_actor_update_surface (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
@ -342,8 +360,10 @@ meta_window_actor_update_surface (MetaWindowActor *self)
if (window->surface)
surface_actor = window->surface->surface_actor;
else
else if (!meta_is_wayland_compositor ())
surface_actor = meta_surface_actor_x11_new (window);
else
surface_actor = NULL;
set_surface (self, surface_actor);
}
@ -650,8 +670,11 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
meta_window_actor_get_shape_bounds (self, &bounds);
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
if (priv->surface)
{
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
}
if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
{
@ -762,21 +785,26 @@ meta_window_actor_get_meta_window (MetaWindowActor *self)
* meta_window_actor_get_texture:
* @self: a #MetaWindowActor
*
* Gets the ClutterActor that is used to display the contents of the window
* Gets the ClutterActor that is used to display the contents of the window,
* or NULL if no texture is shown yet, because the window is not mapped.
*
* Return value: (transfer none): the #ClutterActor for the contents
*/
ClutterActor *
meta_window_actor_get_texture (MetaWindowActor *self)
{
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
if (self->priv->surface)
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
else
return NULL;
}
/**
* meta_window_actor_get_surface:
* @self: a #MetaWindowActor
*
* Gets the MetaSurfaceActor that draws the content of this window
* Gets the MetaSurfaceActor that draws the content of this window,
* or NULL if there is no surface yet associated with this window.
*
* Return value: (transfer none): the #MetaSurfaceActor for the contents
*/
@ -875,7 +903,12 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
if (!priv->repaint_scheduled)
{
gboolean is_obscured = meta_surface_actor_is_obscured (priv->surface);
gboolean is_obscured;
if (priv->surface)
is_obscured = meta_surface_actor_is_obscured (priv->surface);
else
is_obscured = FALSE;
/* A frame was marked by the client without actually doing any
* damage or any unobscured, or while we had the window frozen
@ -891,9 +924,12 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
}
else
{
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
priv->repaint_scheduled = TRUE;
if (priv->surface)
{
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
priv->repaint_scheduled = TRUE;
}
}
}
}
@ -1066,7 +1102,10 @@ gboolean
meta_window_actor_should_unredirect (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
return meta_surface_actor_should_unredirect (priv->surface);
if (priv->surface)
return meta_surface_actor_should_unredirect (priv->surface);
else
return FALSE;
}
void
@ -1074,6 +1113,8 @@ meta_window_actor_set_unredirected (MetaWindowActor *self,
gboolean unredirected)
{
MetaWindowActorPrivate *priv = self->priv;
g_assert(priv->surface); /* because otherwise should_unredirect() is FALSE */
meta_surface_actor_set_unredirected (priv->surface, unredirected);
}
@ -1519,11 +1560,12 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
{
MetaWindowActorPrivate *priv = self->priv;
meta_surface_actor_process_damage (priv->surface,
event->area.x,
event->area.y,
event->area.width,
event->area.height);
if (priv->surface)
meta_surface_actor_process_damage (priv->surface,
event->area.x,
event->area.y,
event->area.width,
event->area.height);
}
void
@ -1718,21 +1760,27 @@ meta_window_actor_update_input_region (MetaWindowActor *self,
MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *region = NULL;
if (priv->window->frame != NULL && priv->window->input_region != NULL)
if (priv->window->frame != NULL)
{
region = meta_frame_get_frame_bounds (priv->window->frame);
cairo_region_subtract_rectangle (region, client_area);
/* input_region is in client window coordinates, so translate the
/* client area is in client window coordinates, so translate the
* input region into that coordinate system and back */
cairo_region_translate (region, -client_area->x, -client_area->y);
cairo_region_union (region, priv->window->input_region);
cairo_region_union_rectangle (region, client_area);
cairo_region_translate (region, client_area->x, client_area->y);
}
else if (priv->window->input_region != NULL)
else if (priv->window->shape_region != NULL ||
priv->window->input_region != NULL)
{
region = cairo_region_reference (priv->window->input_region);
if (priv->window->shape_region != NULL)
{
region = cairo_region_copy (priv->window->shape_region);
if (priv->window->input_region != NULL)
cairo_region_intersect (region, priv->window->input_region);
}
else
region = cairo_region_reference (priv->window->input_region);
}
else
{
@ -2026,7 +2074,8 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
clutter_actor_set_opacity (CLUTTER_ACTOR (self->priv->surface), window->opacity);
if (priv->surface)
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
}
void

View File

@ -350,11 +350,43 @@ meta_window_set_input_region (MetaWindow *window,
meta_compositor_window_shape_changed (window->display->compositor, window);
}
#if 0
/* Print out a region; useful for debugging */
static void
print_region (cairo_region_t *region)
{
int n_rects;
int i;
n_rects = cairo_region_num_rectangles (region);
g_print ("[");
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
g_print ("+%d+%dx%dx%d ",
rect.x, rect.y, rect.width, rect.height);
}
g_print ("]\n");
}
#endif
void
meta_window_x11_update_input_region (MetaWindow *window)
{
cairo_region_t *region = NULL;
/* Decorated windows don't have an input region, because
we don't shape the frame to match the client windows
(so the events are blocked by the frame anyway)
*/
if (window->decorated)
{
if (window->input_region)
meta_window_set_input_region (window, NULL);
return;
}
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (window->display))
{
@ -363,17 +395,6 @@ meta_window_x11_update_input_region (MetaWindow *window)
XRectangle *rects = NULL;
int n_rects, ordering;
int x_bounding, y_bounding, x_clip, y_clip;
unsigned w_bounding, h_bounding, w_clip, h_clip;
int bounding_shaped, clip_shaped;
meta_error_trap_push (window->display);
XShapeQueryExtents (window->display->xdisplay, window->xwindow,
&bounding_shaped, &x_bounding, &y_bounding,
&w_bounding, &h_bounding,
&clip_shaped, &x_clip, &y_clip,
&w_clip, &h_clip);
rects = XShapeGetRectangles (window->display->xdisplay,
window->xwindow,
ShapeInput,
@ -388,10 +409,10 @@ meta_window_x11_update_input_region (MetaWindow *window)
{
if (n_rects > 1 ||
(n_rects == 1 &&
(rects[0].x != x_bounding ||
rects[0].y != y_bounding ||
rects[0].width != w_bounding ||
rects[0].height != h_bounding)))
(rects[0].x != 0 ||
rects[0].y != 0 ||
rects[0].width != window->rect.width ||
rects[0].height != window->rect.height)))
region = region_create_from_x_rectangles (rects, n_rects);
XFree (rects);
@ -1453,6 +1474,11 @@ meta_window_x11_new (MetaDisplay *display,
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
}
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display))
XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask);
#endif
/* Get rid of any borders */
if (attrs.border_width != 0)
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);

View File

@ -66,6 +66,8 @@ void meta_compositor_window_shape_changed (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_window_opacity_changed (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_window_surface_changed (MetaCompositor *compositor,
MetaWindow *window);
gboolean meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,

View File

@ -51,6 +51,8 @@ xserver_set_window_id (struct wl_client *client,
surface->window = window;
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
}
static const struct xserver_interface xserver_implementation = {