Allow setting input region before output window is created

If mutter_plugin_set_stage_input_region() and related methods are
called before the output window is available, save the set input
region and apply it to the output window later on.

compository-mutter.[ch]: Add mutter_set_stage_input_region() and
mutter_empty_stage_input_region(), move the input region handling
here and implement the delayed shape setting described
above.

mutter-plugin.c: Implement shape setting in terms of the new methods.

http://bugzilla.gnome.org/show_bug.cgi?id=580042
This commit is contained in:
Owen W. Taylor 2009-04-23 16:33:16 -04:00 committed by Owen W. Taylor
parent 76a3f9d402
commit 7a7632fa98
3 changed files with 62 additions and 49 deletions

View File

@ -148,6 +148,9 @@ typedef struct _MetaCompScreen
Window output;
GSList *dock_windows;
/* Before we create the output window */
XserverRegion pending_input_region;
gint switch_workspace_in_progress;
MutterPluginManager *plugin_mgr;
@ -1827,6 +1830,45 @@ mutter_get_windows (MetaScreen *screen)
return info->windows;
}
void
mutter_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
if (info->stage && info->output)
{
Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
}
else if (region != None)
{
info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
XFixesCopyRegion (xdpy, info->pending_input_region, region);
}
}
void
mutter_empty_stage_input_region (MetaScreen *screen)
{
/* Using a static region here is a bit hacky, but Metacity never opens more than
* one XDisplay, so it works fine. */
static XserverRegion region = None;
if (region == None)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
region = XFixesCreateRegion (xdpy, NULL, 0);
}
mutter_set_stage_input_region (screen, region);
}
static void
clutter_cmp_manage_screen (MetaCompositor *compositor,
MetaScreen *screen)
@ -1914,15 +1956,22 @@ clutter_cmp_manage_screen (MetaCompositor *compositor,
/*
* Delay the creation of the overlay window as long as we can, to avoid
* blanking out the screen. This means that during the plugin loading, the
* overlay window is not accessible, and so the plugins cannot do stuff
* like changing input shape; if that is required, the plugin should hook into
* "show" signal on stage, and do its stuff there.
* overlay window is not accessible; if the plugin needs to access it
* directly, it should hook into the "show" signal on stage, and do
* its stuff there.
*/
info->output = get_output_window (screen);
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
show_overlay_window (xdisplay, xwin, info->output);
if (info->pending_input_region != None)
{
mutter_set_stage_input_region (screen, info->pending_input_region);
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
}
clutter_actor_show (info->overlay_group);
clutter_actor_show (info->stage);
#endif

View File

@ -408,34 +408,11 @@ mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
stage = mutter_get_stage_for_screen (screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (screen);
static XserverRegion region = None;
if (region == None)
region = XFixesCreateRegion (xdpy, NULL, 0);
if (reactive)
{
XFixesSetWindowShapeRegion (xdpy, xstage,
ShapeInput, 0, 0, None);
XFixesSetWindowShapeRegion (xdpy, xoverlay,
ShapeInput, 0, 0, None);
}
mutter_set_stage_input_region (screen, None);
else
{
XFixesSetWindowShapeRegion (xdpy, xstage,
ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay,
ShapeInput, 0, 0, region);
}
mutter_empty_stage_input_region (screen);
}
void
@ -446,25 +423,16 @@ mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
XRectangle rect;
XserverRegion region;
stage = mutter_get_stage_for_screen (screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (screen);
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
region = XFixesCreateRegion (xdpy, &rect, 1);
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region);
mutter_set_stage_input_region (screen, region);
XFixesDestroyRegion (xdpy, region);
}
@ -473,18 +441,9 @@ mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
XserverRegion region)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage, xoverlay;
ClutterActor *stage;
MetaScreen *screen = priv->screen;
stage = mutter_get_stage_for_screen (screen);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xoverlay = mutter_get_overlay_window (screen);
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region);
mutter_set_stage_input_region (screen, region);
}
GList *

View File

@ -26,6 +26,7 @@
#define MUTTER_H_
#include <clutter/clutter.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xlib.h>
#include "types.h"
@ -80,4 +81,8 @@ Window mutter_get_overlay_window (MetaScreen *screen);
GList * mutter_get_windows (MetaScreen *screen);
ClutterActor * mutter_get_window_group_for_screen (MetaScreen *screen);
void mutter_set_stage_input_region (MetaScreen *screen,
XserverRegion region);
void mutter_empty_stage_input_region (MetaScreen *screen);
#endif