static void
clutter_backend_win32_dispose (GObject *gobject)
{
  ClutterBackend *backend = CLUTTER_BACKEND (gobject);
  ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (gobject);
  ClutterStageManager *stage_manager;

  CLUTTER_NOTE (BACKEND, "Disposing the of stages");
  stage_manager = clutter_stage_manager_get_default ();

  g_object_unref (stage_manager);

  CLUTTER_NOTE (BACKEND, "Removing the event source");
  _clutter_backend_win32_events_uninit (CLUTTER_BACKEND (backend_win32));

  /* Unrealize all shaders, since the GL context is going away */
  _clutter_shader_release_all ();

  G_OBJECT_CLASS (clutter_backend_win32_parent_class)->dispose (gobject);

  if (backend->cogl_context)
    {
      cogl_object_unref (backend->cogl_context);
      backend->cogl_context = NULL;
    }
}
示例#2
0
static void
events_queue (ClutterBackendX11 *backend_x11)
{
  ClutterBackend *backend = CLUTTER_BACKEND (backend_x11);
  Display *xdisplay = backend_x11->xdpy;
  ClutterEvent *event;
  XEvent xevent;

  while (!clutter_events_pending () && XPending (xdisplay))
    {
      XNextEvent (xdisplay, &xevent);

      event = clutter_event_new (CLUTTER_NOTHING);

#ifdef HAVE_XGE
      XGetEventData (xdisplay, &xevent.xcookie);
#endif

      if (_clutter_backend_translate_event (backend, &xevent, event))
        _clutter_event_push (event, FALSE);
      else
        clutter_event_free (event);

#ifdef HAVE_XGE
      XFreeEventData (xdisplay, &xevent.xcookie);
#endif
    }
}
示例#3
0
static void
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
{
    ClutterBackend *backend = CLUTTER_BACKEND (backend_egl);
    ClutterMainContext  *context;
    int i;

    clutter_backend_set_resolution (backend, 96.0);
    clutter_backend_set_double_click_time (backend, 250);
    clutter_backend_set_double_click_distance (backend, 5);

    context = _clutter_context_get_default ();

#define MAX_FINGERS     5

    for (i = 0; i < MAX_FINGERS; i++)
    {
        ClutterFruityFingerDevice *device;

        device = g_new0 (ClutterFruityFingerDevice, 1);
        context->input_devices = g_slist_append (context->input_devices, device);

        device->device.id = i;
        device->device.click_count = 0;
        device->device.previous_time = 0;
        device->device.previous_x = -1;
        device->device.previous_y = -1;
        device->device.previous_button_number = -1;
        device->x = 0;
        device->y = 0;
    }

#undef MAX_FINGERS
}
static void
clutter_backend_sdl_init (ClutterBackendSDL *backend_sdl)
{
  ClutterBackend *backend = CLUTTER_BACKEND (backend_sdl);

  clutter_backend_set_resolution (backend, 96.0);
  clutter_backend_set_double_click_time (backend, 250);
  clutter_backend_set_double_click_distance (backend, 5);

  backend_sdl->timer = g_timer_new ();
}
示例#5
0
static void
clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
{
  ClutterEventTranslator *translator;
  ClutterBackend *backend;

#ifdef HAVE_XINPUT_2
  if (clutter_enable_xinput)
    {
      int event_base, first_event, first_error;

      if (XQueryExtension (backend_x11->xdpy, "XInputExtension",
                           &event_base,
                           &first_event,
                           &first_error))
        {
          int major = 2;
          int minor = 3;

          if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest)
            {
              CLUTTER_NOTE (BACKEND, "Creating XI2 device manager");
              backend_x11->has_xinput = TRUE;
              backend_x11->device_manager =
                g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_XI2,
                              "backend", backend_x11,
                              "opcode", event_base,
                              NULL);

              backend_x11->xi_minor = minor;
            }
        }
    }

  if (backend_x11->device_manager == NULL)
