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;
|
struct wlr_serial_ringset serials;
|
||||||
bool needs_touch_frame;
|
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
|
// When the client doesn't support high-resolution scroll, accumulate deltas
|
||||||
// until we can notify a discrete event.
|
// until we can notify a discrete event.
|
||||||
// Some mice have a free spinning wheel, making possible to lock the wheel
|
// 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,
|
void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
||||||
const struct wlr_keyboard_modifiers *modifiers);
|
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
|
* 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
|
* 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_data_device.h"
|
||||||
#include "types/wlr_seat.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,
|
static void default_keyboard_enter(struct wlr_seat_keyboard_grab *grab,
|
||||||
struct wlr_surface *surface, const uint32_t keycodes[], size_t num_keycodes,
|
struct wlr_surface *surface, const uint32_t keycodes[], size_t num_keycodes,
|
||||||
const struct wlr_keyboard_modifiers *modifiers) {
|
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,
|
static void default_keyboard_modifiers(struct wlr_seat_keyboard_grab *grab,
|
||||||
const struct wlr_keyboard_modifiers *modifiers) {
|
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) {
|
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);
|
wlr_seat_keyboard_clear_focus(state->seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
static void seat_keyboard_send_modifiers(struct wlr_seat *seat,
|
||||||
const struct wlr_keyboard_modifiers *modifiers) {
|
const struct wlr_keyboard_modifiers *modifiers,
|
||||||
struct wlr_seat_client *client = seat->keyboard_state.focused_client;
|
struct wlr_seat_client *client,
|
||||||
|
bool force) {
|
||||||
|
const struct wlr_keyboard_modifiers empty = {};
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
if (client == NULL) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t serial = wlr_seat_client_next_serial(client);
|
uint32_t serial = wlr_seat_client_next_serial(client);
|
||||||
struct wl_resource *resource;
|
*tracked = *modifiers;
|
||||||
|
|
||||||
wl_resource_for_each(resource, &client->keyboards) {
|
wl_resource_for_each(resource, &client->keyboards) {
|
||||||
if (seat_client_from_keyboard_resource(resource) == NULL) {
|
if (seat_client_from_keyboard_resource(resource) == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modifiers == NULL) {
|
|
||||||
wl_keyboard_send_modifiers(resource, serial, 0, 0, 0, 0);
|
|
||||||
} else {
|
|
||||||
wl_keyboard_send_modifiers(resource, serial,
|
wl_keyboard_send_modifiers(resource, serial,
|
||||||
modifiers->depressed, modifiers->latched,
|
modifiers->depressed, modifiers->latched,
|
||||||
modifiers->locked, modifiers->group);
|
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,
|
void seat_client_send_keyboard_leave_raw(struct wlr_seat_client *seat_client,
|
||||||
struct wlr_surface *surface) {
|
struct wlr_surface *surface) {
|
||||||
uint32_t serial = wlr_seat_client_next_serial(seat_client);
|
uint32_t serial = wlr_seat_client_next_serial(seat_client);
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
|
const struct wlr_keyboard_modifiers unset = {};
|
||||||
|
seat_client->tracked_modifiers = unset;
|
||||||
wl_resource_for_each(resource, &seat_client->keyboards) {
|
wl_resource_for_each(resource, &seat_client->keyboards) {
|
||||||
if (seat_client_from_keyboard_resource(resource) == NULL) {
|
if (seat_client_from_keyboard_resource(resource) == NULL) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue