static gboolean _gdk_wayland_cursor_update (GdkWaylandDisplay *wayland_display, GdkWaylandCursor *cursor) { struct wl_cursor *c; struct wl_cursor_theme *theme; /* Do nothing if this is not a wl_cursor cursor. */ if (cursor->name == NULL) return FALSE; theme = _gdk_wayland_display_get_scaled_cursor_theme (wayland_display, cursor->scale); c = wl_cursor_theme_get_cursor (theme, cursor->name); if (!c) c = wl_cursor_theme_get_cursor (theme, name_fallback (cursor->name)); if (!c) { g_warning (G_STRLOC ": Unable to load %s from the cursor theme", cursor->name); /* return the left_ptr cursor as a fallback */ c = wl_cursor_theme_get_cursor (theme, "left_ptr"); if (!c) return FALSE; } cursor->wl_cursor = c; return TRUE; }
static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct display *d = data; if (strcmp(interface, "wl_compositor") == 0) { d->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1); } else if (strcmp(interface, "xdg_shell") == 0) { d->shell = wl_registry_bind(registry, name, &xdg_shell_interface, 1); xdg_shell_add_listener(d->shell, &xdg_shell_listener, d); xdg_shell_use_unstable_version(d->shell, XDG_VERSION); } else if (strcmp(interface, "wl_seat") == 0) { d->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); wl_seat_add_listener(d->seat, &seat_listener, d); } else if (strcmp(interface, "wl_shm") == 0) { d->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); d->cursor_theme = wl_cursor_theme_load(NULL, 32, d->shm); d->default_cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr"); } }
struct window *window_setup(struct registry *registry, uint32_t width, uint32_t height, bool shell_surface) { struct window *window = malloc(sizeof(struct window)); memset(window, 0, sizeof(struct window)); window->width = width; window->height = height; window->registry = registry; window->surface = wl_compositor_create_surface(registry->compositor); if (shell_surface) { window->shell_surface = wl_shell_get_shell_surface(registry->shell, window->surface); wl_shell_surface_add_listener(window->shell_surface, &surface_listener, window); wl_shell_surface_set_toplevel(window->shell_surface); } if (registry->pointer) { wl_pointer_add_listener(registry->pointer, &pointer_listener, window); } window->cursor.cursor_theme = wl_cursor_theme_load("default", 32, registry->shm); // TODO: let you customize this window->cursor.cursor = wl_cursor_theme_get_cursor(window->cursor.cursor_theme, "left_ptr"); window->cursor.surface = wl_compositor_create_surface(registry->compositor); struct wl_cursor_image *image = window->cursor.cursor->images[0]; struct wl_buffer *cursor_buf = wl_cursor_image_get_buffer(image); wl_surface_attach(window->cursor.surface, cursor_buf, 0, 0); wl_surface_damage(window->cursor.surface, 0, 0, image->width, image->height); wl_surface_commit(window->cursor.surface); return window; }
static void clutter_backend_wayland_load_cursor (ClutterBackendWayland *backend_wayland) { struct wl_cursor *cursor; backend_wayland->cursor_theme = wl_cursor_theme_load (NULL, /* default */ 32, backend_wayland->wayland_shm); cursor = wl_cursor_theme_get_cursor (backend_wayland->cursor_theme, "left_ptr"); backend_wayland->cursor_buffer = wl_cursor_image_get_buffer (cursor->images[0]); if (backend_wayland->cursor_buffer) { backend_wayland->cursor_x = cursor->images[0]->hotspot_x; backend_wayland->cursor_y = cursor->images[0]->hotspot_y; } backend_wayland->cursor_surface = wl_compositor_create_surface (backend_wayland->wayland_compositor); }
static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { if (strcmp(interface, "wl_compositor") == 0) { GLWin.wl_compositor = (wl_compositor *) wl_registry_bind(registry, name, &wl_compositor_interface, 1); } else if (strcmp(interface, "wl_shell") == 0) { GLWin.wl_shell = (wl_shell *)wl_registry_bind(registry, name, &wl_shell_interface, 1); } else if (strcmp(interface, "wl_seat") == 0) { GLWin.wl_seat = (wl_seat *)wl_registry_bind(registry, name, &wl_seat_interface, 1); wl_seat_add_listener(GLWin.wl_seat, &seat_listener, 0); } else if (strcmp(interface, "wl_shm") == 0) { GLWin.wl_shm = (wl_shm *)wl_registry_bind(registry, name, &wl_shm_interface, 1); GLWin.wl_cursor_theme = (wl_cursor_theme *)wl_cursor_theme_load(nullptr, 32, GLWin.wl_shm); GLWin.wl_cursor = (wl_cursor *) wl_cursor_theme_get_cursor(GLWin.wl_cursor_theme, "left_ptr"); } }
static void registry_handle_global (void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { GstGLWindowWaylandEGL *window_egl = data; struct display *d = &window_egl->display; GST_TRACE_OBJECT (window_egl, "registry_handle_global with registry %p, " "interface %s, version %u", registry, interface, version); if (g_strcmp0 (interface, "wl_compositor") == 0) { d->compositor = wl_registry_bind (registry, name, &wl_compositor_interface, 1); } else if (g_strcmp0 (interface, "wl_shell") == 0) { d->shell = wl_registry_bind (registry, name, &wl_shell_interface, 1); } else if (g_strcmp0 (interface, "wl_seat") == 0) { d->seat = wl_registry_bind (registry, name, &wl_seat_interface, 1); wl_seat_add_listener (d->seat, &seat_listener, window_egl); } else if (g_strcmp0 (interface, "wl_shm") == 0) { d->shm = wl_registry_bind (registry, name, &wl_shm_interface, 1); d->cursor_theme = wl_cursor_theme_load (NULL, 32, d->shm); d->default_cursor = wl_cursor_theme_get_cursor (d->cursor_theme, "left_ptr"); } }
static void setCursor(const char* name) { struct wl_buffer* buffer; struct wl_cursor* cursor; struct wl_cursor_image* image; struct wl_surface* surface = _glfw.wl.cursorSurface; cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, name); if (!cursor) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Standard cursor not found"); return; } image = cursor->images[0]; if (!image) return; buffer = wl_cursor_image_get_buffer(image); if (!buffer) return; wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, surface, image->hotspot_x, image->hotspot_y); wl_surface_attach(surface, buffer, 0, 0); wl_surface_damage(surface, 0, 0, image->width, image->height); wl_surface_commit(surface); }
static void load_callback(XcursorImages *images, void *data) { struct wl_cursor_theme *theme = data; struct wl_cursor *cursor; if (wl_cursor_theme_get_cursor(theme, images->name)) { XcursorImagesDestroy(images); return; } cursor = wl_cursor_create_from_xcursor_images(images, theme); if (cursor) { theme->cursor_count++; theme->cursors = realloc(theme->cursors, theme->cursor_count * sizeof theme->cursors[0]); if (theme->cursors == NULL) { theme->cursor_count--; free(cursor); } else { theme->cursors[theme->cursor_count - 1] = cursor; } } XcursorImagesDestroy(images); }
int _glfwPlatformInit(void) { _glfw.wl.display = wl_display_connect(NULL); if (!_glfw.wl.display) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to connect to display"); return GLFW_FALSE; } _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL); _glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*)); _glfw.wl.monitorsSize = 4; _glfw.wl.xkb.context = xkb_context_new(0); if (!_glfw.wl.xkb.context) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to initialize xkb context"); return GLFW_FALSE; } // Sync so we got all registry objects wl_display_roundtrip(_glfw.wl.display); // Sync so we got all initial output events wl_display_roundtrip(_glfw.wl.display); if (!_glfwInitContextAPI()) return GLFW_FALSE; _glfwInitTimer(); _glfwInitJoysticks(); if (_glfw.wl.pointer && _glfw.wl.shm) { _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm); if (!_glfw.wl.cursorTheme) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Unable to load default cursor theme\n"); return GLFW_FALSE; } _glfw.wl.defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, "left_ptr"); if (!_glfw.wl.defaultCursor) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Unable to load default left pointer\n"); return GLFW_FALSE; } _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor); } return GLFW_TRUE; }
static void _eventd_nd_wl_registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { EventdNdBackendContext *self = data; if ( g_strcmp0(interface, "wl_compositor") == 0 ) { self->global_names[EVENTD_ND_WL_GLOBAL_COMPOSITOR] = name; self->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, MIN(version, WL_COMPOSITOR_INTERFACE_VERSION)); } else if ( g_strcmp0(interface, "zww_notification_area_v1") == 0 ) { self->global_names[EVENTD_ND_WL_GLOBAL_NOTIFICATION_DAEMON] = name; self->notification_area = wl_registry_bind(registry, name, &zww_notification_area_v1_interface, WW_NOTIFICATION_AREA_INTERFACE_VERSION); zww_notification_area_v1_add_listener(self->notification_area, &_eventd_nd_wl_notification_area_listener, self); } else if ( g_strcmp0(interface, "wl_shm") == 0 ) { self->global_names[EVENTD_ND_WL_GLOBAL_SHM] = name; self->shm = wl_registry_bind(registry, name, &wl_shm_interface, MIN(version, WL_SHM_INTERFACE_VERSION)); wl_shm_add_listener(self->shm, &_eventd_nd_wl_shm_listener, self); } else if ( g_strcmp0(interface, "wl_seat") == 0 ) { EventdNdWlSeat *seat = g_slice_new0(EventdNdWlSeat); seat->context = self; seat->global_name = name; seat->seat = wl_registry_bind(registry, name, &wl_seat_interface, MIN(version, WL_SEAT_INTERFACE_VERSION)); seat->link = self->seats = g_slist_prepend(self->seats, seat); wl_seat_add_listener(seat->seat, &_eventd_nd_wl_seat_listener, seat); } if ( ( self->cursor.theme == NULL ) && ( self->compositor != NULL ) && ( self->shm != NULL ) ) { self->cursor.theme = wl_cursor_theme_load(self->cursor.theme_name, 32, self->shm); if ( self->cursor.theme != NULL ) { const gchar * const *cname = (const gchar * const *) self->cursor.name; for ( cname = ( cname != NULL ) ? cname : _eventd_nd_cursor_names ; ( self->cursor.cursor == NULL ) && ( *cname != NULL ) ; ++cname ) self->cursor.cursor = wl_cursor_theme_get_cursor(self->cursor.theme, *cname); if ( self->cursor.cursor == NULL ) { wl_cursor_theme_destroy(self->cursor.theme); self->cursor.theme = NULL; } else self->cursor.surface = wl_compositor_create_surface(self->compositor); } } }
struct window *window_setup(struct registry *registry, uint32_t width, uint32_t height, int32_t scale, bool shell_surface) { struct window *window = malloc(sizeof(struct window)); memset(window, 0, sizeof(struct window)); window->width = width; window->height = height; window->scale = scale; window->registry = registry; window->font = "monospace 10"; window->surface = wl_compositor_create_surface(registry->compositor); if (shell_surface) { window_make_shell(window); } if (registry->pointer) { wl_pointer_add_listener(registry->pointer, &pointer_listener, window); } get_next_buffer(window); if (registry->pointer) { char *cursor_theme = getenv("SWAY_CURSOR_THEME"); if (!cursor_theme) { cursor_theme = "default"; } char *cursor_size = getenv("SWAY_CURSOR_SIZE"); if (!cursor_size) { cursor_size = "16"; } sway_log(L_DEBUG, "Cursor scale: %d", scale); window->cursor.cursor_theme = wl_cursor_theme_load(cursor_theme, atoi(cursor_size) * scale, registry->shm); window->cursor.cursor = wl_cursor_theme_get_cursor(window->cursor.cursor_theme, "left_ptr"); window->cursor.surface = wl_compositor_create_surface(registry->compositor); struct wl_cursor_image *image = window->cursor.cursor->images[0]; struct wl_buffer *cursor_buf = wl_cursor_image_get_buffer(image); wl_surface_attach(window->cursor.surface, cursor_buf, 0, 0); wl_surface_set_buffer_scale(window->cursor.surface, scale); wl_surface_damage(window->cursor.surface, 0, 0, image->width, image->height); wl_surface_commit(window->cursor.surface); } return window; }
static struct cursor_surface * cursor_viewer_show_cursor(struct cursor_viewer *viewer, const char *name) { struct wl_cursor_image *cursor_image; struct wl_buffer *cursor_buffer = NULL; struct cursor_surface *cursor = calloc(1, sizeof (struct cursor_surface)); if (!cursor) die("Cannot allocate memory for cursor_surface\n"); cursor->name = name; cursor->surface = wl_compositor_create_surface(viewer->compositor); cursor->shsurf = wl_shell_get_shell_surface(viewer->shell, cursor->surface); wl_shell_surface_add_listener(cursor->shsurf, &shsurf_listener, viewer); wl_shell_surface_set_toplevel(cursor->shsurf); wl_shell_surface_set_title(cursor->shsurf, name); wl_surface_set_user_data(cursor->surface, viewer); cursor->cursor = wl_cursor_theme_get_cursor(viewer->cursor_theme, name); if (!cursor->cursor || cursor->cursor->image_count < 1) { printf("No such cursor: %s\n", name); cursor_surface_destroy(cursor); return NULL; } cursor_image = cursor->cursor->images[0]; cursor_buffer = wl_cursor_image_get_buffer(cursor_image); printf("%s: %s: size=%dx%d image_count=%u\n", __func__, cursor->name, cursor_image->width, cursor_image->height, cursor->cursor->image_count); if (cursor->cursor->image_count > 1) { cursor->frame = wl_surface_frame(cursor->surface); wl_callback_add_listener(cursor->frame, &frame_listener, cursor); } wl_surface_attach(cursor->surface, cursor_buffer, 0, 0); wl_surface_damage(cursor->surface, 0, 0, cursor_image->width, cursor_image->height); wl_surface_commit(cursor->surface); return cursor; }
static void setCursor(_GLFWwindow* window, const char* name) { struct wl_buffer* buffer; struct wl_cursor* cursor; struct wl_cursor_image* image; struct wl_surface* surface = _glfw.wl.cursorSurface; struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; int scale = 1; if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI) { // We only support up to scale=2 for now, since libwayland-cursor // requires us to load a different theme for each size. scale = 2; theme = _glfw.wl.cursorThemeHiDPI; } cursor = wl_cursor_theme_get_cursor(theme, name); if (!cursor) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Standard cursor not found"); return; } // TODO: handle animated cursors too. image = cursor->images[0]; if (!image) return; buffer = wl_cursor_image_get_buffer(image); if (!buffer) return; wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, surface, image->hotspot_x / scale, image->hotspot_y / scale); wl_surface_set_buffer_scale(surface, scale); wl_surface_attach(surface, buffer, 0, 0); wl_surface_damage(surface, 0, 0, image->width, image->height); wl_surface_commit(surface); }
static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) { #ifdef HAVE_OPENGL static const EGLint egl_attribs_gl[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE, }; #endif #ifdef HAVE_OPENGLES #ifdef HAVE_OPENGLES2 static const EGLint egl_attribs_gles[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; #endif #ifdef HAVE_OPENGLES3 #ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; #endif #endif #endif #ifdef HAVE_EGL static const EGLint egl_attribs_vg[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; EGLint major = 0, minor = 0; EGLint n; const EGLint *attrib_ptr = NULL; #endif gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*) calloc(1, sizeof(gfx_ctx_wayland_data_t)); if (!wl) return NULL; (void)video_driver; #ifdef HAVE_EGL switch (wl_api) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL attrib_ptr = egl_attribs_gl; #endif break; case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_OPENGLES #ifdef HAVE_OPENGLES3 #ifdef EGL_KHR_create_context if (g_egl_major >= 3) attrib_ptr = egl_attribs_gles3; else #endif #endif #ifdef HAVE_OPENGLES2 attrib_ptr = egl_attribs_gles; #endif #endif break; case GFX_CTX_OPENVG_API: #ifdef HAVE_VG attrib_ptr = egl_attribs_vg; #endif break; case GFX_CTX_NONE: default: break; } #endif frontend_driver_destroy_signal_handler_state(); wl->input.dpy = wl_display_connect(NULL); wl->buffer_scale = 1; if (!wl->input.dpy) { RARCH_ERR("[Wayland]: Failed to connect to Wayland server.\n"); goto error; } frontend_driver_install_signal_handler(); wl->registry = wl_display_get_registry(wl->input.dpy); wl_registry_add_listener(wl->registry, ®istry_listener, wl); wl_display_roundtrip(wl->input.dpy); if (!wl->compositor) { RARCH_ERR("[Wayland]: Failed to create compositor.\n"); goto error; } if (!wl->shm) { RARCH_ERR("[Wayland]: Failed to create shm.\n"); goto error; } if (!wl->shell) { RARCH_ERR("[Wayland]: Failed to create shell.\n"); goto error; } wl->input.fd = wl_display_get_fd(wl->input.dpy); switch (wl_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: case GFX_CTX_OPENVG_API: #ifdef HAVE_EGL if (!egl_init_context(&wl->egl, EGL_PLATFORM_WAYLAND_KHR, (EGLNativeDisplayType)wl->input.dpy, &major, &minor, &n, attrib_ptr)) { egl_report_error(); goto error; } if (n == 0 || !egl_has_config(&wl->egl)) goto error; #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN if (!vulkan_context_init(&wl->vk, VULKAN_WSI_WAYLAND)) goto error; #endif break; case GFX_CTX_NONE: default: break; } wl->input.keyboard_focus = true; wl->input.mouse.focus = true; wl->cursor.surface = wl_compositor_create_surface(wl->compositor); wl->cursor.theme = wl_cursor_theme_load(NULL, 16, wl->shm); wl->cursor.default_cursor = wl_cursor_theme_get_cursor(wl->cursor.theme, "left_ptr"); flush_wayland_fd(&wl->input); return wl; error: gfx_ctx_wl_destroy_resources(wl); if (wl) free(wl); return NULL; }
void fgPlatformOpenWindow( SFG_Window* window, const char* title, GLboolean positionUse, int x, int y, GLboolean sizeUse, int w, int h, GLboolean gameMode, GLboolean isSubWindow ) { /* Save the display mode if we are creating a menu window */ if( window->IsMenu && ( ! fgStructure.MenuContext ) ) fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ; fghChooseConfig( &window->Window.pContext.egl.Config ); if( ! window->Window.pContext.egl.Config ) { /* * The "fghChooseConfig" returned a null meaning that the visual * context is not available. * Try a couple of variations to see if they will work. */ if( fgState.DisplayMode & GLUT_MULTISAMPLE ) { fgState.DisplayMode &= ~GLUT_MULTISAMPLE ; fghChooseConfig( &window->Window.pContext.egl.Config ); fgState.DisplayMode |= GLUT_MULTISAMPLE; } } FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.pContext.egl.Config != NULL, "EGL configuration with necessary capabilities " "not found", "fgOpenWindow" ); if( ! positionUse ) x = y = -1; /* default window position */ if( ! sizeUse ) w = h = 300; /* default window size */ /* Create the cursor */ window->Window.pContext.cursor = wl_cursor_theme_get_cursor( fgDisplay.pDisplay.cursor_theme, "left_ptr" ); window->Window.pContext.cursor_surface = wl_compositor_create_surface( fgDisplay.pDisplay.compositor ); /* Create the main surface */ window->Window.pContext.surface = wl_compositor_create_surface( fgDisplay.pDisplay.compositor ); /* Create the shell surface with respects to the parent/child tree */ window->Window.pContext.shsurface = wl_shell_get_shell_surface( fgDisplay.pDisplay.shell, window->Window.pContext.surface ); wl_shell_surface_add_listener( window->Window.pContext.shsurface, &fghShSurfaceListener, window ); if( title) wl_shell_surface_set_title( window->Window.pContext.shsurface, title ); if( gameMode ) { window->State.IsFullscreen = GL_TRUE; wl_shell_surface_set_fullscreen( window->Window.pContext.shsurface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL ); } else if( !isSubWindow && !window->IsMenu ) { wl_shell_surface_set_toplevel( window->Window.pContext.shsurface ); } else { wl_shell_surface_set_transient( window->Window.pContext.shsurface, window->Parent->Window.pContext.surface, x, y, 0 ); } /* Create the Wl_EGL_Window */ window->Window.Context = fghCreateNewContext( window ); window->Window.pContext.egl_window = wl_egl_window_create( window->Window.pContext.surface, w, h); window->Window.pContext.egl.Surface = eglCreateWindowSurface( fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Config, (EGLNativeWindowType)window->Window.pContext.egl_window, NULL ); eglMakeCurrent( fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Surface, window->Window.pContext.egl.Surface, window->Window.Context ); window->Window.pContext.pointer_button_pressed = GL_FALSE; }