Move _NET_WM_WINDOW_OPACITY handling to the standard window-props interface

This removes one X11 dependency that the MetaWindowActor interface has,
making it easier for us to use Wayland on this one...

https://bugzilla.gnome.org/show_bug.cgi?id=720106
This commit is contained in:
Jasper St. Pierre 2013-12-09 15:43:52 -05:00
parent 93a8933282
commit 1db95bc32b
8 changed files with 77 additions and 82 deletions

View File

@ -17,7 +17,6 @@ struct _MetaCompositor
{ {
MetaDisplay *display; MetaDisplay *display;
Atom atom_net_wm_window_opacity;
guint repaint_func_id; guint repaint_func_id;
ClutterActor *shadow_src; ClutterActor *shadow_src;

View File

@ -175,31 +175,6 @@ process_damage (MetaCompositor *compositor,
meta_window_actor_process_damage (window_actor, event); meta_window_actor_process_damage (window_actor, event);
} }
static void
process_property_notify (MetaCompositor *compositor,
XPropertyEvent *event,
MetaWindow *window)
{
MetaWindowActor *window_actor;
if (window == NULL)
return;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (window_actor == NULL)
return;
/* Check for the opacity changing */
if (event->atom == compositor->atom_net_wm_window_opacity)
{
meta_window_actor_update_opacity (window_actor);
DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
return;
}
DEBUG_TRACE ("process_property_notify: unknown\n");
}
static Window static Window
get_output_window (MetaScreen *screen) get_output_window (MetaScreen *screen)
{ {
@ -877,6 +852,18 @@ meta_compositor_window_shape_changed (MetaCompositor *compositor,
meta_window_actor_update_shape (window_actor); meta_window_actor_update_shape (window_actor);
} }
void
meta_compositor_window_opacity_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_opacity (window_actor);
}
/* Clutter makes the assumption that there is only one X window /* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic * per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent * application toolkit. As such, it will ignore any events sent
@ -983,28 +970,19 @@ meta_compositor_process_event (MetaCompositor *compositor,
} }
} }
switch (event->type) if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{ {
case PropertyNotify: /* Core code doesn't handle damage events, so we need to extract the MetaWindow
process_property_notify (compositor, (XPropertyEvent *) event, window); * ourselves
break; */
if (window == NULL)
default:
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{ {
/* Core code doesn't handle damage events, so we need to extract the MetaWindow Window xwin = ((XDamageNotifyEvent *) event)->drawable;
* ourselves window = meta_display_lookup_x_window (compositor->display, xwin);
*/
if (window == NULL)
{
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
} }
break;
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
} }
/* Clutter needs to know about MapNotify events otherwise it will /* Clutter needs to know about MapNotify events otherwise it will
@ -1508,12 +1486,7 @@ on_shadow_factory_changed (MetaShadowFactory *factory,
MetaCompositor * MetaCompositor *
meta_compositor_new (MetaDisplay *display) meta_compositor_new (MetaDisplay *display)
{ {
char *atom_names[] = {
"_NET_WM_WINDOW_OPACITY",
};
Atom atoms[G_N_ELEMENTS(atom_names)];
MetaCompositor *compositor; MetaCompositor *compositor;
Display *xdisplay = meta_display_get_xdisplay (display);
if (!composite_at_least_version (display, 0, 3)) if (!composite_at_least_version (display, 0, 3))
return NULL; return NULL;
@ -1525,17 +1498,11 @@ meta_compositor_new (MetaDisplay *display)
if (g_getenv("META_DISABLE_MIPMAPS")) if (g_getenv("META_DISABLE_MIPMAPS"))
compositor->no_mipmaps = TRUE; compositor->no_mipmaps = TRUE;
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
g_signal_connect (meta_shadow_factory_get_default (), g_signal_connect (meta_shadow_factory_get_default (),
"changed", "changed",
G_CALLBACK (on_shadow_factory_changed), G_CALLBACK (on_shadow_factory_changed),
compositor); compositor);
compositor->atom_net_wm_window_opacity = atoms[0];
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func, compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor, compositor,
NULL); NULL);

View File

@ -68,8 +68,6 @@ struct _MetaWindowActorPrivate
Damage damage; Damage damage;
guint8 opacity;
/* A region that matches the shape of the window, including frame bounds */ /* A region that matches the shape of the window, including frame bounds */
cairo_region_t *shape_region; cairo_region_t *shape_region;
/* If the window has an input shape, a region that matches the shape */ /* If the window has an input shape, a region that matches the shape */
@ -270,7 +268,6 @@ meta_window_actor_init (MetaWindowActor *self)
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_WINDOW_ACTOR, META_TYPE_WINDOW_ACTOR,
MetaWindowActorPrivate); MetaWindowActorPrivate);
priv->opacity = 0xff;
priv->shadow_class = NULL; priv->shadow_class = NULL;
} }
@ -319,6 +316,15 @@ window_appears_focused_notify (MetaWindow *mw,
clutter_actor_queue_redraw (CLUTTER_ACTOR (data)); clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
} }
static gboolean
is_non_opaque (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
return priv->argb32 || (window->opacity != 0xFF);
}
static void static void
meta_window_actor_constructed (GObject *object) meta_window_actor_constructed (GObject *object)
{ {
@ -596,7 +602,7 @@ clip_shadow_under_window (MetaWindowActor *self)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
return (priv->argb32 || priv->opacity != 0xff) && priv->window->frame; return is_non_opaque (self) && priv->window->frame;
} }
static void static void
@ -622,6 +628,7 @@ meta_window_actor_paint (ClutterActor *actor)
MetaShadowParams params; MetaShadowParams params;
cairo_rectangle_int_t shape_bounds; cairo_rectangle_int_t shape_bounds;
cairo_region_t *clip = priv->shadow_clip; cairo_region_t *clip = priv->shadow_clip;
MetaWindow *window = priv->window;
meta_window_actor_get_shape_bounds (self, &shape_bounds); meta_window_actor_get_shape_bounds (self, &shape_bounds);
meta_window_actor_get_shadow_params (self, appears_focused, &params); meta_window_actor_get_shadow_params (self, appears_focused, &params);
@ -645,7 +652,7 @@ meta_window_actor_paint (ClutterActor *actor)
params.y_offset + shape_bounds.y, params.y_offset + shape_bounds.y,
shape_bounds.width, shape_bounds.width,
shape_bounds.height, shape_bounds.height,
(clutter_actor_get_paint_opacity (actor) * params.opacity * priv->opacity) / (255 * 255), (clutter_actor_get_paint_opacity (actor) * params.opacity * window->opacity) / (255 * 255),
clip, clip,
clip_shadow_under_window (self)); /* clip_strictly - not just as an optimization */ clip_shadow_under_window (self)); /* clip_strictly - not just as an optimization */
@ -732,10 +739,10 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return TRUE; return TRUE;
/* /*
* Do not add shadows to ARGB windows; eventually we should generate a * Do not add shadows to non-opaque windows; eventually we should generate
* shadow from the input shape for such windows. * a shadow from the input shape for such windows.
*/ */
if (priv->argb32 || priv->opacity != 0xff) if (is_non_opaque (self))
return FALSE; return FALSE;
/* /*
@ -1270,7 +1277,7 @@ meta_window_actor_should_unredirect (MetaWindowActor *self)
if (meta_window_requested_dont_bypass_compositor (metaWindow)) if (meta_window_requested_dont_bypass_compositor (metaWindow))
return FALSE; return FALSE;
if (priv->opacity != 0xff) if (metaWindow->opacity != 0xFF)
return FALSE; return FALSE;
if (metaWindow->shape_region != NULL) if (metaWindow->shape_region != NULL)
@ -1645,8 +1652,9 @@ static cairo_region_t *
meta_window_actor_get_obscured_region (MetaWindowActor *self) meta_window_actor_get_obscured_region (MetaWindowActor *self)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
if (priv->back_pixmap && priv->opacity == 0xff && !priv->window->shaded) if (priv->back_pixmap && window->opacity != 0xFF && !priv->window->shaded)
return priv->opaque_region; return priv->opaque_region;
else else
return NULL; return NULL;
@ -2560,23 +2568,9 @@ void
meta_window_actor_update_opacity (MetaWindowActor *self) meta_window_actor_update_opacity (MetaWindowActor *self)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen); MetaWindow *window = priv->window;
MetaCompositor *compositor = meta_display_get_compositor (display);
Window xwin = meta_window_get_xwindow (priv->window);
gulong value;
guint8 opacity;
if (meta_prop_get_cardinal (display, xwin, clutter_actor_set_opacity (self->priv->actor, window->opacity);
compositor->atom_net_wm_window_opacity,
&value))
{
opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
}
else
opacity = 255;
self->priv->opacity = opacity;
clutter_actor_set_opacity (self->priv->actor, opacity);
} }
void void

View File

@ -355,6 +355,9 @@ struct _MetaWindow
/* the input shape region for picking */ /* the input shape region for picking */
cairo_region_t *input_region; cairo_region_t *input_region;
/* _NET_WM_WINDOW_OPACITY */
guint opacity;
/* if TRUE, the we have the new form of sync request counter which /* if TRUE, the we have the new form of sync request counter which
* also handles application frames */ * also handles application frames */
guint extended_sync_request_counter : 1; guint extended_sync_request_counter : 1;
@ -695,6 +698,8 @@ void meta_window_update_input_region_x11 (MetaWindow *window);
void meta_window_set_shape_region (MetaWindow *window, void meta_window_set_shape_region (MetaWindow *window,
cairo_region_t *region); cairo_region_t *region);
void meta_window_update_shape_region_x11 (MetaWindow *window); void meta_window_update_shape_region_x11 (MetaWindow *window);
void meta_window_set_opacity (MetaWindow *window,
guint opacity);
Window meta_window_get_toplevel_xwindow (MetaWindow *window); Window meta_window_get_toplevel_xwindow (MetaWindow *window);

