Merge branch 'glfw:master' into master

This commit is contained in:
Snowiiii 2022-01-01 22:11:50 +01:00 committed by GitHub
commit b062262fcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 263 additions and 218 deletions

View File

@ -266,6 +266,7 @@ information on what to include when reporting a bug.
undefined behavior (#1986)
- [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
- [Wayland] Added dynamic loading of all Wayland libraries
- [Wayland] Added support for key names via xkbcommon
- [Wayland] Removed support for `wl_shell` (#1443)
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
- [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled
@ -283,6 +284,11 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: Activating a window would emit two input focus events
- [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus
- [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731)
- [Wayland] Bugfix: A key being repeated was not released when window lost focus
- [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event
- [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE`
- [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN`
- [Wayland] Bugfix: Text input did not repeat along with key repeat
- [POSIX] Removed use of deprecated function `gettimeofday`
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
- [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072)

View File

@ -104,9 +104,8 @@ integration by libwayland-egl, and keyboard handling by
from wayland-protocols to provide additional features if the compositor
supports them.
GLFW uses xkbcommon 0.5.0 to provide compose key support. When it has been
built against an older xkbcommon, the compose key will be disabled even if it
has been configured in the compositor.
GLFW uses xkbcommon 0.5.0 to provide key and text input support. Earlier
versions are not supported.
GLFW uses the [xdg-shell
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)

View File

@ -3764,6 +3764,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland Because Wayland wants every frame of the desktop to be
* complete, this function does not immediately make the window visible.
* Instead it will become visible the next time the window framebuffer is
* updated after this call.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_hide
@ -6189,9 +6194,6 @@ GLFWAPI int glfwVulkanSupported(void);
* returned array, as it is an error to specify an extension more than once in
* the `VkInstanceCreateInfo` struct.
*
* @remark @macos GLFW currently supports both the `VK_MVK_macos_surface` and
* the newer `VK_EXT_metal_surface` extensions.
*
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
* should not free it yourself. It is guaranteed to be valid only until the
* library is terminated.
@ -6330,17 +6332,20 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
* eliminate almost all occurrences of these errors.
*
* @remark @macos This function currently only supports the
* `VK_MVK_macos_surface` extension from MoltenVK.
* @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the
* `VK_MVK_macos_surface` extension as a fallback. The name of the selected
* extension, if any, is included in the array returned by @ref
* glfwGetRequiredInstanceExtensions.
*
* @remark @macos This function creates and sets a `CAMetalLayer` instance for
* the window content view, which is required for MoltenVK to function.
*
* @remark @x11 GLFW by default attempts to use the `VK_KHR_xcb_surface`
* extension, if available. You can make it prefer the `VK_KHR_xlib_surface`
* extension by setting the
* @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension,
* with the `VK_KHR_xlib_surface` extension as a fallback. You can make
* `VK_KHR_xlib_surface` the preferred extension by setting the
* [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init
* hint.
* hint. The name of the selected extension, if any, is included in the array
* returned by @ref glfwGetRequiredInstanceExtensions.
*
* @thread_safety This function may be called from any thread. For
* synchronization details of Vulkan objects, see the Vulkan specification.

View File

@ -65,10 +65,6 @@ endif()
if (GLFW_BUILD_WAYLAND)
include(CheckIncludeFiles)
include(CheckFunctionExists)
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
if (HAVE_XKBCOMMON_COMPOSE_H)
target_compile_definitions(glfw PRIVATE HAVE_XKBCOMMON_COMPOSE_H)
endif()
check_function_exists(memfd_create HAVE_MEMFD_CREATE)
if (HAVE_MEMFD_CREATE)
target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE)
@ -173,7 +169,7 @@ if (GLFW_BUILD_WAYLAND)
wayland-client>=0.2.7
wayland-cursor>=0.2.7
wayland-egl>=0.2.7
xkbcommon)
xkbcommon>=0.5.0)
target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS})

View File

@ -140,6 +140,37 @@ static void terminate(void)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Encode a Unicode code point to a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint)
{
size_t count = 0;
if (codepoint < 0x80)
s[count++] = (char) codepoint;
else if (codepoint < 0x800)
{
s[count++] = (codepoint >> 6) | 0xc0;
s[count++] = (codepoint & 0x3f) | 0x80;
}
else if (codepoint < 0x10000)
{
s[count++] = (codepoint >> 12) | 0xe0;
s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
s[count++] = (codepoint & 0x3f) | 0x80;
}
else if (codepoint < 0x110000)
{
s[count++] = (codepoint >> 18) | 0xf0;
s[count++] = ((codepoint >> 12) & 0x3f) | 0x80;
s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
s[count++] = (codepoint & 0x3f) | 0x80;
}
return count;
}
char* _glfw_strdup(const char* source)
{
const size_t length = strlen(source);

View File

@ -302,7 +302,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m
// Notifies shared code of a Unicode codepoint input event
// The 'plain' parameter determines whether to emit a regular character event
//
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain)
{
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
return;

View File

@ -919,7 +919,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
void _glfwInputKey(_GLFWwindow* window,
int key, int scancode, int action, int mods);
void _glfwInputChar(_GLFWwindow* window,
unsigned int codepoint, int mods, GLFWbool plain);
uint32_t codepoint, int mods, GLFWbool plain);
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
@ -995,6 +995,8 @@ GLFWbool _glfwInitVulkan(int mode);
void _glfwTerminateVulkan(void);
const char* _glfwGetVulkanResultString(VkResult result);
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);
char* _glfw_strdup(const char* source);
float _glfw_fminf(float a, float b);
float _glfw_fmaxf(float a, float b);

View File

@ -649,7 +649,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
window->win32.highSurrogate = (WCHAR) wParam;
else
{
unsigned int codepoint = 0;
uint32_t codepoint = 0;
if (wParam >= 0xdc00 && wParam <= 0xdfff)
{
@ -683,7 +683,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return TRUE;
}
_glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE);
_glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE);
return 0;
}

View File

@ -207,12 +207,12 @@ static void pointerHandleMotion(void* data,
return;
x = wl_fixed_to_double(sx);
y = wl_fixed_to_double(sy);
window->wl.cursorPosX = x;
window->wl.cursorPosY = y;
switch (window->wl.decorations.focus)
{
case mainWindow:
window->wl.cursorPosX = x;
window->wl.cursorPosY = y;
_glfwInputCursorPos(window, x, y);
_glfw.wl.cursorPreviousName = NULL;
return;
@ -272,9 +272,7 @@ static void pointerHandleButton(void* data,
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else
{
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
}
break;
case leftDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
@ -303,6 +301,7 @@ static void pointerHandleButton(void* data,
{
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
serial, edges);
return;
}
}
else if (button == BTN_RIGHT)
@ -378,11 +377,8 @@ static void keyboardHandleKeymap(void* data,
{
struct xkb_keymap* keymap;
struct xkb_state* state;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
struct xkb_compose_table* composeTable;
struct xkb_compose_state* composeState;
#endif
char* mapStr;
const char* locale;
@ -431,7 +427,6 @@ static void keyboardHandleKeymap(void* data,
if (!locale)
locale = "C";
#ifdef HAVE_XKBCOMMON_COMPOSE_H
composeTable =
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
XKB_COMPOSE_COMPILE_NO_FLAGS);
@ -451,7 +446,6 @@ static void keyboardHandleKeymap(void* data,
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create XKB compose table");
}
#endif
xkb_keymap_unref(_glfw.wl.xkb.keymap);
xkb_state_unref(_glfw.wl.xkb.state);
@ -505,23 +499,22 @@ static void keyboardHandleLeave(void* data,
if (!window)
return;
struct itimerspec timer = {};
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
_glfw.wl.serial = serial;
_glfw.wl.keyboardFocus = NULL;
_glfwInputWindowFocus(window, GLFW_FALSE);
struct itimerspec timer = {};
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
}
static int toGLFWKeyCode(uint32_t key)
static int translateKey(uint32_t scancode)
{
if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
return _glfw.wl.keycodes[key];
if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
return _glfw.wl.keycodes[scancode];
return GLFW_KEY_UNKNOWN;
}
#ifdef HAVE_XKBCOMMON_COMPOSE_H
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
{
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
@ -541,77 +534,65 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
return sym;
}
}
#endif
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode)
{
uint32_t code, numSyms;
long cp;
const xkb_keysym_t *syms;
xkb_keysym_t sym;
const xkb_keysym_t* keysyms;
const xkb_keycode_t keycode = scancode + 8;
code = key + 8;
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
if (numSyms == 1)
if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
{
#ifdef HAVE_XKBCOMMON_COMPOSE_H
sym = composeSymbol(syms[0]);
#else
sym = syms[0];
#endif
cp = _glfwKeySym2Unicode(sym);
if (cp != -1)
const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
{
const int mods = _glfw.wl.xkb.modifiers;
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputChar(window, cp, mods, plain);
_glfwInputChar(window, codepoint, mods, plain);
}
}
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code);
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode);
}
static void keyboardHandleKey(void* data,
struct wl_keyboard* keyboard,
uint32_t serial,
uint32_t time,
uint32_t key,
uint32_t scancode,
uint32_t state)
{
int keyCode;
int action;
_GLFWwindow* window = _glfw.wl.keyboardFocus;
GLFWbool shouldRepeat;
struct itimerspec timer = {};
if (!window)
return;
keyCode = toGLFWKeyCode(key);
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
? GLFW_PRESS : GLFW_RELEASE;
const int key = translateKey(scancode);
const int action =
state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
_glfw.wl.serial = serial;
_glfwInputKey(window, keyCode, key, action,
_glfw.wl.xkb.modifiers);
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
struct itimerspec timer = {};
if (action == GLFW_PRESS)
{
shouldRepeat = inputChar(window, key);
const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode);
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
{
_glfw.wl.keyboardLastKey = keyCode;
_glfw.wl.keyboardLastScancode = key;
_glfw.wl.keyboardLastKey = key;
_glfw.wl.keyboardLastScancode = scancode;
if (_glfw.wl.keyboardRepeatRate > 1)
timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
else
timer.it_interval.tv_sec = 1;
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
}
}
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
}
@ -623,9 +604,6 @@ static void keyboardHandleModifiers(void* data,
uint32_t modsLocked,
uint32_t group)
{
xkb_mod_mask_t mask;
unsigned int modifiers = 0;
_glfw.wl.serial = serial;
if (!_glfw.wl.xkb.keymap)
@ -639,24 +617,29 @@ static void keyboardHandleModifiers(void* data,
0,
group);
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
XKB_STATE_MODS_DEPRESSED |
XKB_STATE_LAYOUT_DEPRESSED |
XKB_STATE_MODS_LATCHED |
XKB_STATE_LAYOUT_LATCHED);
const xkb_mod_mask_t mask =
xkb_state_serialize_mods(_glfw.wl.xkb.state,
XKB_STATE_MODS_DEPRESSED |
XKB_STATE_LAYOUT_DEPRESSED |
XKB_STATE_MODS_LATCHED |
XKB_STATE_LAYOUT_LATCHED);
unsigned int mods = 0;
if (mask & _glfw.wl.xkb.controlMask)
modifiers |= GLFW_MOD_CONTROL;
mods |= GLFW_MOD_CONTROL;
if (mask & _glfw.wl.xkb.altMask)
modifiers |= GLFW_MOD_ALT;
mods |= GLFW_MOD_ALT;
if (mask & _glfw.wl.xkb.shiftMask)
modifiers |= GLFW_MOD_SHIFT;
mods |= GLFW_MOD_SHIFT;
if (mask & _glfw.wl.xkb.superMask)
modifiers |= GLFW_MOD_SUPER;
mods |= GLFW_MOD_SUPER;
if (mask & _glfw.wl.xkb.capsLockMask)
modifiers |= GLFW_MOD_CAPS_LOCK;
mods |= GLFW_MOD_CAPS_LOCK;
if (mask & _glfw.wl.xkb.numLockMask)
modifiers |= GLFW_MOD_NUM_LOCK;
_glfw.wl.xkb.modifiers = modifiers;
mods |= GLFW_MOD_NUM_LOCK;
_glfw.wl.xkb.modifiers = mods;
}
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
@ -973,7 +956,7 @@ static void createKeyTables(void)
_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_MENU] = GLFW_KEY_MENU;
_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;
@ -1016,7 +999,7 @@ static void createKeyTables(void)
_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_KPDOT] = GLFW_KEY_KP_MULTIPLY;
_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;
@ -1029,9 +1012,10 @@ static void createKeyTables(void)
_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_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
_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 (int scancode = 0; scancode < 256; scancode++)
{
@ -1290,6 +1274,8 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
_glfwPlatformGetModuleSymbol(_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)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level");
_glfw.wl.xkb.state_new = (PFN_xkb_state_new)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_new");
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
@ -1300,8 +1286,8 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask");
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
#ifdef HAVE_XKBCOMMON_COMPOSE_H
_glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
@ -1316,7 +1302,6 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
#endif
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
@ -1404,10 +1389,8 @@ void _glfwTerminateWayland(void)
_glfw.wl.egl.handle = NULL;
}
#ifdef HAVE_XKBCOMMON_COMPOSE_H
if (_glfw.wl.xkb.composeState)
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
#endif
if (_glfw.wl.xkb.keymap)
xkb_keymap_unref(_glfw.wl.xkb.keymap);
if (_glfw.wl.xkb.state)

