mirror of
https://github.com/swaywm/sway.git
synced 2024-11-29 19:31:29 +00:00
commit
fe3b85d65f
|
@ -3,13 +3,15 @@
|
|||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
|
||||
struct cmd_handler {
|
||||
char *command;
|
||||
enum cmd_status {
|
||||
|
||||
enum cmd_status {
|
||||
CMD_SUCCESS,
|
||||
CMD_FAILURE,
|
||||
CMD_INVALID,
|
||||
CMD_DEFER,
|
||||
} (*handle)(int argc, char **argv);
|
||||
// Config Blocks
|
||||
CMD_BLOCK_END,
|
||||
CMD_BLOCK_MODE,
|
||||
};
|
||||
|
||||
enum cmd_status handle_command(char *command);
|
||||
|
|
|
@ -8,10 +8,11 @@ extern int setenv(const char *, const char *, int);
|
|||
#endif
|
||||
|
||||
// array of whitespace characters to use for delims
|
||||
extern const char *whitespace;
|
||||
extern const char whitespace[];
|
||||
|
||||
char *strip_whitespace(char *str);
|
||||
char *strip_comments(char *str);
|
||||
void strip_quotes(char *str);
|
||||
|
||||
// Simply split a string with delims, free with `free_flat_list`
|
||||
list_t *split_string(const char *str, const char *delims);
|
||||
|
@ -27,5 +28,10 @@ int unescape_string(char *string);
|
|||
char *join_args(char **argv, int argc);
|
||||
char *join_list(list_t *list, char *separator);
|
||||
|
||||
// split string into 2 by delim.
|
||||
char *cmdsep(char **stringp, const char *delim);
|
||||
// Split string into 2 by delim, handle quotes
|
||||
char *argsep(char **stringp, const char *delim);
|
||||
|
||||
char *strdup(const char *);
|
||||
#endif
|
||||
|
|
225
sway/commands.c
225
sway/commands.c
|
@ -20,6 +20,40 @@
|
|||
#include "sway.h"
|
||||
#include "resize.h"
|
||||
|
||||
typedef enum cmd_status sway_cmd(int argc, char **argv);
|
||||
|
||||
struct cmd_handler {
|
||||
char *command;
|
||||
sway_cmd *handle;
|
||||
};
|
||||
|
||||
static sway_cmd cmd_bindsym;
|
||||
static sway_cmd cmd_orientation;
|
||||
static sway_cmd cmd_exec;
|
||||
static sway_cmd cmd_exec_always;
|
||||
static sway_cmd cmd_exit;
|
||||
static sway_cmd cmd_floating;
|
||||
static sway_cmd cmd_floating_mod;
|
||||
static sway_cmd cmd_focus;
|
||||
static sway_cmd cmd_focus_follows_mouse;
|
||||
static sway_cmd cmd_fullscreen;
|
||||
static sway_cmd cmd_gaps;
|
||||
static sway_cmd cmd_kill;
|
||||
static sway_cmd cmd_layout;
|
||||
static sway_cmd cmd_log_colors;
|
||||
static sway_cmd cmd_mode;
|
||||
static sway_cmd cmd_move;
|
||||
static sway_cmd cmd_output;
|
||||
static sway_cmd cmd_reload;
|
||||
static sway_cmd cmd_resize;
|
||||
static sway_cmd cmd_scratchpad;
|
||||
static sway_cmd cmd_set;
|
||||
static sway_cmd cmd_split;
|
||||
static sway_cmd cmd_splith;
|
||||
static sway_cmd cmd_splitv;
|
||||
static sway_cmd cmd_workspace;
|
||||
static sway_cmd cmd_ws_auto_back_and_forth;
|
||||
|
||||
swayc_t *sp_view;
|
||||
int sp_index = 0;
|
||||
|
||||
|
@ -147,37 +181,33 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_exec_always(int argc, char **argv) {
|
||||
if (!config->active) return CMD_DEFER;
|
||||
if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
if (!config->active) {
|
||||
return CMD_DEFER;
|
||||
}
|
||||
// Put argument into cmd array
|
||||
char *tmp = join_args(argv, argc);
|
||||
char cmd[4096];
|
||||
strcpy(cmd, tmp);
|
||||
free(tmp);
|
||||
|
||||
pid_t pid = fork();
|
||||
/* Failed to fork */
|
||||
if (pid < 0) {
|
||||
sway_log(L_ERROR, "exec command failed, sway did not fork");
|
||||
char *args[] = {"sh", "-c", cmd, 0 };
|
||||
sway_log(L_DEBUG, "Executing %s", cmd);
|
||||
|
||||
pid_t pid;
|
||||
if ((pid = fork()) == 0) {
|
||||
execv("/bin/sh", args);
|
||||
_exit(-1);
|
||||
} else if (pid < 0) {
|
||||
sway_log(L_ERROR, "exec command failed, sway could not fork");
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
/* Child process */
|
||||
if (pid == 0) {
|
||||
char *args = join_args(argv, argc);
|
||||
sway_log(L_DEBUG, "Executing %s", args);
|
||||
execl("/bin/sh", "sh", "-c", args, (char *)NULL);
|
||||
/* Execl doesnt return unless failure */
|
||||
sway_log(L_ERROR, "could not find /bin/sh");
|
||||
free(args);
|
||||
exit(-1);
|
||||
}
|
||||
/* Parent */
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static enum cmd_status cmd_exec(int argc, char **argv) {
|
||||
if (!config->active) {
|
||||
return CMD_DEFER;
|
||||
}
|
||||
if (!config->active) return CMD_DEFER;
|
||||
|
||||
if (config->reloading) {
|
||||
char *args = join_args(argv, argc);
|
||||
sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args);
|
||||
|
@ -194,8 +224,8 @@ static void kill_views(swayc_t *container, void *data) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_exit(int argc, char **argv) {
|
||||
if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)
|
||||
|| config->reading || !config->active) {
|
||||
if (config->reading) return CMD_INVALID;
|
||||
if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
// Close all views
|
||||
|
@ -205,8 +235,8 @@ static enum cmd_status cmd_exit(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_floating(int argc, char **argv) {
|
||||
if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)
|
||||
|| config->reading || !config->active) {
|
||||
if (config->reading) return CMD_INVALID;
|
||||
if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -267,8 +297,8 @@ static enum cmd_status cmd_floating(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_floating_mod(int argc, char **argv) {
|
||||
if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)
|
||||
|| !config->reading) {
|
||||
if (!config->reading) return CMD_INVALID;
|
||||
if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
int i, j;
|
||||
|
@ -292,10 +322,10 @@ static enum cmd_status cmd_floating_mod(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_focus(int argc, char **argv) {
|
||||
if (config->reading) return CMD_INVALID;
|
||||
static int floating_toggled_index = 0;
|
||||
static int tiled_toggled_index = 0;
|
||||
if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)
|
||||
|| config->reading || !config->active) {
|
||||
if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
if (strcasecmp(argv[0], "left") == 0) {
|
||||
|
@ -350,6 +380,7 @@ static enum cmd_status cmd_focus(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) {
|
||||
if (!config->reading) return CMD_INVALID;
|
||||
if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
@ -359,7 +390,7 @@ static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static void hide_view_in_scratchpad(swayc_t *sp_view) {
|
||||
if(sp_view == NULL) {
|
||||
if (sp_view == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -375,15 +406,19 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_mode(int argc, char **argv) {
|
||||
if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
|
||||
if (!checkarg(argc, "mode", EXPECTED_AT_LEAST, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
bool mode_make = !strcmp(argv[argc-1], "{");
|
||||
if (mode_make && !config->reading) {
|
||||
return CMD_FAILURE;
|
||||
char *mode_name = join_args(argv, argc);
|
||||
int mode_len = strlen(mode_name);
|
||||
bool mode_make = mode_name[mode_len-1] == '{';
|
||||
if (mode_make) {
|
||||
if (!config->reading) return CMD_INVALID;
|
||||
// Trim trailing spaces
|
||||
do {
|
||||
mode_name[--mode_len] = 0;
|
||||
} while(isspace(mode_name[mode_len-1]));
|
||||
}
|
||||
|
||||
char *mode_name = join_args(argv, argc - mode_make);
|
||||
struct sway_mode *mode = NULL;
|
||||
// Find mode
|
||||
int i, len = config->modes->length;
|
||||
|
@ -406,16 +441,18 @@ static enum cmd_status cmd_mode(int argc, char **argv) {
|
|||
free(mode_name);
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
if ((config->reading && mode_make) || (!config->reading && !mode_make)) {
|
||||
sway_log(L_DEBUG, "Switching to mode `%s'",mode->name);
|
||||
}
|
||||
free(mode_name);
|
||||
// Set current mode
|
||||
config->current_mode = mode;
|
||||
return CMD_SUCCESS;
|
||||
return mode_make ? CMD_BLOCK_MODE : CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static enum cmd_status cmd_move(int argc, char **argv) {
|
||||
if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)
|
||||
|| config->reading || !config->active) {
|
||||
if (config->reading) return CMD_FAILURE;
|
||||
if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -485,10 +522,11 @@ static enum cmd_status cmd_move(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_orientation(int argc, char **argv) {
|
||||
if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1)
|
||||
|| !config->reading) {
|
||||
if (!config->reading) return CMD_FAILURE;
|
||||
if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[0], "horizontal") == 0) {
|
||||
config->default_orientation = L_HORIZ;
|
||||
} else if (strcasecmp(argv[0], "vertical") == 0) {
|
||||
|
@ -502,6 +540,7 @@ static enum cmd_status cmd_orientation(int argc, char **argv) {
|
|||
}
|
||||
|
||||
static enum cmd_status cmd_output(int argc, char **argv) {
|
||||
if (!config->reading) return CMD_FAILURE;
|
||||
if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) {
|
||||
return CMD_FAILURE;
|
||||
}
|
||||
|
@ -512,7 +551,6 @@ static enum cmd_status cmd_output(int argc, char **argv) {
|
|||
output->enabled = true;
|
||||
|
||||
// TODO: atoi doesn't handle invalid numbers
|
||||
|
||||
if (strcasecmp(argv[1], "disable") == 0) {
|
||||
output->enabled = false;
|
||||
}
|
||||
|
@ -953,7 +991,7 @@ static enum cmd_status cmd_log_colors(int argc, char **argv) {
|
|||
}
|
||||
if (strcasecmp(argv[0], "no") == 0) {
|
||||
sway_log_colors(0);
|
||||
} else if(strcasecmp(argv[0], "yes") == 0) {
|
||||
} else if (strcasecmp(argv[0], "yes") == 0) {
|
||||
sway_log_colors(1);
|
||||
} else {
|
||||
sway_log(L_ERROR, "Invalid log_colors command (expected `yes` or `no`, got '%s')", argv[0]);
|
||||
|
@ -1089,57 +1127,88 @@ static struct cmd_handler *find_handler(char *line) {
|
|||
return res;
|
||||
}
|
||||
|
||||
enum cmd_status handle_command(char *exec) {
|
||||
sway_log(L_INFO, "Handling command '%s'", exec);
|
||||
int argc;
|
||||
char **argv = split_args(exec, &argc);
|
||||
enum cmd_status status = CMD_FAILURE;
|
||||
struct cmd_handler *handler;
|
||||
if (!argc) {
|
||||
return status;
|
||||
enum cmd_status handle_command(char *_exec) {
|
||||
enum cmd_status status = CMD_SUCCESS;
|
||||
char *exec = strdup(_exec);
|
||||
char *head = exec;
|
||||
char *cmdlist;
|
||||
char *cmd;
|
||||
char *criteria __attribute__((unused));
|
||||
|
||||
head = exec;
|
||||
do {
|
||||
// Handle criteria
|
||||
if (*head == '[') {
|
||||
criteria = argsep(&head, "]");
|
||||
if (head) {
|
||||
++head;
|
||||
// TODO handle criteria
|
||||
} else {
|
||||
sway_log(L_ERROR, "Unmatched [");
|
||||
status = CMD_INVALID;
|
||||
}
|
||||
if ((handler = find_handler(argv[0])) == NULL
|
||||
|| (status = handler->handle(argc - 1, argv + 1)) != CMD_SUCCESS) {
|
||||
sway_log(L_ERROR, "Command failed: %s", argv[0]);
|
||||
// Skip leading whitespace
|
||||
head += strspn(head, whitespace);
|
||||
}
|
||||
// Split command list
|
||||
cmdlist = argsep(&head, ";");
|
||||
cmdlist += strspn(cmdlist, whitespace);
|
||||
do {
|
||||
// Split commands
|
||||
cmd = argsep(&cmdlist, ",");
|
||||
cmd += strspn(cmd, whitespace);
|
||||
sway_log(L_INFO, "Handling command '%s'", cmd);
|
||||
//TODO better handling of argv
|
||||
int argc;
|
||||
char **argv = split_args(cmd, &argc);
|
||||
if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) {
|
||||
strip_quotes(argv[1]);
|
||||
}
|
||||
struct cmd_handler *handler = find_handler(argv[0]);
|
||||
enum cmd_status res = CMD_INVALID;
|
||||
if (!handler
|
||||
|| (res = handler->handle(argc-1, argv+1)) != CMD_SUCCESS) {
|
||||
sway_log(L_ERROR, "Command '%s' failed", cmd);
|
||||
free_argv(argc, argv);
|
||||
status = res;
|
||||
goto cleanup;
|
||||
}
|
||||
free_argv(argc, argv);
|
||||
} while(cmdlist);
|
||||
} while(head);
|
||||
cleanup:
|
||||
free(exec);
|
||||
return status;
|
||||
}
|
||||
|
||||
enum cmd_status config_command(char *exec) {
|
||||
sway_log(L_INFO, "handling config command '%s'", exec);
|
||||
enum cmd_status status = CMD_SUCCESS;
|
||||
int argc;
|
||||
char **argv = split_args(exec, &argc);
|
||||
enum cmd_status status = CMD_FAILURE;
|
||||
struct cmd_handler *handler;
|
||||
if (!argc) {
|
||||
status = CMD_SUCCESS;
|
||||
if (!argc) goto cleanup;
|
||||
|
||||
sway_log(L_INFO, "handling config command '%s'", exec);
|
||||
// Endblock
|
||||
if (**argv == '}') {
|
||||
status = CMD_BLOCK_END;
|
||||
goto cleanup;
|
||||
}
|
||||
// TODO better block handling
|
||||
if (strncmp(argv[0], "}", 1) == 0) {
|
||||
config->current_mode = config->modes->items[0];
|
||||
status = CMD_SUCCESS;
|
||||
struct cmd_handler *handler = find_handler(argv[0]);
|
||||
if (!handler) {
|
||||
status = CMD_INVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((handler = find_handler(argv[0]))) {
|
||||
// Dont replace first argument in cmd_set
|
||||
int i = handler->handle == cmd_set ? 2 : 1;
|
||||
int e = argc;
|
||||
for (; i < e; ++i) {
|
||||
int i;
|
||||
// Var replacement, for all but first argument of set
|
||||
for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) {
|
||||
argv[i] = do_var_replacement(argv[i]);
|
||||
}
|
||||
status = handler->handle(argc - 1, argv + 1);
|
||||
if (status == CMD_FAILURE) {
|
||||
sway_log(L_ERROR, "Config load failed for line `%s'", exec);
|
||||
} else if (status == CMD_DEFER) {
|
||||
sway_log(L_DEBUG, "Defferring command `%s'", exec);
|
||||
list_add(config->cmd_queue, strdup(exec));
|
||||
status = CMD_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
sway_log(L_ERROR, "Unknown command `%s'", exec);
|
||||
/* Strip quotes for first argument.
|
||||
* TODO This part needs to be handled much better */
|
||||
if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) {
|
||||
strip_quotes(argv[1]);
|
||||
}
|
||||
status = handler->handle(argc-1, argv+1);
|
||||
cleanup:
|
||||
free_argv(argc, argv);
|
||||
return status;
|
||||
|
|
|
@ -110,41 +110,42 @@ static void config_defaults(struct sway_config *config) {
|
|||
|
||||
static char *get_config_path(void) {
|
||||
char *config_path = NULL;
|
||||
char *paths[3] = {getenv("HOME"), getenv("XDG_CONFIG_HOME"), ""};
|
||||
int pathlen[3] = {0, 0, 0};
|
||||
char *paths[3] = { getenv("HOME"), getenv("XDG_CONFIG_HOME"), "" };
|
||||
int pathlen[3] = { 0, 0, 0 };
|
||||
int i;
|
||||
#define home paths[0]
|
||||
#define conf paths[1]
|
||||
// Get home and config directories
|
||||
conf = conf ? strdup(conf) : NULL;
|
||||
home = home ? strdup(home) : NULL;
|
||||
if (conf) {
|
||||
conf = strdup(conf);
|
||||
} else if (home) {
|
||||
// If config folder is unset, set it to $HOME/.config
|
||||
if (!conf && home) {
|
||||
const char *def = "/.config";
|
||||
conf = malloc(strlen(home) + strlen(def) + 1);
|
||||
strcpy(conf, home);
|
||||
strcat(conf, def);
|
||||
} else {
|
||||
home = strdup("");
|
||||
conf = strdup("");
|
||||
}
|
||||
pathlen[0] = strlen(home);
|
||||
pathlen[1] = strlen(conf);
|
||||
// Get path lengths
|
||||
pathlen[0] = home ? strlen(home) : 0;
|
||||
pathlen[1] = conf ? strlen(conf) : 0;
|
||||
#undef home
|
||||
#undef conf
|
||||
|
||||
// Search for config file from search paths
|
||||
static const char *search_paths[] = {
|
||||
"/.sway/config", // Prepend with $home
|
||||
"/sway/config", // Prepend with $config
|
||||
"/etc/sway/config",
|
||||
"/.i3/config", // $home
|
||||
"/.i3/config", // $config
|
||||
"/i3/config", // $config
|
||||
"/etc/i3/config"
|
||||
};
|
||||
for (i = 0; i < (int)(sizeof(search_paths) / sizeof(char *)); ++i) {
|
||||
// Only try path if it is set by enviroment variables
|
||||
if (paths[i%3]) {
|
||||
char *test = malloc(pathlen[i%3] + strlen(search_paths[i]) + 1);
|
||||
strcpy(test, paths[i%3]);
|
||||
strcat(test, search_paths[i]);
|
||||
strcpy(test + pathlen[i%3], search_paths[i]);
|
||||
sway_log(L_DEBUG, "Checking for config at %s", test);
|
||||
if (file_exists(test)) {
|
||||
config_path = test;
|
||||
|
@ -152,6 +153,7 @@ static char *get_config_path(void) {
|
|||
}
|
||||
free(test);
|
||||
}
|
||||
}
|
||||
|
||||
sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS");
|
||||
char *xdg_config_dirs = getenv("XDG_CONFIG_DIRS");
|
||||
|
@ -225,14 +227,46 @@ bool read_config(FILE *file, bool is_active) {
|
|||
config->active = true;
|
||||
}
|
||||
bool success = true;
|
||||
enum cmd_status block = CMD_BLOCK_END;
|
||||
|
||||
char *line;
|
||||
while (!feof(file)) {
|
||||
line = read_line(file);
|
||||
line = strip_comments(line);
|
||||
if (config_command(line) == CMD_FAILURE) {
|
||||
switch(config_command(line)) {
|
||||
case CMD_FAILURE:
|
||||
case CMD_INVALID:
|
||||
sway_log(L_ERROR, "Error on line '%s'", line);
|
||||
success = false;
|
||||
break;
|
||||
|
||||
case CMD_DEFER:
|
||||
sway_log(L_DEBUG, "Defferring command `%s'", line);
|
||||
list_add(config->cmd_queue, strdup(line));
|
||||
break;
|
||||
|
||||
case CMD_BLOCK_MODE:
|
||||
if (block == CMD_BLOCK_END) {
|
||||
block = CMD_BLOCK_MODE;
|
||||
} else {
|
||||
sway_log(L_ERROR, "Invalid block '%s'", line);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_BLOCK_END:
|
||||
switch(block) {
|
||||
case CMD_BLOCK_MODE:
|
||||
sway_log(L_DEBUG, "End of mode block");
|
||||
config->current_mode = config->modes->items[0];
|
||||
break;
|
||||
|
||||
case CMD_BLOCK_END:
|
||||
sway_log(L_ERROR, "Unmatched }");
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
|
|
@ -405,7 +405,7 @@ swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *dat
|
|||
}
|
||||
|
||||
static bool test_name(swayc_t *view, void *data) {
|
||||
if (!view && !view->name) {
|
||||
if (!view || !view->name) {
|
||||
return false;
|
||||
}
|
||||
return strcmp(view->name, data) == 0;
|
||||
|
|
|
@ -253,8 +253,8 @@ static void handle_view_focus(wlc_handle view, bool focus) {
|
|||
}
|
||||
|
||||
static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry *geometry) {
|
||||
sway_log(L_DEBUG, "geometry request %d x %d : %d x %d",
|
||||
geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h);
|
||||
sway_log(L_DEBUG, "geometry request for %ld %dx%d : %dx%d",
|
||||
handle, geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h);
|
||||
// If the view is floating, then apply the geometry.
|
||||
// Otherwise save the desired width/height for the view.
|
||||
// This will not do anything for the time being as WLC improperly sends geometry requests
|
||||
|
@ -331,7 +331,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
|
|||
struct sway_binding *binding = mode->bindings->items[i];
|
||||
|
||||
if ((modifiers->mods ^ binding->modifiers) == 0) {
|
||||
bool match;
|
||||
bool match = false;
|
||||
int j;
|
||||
for (j = 0; j < binding->keys->length; ++j) {
|
||||
xkb_keysym_t *key = binding->keys->items[j];
|
||||
|
|
|
@ -206,7 +206,8 @@ void swap_geometry(swayc_t *a, swayc_t *b) {
|
|||
|
||||
void move_container(swayc_t *container, enum movement_direction dir) {
|
||||
enum swayc_layouts layout;
|
||||
if (container->is_floating) {
|
||||
if (container->is_floating
|
||||
|| (container->type != C_VIEW && container->type != C_CONTAINER)) {
|
||||
return;
|
||||
}
|
||||
if (dir == MOVE_UP || dir == MOVE_DOWN) {
|
||||
|
@ -280,7 +281,6 @@ void move_container(swayc_t *container, enum movement_direction dir) {
|
|||
// Dirty hack to fix a certain case
|
||||
arrange_windows(parent, -1, -1);
|
||||
arrange_windows(parent->parent, -1, -1);
|
||||
update_visibility(parent->parent);
|
||||
set_focused_container_for(parent->parent, container);
|
||||
}
|
||||
|
||||
|
@ -319,31 +319,34 @@ void update_geometry(swayc_t *container) {
|
|||
if (container->type != C_VIEW) {
|
||||
return;
|
||||
}
|
||||
int gap = swayc_gap(container);
|
||||
swayc_t *ws = swayc_parent_by_type(container, C_WORKSPACE);
|
||||
swayc_t *op = ws->parent;
|
||||
int gap = container->is_floating ? 0 : swayc_gap(container);
|
||||
|
||||
struct wlc_geometry geometry = {
|
||||
.origin = {
|
||||
.x = container->x + (container->is_floating ? 0 : gap / 2),
|
||||
.y = container->y + (container->is_floating ? 0 : gap / 2)
|
||||
.x = container->x + gap/2 < op->width ? container->x + gap/2 : op->width-1,
|
||||
.y = container->y + gap/2 < op->height ? container->y + gap/2 : op->height-1
|
||||
},
|
||||
.size = {
|
||||
.w = container->width > (container->is_floating ? 0 : gap) ?
|
||||
container->width - (container->is_floating ? 0 : gap) : 0,
|
||||
.h = container->height > (container->is_floating ? 0 : gap) ?
|
||||
container->height - (container->is_floating ? 0 : gap) : 0,
|
||||
.w = container->width > gap ? container->width - gap : 1,
|
||||
.h = container->height > gap ? container->height - gap : 1,
|
||||
}
|
||||
};
|
||||
if (swayc_is_fullscreen(container)) {
|
||||
swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT);
|
||||
geometry.origin.x = 0;
|
||||
geometry.origin.y = 0;
|
||||
geometry.size.w = parent->width;
|
||||
geometry.size.h = parent->height;
|
||||
geometry.size.w = op->width;
|
||||
geometry.size.h = op->height;
|
||||
if (op->focused == ws) {
|
||||
wlc_view_bring_to_front(container->handle);
|
||||
}
|
||||
}
|
||||
wlc_view_set_geometry(container->handle, 0, &geometry);
|
||||
return;
|
||||
}
|
||||
|
||||
void arrange_windows(swayc_t *container, double width, double height) {
|
||||
static void arrange_windows_r(swayc_t *container, double width, double height) {
|
||||
int i;
|
||||
if (width == -1 || height == -1) {
|
||||
sway_log(L_DEBUG, "Arranging layout for %p", container);
|
||||
|
@ -357,7 +360,7 @@ void arrange_windows(swayc_t *container, double width, double height) {
|
|||
for (i = 0; i < container->children->length; ++i) {
|
||||
swayc_t *child = container->children->items[i];
|
||||
sway_log(L_DEBUG, "Arranging output at %d", x);
|
||||
arrange_windows(child, -1, -1);
|
||||
arrange_windows_r(child, -1, -1);
|
||||
x += child->width;
|
||||
}
|
||||
return;
|
||||
|
@ -373,7 +376,7 @@ void arrange_windows(swayc_t *container, double width, double height) {
|
|||
child->width = width - gap * 2;
|
||||
child->height = height - gap * 2;
|
||||
sway_log(L_DEBUG, "Arranging workspace #%d at %f, %f", i, child->x, child->y);
|
||||
arrange_windows(child, -1, -1);
|
||||
arrange_windows_r(child, -1, -1);
|
||||
}
|
||||
return;
|
||||
case C_VIEW:
|
||||
|
@ -417,7 +420,7 @@ void arrange_windows(swayc_t *container, double width, double height) {
|
|||
sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale);
|
||||
child->x = x + container->x;
|
||||
child->y = y + container->y;
|
||||
arrange_windows(child, child->width * scale, height);
|
||||
arrange_windows_r(child, child->width * scale, height);
|
||||
x += child->width;
|
||||
}
|
||||
}
|
||||
|
@ -444,7 +447,7 @@ void arrange_windows(swayc_t *container, double width, double height) {
|
|||
sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale);
|
||||
child->x = x + container->x;
|
||||
child->y = y + container->y;
|
||||
arrange_windows(child, width, child->height * scale);
|
||||
arrange_windows_r(child, width, child->height * scale);
|
||||
y += child->height;
|
||||
}
|
||||
}
|
||||
|
@ -466,6 +469,11 @@ void arrange_windows(swayc_t *container, double width, double height) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void arrange_windows(swayc_t *container, double width, double height) {
|
||||
update_visibility(container);
|
||||
arrange_windows_r(container, width, height);
|
||||
layout_log(&root_container, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ int colored = 1;
|
|||
log_importance_t v = L_SILENT;
|
||||
|
||||
static const char *verbosity_colors[] = {
|
||||
"", // L_SILENT
|
||||
"\x1B[1;31m", // L_ERROR
|
||||
"\x1B[1;34m", // L_INFO
|
||||
"\x1B[1;30m", // L_DEBUG
|
||||
[L_SILENT] = "",
|
||||
[L_ERROR ] = "\x1B[1;31m",
|
||||
[L_INFO ] = "\x1B[1;34m",
|
||||
[L_DEBUG ] = "\x1B[1;30m",
|
||||
};
|
||||
|
||||
void init_log(log_importance_t verbosity) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include "stringop.h"
|
||||
|
@ -7,7 +8,7 @@
|
|||
#include "string.h"
|
||||
#include "list.h"
|
||||
|
||||
const char *whitespace = " \f\n\r\t\v";
|
||||
const char whitespace[] = " \f\n\r\t\v";
|
||||
|
||||
/* Note: This returns 8 characters for trimmed_start per tab character. */
|
||||
char *strip_whitespace(char *_str) {
|
||||
|
@ -105,6 +106,7 @@ char **split_args(const char *start, int *argc) {
|
|||
bool in_char = false;
|
||||
bool escaped = false;
|
||||
const char *end = start;
|
||||
if (start) {
|
||||
while (*start) {
|
||||
if (!in_token) {
|
||||
start = (end += strspn(end, whitespace));
|
||||
|
@ -118,20 +120,18 @@ char **split_args(const char *start, int *argc) {
|
|||
escaped = !escaped;
|
||||
} else if (*end == '\0' || (!in_string && !in_char && !escaped
|
||||
&& strchr(whitespace, *end))) {
|
||||
goto add_part;
|
||||
goto add_token;
|
||||
}
|
||||
if (*end != '\\') {
|
||||
escaped = false;
|
||||
}
|
||||
++end;
|
||||
continue;
|
||||
add_part:
|
||||
add_token:
|
||||
if (end - start > 0) {
|
||||
char *token = malloc(end - start + 1);
|
||||
strncpy(token, start, end - start + 1);
|
||||
token[end - start] = '\0';
|
||||
strip_quotes(token);
|
||||
unescape_string(token);
|
||||
argv[*argc] = token;
|
||||
if (++*argc + 1 == alloc) {
|
||||
argv = realloc(argv, (alloc *= 2) * sizeof(char *));
|
||||
|
@ -140,6 +140,7 @@ char **split_args(const char *start, int *argc) {
|
|||
in_token = false;
|
||||
escaped = false;
|
||||
}
|
||||
}
|
||||
argv[*argc] = NULL;
|
||||
return argv;
|
||||
}
|
||||
|
@ -312,6 +313,56 @@ char *join_list(list_t *list, char *separator) {
|
|||
return res;
|
||||
}
|
||||
|
||||
char *cmdsep(char **stringp, const char *delim) {
|
||||
// skip over leading delims
|
||||
char *head = *stringp + strspn(*stringp, delim);
|
||||
// Find end token
|
||||
char *tail = *stringp += strcspn(*stringp, delim);
|
||||
// Set stringp to begining of next token
|
||||
*stringp += strspn(*stringp, delim);
|
||||
// Set stringp to null if last token
|
||||
if (!**stringp) *stringp = NULL;
|
||||
// Nullify end of first token
|
||||
*tail = 0;
|
||||
return head;
|
||||
}
|
||||
|
||||
char *argsep(char **stringp, const char *delim) {
|
||||
char *start = *stringp;
|
||||
char *end = start;
|
||||
bool in_string = false;
|
||||
bool in_char = false;
|
||||
bool escaped = false;
|
||||
while (1) {
|
||||
if (*end == '"' && !in_char && !escaped) {
|
||||
in_string = !in_string;
|
||||
} else if (*end == '\'' && !in_string && !escaped) {
|
||||
in_char = !in_char;
|
||||
} else if (*end == '\\') {
|
||||
escaped = !escaped;
|
||||
} else if (*end == '\0') {
|
||||
*stringp = NULL;
|
||||
goto found;
|
||||
} else if (!in_string && !in_char && !escaped && strchr(delim, *end)) {
|
||||
if (end - start) {
|
||||
*(end++) = 0;
|
||||
*stringp = end + strspn(end, delim);;
|
||||
if (!**stringp) *stringp = NULL;
|
||||
goto found;
|
||||
} else {
|
||||
++start;
|
||||
end = start;
|
||||
}
|
||||
}
|
||||
if (*end != '\\') {
|
||||
escaped = false;
|
||||
}
|
||||
++end;
|
||||
}
|
||||
found:
|
||||
return start;
|
||||
}
|
||||
|
||||
char *strdup(const char *str) {
|
||||
char *dup = malloc(strlen(str) + 1);
|
||||
if (dup) {
|
||||
|
@ -319,3 +370,4 @@ char *strdup(const char *str) {
|
|||
}
|
||||
return dup;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue