Esempio n. 1
0
Workspace::Workspace() : mDamage( None ), mWaitForClients( false ), mInitialRepaint( true )
{
    Extensions::initialize();

	XGrabServer( dpy );

	// Redirect all toplevel window contents to offscreen storage
	XCompositeRedirectSubwindows( dpy, rootId(), CompositeRedirectManual );

    initClientList();

	// Request notification about toplevel window state changes
	XSelectInput( dpy, rootId(),
			SubstructureNotifyMask | ExposureMask |
			StructureNotifyMask | PropertyChangeMask );

	XUngrabServer( dpy );

	// Get the picture format for the root window
	mFormat = XRenderFindVisualFormat( dpy, visual() );

	// Create an unclipped picture for drawing on the root window
	XRenderPictureAttributes pa;
	pa.subwindow_mode = IncludeInferiors;
	mFrontbuffer = XRenderCreatePicture( dpy, rootId(), format(), CPSubwindowMode, &pa );

	createBackbuffer();

	XSync( dpy, false );
}
/*! Tries to ask the X Composite extension (if supported) to redirect all
    windows on all screens to backing storage. This does not have
    any effect if another application already requested the same
    thing (typically the window manager does this).
*/
void WindowImageProvider::activateComposite()
{
    int event_base;
    int error_base;

    Display *display = QX11Info::display();
    bool compositeSupport = false;

    if (XCompositeQueryExtension(display, &event_base, &error_base)) {
        int major = 0;
        int minor = 2;
        XCompositeQueryVersion(display, &major, &minor);

        if (major > 0 || minor >= 2) {
            compositeSupport = true;
            (UQ_DEBUG).nospace() << "Server supports the Composite extension (ver "
                    << major << "." << minor << ")";
        }
        else {
            (UQ_DEBUG).nospace() << "Server supports the Composite extension, but "
                                  "version is < 0.2 (ver " << major << "." << minor << ")";
        }
    } else {
        UQ_DEBUG << "Server doesn't support the Composite extension.";
    }

    if (compositeSupport) {
        int screens = ScreenCount(display);
        for (int i = 0; i < screens; ++i) {
            XCompositeRedirectSubwindows(display, RootWindow(display, i),
                                         CompositeRedirectAutomatic);
        }
    }
}
Esempio n. 3
0
File: main.c Progetto: czaber/ogwm
void setup_x(void) {
	screen = DefaultScreen(dpy);
	root = RootWindow(dpy, screen);

	XSetErrorHandler(on_xerror);
	XSelectInput (dpy, root, SubstructureNotifyMask|KeyPressMask|VisibilityChangeMask|ExposureMask);
	XCompositeRedirectSubwindows(dpy, root, CompositeRedirectAutomatic);

	overlay = create_overlay();
	canvas = create_canvas();
	debug("Root 0x%x, Overlay 0x%x, Canvas 0x%x\n", root, overlay, canvas);

	stop = 0;
}
void MCompositeScene::prepareRoot()
{
    Display *dpy = QX11Info::display();
    Window root =  QX11Info::appRootWindow();

    XSetWindowAttributes sattr;
    sattr.event_mask =  SubstructureRedirectMask | SubstructureNotifyMask | StructureNotifyMask | PropertyChangeMask;

    // All newly mapped windows should be redirected to avoid double Expose
    XCompositeRedirectSubwindows(dpy, root, CompositeRedirectManual);

    XChangeWindowAttributes(dpy, root, CWEventMask, &sattr);
    XSelectInput(dpy, root, SubstructureNotifyMask | SubstructureRedirectMask
                            | StructureNotifyMask | PropertyChangeMask
                            | FocusChangeMask);
    XSetErrorHandler(error_handler);
}
Esempio n. 5
0
static void
redirect_windows (MetaScreen *screen)
{
  MetaDisplay *display       = meta_screen_get_display (screen);
  Display     *xdisplay      = meta_display_get_xdisplay (display);
  Window       xroot         = meta_screen_get_xroot (screen);
  int          screen_number = meta_screen_get_screen_number (screen);
  guint        n_retries;
  guint        max_retries;

  if (meta_get_replace_current_wm ())
    max_retries = 5;
  else
    max_retries = 1;

  n_retries = 0;

  /* Some compositors (like old versions of Mutter) might not properly unredirect
   * subwindows before destroying the WM selection window; so we wait a while
   * for such a compositor to exit before giving up.
   */
  while (TRUE)
    {
      meta_error_trap_push (display);
      XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
      XSync (xdisplay, FALSE);

      if (!meta_error_trap_pop_with_return (display))
        break;

      if (n_retries == max_retries)
        {
          /* This probably means that a non-WM compositor like xcompmgr is running;
           * we have no way to get it to exit */
          meta_fatal (_("Another compositing manager is already running on screen %i on display \"%s\"."),
                      screen_number, display->name);
        }

      n_retries++;
      g_usleep (G_USEC_PER_SEC);
    }
}
gboolean
init_composite (void)
{
  Display *display;
  display = gdk_x11_get_default_xdisplay ();

  // First, check the Composite extension, then the Render extension.
  int error_base;
  int event_base;
  int version_major;
  int version_minor;

  if (!XCompositeQueryExtension (display, &event_base, &error_base)) {
    return FALSE;
  }

  // We need at least version 0.2, for XCompositeNameWindowPixmap.
  XCompositeQueryVersion (display, &version_major, &version_minor);
  if (version_major <= 0 && version_minor < 2) {
    return FALSE;
  }

  if (!XRenderQueryExtension (display, &event_base, &error_base)) {
    return FALSE;
  }

  // We need at least version 0.6, for XRenderSetPictureTransform.
  XRenderQueryVersion (display, &version_major, &version_minor);
  if (version_major <= 0 && version_minor < 6) {
    return FALSE;
  }

  XCompositeRedirectSubwindows (display,
      GDK_WINDOW_XWINDOW (gdk_get_default_root_window ()),
      CompositeRedirectAutomatic);
  return TRUE;
}
Esempio n. 7
0
KWD::Decorator::Decorator () :
    KApplication (),
    mConfig (0),
    mCompositeWindow (0),
    mSwitcher (0)
{
    XSetWindowAttributes attr;
    int			 i, j;

    mSelf = this;

    mRootInfo = new NETRootInfo (QX11Info::display (), 0);

    mActiveId = 0;

    KConfigGroup cfg (KSharedConfig::openConfig ("plasmarc"),
						 QString ("Theme"));
    Plasma::Theme::defaultTheme ()->setThemeName (cfg.readEntry ("name"));

    Atoms::init ();

    new KWinAdaptor (this);

    mConfig = new KConfig ("kwinrc");

    mOptions = new KWD::Options (mConfig);
    mPlugins = new PluginManager (KSharedConfig::openConfig ("kwinrc"));

    mActiveShadowOptions.shadow_radius   = SHADOW_RADIUS;
    mActiveShadowOptions.shadow_opacity  = SHADOW_OPACITY;
    mActiveShadowOptions.shadow_offset_x = SHADOW_OFFSET_X;
    mActiveShadowOptions.shadow_offset_y = SHADOW_OFFSET_Y;
    mActiveShadowOptions.shadow_color[0] = SHADOW_COLOR_RED;
    mActiveShadowOptions.shadow_color[1] = SHADOW_COLOR_GREEN;
    mActiveShadowOptions.shadow_color[2] = SHADOW_COLOR_BLUE;

    mInactiveShadowOptions.shadow_radius   = SHADOW_RADIUS;
    mInactiveShadowOptions.shadow_opacity  = SHADOW_OPACITY;
    mInactiveShadowOptions.shadow_offset_x = SHADOW_OFFSET_X;
    mInactiveShadowOptions.shadow_offset_y = SHADOW_OFFSET_Y;
    mInactiveShadowOptions.shadow_color[0] = SHADOW_COLOR_RED;
    mInactiveShadowOptions.shadow_color[1] = SHADOW_COLOR_GREEN;
    mInactiveShadowOptions.shadow_color[2] = SHADOW_COLOR_BLUE;

    updateShadowProperties (QX11Info::appRootWindow ());

    for (i = 0; i < 3; i++)
    {
	for (j = 0; j < 3; j++)
	{
	    if (cursors[i][j].shape != XC_left_ptr)
		cursors[i][j].cursor =
		    XCreateFontCursor (QX11Info::display (),
				       cursors[i][j].shape);
	}
    }

    attr.override_redirect = True;

    mCompositeWindow = XCreateWindow (QX11Info::display (),
				      QX11Info::appRootWindow (),
				      -ROOT_OFF_X, -ROOT_OFF_Y, 1, 1, 0,
				      CopyFromParent,
				      CopyFromParent,
				      CopyFromParent,
				      CWOverrideRedirect, &attr);

    long data = 1;
    XChangeProperty (QX11Info::display(), mCompositeWindow, Atoms::enlightmentDesktop,
		      XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &data, 1);

    XCompositeRedirectSubwindows (QX11Info::display (), mCompositeWindow,
				  CompositeRedirectManual);

    XMapWindow (QX11Info::display (), mCompositeWindow);

    QDBusConnection dbus = QDBusConnection::sessionBus ();
    dbus.connect (KDED_SERVICE, KDED_APPMENU_PATH, KDED_INTERFACE, "showRequest",
		 this, SIGNAL (showRequest (qulonglong)));
    dbus.connect (KDED_SERVICE, KDED_APPMENU_PATH, KDED_INTERFACE, "menuAvailable",
		 this, SLOT (menuAvailable (qulonglong)));
    dbus.connect (KDED_SERVICE, KDED_APPMENU_PATH, KDED_INTERFACE, "clearMenus",
		 this, SLOT (clearMenus ()));
    dbus.connect (KDED_SERVICE, KDED_APPMENU_PATH, KDED_INTERFACE, "menuHidden",
		 this, SIGNAL (menuHidden ()));
}
int
main (int argc, char *argv[])
{
  GstPipeline *pipeline;
  GstBus *bus;

  GstElement *srcbin;
  GstElement *tee;
  GstElement *queue[N_ACTORS], *sink[N_ACTORS];
  GstElement *upload[N_ACTORS];
/*
  GstElement *effect[N_ACTORS];
*/
  ClutterActor *stage;
  GstGLClutterActor *actor[N_ACTORS];
  Display *disp;
  Window stage_win;
  const gchar *desc;
  gint i;
  gint ok = FALSE;
  ClutterInitError clutter_err = CLUTTER_INIT_ERROR_UNKNOWN;

  clutter_err = clutter_init (&argc, &argv);
  if (clutter_err != CLUTTER_INIT_SUCCESS)
    g_warning ("Failed to initalize clutter: %d\n", clutter_err);

  gst_init (&argc, &argv);

  disp = clutter_x11_get_default_display ();
  if (!clutter_x11_has_composite_extension ()) {
    g_error ("XComposite extension missing");
  }

  stage = clutter_stage_get_default ();
  clutter_actor_set_size (CLUTTER_ACTOR (stage),
      W * COLS + (COLS - 1), H * ROWS + (ROWS - 1));

  stage_win = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
  XCompositeRedirectSubwindows (disp, stage_win, CompositeRedirectManual);

  for (i = 0; i < N_ACTORS; i++) {
    actor[i] = g_new0 (GstGLClutterActor, 1);
    actor[i]->stage = stage;
    actor[i]->win = XCreateSimpleWindow (disp, stage_win, 0, 0, W, H, 0, 0, 0);
    XMapRaised (disp, actor[i]->win);
    XSync (disp, FALSE);
  }
/*
  desc = g_strdup_printf ("v4l2src ! "
                          "video/x-raw, width=640, height=480, framerate=30/1 ! "
                          "videoscale !"
                          "video/x-raw, width=%d, height=%d ! "
                          "identity", W, H);
*/
  desc = g_strdup_printf ("videotestsrc ! "
      "video/x-raw, format=RGB, width=%d, height=%d !" "identity", W, H);
  pipeline = GST_PIPELINE (gst_pipeline_new (NULL));

  srcbin = gst_parse_bin_from_description (desc, TRUE, NULL);
  if (!srcbin)
    g_error ("Source bin creation failed");

  tee = gst_element_factory_make ("tee", NULL);

  gst_bin_add_many (GST_BIN (pipeline), srcbin, tee, NULL);

  for (i = 0; i < N_ACTORS; i++) {
    queue[i] = gst_element_factory_make ("queue", NULL);
    upload[i] = gst_element_factory_make ("glupload", NULL);
/*      effect[i] = gst_element_factory_make ("gleffects", NULL); */
    sink[i] = gst_element_factory_make ("glimagesink", NULL);
/*    gst_bin_add_many (GST_BIN (pipeline),
        queue[i], upload[i], effect[i], sink[i], NULL); */
    gst_bin_add_many (GST_BIN (pipeline), queue[i], upload[i], sink[i], NULL);
  }

  gst_element_link_many (srcbin, tee, NULL);

  for (i = 0; i < N_ACTORS; i++) {
    ok |=
//        gst_element_link_many (tee, queue[i], upload[i], effect[i], sink[i],
        gst_element_link_many (tee, queue[i], upload[i], sink[i], NULL);
  }

  if (!ok)
    g_error ("Failed to link one or more elements");

/*
  for (i = 0; i < N_ACTORS; i++) {
    g_message ("setting effect %d on %s", i + 1,
        gst_element_get_name (effect[i]));
    g_object_set (G_OBJECT (effect[i]), "effect", i + 1, NULL);
  }
*/

  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));

  gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, actor,
      NULL);
  gst_object_unref (bus);

  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);

  clutter_actor_show_all (stage);

  clutter_main ();

  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
  gst_object_unref (pipeline);

  return 0;
}
Esempio n. 9
0
void X11EmbedContainer::embedSystemTrayClient(WId clientId)
{
    Display *display = QX11Info::display();

    if (!XGetWindowAttributes(display, clientId, &d->attr)) {
        emit error(QX11EmbedContainer::Unknown);
        return;
    }

    XSetWindowAttributes sAttr;
    sAttr.background_pixel = BlackPixel(display, DefaultScreen(display));
    sAttr.border_pixel = BlackPixel(display, DefaultScreen(display));
    sAttr.colormap = d->attr.colormap;

    WId parentId = parentWidget() ? parentWidget()->winId() : DefaultRootWindow(display);
    Window winId = XCreateWindow(display, parentId, 0, 0, d->attr.width, d->attr.height,
                                 0, d->attr.depth, InputOutput, d->attr.visual,
                                 CWBackPixel | CWBorderPixel | CWColormap, &sAttr);

    XWindowAttributes attr;
    if (!XGetWindowAttributes(display, winId, &attr)) {
        emit error(QX11EmbedContainer::Unknown);
        return;
    }

    create(winId);

    XRenderPictFormat *format = XRenderFindVisualFormat(display, d->attr.visual);
    if (format && format->type == PictTypeDirect && format->direct.alphaMask &&
        FdoSelectionManager::manager()->haveComposite())
    {
        // Redirect ARGB windows to offscreen storage so we can composite them ourselves
        XRenderPictureAttributes attr;
        attr.subwindow_mode = IncludeInferiors;

        d->picture = XRenderCreatePicture(display, clientId, format, CPSubwindowMode, &attr);
        XCompositeRedirectSubwindows(display, winId, CompositeRedirectManual);
        FdoSelectionManager::manager()->addDamageWatch(this, clientId);

        //kDebug() << "Embedded client uses an ARGB visual -> compositing.";
    } else {
        //kDebug() << "Embedded client is not using an ARGB visual.";
    }

    // repeat everything from QX11EmbedContainer's ctor that might be relevant
    setFocusPolicy(Qt::StrongFocus);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    setAcceptDrops(true);
    setEnabled(false);

    XSelectInput(display, winId,
                 KeyPressMask | KeyReleaseMask |
                 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
                 KeymapStateMask |
                 PointerMotionMask |
                 EnterWindowMask | LeaveWindowMask |
                 FocusChangeMask |
                 ExposureMask |
                 StructureNotifyMask |
                 SubstructureNotifyMask);

    XFlush(display);

    embedClient(clientId);

    // FIXME: This checks that the client is still valid. Qt won't pick it up
    // if the client closes before embedding completes. However, what happens
    // if the close happens after this point? Should checks happen on a timer
    // until embedding completes perhaps?
    if (!XGetWindowAttributes(QX11Info::display(), clientId, &d->attr)) {
        emit error(QX11EmbedContainer::Unknown);
        return;
    }
}
Bool
addDisplay (char *name,
	    char **plugin,
	    int  nPlugin)
{
    CompDisplay *d;
    Display	*dpy;
    int		i;

    d = &compDisplay;

    if (displayPrivateLen)
    {
	d->privates = malloc (displayPrivateLen * sizeof (CompPrivate));
	if (!d->privates)
	    return FALSE;
    }
    else
	d->privates = 0;

    d->screenPrivateIndices = 0;
    d->screenPrivateLen     = 0;

    for (i = 0; i < CompModNum; i++)
	d->modMask[i] = CompNoMask;

    d->plugin.list.type   = CompOptionTypeString;
    d->plugin.list.nValue = 0;
    d->plugin.list.value  = 0;

    compDisplayInitOptions (d, plugin, nPlugin);

    d->textureFilter = GL_LINEAR;

    d->display = dpy = XOpenDisplay (name);
    if (!d->display)
    {
	fprintf (stderr, "%s: Couldn't open display %s\n",
		 programName, XDisplayName (name));
	return FALSE;
    }

#ifdef DEBUG
    XSynchronize (dpy, TRUE);
#endif

    XSetErrorHandler (errorHandler);

    updateModifierMappings (d);

    d->setDisplayOption		 = setDisplayOption;
    d->setDisplayOptionForPlugin = setDisplayOptionForPlugin;

    d->initPluginForDisplay = initPluginForDisplay;
    d->finiPluginForDisplay = finiPluginForDisplay;

    d->handleEvent = handleEvent;

    d->winTypeAtom    = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", 0);
    d->winDesktopAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", 0);
    d->winDockAtom    = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", 0);
    d->winToolbarAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", 0);
    d->winMenuAtom    = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_MENU", 0);
    d->winUtilAtom    = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_UTILITY", 0);
    d->winSplashAtom  = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_SPLASH", 0);
    d->winDialogAtom  = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DIALOG", 0);
    d->winNormalAtom  = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NORMAL", 0);
    d->winOpacityAtom = XInternAtom (dpy, "_NET_WM_WINDOW_OPACITY", 0);
    d->winActiveAtom  = XInternAtom (dpy, "_NET_ACTIVE_WINDOW", 0);

    d->wmStateAtom	  = XInternAtom (dpy, "WM_STATE", 0);
    d->wmDeleteWindowAtom = XInternAtom (dpy, "WM_DELETE_WINDOW", 0);

    d->xBackgroundAtom[0] = XInternAtom (dpy, "_XSETROOT_ID", 0);
    d->xBackgroundAtom[1] = XInternAtom (dpy, "_XROOTPMAP_ID", 0);

    if (testMode)
    {
	d->compositeOpcode = MAXSHORT;
	d->compositeEvent  = MAXSHORT;
	d->compositeError  = MAXSHORT;

	d->damageEvent = MAXSHORT;
	d->damageError = MAXSHORT;
    }
    else
    {
	int compositeMajor, compositeMinor;

	if (!XQueryExtension (dpy,
			      COMPOSITE_NAME,
			      &d->compositeOpcode,
			      &d->compositeEvent,
			      &d->compositeError))
	{
	    fprintf (stderr, "%s: No composite extension\n", programName);
	    return FALSE;
	}

	XCompositeQueryVersion (dpy, &compositeMajor, &compositeMinor);
	if (compositeMajor == 0 && compositeMinor < 2)
	{
	    fprintf (stderr, "%s: Old composite extension\n", programName);
	    return FALSE;
	}

	if (!XDamageQueryExtension (dpy, &d->damageEvent, &d->damageError))
	{
	    fprintf (stderr, "%s: No damage extension\n", programName);
	    return FALSE;
	}
    }

    d->shapeExtension = XShapeQueryExtension (dpy,
					      &d->shapeEvent,
					      &d->shapeError);

    compDisplays = d;

    if (testMode)
    {
	addScreen (d, 0);
    }
    else
    {
	XGrabServer (dpy);

	for (i = 0; i < ScreenCount (dpy); i++)
	{
	    redirectFailed = 0;
	    XCompositeRedirectSubwindows (dpy, XRootWindow (dpy, i),
					  CompositeRedirectManual);
	    XSync (dpy, FALSE);
	    if (redirectFailed)
	    {
		fprintf (stderr, "%s: Another composite manager is already "
			 "running on screen: %d\n", programName, i);
	    }
	    else
	    {
		if (!addScreen (d, i))
		{
		    fprintf (stderr, "%s: Failed to manage screen: %d\n",
			     programName, i);
		}
	    }
	}

	XUngrabServer (dpy);
    }

    if (!d->screens)
    {
	fprintf (stderr, "%s: No managable screens found on display %s\n",
		 programName, XDisplayName (name));
	return FALSE;
    }

    return TRUE;
}
Esempio n. 11
0
void
meta_compositor_manage_screen (MetaCompositor *compositor,
                               MetaScreen     *screen)
{
    MetaCompScreen *info;
    MetaDisplay    *display       = meta_screen_get_display (screen);
    Display        *xdisplay      = meta_display_get_xdisplay (display);
    int             screen_number = meta_screen_get_screen_number (screen);
    Window          xroot         = meta_screen_get_xroot (screen);
    Window          xwin;
    gint            width, height;
    XWindowAttributes attr;
    long            event_mask;
    guint           n_retries;
    guint           max_retries;

    /* Check if the screen is already managed */
    if (meta_screen_get_compositor_data (screen))
        return;

    if (meta_get_replace_current_wm ())
        max_retries = 5;
    else
        max_retries = 1;

    n_retries = 0;

    /* Some compositors (like old versions of Muffin) might not properly unredirect
     * subwindows before destroying the WM selection window; so we wait a while
     * for such a compositor to exit before giving up.
     */
    while (TRUE)
    {
        meta_error_trap_push_with_return (display);
        XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
        XSync (xdisplay, FALSE);

        if (!meta_error_trap_pop_with_return (display))
            break;

        if (n_retries == max_retries)
        {
            /* This probably means that a non-WM compositor like xcompmgr is running;
             * we have no way to get it to exit */
            meta_fatal (_("Another compositing manager is already running on screen %i on display \"%s\"."),
                        screen_number, display->name);
        }

        n_retries++;
        g_usleep (G_USEC_PER_SEC);
    }

    info = g_new0 (MetaCompScreen, 1);
    /*
     * We use an empty input region for Clutter as a default because that allows
     * the user to interact with all the windows displayed on the screen.
     * We have to initialize info->pending_input_region to an empty region explicitly,
     * because None value is used to mean that the whole screen is an input region.
     */
    info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);

    info->screen = screen;

    meta_screen_set_compositor_data (screen, info);

    info->output = None;
    info->windows = NULL;

    meta_screen_set_cm_selection (screen);

    info->stage = clutter_stage_new ();

    meta_screen_get_size (screen, &width, &height);
    clutter_actor_realize (info->stage);

    xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));

    XResizeWindow (xdisplay, xwin, width, height);

    event_mask = FocusChangeMask |
                 ExposureMask |
                 EnterWindowMask | LeaveWindowMask |
                 PointerMotionMask |
                 PropertyChangeMask |
                 ButtonPressMask | ButtonReleaseMask |
                 KeyPressMask | KeyReleaseMask |
                 StructureNotifyMask;

    if (XGetWindowAttributes (xdisplay, xwin, &attr))
    {
        event_mask |= attr.your_event_mask;
    }

    XSelectInput (xdisplay, xwin, event_mask);

    info->window_group = meta_window_group_new (screen);
    info->background_actor = meta_background_actor_new_for_screen (screen);
    info->bottom_window_group = clutter_group_new();
    info->overlay_group = clutter_group_new ();
    info->top_window_group = meta_window_group_new (screen);
    info->hidden_group = clutter_group_new ();

    clutter_container_add (CLUTTER_CONTAINER (info->window_group),
                           info->background_actor,
                           NULL);

    clutter_container_add (CLUTTER_CONTAINER (info->stage),
                           info->window_group,
                           info->overlay_group,
                           info->hidden_group,
                           NULL);

    clutter_actor_hide (info->hidden_group);

    info->plugin_mgr =
        meta_plugin_manager_get (screen);
    meta_plugin_manager_initialize (info->plugin_mgr);

    /*
     * 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; 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);

    /* Make sure there isn't any left-over output shape on the
     * overlay window by setting the whole screen to be an
     * output region.
     *
     * Note: there doesn't seem to be any real chance of that
     *  because the X server will destroy the overlay window
     *  when the last client using it exits.
     */
    XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);

    do_set_stage_input_region (screen, info->pending_input_region);
    if (info->pending_input_region != None)
    {
        XFixesDestroyRegion (xdisplay, info->pending_input_region);
        info->pending_input_region = None;
    }

    clutter_actor_show (info->overlay_group);
    clutter_actor_show (info->stage);
}