View File

@ -26,9 +26,7 @@
#include <wayland-client-core.h>
#include <xkbcommon/xkbcommon.h>
#ifdef HAVE_XKBCOMMON_COMPOSE_H
#include <xkbcommon/xkbcommon-compose.h>
#endif
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
@ -163,24 +161,27 @@ typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**);
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
#define xkb_context_new _glfw.wl.xkb.context_new
#define xkb_context_unref _glfw.wl.xkb.context_unref
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level
#define xkb_state_new _glfw.wl.xkb.state_new
#define xkb_state_unref _glfw.wl.xkb.state_unref
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout
#ifdef HAVE_XKBCOMMON_COMPOSE_H
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
@ -195,7 +196,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
#endif
#define _GLFW_DECORATION_WIDTH 4
#define _GLFW_DECORATION_TOP 24
@ -311,6 +311,7 @@ typedef struct _GLFWlibraryWayland
int timerfd;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5];
struct {
void* handle;
@ -318,9 +319,7 @@ typedef struct _GLFWlibraryWayland
struct xkb_keymap* keymap;
struct xkb_state* state;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
struct xkb_compose_state* composeState;
#endif
xkb_mod_mask_t controlMask;
xkb_mod_mask_t altMask;
@ -336,13 +335,14 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_keymap_unref keymap_unref;
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
PFN_xkb_keymap_key_repeats keymap_key_repeats;
PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level;
PFN_xkb_state_new state_new;
PFN_xkb_state_unref state_unref;
PFN_xkb_state_key_get_syms state_key_get_syms;
PFN_xkb_state_update_mask state_update_mask;
PFN_xkb_state_serialize_mods state_serialize_mods;
PFN_xkb_state_key_get_layout state_key_get_layout;
#ifdef HAVE_XKBCOMMON_COMPOSE_H
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
PFN_xkb_compose_table_unref compose_table_unref;
PFN_xkb_compose_state_new compose_state_new;
@ -350,7 +350,6 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_compose_state_feed compose_state_feed;
PFN_xkb_compose_state_get_status compose_state_get_status;
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
#endif
} xkb;
_GLFWwindow* pointerFocus;
@ -496,4 +495,5 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);

