mirror of
https://github.com/swaywm/sway.git
synced 2026-04-25 06:46:24 -04:00
criteria: Add additional call sites
Now that there are criteria that can be re-executed on state change and match the state of keyboard shortcuts inhibitors, add additional criteria execution call sites right after keyboard shortcuts inhibitor state changes. This allows to immediately and efficiently visually reflect inhibitor state changes to the user (or trigger any other desired action). Since the surface implemenation might already have been destroyed when the keyboard shortcuts inhibitor destruction handler is called, we need to defer criteria execution via the event loop and then go looking whether a matching surface still exists and derive the view to execute the criteria on from that. Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
This commit is contained in:
parent
224576afcc
commit
0889c1816e
6 changed files with 89 additions and 7 deletions
|
|
@ -343,4 +343,7 @@ void view_save_buffer(struct sway_view *view);
|
|||
|
||||
bool view_is_transient_for(struct sway_view *child, struct sway_view *ancestor);
|
||||
|
||||
void view_schedule_criteria_execution_from_wlr_surface(
|
||||
struct wlr_surface *wlr_surface);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "util.h"
|
||||
|
||||
static struct cmd_results *handle_action(struct seat_config *sc,
|
||||
|
|
@ -12,8 +13,17 @@ static struct cmd_results *handle_action(struct seat_config *sc,
|
|||
|
||||
wl_list_for_each(sway_inhibitor,
|
||||
&seat->keyboard_shortcuts_inhibitors, link) {
|
||||
wlr_keyboard_shortcuts_inhibitor_v1_deactivate(
|
||||
sway_inhibitor->inhibitor);
|
||||
struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor =
|
||||
sway_inhibitor->inhibitor;
|
||||
wlr_keyboard_shortcuts_inhibitor_v1_deactivate(inhibitor);
|
||||
|
||||
// execute criteria on the affected view after
|
||||
// inhibitor changed state
|
||||
struct sway_view *view =
|
||||
view_from_wlr_surface(inhibitor->surface);
|
||||
if (view) {
|
||||
view_execute_criteria(view);
|
||||
}
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Deactivated all keyboard shortcuts inhibitors");
|
||||
|
|
@ -46,6 +56,11 @@ static struct cmd_results *handle_action(struct seat_config *sc,
|
|||
|
||||
sway_log(SWAY_DEBUG, "%sctivated keyboard shortcuts inhibitor",
|
||||
inhibit ? "A" : "Dea");
|
||||
|
||||
struct sway_view *view = view_from_wlr_surface(inhibitor->surface);
|
||||
if (view) {
|
||||
view_execute_criteria(view);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
|
|
|
|||
|
|
@ -33,12 +33,20 @@ struct cmd_results *cmd_shortcuts_inhibitor(int argc, char **argv) {
|
|||
continue;
|
||||
}
|
||||
|
||||
wlr_keyboard_shortcuts_inhibitor_v1_deactivate(
|
||||
sway_inhibitor->inhibitor);
|
||||
struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor =
|
||||
sway_inhibitor->inhibitor;
|
||||
wlr_keyboard_shortcuts_inhibitor_v1_deactivate(inhibitor);
|
||||
sway_log(SWAY_DEBUG, "Deactivated keyboard shortcuts "
|
||||
"inhibitor for seat %s on view",
|
||||
seat->wlr_seat->name);
|
||||
|
||||
// execute criteria on the affected view after
|
||||
// inhibitor changed state
|
||||
struct sway_view *view =
|
||||
view_from_wlr_surface(inhibitor->surface);
|
||||
if (view) {
|
||||
view_execute_criteria(view);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
|
|
|
|||
|
|
@ -304,6 +304,11 @@ static void handle_keyboard_shortcuts_inhibitor_destroy(
|
|||
|
||||
sway_log(SWAY_DEBUG, "Removing keyboard shortcuts inhibitor");
|
||||
|
||||
// avoid use-after free of view by scheduling deferred execution of
|
||||
// criteria
|
||||
view_schedule_criteria_execution_from_wlr_surface(
|
||||
sway_inhibitor->inhibitor->surface);
|
||||
|
||||
// sway_seat::keyboard_shortcuts_inhibitors
|
||||
wl_list_remove(&sway_inhibitor->link);
|
||||
wl_list_remove(&sway_inhibitor->destroy.link);
|
||||
|
|
@ -353,6 +358,10 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor(
|
|||
}
|
||||
|
||||
if (inhibit == SHORTCUTS_INHIBIT_DISABLE) {
|
||||
if (view) {
|
||||
view_execute_criteria(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we deny to honour the inhibitor by never sending the
|
||||
* activate signal. We can not, however, destroy the inhibitor
|
||||
|
|
@ -368,6 +377,10 @@ static void handle_keyboard_shortcuts_inhibit_new_inhibitor(
|
|||
}
|
||||
|
||||
wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor);
|
||||
|
||||
if (view) {
|
||||
view_execute_criteria(view);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
|
||||
|
|
|
|||
|
|
@ -266,9 +266,10 @@ correct seat.
|
|||
escape a state where shortcuts are inhibited and the client becomes
|
||||
uncooperative. It is worth noting that whether disabled or deactivated
|
||||
inhibitors are removed is entirely up to the client. Depending on the
|
||||
client it may therefore be possible to (re-)activate them later. Any
|
||||
visual indication that an inhibitor is present is currently left to the
|
||||
client as well.
|
||||
client it may therefore be possible to (re-)activate them later.
|
||||
Note that visual indication of inhibitor presence and state beyond what
|
||||
the client may provide can be implemented using criteria with match
|
||||
_shortcuts_inhibitor_.
|
||||
|
||||
*seat* <name> xcursor_theme <theme> [<size>]
|
||||
Override the system default XCursor theme. The default seat's
|
||||
|
|
|
|||
|
|
@ -1176,3 +1176,45 @@ bool view_is_transient_for(struct sway_view *child,
|
|||
return child->impl->is_transient_for &&
|
||||
child->impl->is_transient_for(child, ancestor);
|
||||
}
|
||||
|
||||
struct view_surface_iterator_context {
|
||||
struct sway_view *view;
|
||||
struct wlr_surface *wlr_surface;
|
||||
};
|
||||
|
||||
static void view_criteria_execution_surface_iterator(
|
||||
struct wlr_surface *surface, int sx, int sy, void *data) {
|
||||
struct view_surface_iterator_context *context = data;
|
||||
|
||||
if (surface != context->wlr_surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
view_execute_criteria(context->view);
|
||||
}
|
||||
|
||||
static void view_criteria_execution_container_iterator(
|
||||
struct sway_container *container, void *data) {
|
||||
if (container->view) {
|
||||
struct view_surface_iterator_context context = {
|
||||
.view = container->view,
|
||||
.wlr_surface = data,
|
||||
};
|
||||
|
||||
view_for_each_surface(container->view,
|
||||
view_criteria_execution_surface_iterator,
|
||||
&context);
|
||||
}
|
||||
}
|
||||
|
||||
static void view_execute_criteria_from_wlr_surface(void *data) {
|
||||
// here we intentionally go looking for a surface matching our argument
|
||||
// because that surface might have since been freed
|
||||
root_for_each_container(view_criteria_execution_container_iterator, data);
|
||||
}
|
||||
|
||||
void view_schedule_criteria_execution_from_wlr_surface(
|
||||
struct wlr_surface *wlr_surface) {
|
||||
wl_event_loop_add_idle(server.wl_event_loop,
|
||||
view_execute_criteria_from_wlr_surface, wlr_surface);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue