static void x11_set_window(CoglOnscreen* onscreen, GdkWindow *window) { cogl_x11_onscreen_set_foreign_window_xid(onscreen, GDK_WINDOW_XID(window), x11_window_update_foreign_event_mask, window); gdk_window_add_filter(window, cogl_gdk_filter, onscreen); }
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); }
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; }