#endif /* HAVE_XINPUT_2 */
    {
      CLUTTER_NOTE (BACKEND, "Creating Core device manager");
      backend_x11->has_xinput = FALSE;
      backend_x11->device_manager =
        g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
                      "backend", backend_x11,
                      NULL);

      backend_x11->xi_minor = -1;
    }

  backend = CLUTTER_BACKEND (backend_x11);
  backend->device_manager = backend_x11->device_manager;

  translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->device_manager);
  _clutter_backend_add_event_translator (backend, translator);
}
static void
clutter_backend_finalize (GObject *gobject)
{
  ClutterBackend *backend = CLUTTER_BACKEND (gobject);

  g_source_destroy (backend->cogl_source);

  g_free (backend->priv->font_name);
  clutter_backend_set_font_options (backend, NULL);

  G_OBJECT_CLASS (clutter_backend_parent_class)->finalize (gobject);
}
示例#7
0
static void
clutter_backend_dispose (GObject *gobject)
{
  ClutterBackendPrivate *priv = CLUTTER_BACKEND (gobject)->priv;
  ClutterMainContext *clutter_context;

  clutter_context = _clutter_context_get_default ();

  if (clutter_context && clutter_context->events_queue)
    {
      g_queue_foreach (clutter_context->events_queue,
                       (GFunc) clutter_event_free,
                       NULL);
      g_queue_free (clutter_context->events_queue);
      clutter_context->events_queue = NULL;
    }

  g_free (priv->font_name);

  clutter_backend_set_font_options (CLUTTER_BACKEND (gobject), NULL);

  G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
}
示例#8
0
static XVisualInfo *
clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
{
  ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend_x11);
  XVisualInfo visinfo_template;
  int template_mask = 0;
  XVisualInfo *visinfo = NULL;
  int visinfos_count;
  EGLint visualid, red_size, green_size, blue_size, alpha_size;

  if (!clutter_backend_egl_create_context (CLUTTER_BACKEND (backend_x11), NULL))
    return NULL;

  visinfo_template.screen = backend_x11->xscreen_num;
  template_mask |= VisualScreenMask;

  eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
                      EGL_NATIVE_VISUAL_ID, &visualid);

  if (visualid != 0)
    {
      visinfo_template.visualid = visualid;
      template_mask |= VisualIDMask;
    }
  else
    {
      /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
       * attribute, so attempt to find the closest match. */

      eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
                          EGL_RED_SIZE, &red_size);
      eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
                          EGL_GREEN_SIZE, &green_size);
      eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
                          EGL_BLUE_SIZE, &blue_size);
      eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
                          EGL_ALPHA_SIZE, &alpha_size);

      visinfo_template.depth = red_size + green_size + blue_size + alpha_size;
      template_mask |= VisualDepthMask;
    }

  visinfo = XGetVisualInfo (backend_x11->xdpy,
                            template_mask,
                            &visinfo_template,
                            &visinfos_count);

  return visinfo;
}
示例#9
0
static void
clutter_backend_dispose (GObject *gobject)
{
  ClutterBackend *backend = CLUTTER_BACKEND (gobject);

  /* clear the events still in the queue of the main context */
  _clutter_clear_events_queue ();

  /* remove all event translators */
  g_clear_pointer (&backend->event_translators, g_list_free);

  g_clear_pointer (&backend->dummy_onscreen, cogl_object_unref);

  G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
}
static void
clutter_stage_wayland_set_fullscreen (ClutterStageWindow *stage_window,
                                      gboolean            fullscreen)
{
    ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window);
    ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
    ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend);
    ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
    ClutterActor *stage = _clutter_stage_window_get_wrapper (stage_window);

    stage_wayland->fullscreen = fullscreen;

    if (!stage_wayland->wayland_shell_surface) /* Not realized yet */
        return;

    if (fullscreen)
    {
        _clutter_stage_update_state (stage_cogl->wrapper,
                                     0,
                                     CLUTTER_STAGE_STATE_FULLSCREEN);

        /* FIXME: In future versions of the Wayland protocol we'll get a
         * configure with the dimensions we can use - but for now we have to
         * use the dimensions from the output's mode
         */
        clutter_actor_set_size (stage,
                                backend_wayland->output_width,
                                backend_wayland->output_height);

        /* FIXME: And we must force a redraw so that new sized buffer gets
         * attached
         */
        _clutter_stage_window_redraw (stage_window);
        wl_shell_surface_set_fullscreen (stage_wayland->wayland_shell_surface,
                                         WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
                                         0,
                                         NULL);
    }
    else
    {
        _clutter_stage_update_state (stage_cogl->wrapper,
                                     CLUTTER_STAGE_STATE_FULLSCREEN,
                                     0);

        wl_shell_surface_set_toplevel (stage_wayland->wayland_shell_surface);
    }
}
static void
clutter_backend_dispose (GObject *gobject)
{
  ClutterBackendPrivate *priv = CLUTTER_BACKEND (gobject)->priv;

  /* clear the events still in the queue of the main context */
  _clutter_clear_events_queue ();

  /* remove all event translators */
  if (priv->event_translators != NULL)
    {
      g_list_free (priv->event_translators);
      priv->event_translators = NULL;
    }

  G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
}
LRESULT CALLBACK
_clutter_stage_win32_window_proc (HWND hwnd, UINT umsg,
				  WPARAM wparam, LPARAM lparam)
{
  ClutterStageWin32 *stage_win32
    = (ClutterStageWin32 *) GetWindowLongPtrW (hwnd, 0);
  gboolean call_def_window_proc = TRUE;

  /* Ignore any messages before SetWindowLongPtr has been called to
     set the stage */
  if (stage_win32 != NULL)
    {
      ClutterBackendWin32 *backend_win32 = stage_win32->backend;
      MSG msg;
      ClutterEvent *event;
      ClutterMainContext *clutter_context;
      DWORD message_pos = GetMessagePos ();

      clutter_context = clutter_context_get_default ();

      msg.hwnd = hwnd;
      msg.message = umsg;
      msg.wParam = wparam;
      msg.lParam = lparam;
      msg.time = GetMessageTime ();
      /* Neither MAKE_POINTS nor GET_[XY]_LPARAM is defined in MinGW
	 headers so we need to convert to a signed type explicitly */
      msg.pt.x = (SHORT) LOWORD (message_pos);
      msg.pt.y = (SHORT) HIWORD (message_pos);

      event = clutter_event_new (CLUTTER_NOTHING);
	  
      if (message_translate (CLUTTER_BACKEND (backend_win32), event,
			     &msg, &call_def_window_proc))
	/* push directly here to avoid copy of queue_put */
	g_queue_push_head (clutter_context->events_queue, event);
      else
	clutter_event_free (event);
    }

  if (call_def_window_proc)
    return DefWindowProcW (hwnd, umsg, wparam, lparam);
  else
    return 0;
}
示例#13
0
static void
clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11)
{
  if (backend_x11->keymap == NULL)
    {
      ClutterEventTranslator *translator;
      ClutterBackend *backend;

      backend_x11->keymap =
        g_object_new (CLUTTER_TYPE_KEYMAP_X11,
                      "backend", backend_x11,
                      NULL);

      backend = CLUTTER_BACKEND (backend_x11);
      translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->keymap);
      _clutter_backend_add_event_translator (backend, translator);
    }
}
示例#14
0
static void
clutter_backend_egl_dispose (GObject *gobject)
{
    ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);

    _clutter_events_uninit (CLUTTER_BACKEND (backend_egl));

    if (backend_egl->egl_context)
    {
        eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
        backend_egl->egl_context = NULL;
    }

    if (backend_egl->edpy)
    {
        eglTerminate (backend_egl->edpy);
        backend_egl->edpy = 0;
    }

    G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject);
}
static void
clutter_backend_sdl_dispose (GObject *gobject)
{
  ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (gobject);

  _clutter_events_uninit (CLUTTER_BACKEND (backend_sdl));

  if (backend_sdl->stage)
    {
      clutter_actor_destroy (CLUTTER_ACTOR (backend_sdl->stage));
      backend_sdl->stage = NULL;
    }

  if (backend_sdl->timer)
    {
      g_timer_destroy (backend_sdl->timer);
      backend_sdl->timer = NULL;
    }

  G_OBJECT_CLASS (clutter_backend_sdl_parent_class)->dispose (gobject);
}
示例#16
0
static gboolean
clutter_stage_win32_realize (ClutterStageWindow *stage_window)
{
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
  ClutterBackend *backend;
  ClutterBackendWin32 *backend_win32;
  CoglFramebuffer *framebuffer;
  gfloat width;
  gfloat height;
  GError *error = NULL;

  CLUTTER_NOTE (MISC, "Realizing main stage");

  backend = CLUTTER_BACKEND (stage_win32->backend);
  backend_win32 = CLUTTER_BACKEND_WIN32 (backend);

  clutter_actor_get_size (CLUTTER_ACTOR (stage_win32->wrapper),
                          &width, &height);

  stage_win32->onscreen = cogl_onscreen_new (backend->cogl_context,
                                             width, height);

  if (stage_win32->hwnd == NULL)
    {
      ATOM window_class = clutter_stage_win32_get_window_class ();
      int win_xpos, win_ypos, win_width, win_height;

      if (window_class == 0)
        {
          g_critical ("Unable to register window class");
          goto fail;
        }

      /* If we're in fullscreen mode then use the fullscreen rect
         instead */
      if (_clutter_stage_is_fullscreen (stage_win32->wrapper))
        {
          get_fullscreen_rect (stage_win32);
          win_xpos = stage_win32->fullscreen_rect.left;
          win_ypos = stage_win32->fullscreen_rect.top;
          win_width = stage_win32->fullscreen_rect.right - win_xpos;
          win_height = stage_win32->fullscreen_rect.bottom - win_ypos;
        }
      else
        {
          win_xpos = win_ypos = CW_USEDEFAULT;

          get_full_window_size (stage_win32,
                                stage_win32->win_width,
                                stage_win32->win_height,
                                &win_width, &win_height);
        }

      if (stage_win32->wtitle == NULL)
        stage_win32->wtitle = g_utf8_to_utf16 (".", -1, NULL, NULL, NULL);

      stage_win32->hwnd = CreateWindowW ((LPWSTR) MAKEINTATOM (window_class),
					 stage_win32->wtitle,
					 get_window_style (stage_win32),
					 win_xpos,
					 win_ypos,
					 win_width,
					 win_height,
					 NULL, NULL,
					 GetModuleHandle (NULL),
					 NULL);

      if (stage_win32->hwnd == NULL)
        {
          g_critical ("Unable to create stage window");
          goto fail;
        }

      /* Store a pointer to the actor in the extra bytes of the window
         so we can quickly access it in the window procedure */
      SetWindowLongPtrW (stage_win32->hwnd, 0, (LONG_PTR) stage_win32);
    }

  cogl_win32_onscreen_set_foreign_window (stage_win32->onscreen,
                                          stage_win32->hwnd);

  cogl_onscreen_set_swap_throttled (stage_win32->onscreen,
                                    _clutter_get_sync_to_vblank ());

  framebuffer = COGL_FRAMEBUFFER (stage_win32->onscreen);
  if (!cogl_framebuffer_allocate (framebuffer, &error))
    {
      g_warning ("Failed to allocate stage: %s", error->message);
      g_error_free (error);
      cogl_object_unref (stage_win32->onscreen);
      stage_win32->onscreen = NULL;
      goto fail;
    }

  /* Create a context. This will be a no-op if we already have one */
  if (!_clutter_backend_create_context (CLUTTER_BACKEND (backend_win32),
                                        &error))
    {
      g_critical ("Unable to realize stage: %s", error->message);
      g_error_free (error);
      goto fail;
    }

  CLUTTER_NOTE (BACKEND, "Successfully realized stage");

  return TRUE;

 fail:
  return FALSE;
}
示例#17
0
static gboolean
clutter_stage_gdk_realize (ClutterStageWindow *stage_window)
{
  ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
  ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend);
  ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
  GdkWindowAttr attributes;
  gboolean cursor_visible;
  gboolean use_alpha;
  gfloat   width, height;

  if (stage_gdk->foreign_window)
    {
      width = gdk_window_get_width (stage_gdk->window);
      height = gdk_window_get_height (stage_gdk->window);
    }
  else
    {
      if (stage_gdk->window != NULL)
        {
          /* complete realizing the stage */
          cairo_rectangle_int_t geometry;

          clutter_stage_gdk_get_geometry (stage_window, &geometry);
          clutter_actor_set_size (CLUTTER_ACTOR (stage_cogl->wrapper),
                                  geometry.width,
                                  geometry.height);

          gdk_window_ensure_native (stage_gdk->window);
          gdk_window_set_events (stage_gdk->window, CLUTTER_STAGE_GDK_EVENT_MASK);

          return TRUE;
        }
      else
        {
          attributes.title = NULL;
          g_object_get (stage_cogl->wrapper,
                        "cursor-visible", &cursor_visible,
                        "title", &attributes.title,
                        "width", &width,
                        "height", &height,
                        "use-alpha", &use_alpha,
                        NULL);

          attributes.width = width;
          attributes.height = height;
          attributes.wclass = GDK_INPUT_OUTPUT;
          attributes.window_type = GDK_WINDOW_TOPLEVEL;
          attributes.event_mask = CLUTTER_STAGE_GDK_EVENT_MASK;

          attributes.cursor = NULL;
          if (!cursor_visible)
            {
              if (stage_gdk->blank_cursor == NULL)
                stage_gdk->blank_cursor = gdk_cursor_new_for_display (backend_gdk->display, GDK_BLANK_CURSOR);

              attributes.cursor = stage_gdk->blank_cursor;
            }

          attributes.visual = NULL;
          if (use_alpha)
            {
              attributes.visual = gdk_screen_get_rgba_visual (backend_gdk->screen);

              if (attributes.visual == NULL)
                clutter_stage_set_use_alpha (stage_cogl->wrapper, FALSE);
            }

          if (attributes.visual == NULL)
            {
             /* This could still be an RGBA visual, although normally it's not */
             attributes.visual = gdk_screen_get_system_visual (backend_gdk->screen);
            }

          stage_gdk->foreign_window = FALSE;
          stage_gdk->window = gdk_window_new (NULL, &attributes,
                                              GDK_WA_TITLE | GDK_WA_CURSOR | GDK_WA_VISUAL);

          g_free (attributes.title);
        }

      clutter_stage_gdk_set_gdk_geometry (stage_gdk);
    }

  gdk_window_ensure_native (stage_gdk->window);

  g_object_set_data (G_OBJECT (stage_gdk->window),
                     "clutter-stage-window", stage_gdk);

  stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
					    width, height);