View File

@ -432,35 +432,6 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
}
}
static GLFWbool createSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
if (!window->wl.surface)
return GLFW_FALSE;
wl_surface_add_listener(window->wl.surface,
&surfaceListener,
window);
wl_surface_set_user_data(window->wl.surface, window);
window->wl.native = wl_egl_window_create(window->wl.surface,
wndconfig->width,
wndconfig->height);
if (!window->wl.native)
return GLFW_FALSE;
window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height;
window->wl.scale = 1;
if (!window->wl.transparent)
setOpaqueRegion(window);
return GLFW_TRUE;
}
static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
int refreshRate)
{
@ -644,6 +615,46 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
return GLFW_TRUE;
}
static GLFWbool createSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWfbconfig* fbconfig)
{
window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
if (!window->wl.surface)
return GLFW_FALSE;
wl_surface_add_listener(window->wl.surface,
&surfaceListener,
window);
wl_surface_set_user_data(window->wl.surface, window);
window->wl.native = wl_egl_window_create(window->wl.surface,
wndconfig->width,
wndconfig->height);
if (!window->wl.native)
return GLFW_FALSE;
window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height;
window->wl.scale = 1;
window->wl.title = _glfw_strdup(wndconfig->title);
window->wl.transparent = fbconfig->transparent;
if (!window->wl.transparent)
setOpaqueRegion(window);
if (window->monitor || wndconfig->visible)
{
if (!createXdgSurface(window))
return GLFW_FALSE;
window->wl.visible = GLFW_TRUE;
}
return GLFW_TRUE;
}
static void setCursorImage(_GLFWwindow* window,
_GLFWcursorWayland* cursorWayland)
{
@ -708,22 +719,19 @@ static void incrementCursorImage(_GLFWwindow* window)
static void handleEvents(int timeout)
{
struct wl_display* display = _glfw.wl.display;
struct pollfd fds[] = {
{ wl_display_get_fd(display), POLLIN },
struct pollfd fds[] =
{
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
{ _glfw.wl.timerfd, POLLIN },
{ _glfw.wl.cursorTimerfd, POLLIN },
};
ssize_t read_ret;
uint64_t repeats;
while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display);
while (wl_display_prepare_read(_glfw.wl.display) != 0)
wl_display_dispatch_pending(_glfw.wl.display);
// If an error different from EAGAIN happens, we have likely been
// disconnected from the Wayland session, try to handle that the best we
// can.
if (wl_display_flush(display) < 0 && errno != EAGAIN)
// If an error other than EAGAIN happens, we have likely been disconnected
// from the Wayland session; try to handle that the best we can.
if (wl_display_flush(_glfw.wl.display) < 0 && errno != EAGAIN)
{
_GLFWwindow* window = _glfw.windowListHead;
while (window)
@ -731,7 +739,8 @@ static void handleEvents(int timeout)
_glfwInputWindowCloseRequest(window);
window = window->next;
}
wl_display_cancel_read(display);
wl_display_cancel_read(_glfw.wl.display);
return;
}
@ -739,41 +748,41 @@ static void handleEvents(int timeout)
{
if (fds[0].revents & POLLIN)
{
wl_display_read_events(display);
wl_display_dispatch_pending(display);
wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_pending(_glfw.wl.display);
}
else
{
wl_display_cancel_read(display);
}
wl_display_cancel_read(_glfw.wl.display);
if (fds[1].revents & POLLIN)
{
read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
if (read_ret == 8 && _glfw.wl.keyboardFocus)
uint64_t repeats;
if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8)
{
for (uint64_t i = 0; i < repeats; ++i)
for (uint64_t i = 0; i < repeats; i++)
{
_glfwInputKey(_glfw.wl.keyboardFocus,
_glfw.wl.keyboardLastKey,
_glfw.wl.keyboardLastScancode,
GLFW_REPEAT,
GLFW_PRESS,
_glfw.wl.xkb.modifiers);
_glfwInputTextWayland(_glfw.wl.keyboardFocus,
_glfw.wl.keyboardLastScancode);
}
}
}
if (fds[2].revents & POLLIN)
{
read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));
if (read_ret == 8)
uint64_t repeats;
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
incrementCursorImage(_glfw.wl.pointerFocus);
}
}
else
{
wl_display_cancel_read(display);
}
wl_display_cancel_read(_glfw.wl.display);
}
//////////////////////////////////////////////////////////////////////////
@ -785,9 +794,7 @@ int _glfwCreateWindowWayland(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
window->wl.transparent = fbconfig->transparent;
if (!createSurface(window, wndconfig))
if (!createSurface(window, wndconfig, fbconfig))
return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API)
@ -809,15 +816,6 @@ int _glfwCreateWindowWayland(_GLFWwindow* window,
}
}
if (wndconfig->title)
window->wl.title = _glfw_strdup(wndconfig->title);
window->wl.currentCursor = NULL;
window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*));
window->wl.monitorsCount = 0;
window->wl.monitorsSize = 1;
return GLFW_TRUE;
}
@ -1010,6 +1008,7 @@ void _glfwShowWindowWayland(_GLFWwindow* window)
createXdgSurface(window);
window->wl.visible = GLFW_TRUE;
_glfwInputWindowDamage(window);
}
}
@ -1196,10 +1195,57 @@ void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
const char* _glfwGetScancodeNameWayland(int scancode)
{
// TODO
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
"Wayland: Key names not yet implemented");
return NULL;
if (scancode < 0 || scancode > 255 ||
_glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Wayland: Invalid scancode %i",
scancode);
return NULL;
}
const int key = _glfw.wl.keycodes[scancode];
const xkb_keycode_t keycode = scancode + 8;
const xkb_layout_index_t layout =
xkb_state_key_get_layout(_glfw.wl.xkb.state, keycode);
if (layout == XKB_LAYOUT_INVALID)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to retrieve layout for key name");
return NULL;
}
const xkb_keysym_t* keysyms = NULL;
xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap,
keycode,
layout,
0,
&keysyms);
if (keysyms == NULL)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to retrieve keysym for key name");
return NULL;
}
const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]);
if (codepoint == GLFW_INVALID_CODEPOINT)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to retrieve codepoint for key name");
return NULL;
}
const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], codepoint);
if (count == 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to encode codepoint for key name");
return NULL;
}
_glfw.wl.keynames[key][count] = '\0';
return _glfw.wl.keynames[key];
}
int _glfwGetKeyScancodeWayland(int key)

