Support _NET_WM_OPAQUE_REGION
This new hint allows compositors to know what portions of a window will be obscured, as a region above them is opaque. For an RGB window, possible to glean this information from the bounding shape region of a client window, but not for an ARGB32 window. This new hint allows clients that use ARGB32 windows to say which part of the window is opaque, allowing this sort of optimization. https://bugzilla.gnome.org/show_bug.cgi?id=679901
This commit is contained in:
parent
3fe5a676c2
commit
a613a55658
@ -70,6 +70,9 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
/* A region that matches the shape of the window, including frame bounds */
|
||||
cairo_region_t *shape_region;
|
||||
/* The opaque region, from _NET_WM_OPAQUE_REGION, intersected with
|
||||
* the shape region. */
|
||||
cairo_region_t *opaque_region;
|
||||
/* The region we should clip to when painting the shadow */
|
||||
cairo_region_t *shadow_clip;
|
||||
|
||||
@ -387,6 +390,7 @@ meta_window_actor_dispose (GObject *object)
|
||||
meta_window_actor_detach (self);
|
||||
|
||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
||||
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
||||
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
|
||||
|
||||
g_clear_pointer (&priv->shadow_class, g_free);
|
||||
@ -1551,8 +1555,8 @@ meta_window_actor_get_obscured_region (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
if (!priv->argb32 && priv->opacity == 0xff && priv->back_pixmap)
|
||||
return priv->shape_region;
|
||||
if (priv->back_pixmap && priv->opacity == 0xff)
|
||||
return priv->opaque_region;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@ -2182,6 +2186,27 @@ check_needs_reshape (MetaWindowActor *self)
|
||||
/* The region at this point should be constrained to the
|
||||
* bounds of the client rectangle. */
|
||||
|
||||
if (priv->argb32 && priv->window->opaque_region != NULL)
|
||||
{
|
||||
/* The opaque region is defined to be a part of the
|
||||
* window which ARGB32 will always paint with opaque
|
||||
* pixels. For these regions, we want to avoid painting
|
||||
* windows and shadows beneath them.
|
||||
*
|
||||
* If the client gives bad coordinates where it does not
|
||||
* fully paint, the behavior is defined by the specification
|
||||
* to be undefined, and considered a client bug. In mutter's
|
||||
* case, graphical glitches will occur.
|
||||
*/
|
||||
priv->opaque_region = cairo_region_copy (priv->window->opaque_region);
|
||||
cairo_region_translate (priv->opaque_region, client_area.x, client_area.y);
|
||||
cairo_region_intersect (priv->opaque_region, region);
|
||||
}
|
||||
else if (priv->argb32)
|
||||
priv->opaque_region = NULL;
|
||||
else
|
||||
priv->opaque_region = cairo_region_reference (region);
|
||||
|
||||
if (needs_mask)
|
||||
{
|
||||
/* This takes the region, generates a mask using GTK+
|
||||
|
@ -346,6 +346,9 @@ struct _MetaWindow
|
||||
/* if non-NULL, the bounds of the window frame */
|
||||
cairo_region_t *frame_bounds;
|
||||
|
||||
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
|
||||
cairo_region_t *opaque_region;
|
||||
|
||||
/* Note: can be NULL */
|
||||
GSList *struts;
|
||||
|
||||
@ -648,6 +651,7 @@ void meta_window_update_icon_now (MetaWindow *window);
|
||||
|
||||
void meta_window_update_role (MetaWindow *window);
|
||||
void meta_window_update_net_wm_type (MetaWindow *window);
|
||||
void meta_window_update_opaque_region (MetaWindow *window);
|
||||
void meta_window_update_for_monitors_changed (MetaWindow *window);
|
||||
void meta_window_update_on_all_workspaces (MetaWindow *window);
|
||||
|
||||
|
@ -520,6 +520,14 @@ reload_wm_name (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reload_opaque_region (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
gboolean initial)
|
||||
{
|
||||
meta_window_update_opaque_region (window);
|
||||
}
|
||||
|
||||
static void
|
||||
reload_mutter_hints (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
@ -1706,6 +1714,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
|
||||
{ display->atom__NET_WM_PID, META_PROP_VALUE_CARDINAL, reload_net_wm_pid, TRUE, TRUE },
|
||||
{ XA_WM_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name, TRUE, TRUE },
|
||||
{ display->atom__MUTTER_HINTS, META_PROP_VALUE_TEXT_PROPERTY, reload_mutter_hints, TRUE, TRUE },
|
||||
{ display->atom__NET_WM_OPAQUE_REGION, META_PROP_VALUE_CARDINAL_LIST, reload_opaque_region, TRUE, TRUE },
|
||||
{ display->atom__NET_WM_ICON_NAME, META_PROP_VALUE_UTF8, reload_net_wm_icon_name, TRUE, FALSE },
|
||||
{ XA_WM_ICON_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name, TRUE, FALSE },
|
||||
{ display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop, TRUE, FALSE },
|
||||
|
@ -226,6 +226,9 @@ meta_window_finalize (GObject *object)
|
||||
if (window->frame_bounds)
|
||||
cairo_region_destroy (window->frame_bounds);
|
||||
|
||||
if (window->opaque_region)
|
||||
cairo_region_destroy (window->opaque_region);
|
||||
|
||||
meta_icon_cache_free (&window->icon_cache);
|
||||
|
||||
g_free (window->sm_client_id);
|
||||
@ -7388,6 +7391,64 @@ meta_window_update_net_wm_type (MetaWindow *window)
|
||||
meta_window_recalc_window_type (window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_update_opaque_region (MetaWindow *window)
|
||||
{
|
||||
cairo_region_t *opaque_region = NULL;
|
||||
gulong *region = NULL;
|
||||
int nitems;
|
||||
|
||||
g_clear_pointer (&window->opaque_region, cairo_region_destroy);
|
||||
|
||||
if (meta_prop_get_cardinal_list (window->display,
|
||||
window->xwindow,
|
||||
window->display->atom__NET_WM_OPAQUE_REGION,
|
||||
®ion, &nitems))
|
||||
{
|
||||
cairo_rectangle_int_t *rects;
|
||||
int i, rect_index, nrects;
|
||||
|
||||
if (nitems % 4 != 0)
|
||||
{
|
||||
meta_verbose ("_NET_WM_OPAQUE_REGION does not have a list of 4-tuples.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* empty region */
|
||||
if (nitems == 0)
|
||||
goto out;
|
||||
|
||||
nrects = nitems / 4;
|
||||
|
||||
rects = g_new (cairo_rectangle_int_t, nrects);
|
||||
|
||||
rect_index = 0;
|
||||
i = 0;
|
||||
while (i < nitems)
|
||||
{
|
||||
cairo_rectangle_int_t *rect = &rects[rect_index];
|
||||
|
||||
rect->x = region[i++];
|
||||
rect->y = region[i++];
|
||||
rect->width = region[i++];
|
||||
rect->height = region[i++];
|
||||
|
||||
rect_index++;
|
||||
}
|
||||
|
||||
opaque_region = cairo_region_create_rectangles (rects, nrects);
|
||||
|
||||
g_free (rects);
|
||||
}
|
||||
|
||||
out:
|
||||
window->opaque_region = opaque_region;
|
||||
meta_XFree (region);
|
||||
|
||||
if (window->display->compositor)
|
||||
meta_compositor_window_shape_changed (window->display->compositor, window);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_icon (MetaWindow *window)
|
||||
{
|
||||
|
@ -173,6 +173,7 @@ item(_NET_WM_STATE_STICKY)
|
||||
item(_NET_WM_FULLSCREEN_MONITORS)
|
||||
item(_NET_WM_STATE_FOCUSED)
|
||||
item(_NET_WM_BYPASS_COMPOSITOR)
|
||||
item(_NET_WM_OPAQUE_REGION)
|
||||
|
||||
#if 0
|
||||
/* We apparently never use: */
|
||||
|
Loading…
Reference in New Issue
Block a user