mirror of
https://github.com/glfw/glfw.git
synced 2026-02-17 21:12:34 +01:00
The cursor theme was only loaded if the chosen seat had a mouse
(wl_pointer) during initialization. If a mouse was connected only after
glfwInit, there would be no cursor theme but the rest of the cursor
related code assumed one had already been loaded.
This also moves the details of cursor theme loading out into a separate
function to declutter platform init.
Because the original cursor theme loading code checked whether we got
a wl_shm, and because the rest of the code just assumes we have
a wl_shm, initialization will now fail if there isn't one.
Fixes #1450
(cherry picked from commit 71be34a6c3)
610 lines
23 KiB
C
610 lines
23 KiB
C
//========================================================================
|
|
// GLFW 3.3 Wayland - www.glfw.org
|
|
//------------------------------------------------------------------------
|
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would
|
|
// be appreciated but is not required.
|
|
//
|
|
// 2. Altered source versions must be plainly marked as such, and must not
|
|
// be misrepresented as being the original software.
|
|
//
|
|
// 3. This notice may not be removed or altered from any source
|
|
// distribution.
|
|
//
|
|
//========================================================================
|
|
// It is fine to use C99 in this file because it will not be built with VS
|
|
//========================================================================
|
|
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
#include "internal.h"
|
|
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <linux/input.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/timerfd.h>
|
|
#include <unistd.h>
|
|
#include <wayland-client.h>
|
|
|
|
static void wmBaseHandlePing(void* userData,
|
|
struct xdg_wm_base* wmBase,
|
|
uint32_t serial)
|
|
{
|
|
xdg_wm_base_pong(wmBase, serial);
|
|
}
|
|
|
|
static const struct xdg_wm_base_listener wmBaseListener =
|
|
{
|
|
wmBaseHandlePing
|
|
};
|
|
|
|
static void registryHandleGlobal(void* userData,
|
|
struct wl_registry* registry,
|
|
uint32_t name,
|
|
const char* interface,
|
|
uint32_t version)
|
|
{
|
|
if (strcmp(interface, "wl_compositor") == 0)
|
|
{
|
|
_glfw.wl.compositorVersion = _glfw_min(3, version);
|
|
_glfw.wl.compositor =
|
|
wl_registry_bind(registry, name, &wl_compositor_interface,
|
|
_glfw.wl.compositorVersion);
|
|
}
|
|
else if (strcmp(interface, "wl_subcompositor") == 0)
|
|
{
|
|
_glfw.wl.subcompositor =
|
|
wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
|
|
}
|
|
else if (strcmp(interface, "wl_shm") == 0)
|
|
{
|
|
_glfw.wl.shm =
|
|
wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
|
}
|
|
else if (strcmp(interface, "wl_output") == 0)
|
|
{
|
|
_glfwAddOutputWayland(name, version);
|
|
}
|
|
else if (strcmp(interface, "wl_seat") == 0)
|
|
{
|
|
if (!_glfw.wl.seat)
|
|
{
|
|
_glfw.wl.seatVersion = _glfw_min(4, version);
|
|
_glfw.wl.seat =
|
|
wl_registry_bind(registry, name, &wl_seat_interface,
|
|
_glfw.wl.seatVersion);
|
|
_glfwAddSeatListenerWayland(_glfw.wl.seat);
|
|
}
|
|
}
|
|
else if (strcmp(interface, "wl_data_device_manager") == 0)
|
|
{
|
|
if (!_glfw.wl.dataDeviceManager)
|
|
{
|
|
_glfw.wl.dataDeviceManager =
|
|
wl_registry_bind(registry, name,
|
|
&wl_data_device_manager_interface, 1);
|
|
}
|
|
}
|
|
else if (strcmp(interface, "xdg_wm_base") == 0)
|
|
{
|
|
_glfw.wl.wmBase =
|
|
wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
|
|
xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
|
|
}
|
|
else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
|
|
{
|
|
_glfw.wl.decorationManager =
|
|
wl_registry_bind(registry, name,
|
|
&zxdg_decoration_manager_v1_interface,
|
|
1);
|
|
}
|
|
else if (strcmp(interface, "wp_viewporter") == 0)
|
|
{
|
|
_glfw.wl.viewporter =
|
|
wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
|
|
}
|
|
else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
|
|
{
|
|
_glfw.wl.relativePointerManager =
|
|
wl_registry_bind(registry, name,
|
|
&zwp_relative_pointer_manager_v1_interface,
|
|
1);
|
|
}
|
|
else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
|
|
{
|
|
_glfw.wl.pointerConstraints =
|
|
wl_registry_bind(registry, name,
|
|
&zwp_pointer_constraints_v1_interface,
|
|
1);
|
|
}
|
|
else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
|
|
{
|
|
_glfw.wl.idleInhibitManager =
|
|
wl_registry_bind(registry, name,
|
|
&zwp_idle_inhibit_manager_v1_interface,
|
|
1);
|
|
}
|
|
}
|
|
|
|
static void registryHandleGlobalRemove(void* userData,
|
|
struct wl_registry* registry,
|
|
uint32_t name)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < _glfw.monitorCount; ++i)
|
|
{
|
|
_GLFWmonitor* monitor = _glfw.monitors[i];
|
|
if (monitor->wl.name == name)
|
|
{
|
|
_glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static const struct wl_registry_listener registryListener =
|
|
{
|
|
registryHandleGlobal,
|
|
registryHandleGlobalRemove
|
|
};
|
|
|
|
// Create key code translation tables
|
|
//
|
|
static void createKeyTables(void)
|
|
{
|
|
int scancode;
|
|
|
|
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
|
|
memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
|
|
|
|
_glfw.wl.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
|
_glfw.wl.keycodes[KEY_1] = GLFW_KEY_1;
|
|
_glfw.wl.keycodes[KEY_2] = GLFW_KEY_2;
|
|
_glfw.wl.keycodes[KEY_3] = GLFW_KEY_3;
|
|
_glfw.wl.keycodes[KEY_4] = GLFW_KEY_4;
|
|
_glfw.wl.keycodes[KEY_5] = GLFW_KEY_5;
|
|
_glfw.wl.keycodes[KEY_6] = GLFW_KEY_6;
|
|
_glfw.wl.keycodes[KEY_7] = GLFW_KEY_7;
|
|
_glfw.wl.keycodes[KEY_8] = GLFW_KEY_8;
|
|
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
|
|
_glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
|
|
_glfw.wl.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
|
|
_glfw.wl.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
|
|
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
|
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
|
|
_glfw.wl.keycodes[KEY_W] = GLFW_KEY_W;
|
|
_glfw.wl.keycodes[KEY_E] = GLFW_KEY_E;
|
|
_glfw.wl.keycodes[KEY_R] = GLFW_KEY_R;
|
|
_glfw.wl.keycodes[KEY_T] = GLFW_KEY_T;
|
|
_glfw.wl.keycodes[KEY_Y] = GLFW_KEY_Y;
|
|
_glfw.wl.keycodes[KEY_U] = GLFW_KEY_U;
|
|
_glfw.wl.keycodes[KEY_I] = GLFW_KEY_I;
|
|
_glfw.wl.keycodes[KEY_O] = GLFW_KEY_O;
|
|
_glfw.wl.keycodes[KEY_P] = GLFW_KEY_P;
|
|
_glfw.wl.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
|
_glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
|
_glfw.wl.keycodes[KEY_A] = GLFW_KEY_A;
|
|
_glfw.wl.keycodes[KEY_S] = GLFW_KEY_S;
|
|
_glfw.wl.keycodes[KEY_D] = GLFW_KEY_D;
|
|
_glfw.wl.keycodes[KEY_F] = GLFW_KEY_F;
|
|
_glfw.wl.keycodes[KEY_G] = GLFW_KEY_G;
|
|
_glfw.wl.keycodes[KEY_H] = GLFW_KEY_H;
|
|
_glfw.wl.keycodes[KEY_J] = GLFW_KEY_J;
|
|
_glfw.wl.keycodes[KEY_K] = GLFW_KEY_K;
|
|
_glfw.wl.keycodes[KEY_L] = GLFW_KEY_L;
|
|
_glfw.wl.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
|
_glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
|
_glfw.wl.keycodes[KEY_Z] = GLFW_KEY_Z;
|
|
_glfw.wl.keycodes[KEY_X] = GLFW_KEY_X;
|
|
_glfw.wl.keycodes[KEY_C] = GLFW_KEY_C;
|
|
_glfw.wl.keycodes[KEY_V] = GLFW_KEY_V;
|
|
_glfw.wl.keycodes[KEY_B] = GLFW_KEY_B;
|
|
_glfw.wl.keycodes[KEY_N] = GLFW_KEY_N;
|
|
_glfw.wl.keycodes[KEY_M] = GLFW_KEY_M;
|
|
_glfw.wl.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
|
|
_glfw.wl.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
|
|
_glfw.wl.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
|
|
_glfw.wl.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
|
_glfw.wl.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
|
|
_glfw.wl.keycodes[KEY_TAB] = GLFW_KEY_TAB;
|
|
_glfw.wl.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
|
_glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
|
_glfw.wl.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
|
_glfw.wl.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
|
_glfw.wl.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
|
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
|
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
|
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
|
_glfw.wl.keycodes[KEY_COMPOSE] = GLFW_KEY_MENU;
|
|
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
|
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
|
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
|
_glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
|
_glfw.wl.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
|
_glfw.wl.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
|
|
_glfw.wl.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
|
_glfw.wl.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
|
|
_glfw.wl.keycodes[KEY_HOME] = GLFW_KEY_HOME;
|
|
_glfw.wl.keycodes[KEY_END] = GLFW_KEY_END;
|
|
_glfw.wl.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
|
_glfw.wl.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
|
_glfw.wl.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
|
|
_glfw.wl.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
|
|
_glfw.wl.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
|
_glfw.wl.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
|
|
_glfw.wl.keycodes[KEY_UP] = GLFW_KEY_UP;
|
|
_glfw.wl.keycodes[KEY_F1] = GLFW_KEY_F1;
|
|
_glfw.wl.keycodes[KEY_F2] = GLFW_KEY_F2;
|
|
_glfw.wl.keycodes[KEY_F3] = GLFW_KEY_F3;
|
|
_glfw.wl.keycodes[KEY_F4] = GLFW_KEY_F4;
|
|
_glfw.wl.keycodes[KEY_F5] = GLFW_KEY_F5;
|
|
_glfw.wl.keycodes[KEY_F6] = GLFW_KEY_F6;
|
|
_glfw.wl.keycodes[KEY_F7] = GLFW_KEY_F7;
|
|
_glfw.wl.keycodes[KEY_F8] = GLFW_KEY_F8;
|
|
_glfw.wl.keycodes[KEY_F9] = GLFW_KEY_F9;
|
|
_glfw.wl.keycodes[KEY_F10] = GLFW_KEY_F10;
|
|
_glfw.wl.keycodes[KEY_F11] = GLFW_KEY_F11;
|
|
_glfw.wl.keycodes[KEY_F12] = GLFW_KEY_F12;
|
|
_glfw.wl.keycodes[KEY_F13] = GLFW_KEY_F13;
|
|
_glfw.wl.keycodes[KEY_F14] = GLFW_KEY_F14;
|
|
_glfw.wl.keycodes[KEY_F15] = GLFW_KEY_F15;
|
|
_glfw.wl.keycodes[KEY_F16] = GLFW_KEY_F16;
|
|
_glfw.wl.keycodes[KEY_F17] = GLFW_KEY_F17;
|
|
_glfw.wl.keycodes[KEY_F18] = GLFW_KEY_F18;
|
|
_glfw.wl.keycodes[KEY_F19] = GLFW_KEY_F19;
|
|
_glfw.wl.keycodes[KEY_F20] = GLFW_KEY_F20;
|
|
_glfw.wl.keycodes[KEY_F21] = GLFW_KEY_F21;
|
|
_glfw.wl.keycodes[KEY_F22] = GLFW_KEY_F22;
|
|
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
|
|
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
|
|
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
|
_glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY;
|
|
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
|
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
|
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
|
_glfw.wl.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
|
|
_glfw.wl.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
|
|
_glfw.wl.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
|
|
_glfw.wl.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
|
|
_glfw.wl.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
|
|
_glfw.wl.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
|
|
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
|
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
|
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
|
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_DECIMAL;
|
|
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
|
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
|
_glfw.wl.keycodes[KEY_102ND] = GLFW_KEY_WORLD_2;
|
|
|
|
for (scancode = 0; scancode < 256; scancode++)
|
|
{
|
|
if (_glfw.wl.keycodes[scancode] > 0)
|
|
_glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
|
|
}
|
|
}
|
|
|
|
static GLFWbool loadCursorTheme(void)
|
|
{
|
|
const char* cursorTheme;
|
|
const char* cursorSizeStr;
|
|
char* cursorSizeEnd;
|
|
long cursorSizeLong;
|
|
int cursorSize;
|
|
|
|
cursorTheme = getenv("XCURSOR_THEME");
|
|
cursorSizeStr = getenv("XCURSOR_SIZE");
|
|
cursorSize = 32;
|
|
if (cursorSizeStr)
|
|
{
|
|
errno = 0;
|
|
cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
|
|
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
|
|
cursorSize = (int)cursorSizeLong;
|
|
}
|
|
_glfw.wl.cursorTheme =
|
|
wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
|
|
if (!_glfw.wl.cursorTheme)
|
|
{
|
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
"Wayland: Failed to load default cursor theme");
|
|
return GLFW_FALSE;
|
|
}
|
|
// If this happens to be NULL, we just fallback to the scale=1 version.
|
|
_glfw.wl.cursorThemeHiDPI =
|
|
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
|
|
_glfw.wl.cursorSurface =
|
|
wl_compositor_create_surface(_glfw.wl.compositor);
|
|
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
|
return GLFW_TRUE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
////// GLFW platform API //////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
int _glfwPlatformInit(void)
|
|
{
|
|
// These must be set before any failure checks
|
|
_glfw.wl.keyRepeatTimerfd = -1;
|
|
_glfw.wl.cursorTimerfd = -1;
|
|
|
|
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
|
|
if (!_glfw.wl.cursor.handle)
|
|
{
|
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
"Wayland: Failed to load libwayland-cursor");
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
_glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
|
|
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
|
|
_glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
|
|
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
|
|
_glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
|
|
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
|
|
_glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
|
|
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
|
|
|
|
_glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
|
|
if (!_glfw.wl.egl.handle)
|
|
{
|
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
"Wayland: Failed to load libwayland-egl");
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
_glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
|
|
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");
|
|
_glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
|
|
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
|
|
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
|
|
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
|
|
|
|
_glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
|
|
if (!_glfw.wl.xkb.handle)
|
|
{
|
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
"Wayland: Failed to load libxkbcommon");
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
_glfw.wl.xkb.context_new = (PFN_xkb_context_new)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
|
|
_glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
|
|
_glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
|
|
_glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
|
|
_glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
|
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
|
|
_glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level");
|
|
_glfw.wl.xkb.state_new = (PFN_xkb_state_new)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
|
|
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
|
|
_glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
|
|
_glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
|
|
_glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
|
|
_glfw.wl.xkb.state_mod_index_is_active = (PFN_xkb_state_mod_index_is_active)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_mod_index_is_active");
|
|
|
|
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
|
|
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
|
|
_glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
|
|
_glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
|
|
_glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
|
|
_glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
|
|
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
|
|
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
|
|
|
|
_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);
|
|
|
|
createKeyTables();
|
|
|
|
_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);
|
|
|
|
#ifdef __linux__
|
|
if (!_glfwInitJoysticksLinux())
|
|
return GLFW_FALSE;
|
|
#endif
|
|
|
|
_glfwInitTimerPOSIX();
|
|
|
|
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
|
if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
|
|
{
|
|
_glfw.wl.keyRepeatTimerfd =
|
|
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
|
}
|
|
#endif
|
|
|
|
if (!_glfw.wl.wmBase)
|
|
{
|
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
"Wayland: Failed to find xdg-shell in your compositor");
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
if (!_glfw.wl.shm)
|
|
{
|
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
"Wayland: Failed to find wl_shm in your compositor");
|
|
return GLFW_FALSE;
|
|
}
|
|
|
|
if (!loadCursorTheme())
|
|
return GLFW_FALSE;
|
|
|
|
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
|
|
{
|
|
_glfw.wl.dataDevice =
|
|
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
|
|
_glfw.wl.seat);
|
|
_glfwAddDataDeviceListenerWayland(_glfw.wl.dataDevice);
|
|
}
|
|
|
|
return GLFW_TRUE;
|
|
}
|
|
|
|
void _glfwPlatformTerminate(void)
|
|
{
|
|
#ifdef __linux__
|
|
_glfwTerminateJoysticksLinux();
|
|
#endif
|
|
_glfwTerminateEGL();
|
|
_glfwTerminateOSMesa();
|
|
|
|
if (_glfw.wl.egl.handle)
|
|
{
|
|
_glfw_dlclose(_glfw.wl.egl.handle);
|
|
_glfw.wl.egl.handle = NULL;
|
|
}
|
|
|
|
if (_glfw.wl.xkb.composeState)
|
|
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
|
if (_glfw.wl.xkb.keymap)
|
|
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
|
if (_glfw.wl.xkb.state)
|
|
xkb_state_unref(_glfw.wl.xkb.state);
|
|
if (_glfw.wl.xkb.context)
|
|
xkb_context_unref(_glfw.wl.xkb.context);
|
|
if (_glfw.wl.xkb.handle)
|
|
{
|
|
_glfw_dlclose(_glfw.wl.xkb.handle);
|
|
_glfw.wl.xkb.handle = NULL;
|
|
}
|
|
|
|
if (_glfw.wl.cursorTheme)
|
|
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
|
if (_glfw.wl.cursorThemeHiDPI)
|
|
wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
|
|
if (_glfw.wl.cursor.handle)
|
|
{
|
|
_glfw_dlclose(_glfw.wl.cursor.handle);
|
|
_glfw.wl.cursor.handle = NULL;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
|
|
wl_data_offer_destroy(_glfw.wl.offers[i].offer);
|
|
|
|
free(_glfw.wl.offers);
|
|
|
|
if (_glfw.wl.cursorSurface)
|
|
wl_surface_destroy(_glfw.wl.cursorSurface);
|
|
if (_glfw.wl.subcompositor)
|
|
wl_subcompositor_destroy(_glfw.wl.subcompositor);
|
|
if (_glfw.wl.compositor)
|
|
wl_compositor_destroy(_glfw.wl.compositor);
|
|
if (_glfw.wl.shm)
|
|
wl_shm_destroy(_glfw.wl.shm);
|
|
if (_glfw.wl.viewporter)
|
|
wp_viewporter_destroy(_glfw.wl.viewporter);
|
|
if (_glfw.wl.decorationManager)
|
|
zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
|
|
if (_glfw.wl.wmBase)
|
|
xdg_wm_base_destroy(_glfw.wl.wmBase);
|
|
if (_glfw.wl.selectionOffer)
|
|
wl_data_offer_destroy(_glfw.wl.selectionOffer);
|
|
if (_glfw.wl.dragOffer)
|
|
wl_data_offer_destroy(_glfw.wl.dragOffer);
|
|
if (_glfw.wl.selectionSource)
|
|
wl_data_source_destroy(_glfw.wl.selectionSource);
|
|
if (_glfw.wl.dataDevice)
|
|
wl_data_device_destroy(_glfw.wl.dataDevice);
|
|
if (_glfw.wl.dataDeviceManager)
|
|
wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
|
|
if (_glfw.wl.pointer)
|
|
wl_pointer_destroy(_glfw.wl.pointer);
|
|
if (_glfw.wl.keyboard)
|
|
wl_keyboard_destroy(_glfw.wl.keyboard);
|
|
if (_glfw.wl.seat)
|
|
wl_seat_destroy(_glfw.wl.seat);
|
|
if (_glfw.wl.relativePointerManager)
|
|
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
|
|
if (_glfw.wl.pointerConstraints)
|
|
zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
|
|
if (_glfw.wl.idleInhibitManager)
|
|
zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
|
|
if (_glfw.wl.registry)
|
|
wl_registry_destroy(_glfw.wl.registry);
|
|
if (_glfw.wl.display)
|
|
{
|
|
wl_display_flush(_glfw.wl.display);
|
|
wl_display_disconnect(_glfw.wl.display);
|
|
}
|
|
|
|
if (_glfw.wl.keyRepeatTimerfd >= 0)
|
|
close(_glfw.wl.keyRepeatTimerfd);
|
|
if (_glfw.wl.cursorTimerfd >= 0)
|
|
close(_glfw.wl.cursorTimerfd);
|
|
|
|
free(_glfw.wl.clipboardString);
|
|
}
|
|
|
|
const char* _glfwPlatformGetVersionString(void)
|
|
{
|
|
return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa"
|
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
|
" clock_gettime"
|
|
#else
|
|
" gettimeofday"
|
|
#endif
|
|
" evdev"
|
|
#if defined(_GLFW_BUILD_DLL)
|
|
" shared"
|
|
#endif
|
|
;
|
|
}
|