コード例 #1
0
ファイル: compositor.c プロジェクト: MaximeMorel/mutter
void
meta_set_stage_input_region (MetaScreen   *screen,
                             XserverRegion region)
{
  /* As a wayland compositor we can simply ignore all this trickery
   * for setting an input region on the stage for capturing events in
   * clutter since all input comes to us first and we get to choose
   * who else sees them.
   */
  if (!meta_is_wayland_compositor ())
    {
      MetaDisplay *display = screen->display;
      MetaCompositor *compositor = display->compositor;
      Display *xdpy = meta_display_get_xdisplay (display);
      Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));

      XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);

      /* It's generally a good heuristic that when a crossing event is generated because
       * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
       * it's not the user doing something, it's the environment changing under the user.
       */
      meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
      XFixesSetWindowShapeRegion (xdpy, compositor->output, ShapeInput, 0, 0, region);
    }
}
コード例 #2
0
ファイル: compositor.c プロジェクト: nkoep/muffin
static void
do_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);
    Window        xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));

    XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);

    /* It's generally a good heuristic that when a crossing event is generated because
     * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
     * it's not the user doing something, it's the environment changing under the user.
     */
    meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
    XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
}
コード例 #3
0
ファイル: compositor.c プロジェクト: MaximeMorel/mutter
/**
 * meta_shape_cow_for_window:
 * @compositor: A #MetaCompositor
 * @window: (nullable): A #MetaWindow to shape the COW for
 *
 * Sets an bounding shape on the COW so that the given window
 * is exposed. If @window is %NULL it clears the shape again.
 *
 * Used so we can unredirect windows, by shaping away the part
 * of the COW, letting the raw window be seen through below.
 */
static void
meta_shape_cow_for_window (MetaCompositor *compositor,
                           MetaWindow *window)
{
  MetaDisplay *display = compositor->display;
  Display *xdisplay = meta_display_get_xdisplay (display);

  if (window == NULL)
    XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, None);
  else
    {
      XserverRegion output_region;
      XRectangle screen_rect, window_bounds;
      int width, height;
      MetaRectangle rect;

      meta_window_get_frame_rect (window, &rect);

      window_bounds.x = rect.x;
      window_bounds.y = rect.y;
      window_bounds.width = rect.width;
      window_bounds.height = rect.height;

      meta_screen_get_size (display->screen, &width, &height);
      screen_rect.x = 0;
      screen_rect.y = 0;
      screen_rect.width = width;
      screen_rect.height = height;

      output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);

      XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
      XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, output_region);
      XFixesDestroyRegion (xdisplay, output_region);
    }
}
コード例 #4
0
ファイル: compositor.c プロジェクト: nkoep/muffin
/*
 * Shapes the cow so that the given window is exposed,
 * when metaWindow is NULL it clears the shape again
 */
