Use stored commands for bindings

The preceding commit includes motivation; specifically,
invoking keyboard and mouse bindings should never fail
unless they perform an action which can fail. For instance,
a `bindcode Ctrl+9 exit` should always exit; of course,
`exec` may fail for external reasons.

The core changes are to bind.c and commands.c. As a single
command may actually, on being parsed, generate multiple
commands to be executed (consider `workspace 1; splith`),
the parsing code in execute_command is moved to a separate
function, parse_command, which returns a list_t of stored
commands; leaving execute_command to parse the command,
execute each resulting list element; and then cleanup.

An additional field for the list of parsed stored commands,
is added to struct sway_binding, usurping the name "command".
This is initialized via parse_command, and then
seat_execute_command is adjusted accordingly.

Side effects of this change include:
* Reference counting `struct criteria`, because a criterion
parsed once may apply to multiple stored commands, and
the alternative of duplicating criteria is even more
complicated.
* Adding reading and active arguments to config_handler,
because when bindsyms parse commands, they require handler
lookups to be performed as though it were runtime.
* Reference counting `struct sway_binding`, because the
alternative of updating sway_binding_dup is even more
complicated when allocation failures are be taken into
account.
This commit is contained in:
mstoeckl 2018-08-23 20:04:44 -04:00
parent f8b9c796f4
commit 6a805aace0
13 changed files with 217 additions and 135 deletions

View file

@ -47,7 +47,7 @@ struct cmd_results *checkarg(int argc, const char *name,
enum expected_args type, int val);
struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers,
int handlers_size);
int handlers_size, bool reading, bool active);
/**
* Parse and executes a command.
*/
@ -56,10 +56,17 @@ struct cmd_results *execute_command(const char *command, struct sway_seat *seat
struct stored_command {
sway_cmd *handle;
int argc;
char** argv;
struct criteria* criteria;
char **argv;
struct criteria *criteria;
};
void free_stored_command(struct stored_command *command);
/**
* Parses a command, and returns a list of stored_commands. If `for_runtime`
* is true, then command handler lookup is performed as though it were runtime;
* otherwise, as appropriate for the current `config` state.
*/
list_t *parse_command(const char *command, bool for_runtime);
/**
* Executes a pre-parsed command. (Returns NULL if command was not unsuccessful: TODO, fix)
*/

View file

@ -38,7 +38,9 @@ enum binding_flags {
};
/**
* A key binding and an associated command.
* A key binding and an associated command. In order to extend the lifetime
* of a binding slightly while executing the reload command, bindings are
* reference counted, and should only be freed if the reference count is <= 0.
*/
struct sway_binding {
enum binding_input_type type;
@ -46,15 +48,9 @@ struct sway_binding {
uint32_t flags;
list_t *keys; // sorted in ascending order
uint32_t modifiers;
char *command;
};
/**
* A mouse binding and an associated command.
*/
struct sway_mouse_binding {
uint32_t button;
char *command;
char *command_str; // original command string for IPC compatibility
list_t *command; // a preparsed list of struct stored_command
int refcount;
};
/**

View file

@ -36,6 +36,9 @@ struct criteria {
bool tiling;
char urgent; // 'l' for latest or 'o' for oldest
char *workspace;
// optional refcount for users (like struct stored_command) for which
// a criterion may be referenced multiple times.
int refcount;
};
bool criteria_is_empty(struct criteria *criteria);