Deny repeating reload by holding key

Fixes #2568

The binding that gets stored in the keyboard's `repeat_binding` would
get freed on reload, leaving a dangling pointer.

Rather than attempt to unset the keyboard's `repeat_binding` along with
the other bindings, I opted to just not set it for the reload command
because there's no point in reloading repeatedly by holding the binding.
This disables repeat bindings for the reload command.

As we now need to detect whether it's a reload command in two places,
I've added a binding flag to track whether it's a reload or not.
This commit is contained in:
Ryan Dwyer 2018-09-04 20:00:04 +10:00
parent 6dd3e0caf5
commit 7797490e9e
3 changed files with 14 additions and 9 deletions

View file

@ -34,7 +34,8 @@ enum binding_flags {
BINDING_LOCKED=2, // keyboard only BINDING_LOCKED=2, // keyboard only
BINDING_BORDER=4, // mouse only; trigger on container border BINDING_BORDER=4, // mouse only; trigger on container border
BINDING_CONTENTS=8, // mouse only; trigger on container contents BINDING_CONTENTS=8, // mouse only; trigger on container contents
BINDING_TITLEBAR=16 // mouse only; trigger on container titlebar BINDING_TITLEBAR=16, // mouse only; trigger on container titlebar
BINDING_RELOAD=32, // the binding runs the reload command
}; };
/** /**

View file

@ -214,6 +214,9 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
} }
binding->command = join_args(argv + 1, argc - 1); binding->command = join_args(argv + 1, argc - 1);
if (strcasestr(binding->command, "reload")) {
binding->flags |= BINDING_RELOAD;
}
list_t *split = split_string(argv[0], "+"); list_t *split = split_string(argv[0], "+");
for (int i = 0; i < split->length; ++i) { for (int i = 0; i < split->length; ++i) {
@ -307,11 +310,9 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
binding->command); binding->command);
struct sway_binding *binding_copy = binding; struct sway_binding *binding_copy = binding;
bool reload = false;
// if this is a reload command we need to make a duplicate of the // if this is a reload command we need to make a duplicate of the
// binding since it will be gone after the reload has completed. // binding since it will be gone after the reload has completed.
if (strcasestr(binding->command, "reload")) { if (binding->flags & BINDING_RELOAD) {
reload = true;
binding_copy = sway_binding_dup(binding); binding_copy = sway_binding_dup(binding);
if (!binding_copy) { if (!binding_copy) {
wlr_log(WLR_ERROR, "Failed to duplicate binding during reload"); wlr_log(WLR_ERROR, "Failed to duplicate binding during reload");
@ -328,7 +329,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
binding->command, results->error); binding->command, results->error);
} }
if (reload) { // free the binding if we made a copy if (binding->flags & BINDING_RELOAD) { // free the binding if we made a copy
free_sway_binding(binding_copy); free_sway_binding(binding_copy);
} }
free_cmd_results(results); free_cmd_results(results);

View file

@ -280,9 +280,12 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
if (binding_pressed) { if (binding_pressed) {
seat_execute_command(seat, binding_pressed); seat_execute_command(seat, binding_pressed);
handled = true; handled = true;
if ((binding_pressed->flags & BINDING_RELOAD) == 0) {
next_repeat_binding = binding_pressed; next_repeat_binding = binding_pressed;
} }
} }
}
// Set up (or clear) keyboard repeat for a pressed binding // Set up (or clear) keyboard repeat for a pressed binding
if (next_repeat_binding && wlr_device->keyboard->repeat_info.delay > 0) { if (next_repeat_binding && wlr_device->keyboard->repeat_info.delay > 0) {