mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-14 08:22:25 -04:00
seat/keyboard: support sending modifiers when not focused
This adds wlr_seat_client_notify_modifiers which sends the current keyboard modifiers to an additional client, tracking what the client last saw to avoid unneeded duplicates. This is useful to make actions like "ctrl+scroll" work correctly when pointer and keyboard focus are on distinct clients. The tracked modifier state is also used to avoid sending unneeded modifiers events in default_keyboard_modifiers. No de-duplication is performed in wlr_seat_keyboard_send_modifiers because that function is used in cases where the protocol unconditionally requires a modifiers event to be sent (such as after wl_keyboard_enter).
This commit is contained in:
parent
3ad4374a54
commit
8ad0c0166b
2 changed files with 65 additions and 12 deletions
|
|
@ -55,6 +55,13 @@ struct wlr_seat_client {
|
|||
struct wlr_serial_ringset serials;
|
||||
bool needs_touch_frame;
|
||||
|
||||
// The client's current knowledge of the keyboard modifier state. This
|
||||
// will lag behind the actual state if the client does not have
|
||||
// keyboard focus; it is used by wlr_seat_client_notify_modifiers to
|
||||
// allow actions like ctrl+scroll to work without sending duplicate
|
||||
// events if modifiers are unchanged.
|
||||
struct wlr_keyboard_modifiers tracked_modifiers;
|
||||
|
||||
// When the client doesn't support high-resolution scroll, accumulate deltas
|
||||
// until we can notify a discrete event.
|
||||
// Some mice have a free spinning wheel, making possible to lock the wheel
|
||||
|
|
@ -526,6 +533,14 @@ void wlr_seat_keyboard_send_key(struct wlr_seat *seat, uint32_t time_msec,
|
|||
void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
||||
const struct wlr_keyboard_modifiers *modifiers);
|
||||
|
||||
/**
|
||||
* Update an additional client's view of the keyboard modifier state. This
|
||||
* does nothing if the target has keyboard focus or if its view of the modifier
|
||||
* state still matches the current modifier state.
|
||||
*/
|
||||
void wlr_seat_client_notify_modifiers(struct wlr_seat *seat,
|
||||
struct wlr_seat_client *target);
|
||||
|
||||
/**
|
||||
* Send a keyboard enter event to the given surface and consider it to be the
|
||||
* focused surface for the keyboard. This will send a leave event to the last
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@
|
|||
#include "types/wlr_data_device.h"
|
||||
#include "types/wlr_seat.h"
|
||||
|
||||
static void seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
||||
const struct wlr_keyboard_modifiers *modifiers,
|
||||
struct wlr_seat_client *client,
|
||||
bool force);
|
||||
|
||||
static void default_keyboard_enter(struct wlr_seat_keyboard_grab *grab,
|
||||
struct wlr_surface *surface, const uint32_t keycodes[], size_t num_keycodes,
|
||||
const struct wlr_keyboard_modifiers *modifiers) {
|
||||
|
|
@ -27,7 +32,7 @@ static void default_keyboard_key(struct wlr_seat_keyboard_grab *grab,
|
|||
|
||||
static void default_keyboard_modifiers(struct wlr_seat_keyboard_grab *grab,
|
||||
const struct wlr_keyboard_modifiers *modifiers) {
|
||||
wlr_seat_keyboard_send_modifiers(grab->seat, modifiers);
|
||||
seat_keyboard_send_modifiers(grab->seat, modifiers, NULL, false);
|
||||
}
|
||||
|
||||
static void default_keyboard_cancel(struct wlr_seat_keyboard_grab *grab) {
|
||||
|
|
@ -195,34 +200,67 @@ static void seat_keyboard_handle_surface_destroy(struct wl_listener *listener,
|
|||
wlr_seat_keyboard_clear_focus(state->seat);
|
||||
}
|
||||
|
||||
void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
||||
const struct wlr_keyboard_modifiers *modifiers) {
|
||||
struct wlr_seat_client *client = seat->keyboard_state.focused_client;
|
||||
static void seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
||||
const struct wlr_keyboard_modifiers *modifiers,
|
||||
struct wlr_seat_client *client,
|
||||
bool force) {
|
||||
const struct wlr_keyboard_modifiers empty = {};
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (client == NULL) {
|
||||
client = seat->keyboard_state.focused_client;
|
||||
}
|
||||
if (client == NULL) {
|
||||
return;
|
||||
}
|
||||
if (modifiers == NULL) {
|
||||
modifiers = ∅
|
||||
}
|
||||
|
||||
struct wlr_keyboard_modifiers *tracked = &client->tracked_modifiers;
|
||||
if (!force && tracked->depressed == modifiers->depressed &&
|
||||
tracked->latched == modifiers->latched &&
|
||||
tracked->locked == modifiers->locked &&
|
||||
tracked->group == modifiers->group) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t serial = wlr_seat_client_next_serial(client);
|
||||
struct wl_resource *resource;
|
||||
*tracked = *modifiers;
|
||||
|
||||
wl_resource_for_each(resource, &client->keyboards) {
|
||||
if (seat_client_from_keyboard_resource(resource) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (modifiers == NULL) {
|
||||
wl_keyboard_send_modifiers(resource, serial, 0, 0, 0, 0);
|
||||
} else {
|
||||
wl_keyboard_send_modifiers(resource, serial,
|
||||
modifiers->depressed, modifiers->latched,
|
||||
modifiers->locked, modifiers->group);
|
||||
}
|
||||
wl_keyboard_send_modifiers(resource, serial,
|
||||
modifiers->depressed, modifiers->latched,
|
||||
modifiers->locked, modifiers->group);
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
||||
const struct wlr_keyboard_modifiers *modifiers) {
|
||||
seat_keyboard_send_modifiers(seat, modifiers, NULL, true);
|
||||
}
|
||||
|
||||
void wlr_seat_client_notify_modifiers(struct wlr_seat *seat,
|
||||
struct wlr_seat_client *target) {
|
||||
struct wlr_seat_client *focused = seat->keyboard_state.focused_client;
|
||||
if (target == NULL || target == focused) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_keyboard_modifiers *modifiers = &seat->keyboard_state.keyboard->modifiers;
|
||||
seat_keyboard_send_modifiers(seat, modifiers, target, false);
|
||||
}
|
||||
|
||||
void seat_client_send_keyboard_leave_raw(struct wlr_seat_client *seat_client,
|
||||
struct wlr_surface *surface) {
|
||||
uint32_t serial = wlr_seat_client_next_serial(seat_client);
|
||||
struct wl_resource *resource;
|
||||
const struct wlr_keyboard_modifiers unset = {};
|
||||
seat_client->tracked_modifiers = unset;
|
||||
wl_resource_for_each(resource, &seat_client->keyboards) {
|
||||
if (seat_client_from_keyboard_resource(resource) == NULL) {
|
||||
continue;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue