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;
}
window->wl.decorations.focus = focus;
_glfw.wl.serial = serial;
_glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
_glfw.wl.pointerFocus = window;
window->wl.hovered = true;
@ -311,7 +311,7 @@ static void pointerHandleButton(void* data UNUSED,
if (window->wl.decorations.focus != CENTRAL_WINDOW)
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
* codes. */
@ -463,7 +463,7 @@ static void keyboardHandleEnter(void* data UNUSED,
return;
}
_glfw.wl.serial = serial;
_glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
_glfw.wl.keyboardFocusId = window->id;
_glfwInputWindowFocus(window, true);
uint32_t* key;
@ -516,7 +516,7 @@ static void keyboardHandleKey(void* data UNUSED,
return;
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);
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 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);
}

2
glfw/wl_platform.h vendored
View File

@ -293,7 +293,7 @@ typedef struct _GLFWlibraryWayland
struct wl_surface* cursorSurface;
GLFWCursorShape cursorPreviousShape;
uint32_t serial;
uint32_t serial, input_serial;
int32_t keyboardRepeatRate;
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);
}
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++) {
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)
@ -1174,10 +1179,21 @@ int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
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)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: The platform does not support setting the input focus");
// Attempt to focus the window by using the activation protocol, whether it works
// 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,