Try to use the activation protocol to focus windows

This commit is contained in:
Kovid Goyal 2022-09-11 10:39:28 +05:30
parent 4d30ae55f3
commit ba8d30896b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 27 additions and 11 deletions

10
glfw/wl_init.c vendored
View File

@ -99,7 +99,7 @@ static void pointerHandleEnter(void* data UNUSED,
return; return;
} }
window->wl.decorations.focus = focus; window->wl.decorations.focus = focus;
_glfw.wl.serial = serial; _glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
_glfw.wl.pointerFocus = window; _glfw.wl.pointerFocus = window;
window->wl.hovered = true; window->wl.hovered = true;
@ -311,7 +311,7 @@ static void pointerHandleButton(void* data UNUSED,
if (window->wl.decorations.focus != CENTRAL_WINDOW) if (window->wl.decorations.focus != CENTRAL_WINDOW)
return; return;
_glfw.wl.serial = serial; _glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
* codes. */ * codes. */
@ -463,7 +463,7 @@ static void keyboardHandleEnter(void* data UNUSED,
return; return;
} }
_glfw.wl.serial = serial; _glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
_glfw.wl.keyboardFocusId = window->id; _glfw.wl.keyboardFocusId = window->id;
_glfwInputWindowFocus(window, true); _glfwInputWindowFocus(window, true);
uint32_t* key; uint32_t* key;
@ -516,7 +516,7 @@ static void keyboardHandleKey(void* data UNUSED,
return; return;
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
_glfw.wl.serial = serial; _glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action); glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key)) if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key))
@ -539,7 +539,7 @@ static void keyboardHandleModifiers(void* data UNUSED,
uint32_t modsLocked, uint32_t modsLocked,
uint32_t group) uint32_t group)
{ {
_glfw.wl.serial = serial; _glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group); glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group);
} }

2
glfw/wl_platform.h vendored
View File

@ -293,7 +293,7 @@ typedef struct _GLFWlibraryWayland
struct wl_surface* cursorSurface; struct wl_surface* cursorSurface;
GLFWCursorShape cursorPreviousShape; GLFWCursorShape cursorPreviousShape;
uint32_t serial; uint32_t serial, input_serial;
int32_t keyboardRepeatRate; int32_t keyboardRepeatRate;
monotonic_t keyboardRepeatDelay; monotonic_t keyboardRepeatDelay;

26
glfw/wl_window.c vendored
View File

@ -1160,12 +1160,17 @@ request_attention(GLFWwindow *window, const char *token, void *data UNUSED) {
if (window && token && token[0]) xdg_activation_v1_activate(_glfw.wl.xdg_activation_v1, token, ((_GLFWwindow*)window)->wl.surface); if (window && token && token[0]) xdg_activation_v1_activate(_glfw.wl.xdg_activation_v1, token, ((_GLFWwindow*)window)->wl.surface);
} }
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) { static bool
has_activation_in_flight(_GLFWwindow* window, GLFWactivationcallback callback) {
for (size_t i = 0; i < _glfw.wl.activation_requests.sz; i++) { for (size_t i = 0; i < _glfw.wl.activation_requests.sz; i++) {
glfw_wl_xdg_activation_request *r = _glfw.wl.activation_requests.array + i; glfw_wl_xdg_activation_request *r = _glfw.wl.activation_requests.array + i;
if (r->window_id == window->id && r->callback == request_attention) return; if (r->window_id == window->id && r->callback == callback) return true;
} }
get_activation_token(window, 0, request_attention, NULL); return false;
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) {
if (!has_activation_in_flight(window, request_attention)) get_activation_token(window, 0, request_attention, NULL);
} }
int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED) int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
@ -1174,10 +1179,21 @@ int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
return false; return false;
} }
static void
focus_window(GLFWwindow *window, const char *token, void *data UNUSED) {
if (!window) return;
if (token && token[0]) xdg_activation_v1_activate(_glfw.wl.xdg_activation_v1, token, ((_GLFWwindow*)window)->wl.surface);
else {
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Window focus request via xdg-activation protocol was denied by the compositor. Use a better compositor.");
}
}
void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED) void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
{ {
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, // Attempt to focus the window by using the activation protocol, whether it works
"Wayland: The platform does not support setting the input focus"); // is entirely compositor dependent and as we all know Wayland and its ecosystem is
// the product of morons.
if (_glfw.wl.input_serial && !has_activation_in_flight(window, focus_window)) get_activation_token(window, _glfw.wl.input_serial, focus_window, NULL);
} }
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,