View File

@ -429,44 +429,13 @@ static char** parseUriList(char* text, int* count)
return paths;
}
// Encode a Unicode code point to a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
static size_t encodeUTF8(char* s, unsigned int ch)
{
size_t count = 0;
if (ch < 0x80)
s[count++] = (char) ch;
else if (ch < 0x800)
{
s[count++] = (ch >> 6) | 0xc0;
s[count++] = (ch & 0x3f) | 0x80;
}
else if (ch < 0x10000)
{
s[count++] = (ch >> 12) | 0xe0;
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
s[count++] = (ch & 0x3f) | 0x80;
}
else if (ch < 0x110000)
{
s[count++] = (ch >> 18) | 0xf0;
s[count++] = ((ch >> 12) & 0x3f) | 0x80;
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
s[count++] = (ch & 0x3f) | 0x80;
}
return count;
}
// Decode a Unicode code point from a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
static unsigned int decodeUTF8(const char** s)
static uint32_t decodeUTF8(const char** s)
{
unsigned int ch = 0, count = 0;
static const unsigned int offsets[] =
uint32_t codepoint = 0, count = 0;
static const uint32_t offsets[] =
{
0x00000000u, 0x00003080u, 0x000e2080u,
0x03c82080u, 0xfa082080u, 0x82082080u
@ -474,13 +443,13 @@ static unsigned int decodeUTF8(const char** s)
do
{
ch = (ch << 6) + (unsigned char) **s;
codepoint = (codepoint << 6) + (unsigned char) **s;
(*s)++;
count++;
} while ((**s & 0xc0) == 0x80);
assert(count <= 6);
return ch - offsets[count - 1];
return codepoint - offsets[count - 1];
}
// Convert the specified Latin-1 string to UTF-8
@ -497,7 +466,7 @@ static char* convertLatin1toUTF8(const char* source)
char* tp = target;
for (sp = source; *sp; sp++)
tp += encodeUTF8(tp, *sp);
tp += _glfwEncodeUTF8(tp, *sp);
return target;
}
@ -1317,9 +1286,9 @@ static void processEvent(XEvent *event)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
const long character = _glfwKeySym2Unicode(keysym);
if (character != -1)
_glfwInputChar(window, character, mods, plain);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
_glfwInputChar(window, codepoint, mods, plain);
}
return;
@ -2899,11 +2868,11 @@ const char* _glfwGetScancodeNameX11(int scancode)
if (keysym == NoSymbol)
return NULL;
const long ch = _glfwKeySym2Unicode(keysym);
if (ch == -1)
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint == GLFW_INVALID_CODEPOINT)
return NULL;
const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch);
const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], codepoint);
if (count == 0)
return NULL;

View File

@ -907,7 +907,7 @@ static const struct codepair {
// Convert XKB KeySym to Unicode
//
long _glfwKeySym2Unicode(unsigned int keysym)
uint32_t _glfwKeySym2Unicode(unsigned int keysym)
{
int min = 0;
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
@ -937,6 +937,6 @@ long _glfwKeySym2Unicode(unsigned int keysym)
}
// No matching Unicode value found
return -1;
return GLFW_INVALID_CODEPOINT;
}

View File

@ -24,5 +24,7 @@
//
//========================================================================
long _glfwKeySym2Unicode(unsigned int keysym);
#define GLFW_INVALID_CODEPOINT 0xffffffffu
uint32_t _glfwKeySym2Unicode(unsigned int keysym);

View File

@ -113,6 +113,12 @@ int main(int argc, char** argv)
{
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
if (!ramp)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
const size_t array_size = ramp->size * sizeof(short);
orig_ramp.size = ramp->size;
orig_ramp.red = malloc(array_size);