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; } }
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 } }
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 (); }
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); }
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); }
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; }
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; }
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); } }
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); }
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; }
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; }