From 0b7ee0b4a65466c40a5c83dec26a43a65c16f87c Mon Sep 17 00:00:00 2001 From: Michael Weiser Date: Sun, 18 Apr 2021 00:10:31 +0200 Subject: [PATCH 1/3] Add keyboard shortcuts inhibitors to ipc json output Extend the container description in IPC JSON to include keyboard shortcut inhibitor state so it can be evaluated by clients. This requires adding a new function that can retrieve a keyboard shortcuts inhibitor applying to a specific surface no matter what seat it is attached to. Signed-off-by: Michael Weiser --- include/sway/input/seat.h | 8 ++++++++ sway/input/seat.c | 15 +++++++++++++++ sway/ipc-json.c | 19 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index e5aa84783..837b79620 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -368,4 +368,12 @@ keyboard_shortcuts_inhibitor_get_for_surface(const struct sway_seat *seat, struct sway_keyboard_shortcuts_inhibitor * keyboard_shortcuts_inhibitor_get_for_focused_surface(const struct sway_seat *seat); +/** + * Returns the keyboard shortcuts inhibitor that applies to the given surface + * or NULL if none exists. It looks at inhibitors attached to all seats. + */ +struct sway_keyboard_shortcuts_inhibitor * +keyboard_shortcuts_inhibitor_get_for_surface_on_any_seat( + const struct wlr_surface *surface); + #endif diff --git a/sway/input/seat.c b/sway/input/seat.c index 75fea484c..aa4b0490f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1715,3 +1715,18 @@ keyboard_shortcuts_inhibitor_get_for_focused_surface( return keyboard_shortcuts_inhibitor_get_for_surface(seat, seat->wlr_seat->keyboard_state.focused_surface); } + +struct sway_keyboard_shortcuts_inhibitor * +keyboard_shortcuts_inhibitor_get_for_surface_on_any_seat( + const struct wlr_surface *surface) { + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &server.input->seats, link) { + struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = + keyboard_shortcuts_inhibitor_get_for_surface(seat, surface); + if (sway_inhibitor) { + return sway_inhibitor; + } + } + + return NULL; +} diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 58356d4ea..666468e7e 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -220,6 +220,19 @@ static const char *ipc_json_content_type_description(enum wp_content_type_v1_typ return NULL; } +static const char *ipc_json_keyboard_shortcuts_inhibitor_description( + struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor) { + if (!sway_inhibitor) { + return "none"; + } + + if (!sway_inhibitor->inhibitor->active) { + return "inactive"; + } + + return "active"; +} + json_object *ipc_json_get_version(void) { int major = 0, minor = 0, patch = 0; json_object *version = json_object_new_object(); @@ -631,6 +644,12 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object json_object_new_string(ipc_json_content_type_description(content_type))); } + json_object_object_add(object, "keyboard_shortcuts_inhibitor", + json_object_new_string( + ipc_json_keyboard_shortcuts_inhibitor_description( + keyboard_shortcuts_inhibitor_get_for_surface_on_any_seat( + c->view->surface)))); + #if HAVE_XWAYLAND if (c->view->type == SWAY_VIEW_XWAYLAND) { json_object_object_add(object, "window", From d48c2998e30e08b4cf151d3d1d7b2ea71978bc33 Mon Sep 17 00:00:00 2001 From: Michael Weiser Date: Thu, 15 Apr 2021 19:34:56 +0200 Subject: [PATCH 2/3] Add idle-inhibitor ipc subscription type Add a new type of ipc subscription so clients can be notified of changes in idle inhibitors. This allows to react to those events by e.g. changing container properties (title, ...) to notify the user about this circumstance (add marker, change color, ...). For this reason the event includes information about the affected container as well. Signed-off-by: Michael Weiser --- include/ipc.h | 1 + include/sway/desktop/idle_inhibit_v1.h | 4 +++ include/sway/ipc-json.h | 4 +++ include/sway/ipc-server.h | 2 ++ sway/commands/inhibit_idle.c | 2 +- sway/desktop/idle_inhibit_v1.c | 15 ++++++++++++ sway/ipc-json.c | 34 ++++++++++++++++++++++++++ sway/ipc-server.c | 17 +++++++++++++ 8 files changed, 78 insertions(+), 1 deletion(-) diff --git a/include/ipc.h b/include/ipc.h index ff0117502..9deafff43 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -36,6 +36,7 @@ enum ipc_command_type { // sway-specific event types IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20), IPC_EVENT_INPUT = ((1<<31) | 21), + IPC_EVENT_IDLE_INHIBITOR = ((1<<31) | 22), }; #endif diff --git a/include/sway/desktop/idle_inhibit_v1.h b/include/sway/desktop/idle_inhibit_v1.h index 84cc666d0..047762450 100644 --- a/include/sway/desktop/idle_inhibit_v1.h +++ b/include/sway/desktop/idle_inhibit_v1.h @@ -39,6 +39,10 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_view( struct sway_view *view); +void sway_idle_inhibit_v1_user_inhibitor_update_mode( + struct sway_idle_inhibitor_v1 *inhibitor, + enum sway_idle_inhibit_mode mode); + void sway_idle_inhibit_v1_user_inhibitor_destroy( struct sway_idle_inhibitor_v1 *inhibitor); diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index bc9f49856..665203503 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -3,7 +3,9 @@ #include #include "sway/output.h" #include "sway/tree/container.h" +#include "sway/desktop/idle_inhibit_v1.h" #include "sway/input/input-manager.h" +#include "sway/tree/container.h" json_object *ipc_json_get_version(void); @@ -16,5 +18,7 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node); json_object *ipc_json_describe_input(struct sway_input_device *device); json_object *ipc_json_describe_seat(struct sway_seat *seat); json_object *ipc_json_describe_bar_config(struct bar_config *bar); +json_object *ipc_json_describe_idle_inhibitor( + struct sway_idle_inhibitor_v1 *sway_inhibitor); #endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index d4c009427..8e5336f1d 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -2,6 +2,7 @@ #define _SWAY_IPC_SERVER_H #include #include "sway/config.h" +#include "sway/desktop/idle_inhibit_v1.h" #include "sway/input/input-manager.h" #include "sway/tree/container.h" #include "ipc.h" @@ -22,5 +23,6 @@ void ipc_event_shutdown(const char *reason); void ipc_event_binding(struct sway_binding *binding); void ipc_event_input(const char *change, struct sway_input_device *device); void ipc_event_output(void); +void ipc_event_idle_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor, const char *change); #endif diff --git a/sway/commands/inhibit_idle.c b/sway/commands/inhibit_idle.c index 6125736ac..23cdb7f8d 100644 --- a/sway/commands/inhibit_idle.c +++ b/sway/commands/inhibit_idle.c @@ -40,7 +40,7 @@ struct cmd_results *cmd_inhibit_idle(int argc, char **argv) { if (clear) { sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor); } else { - inhibitor->mode = mode; + sway_idle_inhibit_v1_user_inhibitor_update_mode(inhibitor, mode); sway_idle_inhibit_v1_check_active(); } } else if (!clear) { diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index f3af7aa1b..2f2306fa9 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c @@ -3,12 +3,14 @@ #include "log.h" #include "sway/desktop/idle_inhibit_v1.h" #include "sway/input/seat.h" +#include "sway/ipc-server.h" #include "sway/tree/container.h" #include "sway/tree/view.h" #include "sway/server.h" static void destroy_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor) { + ipc_event_idle_inhibitor(inhibitor, "destroy"); wl_list_remove(&inhibitor->link); wl_list_remove(&inhibitor->destroy.link); sway_idle_inhibit_v1_check_active(); @@ -36,6 +38,9 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { inhibitor->mode = INHIBIT_IDLE_APPLICATION; inhibitor->wlr_inhibitor = wlr_inhibitor; + + ipc_event_idle_inhibitor(inhibitor, "create"); + wl_list_insert(&manager->inhibitors, &inhibitor->link); inhibitor->destroy.notify = handle_destroy; @@ -56,6 +61,9 @@ void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, inhibitor->mode = mode; inhibitor->view = view; + + ipc_event_idle_inhibitor(inhibitor, "create"); + wl_list_insert(&manager->inhibitors, &inhibitor->link); inhibitor->destroy.notify = handle_destroy; @@ -90,6 +98,13 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_vi return NULL; } +void sway_idle_inhibit_v1_user_inhibitor_update_mode( + struct sway_idle_inhibitor_v1 *inhibitor, + enum sway_idle_inhibit_mode mode) { + inhibitor->mode = mode; + ipc_event_idle_inhibitor(inhibitor, "mode"); +} + void sway_idle_inhibit_v1_user_inhibitor_destroy( struct sway_idle_inhibitor_v1 *inhibitor) { if (!inhibitor) { diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 666468e7e..6f6a3dc6a 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1434,3 +1434,37 @@ json_object *ipc_json_get_binding_mode(void) { json_object_new_string(config->current_mode->name)); return current_mode; } + +json_object *ipc_json_describe_idle_inhibitor( + struct sway_idle_inhibitor_v1 *sway_inhibitor) { + json_object *object = json_object_new_object(); + + json_object_object_add(object, "active", + json_object_new_boolean( + sway_idle_inhibit_v1_is_active(sway_inhibitor))); + + const char *type = NULL; + struct sway_view *view = NULL; + if (sway_inhibitor->mode == INHIBIT_IDLE_APPLICATION) { + type = "application"; + view = view_from_wlr_surface(sway_inhibitor->wlr_inhibitor->surface); + } else { + type = "user"; + view = sway_inhibitor->view; + json_object_object_add(object, "mode", + json_object_new_string( + ipc_json_user_idle_inhibitor_description( + sway_inhibitor->mode))); + } + + if (type) { + json_object_object_add(object, "type", json_object_new_string(type)); + } + + if (view && view->container) { + json_object_object_add(object, "container", + ipc_json_describe_node(&view->container->node)); + } + + return object; +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 9692a77fd..8a4525676 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -522,6 +522,21 @@ void ipc_event_output(void) { json_object_put(json); } +void ipc_event_idle_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor, const char *change) { + if (!ipc_has_event_listeners(IPC_EVENT_IDLE_INHIBITOR)) { + return; + } + sway_log(SWAY_DEBUG, "Sending idle inhibitor::%s event", change); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, "change", json_object_new_string(change)); + json_object_object_add(obj, "idle_inhibitor", + ipc_json_describe_idle_inhibitor(inhibitor)); + + const char *json_string = json_object_to_json_string(obj); + ipc_send_event(json_string, IPC_EVENT_IDLE_INHIBITOR); + json_object_put(obj); +} + int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; @@ -758,6 +773,8 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt is_tick = true; } else if (strcmp(event_type, "input") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_INPUT); + } else if (strcmp(event_type, "idle_inhibitor") == 0) { + client->subscribed_events |= event_mask(IPC_EVENT_IDLE_INHIBITOR); } else { const char msg[] = "{\"success\": false}"; ipc_send_reply(client, payload_type, msg, strlen(msg)); From b6c689c72e5e8ca4f6488a0cb666d0242b57a0fc Mon Sep 17 00:00:00 2001 From: Michael Weiser Date: Thu, 15 Apr 2021 20:35:42 +0200 Subject: [PATCH 3/3] Add keyboard shortcuts inhibitor ipc subscription Add a new type of ipc subscription so clients can be notified of changes in keyboard shortcuts inhibitors. This allows to react to those events by e.g. changing container properties (title, ...) to notify the user about this circumstance (add marker, change color, ...). For this reason the event includes information about the affected container as well. Signed-off-by: Michael Weiser --- include/ipc.h | 1 + include/sway/ipc-json.h | 3 +++ include/sway/ipc-server.h | 4 ++++ sway/commands/seat/shortcuts_inhibitor.c | 7 +++++++ sway/commands/shortcuts_inhibitor.c | 4 +++- sway/input/input-manager.c | 5 +++++ sway/ipc-json.c | 14 ++++++++++++++ sway/ipc-server.c | 21 +++++++++++++++++++++ 8 files changed, 58 insertions(+), 1 deletion(-) diff --git a/include/ipc.h b/include/ipc.h index 9deafff43..fcf1133bd 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -37,6 +37,7 @@ enum ipc_command_type { IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20), IPC_EVENT_INPUT = ((1<<31) | 21), IPC_EVENT_IDLE_INHIBITOR = ((1<<31) | 22), + IPC_EVENT_KEYBOARD_SHORTCUTS_INHIBITOR = ((1<<31) | 23), }; #endif diff --git a/include/sway/ipc-json.h b/include/sway/ipc-json.h index 665203503..2f36c795e 100644 --- a/include/sway/ipc-json.h +++ b/include/sway/ipc-json.h @@ -5,6 +5,7 @@ #include "sway/tree/container.h" #include "sway/desktop/idle_inhibit_v1.h" #include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/tree/container.h" json_object *ipc_json_get_version(void); @@ -20,5 +21,7 @@ json_object *ipc_json_describe_seat(struct sway_seat *seat); json_object *ipc_json_describe_bar_config(struct bar_config *bar); json_object *ipc_json_describe_idle_inhibitor( struct sway_idle_inhibitor_v1 *sway_inhibitor); +json_object *ipc_json_describe_keyboard_shortcuts_inhibitor( + struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor); #endif diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index 8e5336f1d..4590e0065 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h @@ -4,6 +4,7 @@ #include "sway/config.h" #include "sway/desktop/idle_inhibit_v1.h" #include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/tree/container.h" #include "ipc.h" @@ -24,5 +25,8 @@ void ipc_event_binding(struct sway_binding *binding); void ipc_event_input(const char *change, struct sway_input_device *device); void ipc_event_output(void); void ipc_event_idle_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor, const char *change); +void ipc_event_keyboard_shortcuts_inhibitor( + struct sway_keyboard_shortcuts_inhibitor *inhibitor, + const char *change); #endif diff --git a/sway/commands/seat/shortcuts_inhibitor.c b/sway/commands/seat/shortcuts_inhibitor.c index 7c7f99cf0..ce895cde8 100644 --- a/sway/commands/seat/shortcuts_inhibitor.c +++ b/sway/commands/seat/shortcuts_inhibitor.c @@ -2,6 +2,7 @@ #include "sway/commands.h" #include "sway/input/seat.h" #include "sway/input/input-manager.h" +#include "sway/ipc-server.h" #include "util.h" static struct cmd_results *handle_action(struct seat_config *sc, @@ -12,6 +13,8 @@ static struct cmd_results *handle_action(struct seat_config *sc, wl_list_for_each(sway_inhibitor, &seat->keyboard_shortcuts_inhibitors, link) { + ipc_event_keyboard_shortcuts_inhibitor( + sway_inhibitor, "deactivate"); wlr_keyboard_shortcuts_inhibitor_v1_deactivate( sway_inhibitor->inhibitor); } @@ -39,8 +42,12 @@ static struct cmd_results *handle_action(struct seat_config *sc, } if (inhibit) { + ipc_event_keyboard_shortcuts_inhibitor( + sway_inhibitor, "activate"); wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor); } else { + ipc_event_keyboard_shortcuts_inhibitor( + sway_inhibitor, "deactivate"); wlr_keyboard_shortcuts_inhibitor_v1_deactivate(inhibitor); } diff --git a/sway/commands/shortcuts_inhibitor.c b/sway/commands/shortcuts_inhibitor.c index ffa1a5c99..45eb5d6e6 100644 --- a/sway/commands/shortcuts_inhibitor.c +++ b/sway/commands/shortcuts_inhibitor.c @@ -3,6 +3,7 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" +#include "sway/ipc-server.h" #include "sway/tree/container.h" #include "sway/tree/view.h" @@ -33,12 +34,13 @@ struct cmd_results *cmd_shortcuts_inhibitor(int argc, char **argv) { continue; } + ipc_event_keyboard_shortcuts_inhibitor( + sway_inhibitor, "deactivate"); wlr_keyboard_shortcuts_inhibitor_v1_deactivate( sway_inhibitor->inhibitor); sway_log(SWAY_DEBUG, "Deactivated keyboard shortcuts " "inhibitor for seat %s on view", seat->wlr_seat->name); - } } else { return cmd_results_new(CMD_INVALID, diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index c1bbdde0e..e668f1a7a 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -290,6 +290,8 @@ static void handle_keyboard_shortcuts_inhibitor_destroy( sway_log(SWAY_DEBUG, "Removing keyboard shortcuts inhibitor"); + ipc_event_keyboard_shortcuts_inhibitor(sway_inhibitor, "destroy"); + // sway_seat::keyboard_shortcuts_inhibitors wl_list_remove(&sway_inhibitor->link); wl_list_remove(&sway_inhibitor->destroy.link); @@ -313,6 +315,8 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor( } sway_inhibitor->inhibitor = inhibitor; + ipc_event_keyboard_shortcuts_inhibitor(sway_inhibitor, "create"); + sway_inhibitor->destroy.notify = handle_keyboard_shortcuts_inhibitor_destroy; wl_signal_add(&inhibitor->events.destroy, &sway_inhibitor->destroy); @@ -353,6 +357,7 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor( return; } + ipc_event_keyboard_shortcuts_inhibitor(sway_inhibitor, "activate"); wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor); } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 6f6a3dc6a..562f61c42 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1468,3 +1468,17 @@ json_object *ipc_json_describe_idle_inhibitor( return object; } + +json_object *ipc_json_describe_keyboard_shortcuts_inhibitor( + struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor) { + json_object *object = json_object_new_object(); + + struct sway_view *view = view_from_wlr_surface( + sway_inhibitor->inhibitor->surface); + if (view && view->container) { + json_object_object_add(object, "container", + ipc_json_describe_node(&view->container->node)); + } + + return object; +} diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 8a4525676..e52a26e5a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -537,6 +537,24 @@ void ipc_event_idle_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor, const ch json_object_put(obj); } +void ipc_event_keyboard_shortcuts_inhibitor( + struct sway_keyboard_shortcuts_inhibitor *inhibitor, + const char *change) { + if (!ipc_has_event_listeners(IPC_EVENT_KEYBOARD_SHORTCUTS_INHIBITOR)) { + return; + } + sway_log(SWAY_DEBUG, "Sending keyboard shortcuts " + "inhibitor::%s event", change); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, "change", json_object_new_string(change)); + json_object_object_add(obj, "keyboard_shortcuts_inhibitor", + ipc_json_describe_keyboard_shortcuts_inhibitor(inhibitor)); + + const char *json_string = json_object_to_json_string(obj); + ipc_send_event(json_string, IPC_EVENT_KEYBOARD_SHORTCUTS_INHIBITOR); + json_object_put(obj); +} + int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; @@ -775,6 +793,9 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt client->subscribed_events |= event_mask(IPC_EVENT_INPUT); } else if (strcmp(event_type, "idle_inhibitor") == 0) { client->subscribed_events |= event_mask(IPC_EVENT_IDLE_INHIBITOR); + } else if (strcmp(event_type, "keyboard_shortcuts_inhibitor") == 0) { + client->subscribed_events |= event_mask( + IPC_EVENT_KEYBOARD_SHORTCUTS_INHIBITOR); } else { const char msg[] = "{\"success\": false}"; ipc_send_reply(client, payload_type, msg, strlen(msg));