View File

@ -1709,6 +1709,20 @@ reload_bypass_compositor (MetaWindow *window,
window->bypass_compositor = requested_value; window->bypass_compositor = requested_value;
} }
static void
reload_window_opacity (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
int requested_value = 0xFF;
if (value->type != META_PROP_VALUE_INVALID)
requested_value = (int) value->v.cardinal;
meta_window_set_opacity (window, requested_value);
}
#define RELOAD_STRING(var_name, propname) \ #define RELOAD_STRING(var_name, propname) \
static void \ static void \
reload_ ## var_name (MetaWindow *window, \ reload_ ## var_name (MetaWindow *window, \
@ -1811,6 +1825,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE }, { display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE }, { display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, FALSE, FALSE }, { display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, FALSE, FALSE },
{ display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, TRUE, TRUE },
{ 0 }, { 0 },
}; };

View File

@ -1201,6 +1201,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
*/ */
window->stable_sequence = ++display->window_sequence_counter; window->stable_sequence = ++display->window_sequence_counter;
window->opacity = 0xFF;
/* assign the window to its group, or create a new group if needed /* assign the window to its group, or create a new group if needed
*/ */
window->group = NULL; window->group = NULL;
@ -11444,3 +11446,13 @@ meta_window_get_toplevel_xwindow (MetaWindow *window)
{ {
return window->frame ? window->frame->xwindow : window->xwindow; return window->frame ? window->frame->xwindow : window->xwindow;
} }
void
meta_window_set_opacity (MetaWindow *window,
guint opacity)
{
window->opacity = opacity;
if (window->display->compositor)
meta_compositor_window_opacity_changed (window->display->compositor, window);
}

View File

@ -179,6 +179,7 @@ item(_NET_WM_BYPASS_COMPOSITOR)
item(_NET_WM_OPAQUE_REGION) item(_NET_WM_OPAQUE_REGION)
item(_NET_WM_FRAME_DRAWN) item(_NET_WM_FRAME_DRAWN)
item(_NET_WM_FRAME_TIMINGS) item(_NET_WM_FRAME_TIMINGS)
item(_NET_WM_WINDOW_OPACITY)
#if 0 #if 0
/* We apparently never use: */ /* We apparently never use: */

View File

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