#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
  if (GDK_IS_X11_WINDOW (stage_gdk->window))
    {
      cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
                                                GDK_WINDOW_XID (stage_gdk->window),
                                                clutter_stage_gdk_update_foreign_event_mask,
                                                stage_gdk);
    }
  else
#endif
#if defined(GDK_WINDOWING_WAYLAND) && defined(COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
  if (GDK_IS_WAYLAND_WINDOW (stage_gdk->window))
    {
      cogl_wayland_onscreen_set_foreign_surface (stage_cogl->onscreen,
                                                 gdk_wayland_window_get_wl_surface (stage_gdk->window));
    }
  else
#endif
#if defined(GDK_WINDOWING_WIN32) && defined(COGL_HAS_WIN32_SUPPORT)
  if (GDK_IS_WIN32_WINDOW (stage_gdk->window))
    {
      cogl_win32_onscreen_set_foreign_window (stage_cogl->onscreen,
					      gdk_win32_window_get_handle (stage_gdk->window));
    }
  else
#endif
    {
      g_warning ("Cannot find an appropriate CoglWinsys for a "
		 "GdkWindow of type %s", G_OBJECT_TYPE_NAME (stage_gdk->window));

      cogl_object_unref (stage_cogl->onscreen);
      stage_cogl->onscreen = NULL;

      if (!stage_gdk->foreign_window)
        gdk_window_destroy (stage_gdk->window);

      stage_gdk->window = NULL;

      return FALSE;
    }

  return clutter_stage_window_parent_iface->realize (stage_window);
}
示例#18
0
static gboolean
clutter_stage_x11_realize (ClutterStageWindow *stage_window)
{
  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
  ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend);
  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
  ClutterDeviceManager *device_manager;
  int event_flags;
  gfloat width, height;

  clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper),
			  &width, &height);

  stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
                                            width, height);

  /* We just created a window of the size of the actor. No need to fix
     the size of the stage, just update it. */
  stage_x11->xwin_width = width;
  stage_x11->xwin_height = height;

  if (stage_x11->xwin != None)
    {
      cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
                                                stage_x11->xwin,
                                                _clutter_stage_x11_update_foreign_event_mask,
                                                stage_x11);

    }

  /* Chain to the parent class now. ClutterStageCogl will call cogl_framebuffer_allocate,
     which will create the X Window we need */

  if (!(clutter_stage_window_parent_iface->realize (stage_window)))
    return FALSE;

  if (stage_x11->xwin == None)
    stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_cogl->onscreen);

  if (clutter_stages_by_xid == NULL)
    clutter_stages_by_xid = g_hash_table_new (NULL, NULL);

  g_hash_table_insert (clutter_stages_by_xid,
                       GINT_TO_POINTER (stage_x11->xwin),
                       stage_x11);

  set_wm_pid (stage_x11);
  set_wm_title (stage_x11);
  set_cursor_visible (stage_x11);


  /* the masks for the events we want to select on a stage window;
   * KeyPressMask and KeyReleaseMask are necessary even with XI1
   * because key events are broken with that extension, and will
   * be fixed by XI2
   */
  event_flags = CLUTTER_STAGE_X11_EVENT_MASK;

  /* we unconditionally select input events even with event retrieval
   * disabled because we need to guarantee that the Clutter internal
   * state is maintained when calling clutter_x11_handle_event() without
   * requiring applications or embedding toolkits to select events
   * themselves. if we did that, we'd have to document the events to be
   * selected, and also update applications and embedding toolkits each
   * time we added a new mask, or a new class of events.
   *
   * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=998
   * for the rationale of why we did conditional selection. it is now
   * clear that a compositor should clear out the input region, since
   * it cannot assume a perfectly clean slate coming from us.
   *
   * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=2228
   * for an example of things that break if we do conditional event
   * selection.
   */
  XSelectInput (backend_x11->xdpy, stage_x11->xwin, event_flags);

  /* input events also depent on the actual device, so we need to
   * use the device manager to let every device select them, using
   * the event mask we passed to XSelectInput as the template
   */
  device_manager = clutter_device_manager_get_default ();
  if (G_UNLIKELY (device_manager != NULL))
    {
      _clutter_device_manager_select_stage_events (device_manager,
                                                   stage_cogl->wrapper,
                                                   event_flags);

      g_signal_connect (device_manager, "device-added",
                        G_CALLBACK (stage_events_device_added),
                        stage_window);
    }

  clutter_stage_x11_fix_window_size (stage_x11,
                                     stage_x11->xwin_width,
                                     stage_x11->xwin_height);
  clutter_stage_x11_set_wm_protocols (stage_x11);

  if (stage_x11->fullscreen_on_realize)
    {
      stage_x11->fullscreen_on_realize = FALSE;

      clutter_stage_x11_set_fullscreen (stage_window, TRUE);
    }

  CLUTTER_NOTE (BACKEND, "Successfully realized stage");

  return TRUE;
}