ipc: add an input event

This adds an ipc event related to input devices. Currently the
following changes are supported:
- added: when an input device becomes available
- removed: when an input device is no longer available
- xkb_keymap_changed: (keyboards only) the keymap changed
- xkb_layout_changed: (keyboards only) the effective layout changed
This commit is contained in:
Brian Ashworth 2019-07-17 17:12:20 -04:00 committed by Simon Ser
parent 36aa67e549
commit 6effca7b61
7 changed files with 107 additions and 0 deletions

View file

@ -34,6 +34,7 @@ enum ipc_command_type {
// sway-specific event types // sway-specific event types
IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20), IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20),
IPC_EVENT_INPUT = ((1<<31) | 21),
}; };
#endif #endif

View file

@ -52,6 +52,7 @@ struct sway_keyboard {
struct sway_seat_device *seat_device; struct sway_seat_device *seat_device;
struct xkb_keymap *keymap; struct xkb_keymap *keymap;
xkb_layout_index_t effective_layout;
struct wl_listener keyboard_key; struct wl_listener keyboard_key;
struct wl_listener keyboard_modifiers; struct wl_listener keyboard_modifiers;

View file

@ -2,6 +2,7 @@
#define _SWAY_IPC_SERVER_H #define _SWAY_IPC_SERVER_H
#include <sys/socket.h> #include <sys/socket.h>
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/input-manager.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "ipc.h" #include "ipc.h"
@ -19,5 +20,6 @@ void ipc_event_bar_state_update(struct bar_config *bar);
void ipc_event_mode(const char *mode, bool pango); void ipc_event_mode(const char *mode, bool pango);
void ipc_event_shutdown(const char *reason); void ipc_event_shutdown(const char *reason);
void ipc_event_binding(struct sway_binding *binding); void ipc_event_binding(struct sway_binding *binding);
void ipc_event_input(const char *change, struct sway_input_device *device);
#endif #endif

View file

@ -12,6 +12,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/ipc-server.h"
#include "sway/server.h" #include "sway/server.h"
#include "stringop.h" #include "stringop.h"
#include "list.h" #include "list.h"
@ -584,6 +585,8 @@ static void handle_device_destroy(struct wl_listener *listener, void *data) {
seat_remove_device(seat, input_device); seat_remove_device(seat, input_device);
} }
ipc_event_input("removed", input_device);
wl_list_remove(&input_device->link); wl_list_remove(&input_device->link);
wl_list_remove(&input_device->device_destroy.link); wl_list_remove(&input_device->device_destroy.link);
free(input_device->identifier); free(input_device->identifier);
@ -656,6 +659,8 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
"device '%s' is not configured on any seats", "device '%s' is not configured on any seats",
input_device->identifier); input_device->identifier);
} }
ipc_event_input("added", input_device);
} }
static void handle_inhibit_activate(struct wl_listener *listener, void *data) { static void handle_inhibit_activate(struct wl_listener *listener, void *data) {

View file

@ -473,6 +473,11 @@ static void handle_keyboard_modifiers(struct wl_listener *listener,
uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard);
determine_bar_visibility(modifiers); determine_bar_visibility(modifiers);
if (wlr_device->keyboard->modifiers.group != keyboard->effective_layout) {
keyboard->effective_layout = wlr_device->keyboard->modifiers.group;
ipc_event_input("xkb_layout", keyboard->seat_device->input_device);
}
} }
struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
@ -603,8 +608,23 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
} }
} }
bool keymap_changed = false;
bool effective_layout_changed = keyboard->effective_layout != 0;
if (keyboard->keymap) {
char *old_keymap_string = xkb_keymap_get_as_string(keyboard->keymap,
XKB_KEYMAP_FORMAT_TEXT_V1);
char *new_keymap_string = xkb_keymap_get_as_string(keymap,
XKB_KEYMAP_FORMAT_TEXT_V1);
keymap_changed = strcmp(old_keymap_string, new_keymap_string);
free(old_keymap_string);
free(new_keymap_string);
} else {
keymap_changed = true;
}
xkb_keymap_unref(keyboard->keymap); xkb_keymap_unref(keyboard->keymap);
keyboard->keymap = keymap; keyboard->keymap = keymap;
keyboard->effective_layout = 0;
wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap);
xkb_mod_mask_t locked_mods = 0; xkb_mod_mask_t locked_mods = 0;
@ -654,6 +674,14 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
wl_signal_add(&wlr_device->keyboard->events.modifiers, wl_signal_add(&wlr_device->keyboard->events.modifiers,
&keyboard->keyboard_modifiers); &keyboard->keyboard_modifiers);
keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers;
if (keymap_changed) {
ipc_event_input("xkb_keymap",
keyboard->seat_device->input_device);
} else if (effective_layout_changed) {
ipc_event_input("xkb_layout",
keyboard->seat_device->input_device);
}
} }
void sway_keyboard_destroy(struct sway_keyboard *keyboard) { void sway_keyboard_destroy(struct sway_keyboard *keyboard) {

View file

@ -487,6 +487,21 @@ static void ipc_event_tick(const char *payload) {
json_object_put(json); json_object_put(json);
} }
void ipc_event_input(const char *change, struct sway_input_device *device) {
if (!ipc_has_event_listeners(IPC_EVENT_INPUT)) {
return;
}
sway_log(SWAY_DEBUG, "Sending input event");
json_object *json = json_object_new_object();
json_object_object_add(json, "change", json_object_new_string(change));
json_object_object_add(json, "input", ipc_json_describe_input(device));
const char *json_string = json_object_to_json_string(json);
ipc_send_event(json_string, IPC_EVENT_INPUT);
json_object_put(json);
}
int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
struct ipc_client *client = data; struct ipc_client *client = data;
@ -716,6 +731,8 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt
} else if (strcmp(event_type, "tick") == 0) { } else if (strcmp(event_type, "tick") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_TICK); client->subscribed_events |= event_mask(IPC_EVENT_TICK);
is_tick = true; is_tick = true;
} else if (strcmp(event_type, "input") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_INPUT);
} else { } else {
const char msg[] = "{\"success\": false}"; const char msg[] = "{\"success\": false}";
ipc_send_reply(client, payload_type, msg, strlen(msg)); ipc_send_reply(client, payload_type, msg, strlen(msg));

View file

@ -1371,6 +1371,9 @@ available:
|- 0x80000014 |- 0x80000014
: bar_status_update : bar_status_update
: Send when the visibility of a bar should change due to a modifier : Send when the visibility of a bar should change due to a modifier
|- 0x80000015
: input
: Sent when something related to input devices changes
## 0x80000000. WORKSPACE ## 0x80000000. WORKSPACE
@ -1702,6 +1705,56 @@ event is a single object with the following properties:
} }
``` ```
## 0x80000015. INPUT
Sent when something related to the input devices changes. The event is a single
object with the following properties:
[- *PROPERTY*
:- *DATA TYPE*
:- *DESCRIPTION*
|- change
: string
:[ What has changed
|- input
: object
: An object representing the input that is identical the ones GET_INPUTS gives
The following change types are currently available:
[- *TYPE*
:- *DESCRIPTION*
|- added
:[ The input device became available
|- removed
: The input device is no longer available
|- xkb_keymap
: (Keyboards only) The keymap for the keyboard has changed
|- xkb_layout
: (Keyboards only) The effective layout in the keymap has changed
*Example Event:*
```
{
"change": "xkb_layout",
"input": {
"identifier": "1:1:AT_Translated_Set_2_keyboard",
"name": "AT Translated Set 2 keyboard",
"vendor": 1,
"product": 1,
"type": "keyboard",
"xkb_layout_names": [
"English (US)",
"English (Dvorak)"
],
"xkb_active_layout_index": 1,
"xkb_active_layout_name": "English (Dvorak)",
"libinput": {
"send_events": "enabled"
}
}
}
```
# SEE ALSO # SEE ALSO
*sway*(1) *sway*(5) *sway-bar*(5) *swaymsg*(1) *sway-input*(5) *sway-output*(5) *sway*(1) *sway*(5) *sway-bar*(5) *swaymsg*(1) *sway-input*(5) *sway-output*(5)