示例#1
0
static gboolean
meta_backend_x11_nested_handle_host_xevent (MetaBackendX11 *x11,
                                            XEvent         *event)
{
#ifdef HAVE_WAYLAND
  if (event->type == FocusIn)
    {
      Window xwin = meta_backend_x11_get_xwindow (x11);
      XEvent xev;

      if (event->xfocus.window == xwin)
        {
          MetaWaylandCompositor *compositor =
            meta_wayland_compositor_get_default ();
          Display *xdisplay = meta_backend_x11_get_xdisplay (x11);

          /*
           * Since we've selected for KeymapStateMask, every FocusIn is
           * followed immediately by a KeymapNotify event.
           */
          XMaskEvent (xdisplay, KeymapStateMask, &xev);
          meta_wayland_compositor_update_key_state (compositor,
                                                    xev.xkeymap.key_vector,
                                                    32, 8);
        }
    }
#endif

  return FALSE;
}
示例#2
0
void
meta_xwayland_handle_wl_surface_id (MetaWindow *window,
                                    guint32     surface_id)
{
  MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
  MetaXWaylandManager *manager = &compositor->xwayland_manager;

  if (!associate_window_with_surface_id (manager, window, surface_id))
    {
      /* No surface ID yet... it should arrive after the next
       * iteration through the loop, so queue a later and see
       * what happens.
       */
      AssociateWindowWithSurfaceOp *op = g_new0 (AssociateWindowWithSurfaceOp, 1);
      op->manager = manager;
      op->window = window;
      op->surface_id = surface_id;
      op->later_id = meta_later_add (META_LATER_BEFORE_REDRAW,
                                     associate_window_with_surface_later,
                                     op,
                                     NULL);

      g_signal_connect (op->window, "unmanaged",
                        G_CALLBACK (associate_window_with_surface_window_unmanaged), op);
    }
}
示例#3
0
void
meta_wayland_finalize (void)
{
  MetaWaylandCompositor *compositor;

  compositor = meta_wayland_compositor_get_default ();

  meta_xwayland_stop (&compositor->xwayland_manager);
}
示例#4
0
void
meta_wayland_init (void)
{
  MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
  GSource *wayland_event_source;

  if (!wl_global_create (compositor->wayland_display,
			 &wl_compositor_interface,
			 META_WL_COMPOSITOR_VERSION,
			 compositor, compositor_bind))
    g_error ("Failed to register the global wl_compositor");

  wayland_event_source = wayland_event_source_new (compositor->wayland_display);

  /* XXX: Here we are setting the wayland event source to have a
   * slightly lower priority than the X event source, because we are
   * much more likely to get confused being told about surface changes
   * relating to X clients when we don't know what's happened to them
   * according to the X protocol.
   *
   * At some point we could perhaps try and get the X protocol proxied
   * over the wayland protocol so that we don't have to worry about
   * synchronizing the two command streams. */
  g_source_set_priority (wayland_event_source, GDK_PRIORITY_EVENTS + 1);
  g_source_attach (wayland_event_source, NULL);

  wl_display_init_shm (compositor->wayland_display);

  meta_wayland_outputs_init (compositor);
  meta_wayland_data_device_manager_init (compositor);
  meta_wayland_shell_init (compositor);
  meta_wayland_seat_init (compositor);

  /* FIXME: find the first free name instead */
  compositor->display_name = wl_display_add_socket_auto (compositor->wayland_display);
  if (compositor->display_name == NULL)
    g_error ("Failed to create socket");

  /* XXX: It's important that we only try and start xwayland after we
   * have initialized EGL because EGL implements the "wl_drm"
   * interface which xwayland requires to determine what drm device
   * name it should use.
   *
   * By waiting until we've shown the stage above we ensure that the
   * underlying GL resources for the surface have also been allocated
   * and so EGL must be initialized by this point.
   */

  if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
    g_error ("Failed to start X Wayland");

  set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor));
  set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor));
}
示例#5
0
static void
after_stage_paint (ClutterStage *stage,
                   gpointer      data)
{
  MetaCompositor *compositor = data;
  GList *l;

  for (l = compositor->windows; l; l = l->next)
    meta_window_actor_post_paint (l->data);

  if (meta_is_wayland_compositor ())
    meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
}
示例#6
0
static TestClient *
test_client_new (const char          *id,
                 MetaWindowClientType type,
                 GError             **error)
{
  TestClient *client = g_new0 (TestClient, 1);
  GSubprocessLauncher *launcher;
  GSubprocess *subprocess;

  launcher =  g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);

  g_assert (meta_is_wayland_compositor ());
  MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();

  g_subprocess_launcher_setenv (launcher,
                                "WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor),
                                TRUE);
  g_subprocess_launcher_setenv (launcher,
                                "DISPLAY", meta_wayland_get_xwayland_display_name (compositor),
                                TRUE);

  subprocess = g_subprocess_launcher_spawn (launcher,
                                            error,
                                            test_client_path,
                                            "--client-id",
                                            id,
                                            type == META_WINDOW_CLIENT_TYPE_WAYLAND ? "--wayland" : NULL,
                                            NULL);
  g_object_unref (launcher);

  if (!subprocess)
    return NULL;

  client->type = type;
  client->id = g_strdup (id);
  client->cancellable = g_cancellable_new ();
  client->subprocess = subprocess;
  client->in = g_data_output_stream_new (g_subprocess_get_stdin_pipe (subprocess));
  client->out = g_data_input_stream_new (g_subprocess_get_stdout_pipe (subprocess));
  client->loop = g_main_loop_new (NULL, FALSE);

  if (client->type == META_WINDOW_CLIENT_TYPE_X11)
    client->waiter = async_waiter_new ();

  return client;
}
示例#7
0
static void
handle_host_xevent (MetaBackend *backend,
                    XEvent      *event)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  gboolean bypass_clutter = FALSE;

  XGetEventData (priv->xdisplay, &event->xcookie);

  {
    MetaDisplay *display = meta_get_display ();

    if (display)
      {
        MetaCompositor *compositor = display->compositor;
        if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
          bypass_clutter = TRUE;
      }
  }

  if (priv->mode == META_BACKEND_X11_MODE_NESTED && event->type == FocusIn)
    {
#ifdef HAVE_WAYLAND
      Window xwin = meta_backend_x11_get_xwindow(x11);
      XEvent xev;

      if (event->xfocus.window == xwin)
        {
          /* Since we've selected for KeymapStateMask, every FocusIn is followed immediately
           * by a KeymapNotify event */
          XMaskEvent(priv->xdisplay, KeymapStateMask, &xev);
          MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
          meta_wayland_compositor_update_key_state (compositor, xev.xkeymap.key_vector, 32, 8);
        }
#else
      g_assert_not_reached ();
#endif
    }

  if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
    handle_alarm_notify (backend, event);

  if (event->type == priv->xkb_event_base)
    {
      XkbEvent *xkb_ev = (XkbEvent *) event;

      if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID)
        {
          switch (xkb_ev->any.xkb_type)
            {
            case XkbNewKeyboardNotify:
            case XkbMapNotify:
              keymap_changed (backend);
              break;
            case XkbStateNotify:
              if (xkb_ev->state.changed & XkbGroupLockMask)
                {
                  if (priv->locked_group != xkb_ev->state.locked_group)
                    XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, priv->locked_group);
                }
              break;
            default:
              break;
            }
        }
    }

  {
    MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
    if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
        meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
      bypass_clutter = TRUE;
  }

  if (!bypass_clutter)
    {
      handle_input_event (x11, event);
      clutter_x11_handle_event (event);
    }

  XFreeEventData (priv->xdisplay, &event->xcookie);
}
示例#8
0
static gboolean
meta_display_handle_event (MetaDisplay        *display,
                           const ClutterEvent *event)
{
  MetaWindow *window;
  gboolean bypass_clutter = FALSE;
  G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
  MetaGestureTracker *tracker;
  ClutterEventSequence *sequence;
  ClutterInputDevice *source;

  sequence = clutter_event_get_event_sequence (event);

  /* Set the pointer emulating sequence on touch begin, if eligible */
  if (event->type == CLUTTER_TOUCH_BEGIN)
    {
      if (sequence_is_pointer_emulated (display, event))
        {
          /* This is the new pointer emulating sequence */
          display->pointer_emulating_sequence = sequence;
        }
      else if (display->pointer_emulating_sequence == sequence)
        {
          /* This sequence was "pointer emulating" in a prior incarnation,
           * but now it isn't. We unset the pointer emulating sequence at
           * this point so the current sequence is not mistaken as pointer
           * emulating, while we've ensured that it's been deemed
           * "pointer emulating" throughout all of the event processing
           * of the previous incarnation.
           */
          display->pointer_emulating_sequence = NULL;
        }
    }

#ifdef HAVE_WAYLAND
  MetaWaylandCompositor *compositor = NULL;
  if (meta_is_wayland_compositor ())
    {
      compositor = meta_wayland_compositor_get_default ();
      meta_wayland_compositor_update (compositor, event);
    }
#endif

  if (!display->current_pad_osd &&
      (event->type == CLUTTER_PAD_BUTTON_PRESS ||
       event->type == CLUTTER_PAD_BUTTON_RELEASE))
    {
      MetaBackend *backend = meta_get_backend ();

      if (meta_input_settings_handle_pad_button (meta_backend_get_input_settings (backend),
                                                 clutter_event_get_source_device (event),
                                                 event->type == CLUTTER_PAD_BUTTON_PRESS,
                                                 event->pad_button.button))
        {
          bypass_wayland = bypass_clutter = TRUE;
          goto out;
        }
    }

  source = clutter_event_get_source_device (event);

  if (source)
    {
      meta_backend_update_last_device (meta_get_backend (),
                                       clutter_input_device_get_device_id (source));
    }

#ifdef HAVE_WAYLAND
  if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
    {
      MetaWaylandCompositor *compositor;

      compositor = meta_wayland_compositor_get_default ();

      if (meta_wayland_tablet_manager_consumes_event (compositor->tablet_manager, event))
        {
          meta_wayland_tablet_manager_update_cursor_position (compositor->tablet_manager, event);
        }
      else
        {
          MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
          meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
        }

      display->monitor_cache_invalidated = TRUE;
    }
#endif

  handle_idletime_for_event (event);

  window = get_window_for_event (display, event);

  display->current_time = event->any.time;

  if (window && !window->override_redirect &&
      (event->type == CLUTTER_KEY_PRESS ||
       event->type == CLUTTER_BUTTON_PRESS ||
       event->type == CLUTTER_TOUCH_BEGIN))
    {
      if (CurrentTime == display->current_time)
        {
          /* We can't use missing (i.e. invalid) timestamps to set user time,
           * nor do we want to use them to sanity check other timestamps.
           * See bug 313490 for more details.
           */
          meta_warning ("Event has no timestamp! You may be using a broken "
                        "program such as xse.  Please ask the authors of that "
                        "program to fix it.\n");
        }
      else
        {
          meta_window_set_user_time (window, display->current_time);
          meta_display_sanity_check_timestamps (display, display->current_time);
        }
    }

  tracker = meta_display_get_gesture_tracker (display);

  if (meta_gesture_tracker_handle_event (tracker, event))
    {
      bypass_wayland = bypass_clutter = TRUE;
      goto out;
    }

  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
    {
      if (meta_window_handle_mouse_grab_op_event (window, event))
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
          goto out;
        }
    }

  /* For key events, it's important to enforce single-handling, or
   * we can get into a confused state. So if a keybinding is
   * handled (because it's one of our hot-keys, or because we are
   * in a keyboard-grabbed mode like moving a window, we don't
   * want to pass the key event to the compositor or Wayland at all.
   */
  if (meta_keybindings_process_event (display, window, event))
    {
      bypass_clutter = TRUE;
      bypass_wayland = TRUE;
      goto out;
    }

  /* Do not pass keyboard events to Wayland if key focus is not on the
   * stage in normal mode (e.g. during keynav in the panel)
   */
  if (display->event_route == META_EVENT_ROUTE_NORMAL)
    {
      if (IS_KEY_EVENT (event) && !stage_has_key_focus ())
        {
          bypass_wayland = TRUE;
          goto out;
        }
    }

  if (display->current_pad_osd)
    {
      bypass_wayland = TRUE;
      goto out;
    }

  if (window)
    {
      /* Events that are likely to trigger compositor gestures should
       * be known to clutter so they can propagate along the hierarchy.
       * Gesture-wise, there's two groups of events we should be getting
       * here:
       * - CLUTTER_TOUCH_* with a touch sequence that's not yet accepted
       *   by the gesture tracker, these might trigger gesture actions
       *   into recognition. Already accepted touch sequences are handled
       *   directly by meta_gesture_tracker_handle_event().
       * - CLUTTER_TOUCHPAD_* events over windows. These can likewise
       *   trigger ::captured-event handlers along the way.
       */
      bypass_clutter = !IS_GESTURE_EVENT (event);

      meta_window_handle_ungrabbed_event (window, event);

      /* This might start a grab op. If it does, then filter out the
       * event, and if it doesn't, replay the event to release our
       * own sync grab. */

      if (display->event_route == META_EVENT_ROUTE_WINDOW_OP ||
          display->event_route == META_EVENT_ROUTE_FRAME_BUTTON)
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
        }
      else
        {
          /* Only replay button press events, since that's where we
           * have the synchronous grab. */
          if (event->type == CLUTTER_BUTTON_PRESS)
            {
              MetaBackend *backend = meta_get_backend ();
              if (META_IS_BACKEND_X11 (backend))
                {
                  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
                  meta_verbose ("Allowing events time %u\n",
                                (unsigned int)event->button.time);
                  XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
                                 XIReplayDevice, event->button.time);
                }
            }
        }

      goto out;
    }

 out:
  /* If the compositor has a grab, don't pass that through to Wayland */
  if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
    bypass_wayland = TRUE;

  /* If a Wayland client has a grab, don't pass that through to Clutter */
  if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP)
    bypass_clutter = TRUE;

#ifdef HAVE_WAYLAND
  if (compositor && !bypass_wayland)
    {
      if (meta_wayland_compositor_handle_event (compositor, event))
        bypass_clutter = TRUE;
    }
#endif

  display->current_time = CurrentTime;
  return bypass_clutter;
}
示例#9
0
文件: events.c 项目: mchalupa/mutter
static gboolean
meta_display_handle_event (MetaDisplay        *display,
                           const ClutterEvent *event)
{
  MetaWindow *window;
  gboolean bypass_clutter = FALSE;
  G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
  MetaGestureTracker *tracker;
  ClutterEventSequence *sequence;

  sequence = clutter_event_get_event_sequence (event);

  /* Set the pointer emulating sequence on touch begin, if eligible */
  if (event->type == CLUTTER_TOUCH_BEGIN &&
      !display->pointer_emulating_sequence &&
      sequence_is_pointer_emulated (display, event))
    display->pointer_emulating_sequence = sequence;

#ifdef HAVE_WAYLAND
  MetaWaylandCompositor *compositor = NULL;
  if (meta_is_wayland_compositor ())
    {
      compositor = meta_wayland_compositor_get_default ();
      meta_wayland_compositor_update (compositor, event);
    }
#endif

  if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
    {
      MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
      meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
    }

  handle_idletime_for_event (event);

  window = get_window_for_event (display, event);

  display->current_time = event->any.time;

  if (window && !window->override_redirect &&
      (event->type == CLUTTER_KEY_PRESS ||
       event->type == CLUTTER_BUTTON_PRESS ||
       event->type == CLUTTER_TOUCH_BEGIN))
    {
      if (CurrentTime == display->current_time)
        {
          /* We can't use missing (i.e. invalid) timestamps to set user time,
           * nor do we want to use them to sanity check other timestamps.
           * See bug 313490 for more details.
           */
          meta_warning ("Event has no timestamp! You may be using a broken "
                        "program such as xse.  Please ask the authors of that "
                        "program to fix it.\n");
        }
      else
        {
          meta_window_set_user_time (window, display->current_time);
          meta_display_sanity_check_timestamps (display, display->current_time);
        }
    }

  tracker = meta_display_get_gesture_tracker (display);

  if (meta_gesture_tracker_handle_event (tracker, event))
    {
      bypass_wayland = bypass_clutter = TRUE;
      goto out;
    }

  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
    {
      if (meta_window_handle_mouse_grab_op_event (window, event))
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
          goto out;
        }
    }

  /* For key events, it's important to enforce single-handling, or
   * we can get into a confused state. So if a keybinding is
   * handled (because it's one of our hot-keys, or because we are
   * in a keyboard-grabbed mode like moving a window, we don't
   * want to pass the key event to the compositor or Wayland at all.
   */
  if (meta_keybindings_process_event (display, window, event))
    {
      bypass_clutter = TRUE;
      bypass_wayland = TRUE;
      goto out;
    }

  if (window)
    {
      if (!clutter_event_get_event_sequence (event))
        {
          /* Swallow all non-touch events on windows that come our way.
           * Touch events that reach here aren't yet in an accepted state,
           * so Clutter must see them to maybe trigger gestures into
           * recognition.
           */
          bypass_clutter = TRUE;
        }

      meta_window_handle_ungrabbed_event (window, event);

      /* This might start a grab op. If it does, then filter out the
       * event, and if it doesn't, replay the event to release our
       * own sync grab. */

      if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
        }
      else
        {
          /* Only replay button press events, since that's where we
           * have the synchronous grab. */
          if (event->type == CLUTTER_BUTTON_PRESS)
            {
              MetaBackend *backend = meta_get_backend ();
              if (META_IS_BACKEND_X11 (backend))
                {
                  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
                  meta_verbose ("Allowing events time %u\n",
                                (unsigned int)event->button.time);
                  XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
                                 XIReplayDevice, event->button.time);
                }
            }
        }

      goto out;
    }

 out:
  /* If the compositor has a grab, don't pass that through to Wayland */
  if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
    bypass_wayland = TRUE;

  /* If a Wayland client has a grab, don't pass that through to Clutter */
  if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP)
    bypass_clutter = TRUE;

#ifdef HAVE_WAYLAND
  if (compositor && !bypass_wayland)
    {
      if (meta_wayland_compositor_handle_event (compositor, event))
        bypass_clutter = TRUE;
    }
#endif

  /* Unset the pointer emulating sequence after its end event is processed */
  if (event->type == CLUTTER_TOUCH_END &&
      display->pointer_emulating_sequence == sequence)
    display->pointer_emulating_sequence = NULL;

  display->current_time = CurrentTime;
  return bypass_clutter;
}
示例#10
0
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);
}