static void
meta_shape_cow_for_window (MetaScreen *screen,
                           MetaWindow *metaWindow)
{
    MetaCompScreen *info = meta_screen_get_compositor_data (screen);
    Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));

    if (metaWindow == NULL)
        XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
    else
    {
        XserverRegion output_region;
        XRectangle screen_rect, window_bounds;
        int width, height;
        MetaRectangle rect;

        meta_window_get_outer_rect (metaWindow, &rect);

        window_bounds.x = rect.x;
        window_bounds.y = rect.y;
        window_bounds.width = rect.width;
        window_bounds.height = rect.height;

        meta_screen_get_size (screen, &width, &height);
        screen_rect.x = 0;
        screen_rect.y = 0;
        screen_rect.width = width;
        screen_rect.height = height;

        output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);

        XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
        XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, output_region);
        XFixesDestroyRegion (xdisplay, output_region);
    }
}
コード例 #5
0
EAPI void
ecore_x_region_window_shape_set(Ecore_X_Region     region,
                                Ecore_X_Window     win,
                                Ecore_X_Shape_Type type,
                                int                x_offset,
                                int                y_offset)
{
#ifdef ECORE_XFIXES
   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   XFixesSetWindowShapeRegion(_ecore_x_disp,
                              win,
                              type,
                              x_offset,
                              y_offset,
                              region);
#endif /* ifdef ECORE_XFIXES */
} /* ecore_x_region_window_shape_set */
コード例 #6
0
ファイル: effect.cpp プロジェクト: creideiki/qt-ponies
EffectInstance::EffectInstance(Effect *owner, int64_t started, bool right, QWidget *parent)
    :QMainWindow(parent), time_started(started), label(this), owner(owner)
{
    // Set window properties the same as the pony window
    setAttribute(Qt::WA_TranslucentBackground, true);
    setAttribute(Qt::WA_ShowWithoutActivating);

#ifdef Q_WS_X11
    // Disables shadows under the pony window.
    setAttribute(Qt::WA_X11NetWmWindowTypeDock);
#endif

#if defined QT_MAC_USE_COCOA && QT_VERSION >= 0x040800
    // Removes shadows that lag behind animation on OS X. QT 4.8+ needed.
    setAttribute(Qt::WA_MacNoShadow, true);
#endif

#ifdef QT_MAC_USE_COCOA
    // On OS X, tool windows are hidden when another program gains focus.
    Qt::WindowFlags windowflags = Qt::FramelessWindowHint;
#else
    Qt::WindowFlags windowflags = Qt::FramelessWindowHint | Qt::Tool;
#endif

    if(ConfigWindow::getSetting<bool>("general/always-on-top")) {
        windowflags |= Qt::WindowStaysOnTopHint;
    }

#ifdef Q_WS_X11
    if(ConfigWindow::getSetting<bool>("general/bypass-wm")) {
        // Bypass the window manager
        windowflags |= Qt::X11BypassWindowManagerHint;
    }
#endif

    setWindowFlags( windowflags );

#ifdef Q_WS_X11
    // Qt on X11 does not support the skip taskbar/pager window flags, we have to set them ourselves
    // We let Qt initialize the other window properties, which aren't deleted when we replace them with ours
    // (they probably are appended on show())
    Atom window_state = XInternAtom( QX11Info::display(), "_NET_WM_STATE", False );
    Atom window_props[] = {
        XInternAtom( QX11Info::display(), "_NET_WM_STATE_SKIP_TASKBAR", False ),
        XInternAtom( QX11Info::display(), "_NET_WM_STATE_SKIP_PAGER"  , False )
    };

    XChangeProperty( QX11Info::display(), window()->winId(), window_state, XA_ATOM, 32, PropModeReplace, (unsigned char*)&window_props, 2 );

    // Set a null input region mask for the event window, so that it does not interfere with mouseover effects.
    XRectangle rect{0,0,0,0};
    XserverRegion shapeRegion = XFixesCreateRegion(QX11Info::display(), &rect, 1);
    XFixesSetWindowShapeRegion(QX11Info::display(), winId(), ShapeInput, 0, 0, shapeRegion);
    XFixesDestroyRegion(QX11Info::display(), shapeRegion);
#endif
    // TODO: add WS_EX_TRANSPARENT extended window style on windows.

#ifdef Q_WS_X11
    // Make sure the effect gets drawn on the same desktop as the pony
    Atom wm_desktop = XInternAtom(QX11Info::display(), "_NET_WM_DESKTOP", False);
    Atom type_ret;
    int fmt_ret;
    unsigned long nitems_ret;
    unsigned long bytes_after_ret;
    int *desktop = NULL;

    if(XGetWindowProperty(QX11Info::display(), owner->parent_pony->window()->winId(), wm_desktop, 0, 1,
                          False, XA_CARDINAL, &type_ret, &fmt_ret,
                          &nitems_ret, &bytes_after_ret, reinterpret_cast<unsigned char **>(&desktop))
       == Success && desktop != NULL) {
       XChangeProperty(QX11Info::display(), window()->winId(), wm_desktop, XA_CARDINAL, 32, PropModeReplace,
                       reinterpret_cast<unsigned char*>(desktop), 1);
       XFree(desktop);
    }
#endif

    // Load animations and verify them
    // TODO: Do we need to change the direction of active effects? Maybe we only need to display the image for the direction at witch it was spawned.
    animation_left = new QMovie(QString("%1/%2/%3").arg(ConfigWindow::getSetting<QString>("general/pony-directory"), owner->path, owner->image_left ));
    animation_right = new QMovie(QString("%1/%2/%3").arg(ConfigWindow::getSetting<QString>("general/pony-directory"), owner->path, owner->image_right));

    if(!animation_left->isValid())
        qCritical() << "Effect:"<< owner->path <<"Error opening left animation:"<< owner->image_left << "for effect:"<< owner->name;
    if(!animation_right->isValid())
        qCritical() << "Effect:"<< owner->path <<"Error opening right animation:"<< owner->image_right << "for behavior:"<< owner->name;

    animation_left->setCacheMode(QMovie::CacheAll);
    animation_right->setCacheMode(QMovie::CacheAll);

    if(right){
        current_animation = animation_right;
    }else{
        current_animation = animation_left;
    }

    current_animation->jumpToFrame(0);

    image_width = current_animation->currentImage().width();
    image_height = current_animation->currentImage().height();

    if(right){
        offset = get_location(owner->location_right, owner->center_right);
    }else{
        offset = get_location(owner->location_left, owner->center_left);
    }

    current_animation->start();
    update_animation();
    show();
}
コード例 #7
0
ファイル: compositor.c プロジェクト: MaximeMorel/mutter
void
meta_compositor_manage (MetaCompositor *compositor)
{
  MetaDisplay *display = compositor->display;
  Display *xdisplay = display->xdisplay;
  MetaScreen *screen = display->screen;
  MetaBackend *backend = meta_get_backend ();

  meta_screen_set_cm_selection (display->screen);

  compositor->stage = meta_backend_get_stage (backend);

  /* We use connect_after() here to accomodate code in GNOME Shell that,
   * when benchmarking drawing performance, connects to ::after-paint
   * and calls glFinish(). The timing information from that will be
   * more accurate if we hold off until that completes before we signal
   * apps to begin drawing the next frame. If there are no other
   * connections to ::after-paint, connect() vs. connect_after() doesn't
   * matter.
   */
  g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
                          G_CALLBACK (after_stage_paint), compositor);

  clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);

  compositor->window_group = meta_window_group_new (screen);
  compositor->top_window_group = meta_window_group_new (screen);
  compositor->feedback_group = meta_window_group_new (screen);

  clutter_actor_add_child (compositor->stage, compositor->window_group);
  clutter_actor_add_child (compositor->stage, compositor->top_window_group);
  clutter_actor_add_child (compositor->stage, compositor->feedback_group);

  if (meta_is_wayland_compositor ())
    {
      /* NB: When running as a wayland compositor we don't need an X
       * composite overlay window, and we don't need to play any input
       * region tricks to redirect events into clutter. */
      compositor->output = None;
    }
  else
    {
      Window xwin;

      compositor->output = screen->composite_overlay_window;

      xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));

      XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);

      meta_empty_stage_input_region (screen);

      /* 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, compositor->output, ShapeBounding, 0, 0, None);

      /* Map overlay window before redirecting windows offscreen so we catch their
       * contents until we show the stage.
       */
      XMapWindow (xdisplay, compositor->output);

      compositor->have_x11_sync_object = meta_sync_ring_init (xdisplay);
    }

  redirect_windows (display->screen);

  compositor->plugin_mgr = meta_plugin_manager_new (compositor);
}
コード例 #8
0
ファイル: main.c プロジェクト: czaber/ogwm
void ignore_input(Window w) {
	XserverRegion region = XFixesCreateRegion(dpy, NULL, 0);
	XFixesSetWindowShapeRegion(dpy, w, ShapeBounding, 0, 0, 0);
	XFixesSetWindowShapeRegion(dpy, w, ShapeInput, 0, 0, region);
	XFixesDestroyRegion(dpy, region);
}
コード例 #9
0
ファイル: tablet.c プロジェクト: kingctan/fcitx-tablet
// Creates the event addon
void* FcitxTabletCreate(FcitxInstance* instance) {
	FcitxTablet* tablet = fcitx_utils_new(FcitxTablet);
	FcitxTabletLoadConfig(&tablet->config);
	// TODO select driver from config, currently using lxbi

	{ // Initialise the driver
		switch(tablet->config.Driver) {
		case DRIVER_LXBI:
			tablet->driverInstance = &lxbi;
		break;
		// add other drivers here
		}
		tablet->driverData = tablet->driverInstance->Create();
		tablet->driverPacket = (char*) malloc(tablet->driverInstance->packet_size);
	}

	{ // Initialise the X display
		if(NULL == (tablet->xDisplay = FcitxX11GetDisplay(instance)))  {
			FcitxLog(ERROR, "Unable to open X display");
			return NULL;
		}
		// get dimensions
		int screen = DefaultScreen(tablet->xDisplay);
		tablet->xWidth = tablet->config.Width;
		tablet->xHeight = tablet->config.Height;
		int x = tablet->config.XPos > 0 ? tablet->config.XPos : XDisplayWidth(tablet->xDisplay, screen) - tablet->xWidth + tablet->config.XPos;
		int y = tablet->config.YPos > 0 ? tablet->config.YPos : XDisplayHeight(tablet->xDisplay, screen) - tablet->xHeight + tablet->config.YPos;
		// create colours
		XColor back;
		XColor fore;
		{
			char colourString[32];
			{
				int r = (255*tablet->config.BackgroundColour.r);
				int g = (255*tablet->config.BackgroundColour.g);
				int b = (255*tablet->config.BackgroundColour.b);
				sprintf(colourString,"rgb:%x/%x/%x",r,g,b);
			}
			Colormap defaultCMap = DefaultColormap(tablet->xDisplay, screen);
			XParseColor(tablet->xDisplay, defaultCMap, colourString, &back);
			XAllocColor(tablet->xDisplay, defaultCMap, &back);
			{
				int r = (255*tablet->config.StrokeColour.r);
				int g = (255*tablet->config.StrokeColour.g);
				int b = (255*tablet->config.StrokeColour.b);
				sprintf(colourString,"rgb:%x/%x/%x",r,g,b);
			}
			XParseColor(tablet->xDisplay, defaultCMap, colourString, &fore);
			XAllocColor(tablet->xDisplay, defaultCMap, &fore);
		}
		// set window attributes and create window
		XSetWindowAttributes attrs;
		attrs.override_redirect = True;
		attrs.background_pixel = back.pixel;
		tablet->xWindow = XCreateWindow(tablet->xDisplay, DefaultRootWindow(tablet->xDisplay),
			 x, y, tablet->xWidth, tablet->xHeight, tablet->config.BorderWidth, CopyFromParent,
			 InputOutput, CopyFromParent, CWBackPixel | CWOverrideRedirect, &attrs);
		// set up the foreground line (stroke) style
		XGCValues gcv;
		gcv.function = GXcopy;
		gcv.subwindow_mode = IncludeInferiors;
		gcv.line_width = 3;
		gcv.cap_style = CapRound;
		gcv.join_style = JoinRound;
		tablet->xGC = XCreateGC(tablet->xDisplay, tablet->xWindow, GCFunction | GCSubwindowMode | GCLineWidth | GCCapStyle | GCJoinStyle, &gcv);
		XSetForeground(tablet->xDisplay, tablet->xGC, fore.pixel);
		// prevent the window from getting focus or input
		XRectangle rect = {0,0,0,0};
		XserverRegion region = XFixesCreateRegion(tablet->xDisplay,&rect, 1);
		XFixesSetWindowShapeRegion(tablet->xDisplay, tablet->xWindow, ShapeInput, 0, 0, region);
		XFixesDestroyRegion(tablet->xDisplay, region);
	}

	{ // Initialise the stroke buffer
		tablet->strokesBufferSize = 2048; // should be heaps. Will get automatically enlarged if required
		tablet->strokesBuffer = (pt_t*) malloc(sizeof(pt_t) * tablet->strokesBufferSize);
		tablet->strokesPtr = tablet->strokesBuffer;
	}

	{ // instantiate the engine
		switch(tablet->config.Engine) {
		case ENGINE_ZINNIA:
			tablet->engineInstance = &engZinnia;
			break;
		case ENGINE_FORK:
			tablet->engineInstance = &engFork;
			break;
		// add other engines here
		}
		tablet->engineData = tablet->engineInstance->Create(&tablet->config);
	}

	{ // set up the timerfd
		tablet->timeoutFd = timerfd_create(CLOCK_MONOTONIC, 0);
		tablet->delay.it_interval.tv_sec = 0;
		tablet->delay.it_interval.tv_nsec = 0;
		tablet->delay.it_value.tv_sec = tablet->config.CommitCharMs / 1000;
		tablet->delay.it_value.tv_nsec = (tablet->config.CommitCharMs % 1000) * 1000000;
		tablet->timeoutCommitPending = 0;
	}

	tablet->fcitx = instance;
	return tablet;
}
コード例 #10
0
ファイル: compositor.c プロジェクト: kelsieflynn/mutter
void
meta_compositor_manage (MetaCompositor *compositor)
{
  MetaDisplay *display = compositor->display;
  Display *xdisplay = display->xdisplay;
  MetaScreen *screen = display->screen;
  Window xwin = 0;
  gint width, height;

  meta_screen_set_cm_selection (display->screen);

  if (meta_is_wayland_compositor ())
    {
      MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();

      compositor->stage = meta_stage_new ();

      wayland_compositor->stage = compositor->stage;

      meta_screen_get_size (screen, &width, &height);
      clutter_actor_set_size (compositor->stage, width, height);
      clutter_actor_show (compositor->stage);
    }
  else
    {
      compositor->stage = clutter_stage_new ();

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

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

      XResizeWindow (xdisplay, xwin, width, height);

        {
          MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
          Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
          unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
          XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };

          XISetMask (mask.mask, XI_KeyPress);
          XISetMask (mask.mask, XI_KeyRelease);
          XISetMask (mask.mask, XI_ButtonPress);
          XISetMask (mask.mask, XI_ButtonRelease);
          XISetMask (mask.mask, XI_Enter);
          XISetMask (mask.mask, XI_Leave);
          XISetMask (mask.mask, XI_FocusIn);
          XISetMask (mask.mask, XI_FocusOut);
          XISetMask (mask.mask, XI_Motion);
          XIClearMask (mask.mask, XI_TouchBegin);
          XIClearMask (mask.mask, XI_TouchEnd);
          XIClearMask (mask.mask, XI_TouchUpdate);
          XISelectEvents (backend_xdisplay, xwin, &mask, 1);
        }
    }

  /* We use connect_after() here to accomodate code in GNOME Shell that,
   * when benchmarking drawing performance, connects to ::after-paint
   * and calls glFinish(). The timing information from that will be
   * more accurate if we hold off until that completes before we signal
   * apps to begin drawing the next frame. If there are no other
   * connections to ::after-paint, connect() vs. connect_after() doesn't
   * matter.
   */
  g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
                          G_CALLBACK (after_stage_paint), compositor);

  clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);

  compositor->window_group = meta_window_group_new (screen);
  compositor->top_window_group = meta_window_group_new (screen);

  clutter_actor_add_child (compositor->stage, compositor->window_group);
  clutter_actor_add_child (compositor->stage, compositor->top_window_group);

  if (meta_is_wayland_compositor ())
    {
      /* NB: When running as a wayland compositor we don't need an X
       * composite overlay window, and we don't need to play any input
       * region tricks to redirect events into clutter. */
      compositor->output = None;
    }
  else
    {
      compositor->output = screen->composite_overlay_window;

      XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);

      meta_empty_stage_input_region (screen);

      /* 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, compositor->output, ShapeBounding, 0, 0, None);

      /* Map overlay window before redirecting windows offscreen so we catch their
       * contents until we show the stage.
       */
      XMapWindow (xdisplay, compositor->output);
    }

  redirect_windows (display->screen);

  compositor->plugin_mgr = meta_plugin_manager_new (compositor);
}
コード例 #11
0
ファイル: compositor.c プロジェクト: nkoep/muffin
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);
}