diff options
| -rw-r--r-- | include/commands.h | 16 | ||||
| -rw-r--r-- | include/config.h | 4 | ||||
| -rw-r--r-- | include/container.h | 139 | ||||
| -rw-r--r-- | include/stringop.h | 2 | ||||
| -rw-r--r-- | include/workspace.h | 16 | ||||
| -rw-r--r-- | sway/commands.c | 167 | ||||
| -rw-r--r-- | sway/config.c | 25 | ||||
| -rw-r--r-- | sway/container.c | 415 | ||||
| -rw-r--r-- | sway/handlers.c | 12 | ||||
| -rw-r--r-- | sway/ipc.c | 4 | ||||
| -rw-r--r-- | sway/stringop.c | 2 | ||||
| -rw-r--r-- | sway/workspace.c | 149 |
12 files changed, 581 insertions, 370 deletions
diff --git a/include/commands.h b/include/commands.h index 5c87be51..69ab1380 100644 --- a/include/commands.h +++ b/include/commands.h @@ -3,19 +3,21 @@ #include <stdbool.h> #include "config.h" +typedef enum cmd_status { + CMD_SUCCESS, + CMD_FAILURE, + CMD_DEFER, +} sway_cmd(char *criteria, int argc, char **argv); + struct cmd_handler { - char *command; - enum cmd_status { - CMD_SUCCESS, - CMD_FAILURE, - CMD_DEFER, - } (*handle)(int argc, char **argv); + const char*command; + sway_cmd *handle; }; enum cmd_status handle_command(char *command); // Handles commands during config enum cmd_status config_command(char *command); -void remove_view_from_scratchpad(); +void remove_view_from_scratchpad(swayc_t *view); #endif diff --git a/include/config.h b/include/config.h index 676218c8..04db3e5c 100644 --- a/include/config.h +++ b/include/config.h @@ -63,6 +63,10 @@ bool load_config(const char *file); bool read_config(FILE *file, bool is_active); char *do_var_replacement(char *str); +// Find workspace_output from config by workspace or output name +struct workspace_output *wsop_find_workspace(const char *); +struct workspace_output *wsop_find_output(const char *); + extern struct sway_config *config; #endif diff --git a/include/container.h b/include/container.h index a9b95229..d8590149 100644 --- a/include/container.h +++ b/include/container.h @@ -2,29 +2,25 @@ #define _SWAY_CONTAINER_H #include <wlc/wlc.h> typedef struct sway_container swayc_t; - #include "layout.h" -enum swayc_types{ - C_ROOT, - C_OUTPUT, - C_WORKSPACE, - C_CONTAINER, - C_VIEW, - // Keep last - C_TYPES, +enum swayc_types { + C_ROOT = 1 << 0, + C_OUTPUT = 1 << 1, + C_WORKSPACE = 1 << 2, + C_CONTAINER = 1 << 3, + C_VIEW = 1 << 4, + C_TYPES = 5, }; - -enum swayc_layouts{ - L_NONE, - L_HORIZ, - L_VERT, - L_STACKED, - L_TABBED, - L_FLOATING, - // Keep last - L_LAYOUTS, +enum swayc_layouts { + L_NONE = 1 << 0, + L_HORIZ = 1 << 1, + L_VERT = 1 << 2, + L_STACKED = 1 << 3, + L_TABBED = 1 << 4, + L_FLOATING = 1 << 5, + L_LAYOUTS = 6, }; struct sway_container { @@ -35,13 +31,16 @@ struct sway_container { // Not including borders or margins double width, height; + double x, y; // Used for setting floating geometry int desired_width, desired_height; - double x, y; + enum visibility_mask { + INVISIBLE = 0, + VISIBLE = 1, + } visible; - bool visible; bool is_floating; bool is_focused; @@ -56,70 +55,120 @@ struct sway_container { struct sway_container *focused; }; -enum visibility_mask { - VISIBLE = 1 -}; - -// Container Creation +// swayc Creation +/* Creates and returns new, or an already created output. + * If it creates a new output, it also creates a workspace using + * `new_workspace(outputname, NULL);` */ swayc_t *new_output(wlc_handle handle); + +/* Creates workspace with given name, under given output. + * If workspace with that name already exists, returns that workspace + * If name is NULL, it will choose a name automatically. + * If output is NULL, it will choose an output automatically. */ swayc_t *new_workspace(swayc_t *output, const char *name); + // Creates container Around child (parent child) -> (parent (container child)) swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); + // Creates view as a sibling of current focused container, or as child of a workspace swayc_t *new_view(swayc_t *sibling, wlc_handle handle); + // Creates view as a new floating view which is in the active workspace swayc_t *new_floating_view(wlc_handle handle); // Container Destroying - +// Destroys output and moves workspaces to another output swayc_t *destroy_output(swayc_t *output); + // Destroys workspace if empty and returns parent pointer, else returns NULL swayc_t *destroy_workspace(swayc_t *workspace); + // Destroyes container and all parent container if they are empty, returns // topmost non-empty parent. returns NULL otherwise swayc_t *destroy_container(swayc_t *container); + // Destroys view and all empty parent containers. return topmost non-empty // parent swayc_t *destroy_view(swayc_t *view); -// Container Lookup +// Container Mapping and testing functions +typedef bool swayc_test_func(swayc_t *view, void *data); +typedef void swayc_map_func(swayc_t *view, void *data); + +// Returns the first swayc that matches test() +swayc_t *swayc_by_test_r(swayc_t *root, swayc_test_func test, void *data); +swayc_t *swayc_by_test(swayc_test_func test, void *data); + +// Calls func for all children. +void swayc_map_r(swayc_t *root, swayc_map_func func, void *data); +void swayc_map(swayc_map_func func, void *data); + + +// Call func on container if test passes +void swayc_map_by_test_r(swayc_t *root, + swayc_map_func func, swayc_test_func test, + void *funcdata, void *testdata); +void swayc_map_by_test( + swayc_map_func func, swayc_test_func test, + void *funcdata, void *testdata); + +// Map functions +swayc_map_func set_gaps; +swayc_map_func add_gaps; + +// Test functions +// generic swayc tests +swayc_test_func test_name; +swayc_test_func test_name_regex; +swayc_test_func test_layout; +swayc_test_func test_type; +swayc_test_func test_visibility; +swayc_test_func test_handle; + +// C_VIEW tests +// See wlc_view_*_bit enums +swayc_test_func test_view_state; +swayc_test_func test_view_type; +swayc_test_func test_view_title; +swayc_test_func test_view_class; +swayc_test_func test_view_appid; +swayc_test_func test_view_title_regex; +swayc_test_func test_view_class_regex; +swayc_test_func test_view_appid_regex; + +// functions for test_*_regex +void *compile_regex(const char *regex); +void free_regex(void *); + +// these take a NULL terminated array of test_list struct. +struct test_list { swayc_test_func *test; void *data ; }; +swayc_test_func test_and; +swayc_test_func test_or; -swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); // Follow focused until type/layout swayc_t *swayc_focus_by_type(swayc_t *container, enum swayc_types); swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts); - -swayc_t *swayc_by_handle(wlc_handle handle); -swayc_t *swayc_by_name(const char *name); swayc_t *swayc_active_output(void); swayc_t *swayc_active_workspace(void); swayc_t *swayc_active_workspace_for(swayc_t *view); // Container information - -bool swayc_is_fullscreen(swayc_t *view); -bool swayc_is_active(swayc_t *view); -// Is `parent` the parent of `child` +// if `parent` is the parent of `child` bool swayc_is_parent_of(swayc_t *parent, swayc_t *child); -// Is `child` a child of `parent` +// If `child` is a child of `parent` bool swayc_is_child_of(swayc_t *child, swayc_t *parent); // Return gap of specified container int swayc_gap(swayc_t *container); -// Mapping functions - -void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); +bool swayc_is_fullscreen(swayc_t *view); +bool swayc_is_active(swayc_t *view); -// Mappings -void set_view_visibility(swayc_t *view, void *data); -// Set or add to gaps -void set_gaps(swayc_t *view, void *amount); -void add_gaps(swayc_t *view, void *amount); +// Specialized mapping functions void update_visibility(swayc_t *container); #endif diff --git a/include/stringop.h b/include/stringop.h index dde50f13..6e80e729 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -19,7 +19,7 @@ void free_argv(int argc, char **argv); char *code_strchr(const char *string, char delimiter); char *code_strstr(const char *haystack, const char *needle); int unescape_string(char *string); -char *join_args(char **argv, int argc); +char *join_args(int argc, char **argv); char *join_list(list_t *list, char *separator); char *strdup(const char *); diff --git a/include/workspace.h b/include/workspace.h index 7343b055..3a63ea38 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -7,13 +7,17 @@ extern char *prev_workspace_name; -char *workspace_next_name(void); -swayc_t *workspace_create(const char*); +// Search for available workspace name on output from config +const char *workspace_output_open_name(swayc_t *output); +// Search for any available workspace name +const char *workspace_next_name(void); + + swayc_t *workspace_by_name(const char*); void workspace_switch(swayc_t*); -swayc_t *workspace_output_next(); -swayc_t *workspace_next(); -swayc_t *workspace_output_prev(); -swayc_t *workspace_prev(); +swayc_t *workspace_output_next(void); +swayc_t *workspace_next(void); +swayc_t *workspace_output_prev(void); +swayc_t *workspace_prev(void); #endif diff --git a/sway/commands.c b/sway/commands.c index e79746ae..74e13d6c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -21,6 +21,35 @@ swayc_t *sp_view; int sp_index = 0; +// Commands +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_for_window; +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; + static struct modifier_key { char *name; uint32_t mod; @@ -94,7 +123,7 @@ static int bindsym_sort(const void *_lbind, const void *_rbind) { return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); } -static enum cmd_status cmd_bindsym(int argc, char **argv) { +enum cmd_status cmd_bindsym(char *criteria, int argc, char **argv) { if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1) || !config->reading) { return CMD_FAILURE; @@ -103,7 +132,7 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) { struct sway_binding *binding = malloc(sizeof(struct sway_binding)); binding->keys = create_list(); binding->modifiers = 0; - binding->command = join_args(argv + 1, argc - 1); + binding->command = join_args(argc - 1, argv + 1); list_t *split = split_string(argv[0], "+"); int i; @@ -144,7 +173,7 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_exec_always(int argc, char **argv) { +enum cmd_status cmd_exec_always(char *criteria, int argc, char **argv) { if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { return CMD_FAILURE; } @@ -160,7 +189,7 @@ static enum cmd_status cmd_exec_always(int argc, char **argv) { } /* Child process */ if (pid == 0) { - char *args = join_args(argv, argc); + char *args = join_args(argc, argv); sway_log(L_DEBUG, "Executing %s", args); execl("/bin/sh", "sh", "-c", args, (char *)NULL); /* Execl doesnt return unless failure */ @@ -172,17 +201,17 @@ static enum cmd_status cmd_exec_always(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_exec(int argc, char **argv) { +enum cmd_status cmd_exec(char *criteria, int argc, char **argv) { if (!config->active) { return CMD_DEFER; } if (config->reloading) { - char *args = join_args(argv, argc); + char *args = join_args(argc, argv); sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); free(args); return CMD_SUCCESS; } - return cmd_exec_always(argc, argv); + return cmd_exec_always(criteria, argc, argv); } static void kill_views(swayc_t *container, void *data) { @@ -191,18 +220,19 @@ static void kill_views(swayc_t *container, void *data) { } } -static enum cmd_status cmd_exit(int argc, char **argv) { +enum cmd_status cmd_exit(char *criteria, int argc, char **argv) { + (void) argv; if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0) || config->reading || !config->active) { return CMD_FAILURE; } // Close all views - container_map(&root_container, kill_views, NULL); + swayc_map(kill_views, NULL); sway_terminate(); return CMD_SUCCESS; } -static enum cmd_status cmd_floating(int argc, char **argv) { +enum cmd_status cmd_floating(char *criteria, int argc, char **argv) { if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1) || config->reading || !config->active) { return CMD_FAILURE; @@ -264,7 +294,7 @@ static enum cmd_status cmd_floating(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_floating_mod(int argc, char **argv) { +enum cmd_status cmd_floating_mod(char *criteria, int argc, char **argv) { if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1) || !config->reading) { return CMD_FAILURE; @@ -289,7 +319,7 @@ static enum cmd_status cmd_floating_mod(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_focus(int argc, char **argv) { +enum cmd_status cmd_focus(char *criteria, int argc, char **argv) { static int floating_toggled_index = 0; static int tiled_toggled_index = 0; if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1) @@ -347,7 +377,7 @@ static enum cmd_status cmd_focus(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) { +enum cmd_status cmd_focus_follows_mouse(char *criteria, int argc, char **argv) { if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } @@ -356,6 +386,21 @@ static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) { return CMD_SUCCESS; } +static void debug_for_window(swayc_t *view, void *data) { + layout_log(view, 0); +} + +enum cmd_status cmd_for_window(char *criteria, int argc, char **argv) { + if (!checkarg(argc, "for_window", EXPECTED_AT_LEAST, 2)) { + return CMD_FAILURE; + } + //TODO + void *re = compile_regex(argv[0]); + swayc_map_by_test(debug_for_window, test_view_title_regex, NULL, re); + free_regex(re); + return CMD_FAILURE; +} + static void hide_view_in_scratchpad(swayc_t *sp_view) { if(sp_view == NULL) { return; @@ -372,7 +417,7 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) { set_focused_container(container_under_pointer()); } -static enum cmd_status cmd_mode(int argc, char **argv) { +enum cmd_status cmd_mode(char *criteria, int argc, char **argv) { if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -381,7 +426,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { return CMD_FAILURE; } - char *mode_name = join_args(argv, argc - mode_make); + char *mode_name = join_args(argc - mode_make, argv); struct sway_mode *mode = NULL; // Find mode int i, len = config->modes->length; @@ -411,7 +456,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_move(int argc, char **argv) { +enum cmd_status cmd_move(char *criteria, int argc, char **argv) { if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1) || config->reading || !config->active) { return CMD_FAILURE; @@ -444,11 +489,7 @@ static enum cmd_status cmd_move(int argc, char **argv) { // move "container to workspace number x" ws_name = argv[4]; } - - swayc_t *ws = workspace_by_name(ws_name); - if (ws == NULL) { - ws = workspace_create(ws_name); - } + swayc_t *ws = new_workspace(NULL, ws_name); move_container_to(view, get_focused_container(ws)); } else if (strcasecmp(argv[0], "scratchpad") == 0) { if (view->type != C_CONTAINER && view->type != C_VIEW) { @@ -482,7 +523,7 @@ static enum cmd_status cmd_move(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_orientation(int argc, char **argv) { +enum cmd_status cmd_orientation(char *criteria, int argc, char **argv) { if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1) || !config->reading) { return CMD_FAILURE; @@ -499,7 +540,7 @@ static enum cmd_status cmd_orientation(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_output(int argc, char **argv) { +enum cmd_status cmd_output(char *criteria, int argc, char **argv) { if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -564,7 +605,7 @@ static enum cmd_status cmd_output(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_gaps(int argc, char **argv) { +enum cmd_status cmd_gaps(char *criteria, int argc, char **argv) { if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -698,15 +739,14 @@ static enum cmd_status cmd_gaps(int argc, char **argv) { top = &root_container; } int top_gap = top->gaps; - container_map(top, method == SET ? set_gaps : add_gaps, &amount); + swayc_map_r(top, method == SET ? set_gaps : add_gaps, &amount); top->gaps = top_gap; arrange_windows(top, -1, -1); } - return CMD_SUCCESS; } -static enum cmd_status cmd_kill(int argc, char **argv) { +enum cmd_status cmd_kill(char *criteria, int argc, char **argv) { if (config->reading || !config->active) { return CMD_FAILURE; } @@ -715,7 +755,7 @@ static enum cmd_status cmd_kill(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_layout(int argc, char **argv) { +enum cmd_status cmd_layout(char *criteria, int argc, char **argv) { if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0) || config->reading || !config->active) { return CMD_FAILURE; @@ -741,7 +781,7 @@ static enum cmd_status cmd_layout(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_reload(int argc, char **argv) { +enum cmd_status cmd_reload(char *criteria, int argc, char **argv) { if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0) || config->reading || !load_config(NULL)) { @@ -751,7 +791,7 @@ static enum cmd_status cmd_reload(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_resize(int argc, char **argv) { +enum cmd_status cmd_resize(char *criteria, int argc, char **argv) { if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3) || config->reading || !config->active) { return CMD_FAILURE; @@ -781,7 +821,7 @@ static enum cmd_status cmd_resize(int argc, char **argv) { return CMD_SUCCESS; } -static swayc_t *fetch_view_from_scratchpad() { +static swayc_t *fetch_view_from_scratchpad(void) { if (sp_index >= scratchpad->length) { sp_index = 0; } @@ -826,7 +866,7 @@ void remove_view_from_scratchpad(swayc_t *view) { } } -static enum cmd_status cmd_scratchpad(int argc, char **argv) { +enum cmd_status cmd_scratchpad(char *criteria, int argc, char **argv) { if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1) || config->reading || !config->active) { return CMD_FAILURE; @@ -860,7 +900,7 @@ static int compare_set(const void *_l, const void *_r) { return strlen((*r)->name) - strlen((*l)->name); } -static enum cmd_status cmd_set(int argc, char **argv) { +enum cmd_status cmd_set(char *criteria, int argc, char **argv) { if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2) || !config->reading) { return CMD_FAILURE; @@ -883,11 +923,11 @@ static enum cmd_status cmd_set(int argc, char **argv) { list_add(config->symbols, var); list_sort(config->symbols, compare_set); } - var->value = join_args(argv + 1, argc - 1); + var->value = join_args(argc - 1, argv + 1); return CMD_SUCCESS; } -static enum cmd_status _do_split(int argc, char **argv, int layout) { +static enum cmd_status _do_split(char *criteria, int argc, char **argv, int layout) { char *name = layout == L_VERT ? "splitv" : layout == L_HORIZ ? "splith" : "split"; if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0) @@ -919,16 +959,16 @@ static enum cmd_status _do_split(int argc, char **argv, int layout) { return CMD_SUCCESS; } -static enum cmd_status cmd_split(int argc, char **argv) { +enum cmd_status cmd_split(char *criteria, int argc, char **argv) { if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1) || config->reading || !config->active) { return CMD_FAILURE; } if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { - _do_split(argc - 1, argv + 1, L_VERT); + _do_split(criteria, argc - 1, argv + 1, L_VERT); } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { - _do_split(argc - 1, argv + 1, L_HORIZ); + _do_split(criteria, argc - 1, argv + 1, L_HORIZ); } else { sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); return CMD_FAILURE; @@ -936,15 +976,15 @@ static enum cmd_status cmd_split(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_splitv(int argc, char **argv) { - return _do_split(argc, argv, L_VERT); +enum cmd_status cmd_splitv(char *criteria, int argc, char **argv) { + return _do_split(criteria, argc, argv, L_VERT); } -static enum cmd_status cmd_splith(int argc, char **argv) { - return _do_split(argc, argv, L_HORIZ); +enum cmd_status cmd_splith(char *criteria, int argc, char **argv) { + return _do_split(criteria, argc, argv, L_HORIZ); } -static enum cmd_status cmd_log_colors(int argc, char **argv) { +enum cmd_status cmd_log_colors(char *criteria, int argc, char **argv) { if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1) || !config->reading) { return CMD_FAILURE; @@ -960,7 +1000,7 @@ static enum cmd_status cmd_log_colors(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_fullscreen(int argc, char **argv) { +enum cmd_status cmd_fullscreen(char *criteria, int argc, char **argv) { if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0) || config->reading || !config->active) { return CMD_FAILURE; @@ -980,7 +1020,7 @@ static enum cmd_status cmd_fullscreen(int argc, char **argv) { return CMD_SUCCESS; } -static enum cmd_status cmd_workspace(int argc, char **argv) { +enum cmd_status cmd_workspace(char *criteria, int argc, char **argv) { if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { return CMD_FAILURE; } @@ -989,28 +1029,7 @@ static enum cmd_status cmd_workspace(int argc, char **argv) { if (config->reading || !config->active) { return CMD_DEFER; } - // Handle workspace next/prev - swayc_t *ws = NULL; - if (strcasecmp(argv[0], "next") == 0) { - ws = workspace_next(); - } else if (strcasecmp(argv[0], "prev") == 0) { - ws = workspace_prev(); - } else if (strcasecmp(argv[0], "next_on_output") == 0) { - ws = workspace_output_next(); - } else if (strcasecmp(argv[0], "prev_on_output") == 0) { - ws = workspace_output_prev(); - } else if (strcasecmp(argv[0], "back_and_forth") == 0) { - if (prev_workspace_name) { - if (!(ws = workspace_by_name(prev_workspace_name))) { - ws = workspace_create(prev_workspace_name); - } - } - } else { - if (!(ws= workspace_by_name(argv[0]))) { - ws = workspace_create(argv[0]); - } - } - workspace_switch(ws); + workspace_switch(new_workspace(NULL, argv[0])); } else { if (strcasecmp(argv[1], "output") == 0) { if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3)) { @@ -1021,15 +1040,12 @@ static enum cmd_status cmd_workspace(int argc, char **argv) { wso->workspace = strdup(argv[0]); wso->output = strdup(argv[2]); list_add(config->workspace_outputs, wso); - if (!config->reading) { - // TODO: Move workspace to output. (dont do so when reloading) - } } } return CMD_SUCCESS; } -static enum cmd_status cmd_ws_auto_back_and_forth(int argc, char **argv) { +enum cmd_status cmd_ws_auto_back_and_forth(char *criteria, int argc, char **argv) { if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { return CMD_FAILURE; } @@ -1044,7 +1060,7 @@ static enum cmd_status cmd_ws_auto_back_and_forth(int argc, char **argv) { } /* Keep alphabetized */ -static struct cmd_handler handlers[] = { +static const struct cmd_handler handlers[] = { { "bindsym", cmd_bindsym }, { "default_orientation", cmd_orientation }, { "exec", cmd_exec }, @@ -1054,6 +1070,7 @@ static struct cmd_handler handlers[] = { { "floating_modifier", cmd_floating_mod }, { "focus", cmd_focus }, { "focus_follows_mouse", cmd_focus_follows_mouse }, + { "for_window", cmd_for_window }, { "fullscreen", cmd_fullscreen }, { "gaps", cmd_gaps }, { "kill", cmd_kill }, @@ -1090,6 +1107,7 @@ static struct cmd_handler *find_handler(char *line) { enum cmd_status handle_command(char *exec) { sway_log(L_INFO, "Handling command '%s'", exec); int argc; + char *criteria = NULL; char **argv = split_args(exec, &argc); enum cmd_status status = CMD_FAILURE; struct cmd_handler *handler; @@ -1097,7 +1115,7 @@ enum cmd_status handle_command(char *exec) { return status; } if ((handler = find_handler(argv[0])) == NULL - || (status = handler->handle(argc - 1, argv + 1)) != CMD_SUCCESS) { + || (status = handler->handle(criteria, argc - 1, argv + 1)) != CMD_SUCCESS) { sway_log(L_ERROR, "Command failed: %s", argv[0]); } free_argv(argc, argv); @@ -1108,6 +1126,7 @@ enum cmd_status config_command(char *exec) { sway_log(L_INFO, "handling config command '%s'", exec); int argc; char **argv = split_args(exec, &argc); + char *criteria = NULL; enum cmd_status status = CMD_FAILURE; struct cmd_handler *handler; if (!argc) { @@ -1127,7 +1146,7 @@ enum cmd_status config_command(char *exec) { for (; i < e; ++i) { argv[i] = do_var_replacement(argv[i]); } - status = handler->handle(argc - 1, argv + 1); + status = handler->handle(criteria, argc - 1, argv + 1); if (status == CMD_FAILURE) { sway_log(L_ERROR, "Config load failed for line `%s'", exec); } else if (status == CMD_DEFER) { diff --git a/sway/config.c b/sway/config.c index 23d6ac0d..da92030e 100644 --- a/sway/config.c +++ b/sway/config.c @@ -286,3 +286,28 @@ char *do_var_replacement(char *str) { } return str; } + +struct workspace_output *wsop_find_workspace(const char *name) { + int i, len = config->workspace_outputs->length; + struct workspace_output *wsop; + for (i = 0; i < len; ++i) { + wsop = config->workspace_outputs->items[i]; + if (strcasecmp(wsop->workspace, name) == 0) { + return wsop; + } + } + return NULL; +} + +struct workspace_output *wsop_find_output(const char *name) { + int i, len = config->workspace_outputs->length; + struct workspace_output *wsop; + for (i = 0; i < len; ++i) { + wsop = config->workspace_outputs->items[i]; + if (strcasecmp(wsop->output, name) == 0) { + return wsop; + } + } + return NULL; +} + diff --git a/sway/container.c b/sway/container.c index ef0e6c55..baf84378 100644 --- a/sway/container.c +++ b/sway/container.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <stdbool.h> #include <strings.h> +#include <pcre.h> #include "config.h" #include "container.h" #include "workspace.h" @@ -53,26 +54,30 @@ static void free_swayc(swayc_t *cont) { // New containers swayc_t *new_output(wlc_handle handle) { - const struct wlc_size *size = wlc_output_get_resolution(handle); const char *name = wlc_output_get_name(handle); + int i, len; + // Find current outputs to see if this already exists - { - int i, len = root_container.children->length; + if (name) { + len = root_container.children->length; for (i = 0; i < len; ++i) { swayc_t *op = root_container.children->items[i]; - const char *op_name = op->name; - if (op_name && name && strcmp(op_name, name) == 0) { - sway_log(L_DEBUG, "restoring output %lu:%s", handle, op_name); + if (strcmp(op->name, name) == 0) { + sway_log(L_DEBUG, "restoring output %lu:%s", handle, op->name); return op; } } + } else { + sway_log(L_ERROR, "Output has no given name"); + return NULL; } - sway_log(L_DEBUG, "Added output %lu:%s", handle, name); + sway_log(L_DEBUG, "Adding output %lu:%s", handle, name); + // Find output config struct output_config *oc = NULL; - int i; - for (i = 0; i < config->output_configs->length; ++i) { + len = config->output_configs->length; + for (i = 0; i < len; ++i) { oc = config->output_configs->items[i]; if (strcasecmp(name, oc->name) == 0) { sway_log(L_DEBUG, "Matched output config for %s", name); @@ -86,77 +91,88 @@ swayc_t *new_output(wlc_handle handle) { } swayc_t *output = new_swayc(C_OUTPUT); - if (oc && oc->width != -1 && oc->height != -1) { - output->width = oc->width; - output->height = oc->height; - struct wlc_size new_size = { .w = oc->width, .h = oc->height }; - wlc_output_set_resolution(handle, &new_size); - } else { - output->width = size->w; - output->height = size->h; - } output->handle = handle; output->name = name ? strdup(name) : NULL; - - // Find position for it - if (oc && oc->x != -1 && oc->y != -1) { - sway_log(L_DEBUG, "Set %s position to %d, %d", name, oc->x, oc->y); - output->x = oc->x; - output->y = oc->y; - } else { - int x = 0; - for (i = 0; i < root_container.children->length; ++i) { - swayc_t *c = root_container.children->items[i]; - if (c->type == C_OUTPUT) { - if (c->width + c->x > x) { - x = c->width + c->x; - } - } - } - output->x = x; - } - add_child(&root_container, output); - - // Create workspace - char *ws_name = NULL; - if (name) { - for (i = 0; i < config->workspace_outputs->length; ++i) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->output, name) == 0) { - sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); - // Check if any other workspaces are using this name - if (workspace_by_name(wso->workspace)) { - sway_log(L_DEBUG, "But it's already taken"); - break; + if (oc) { + // Set output width/height + if (oc->width > 0 && oc->height > 0) { + output->width = oc->width; + output->height = oc->height; + struct wlc_size geo = { .w = oc->width, .h = oc->height}; + wlc_output_set_resolution(handle, &geo); + } else { + struct wlc_size geo = *wlc_output_get_resolution(handle); + output->width = geo.w; + output->height = geo.h; + } + // find position in config or find where it should go + // TODO more intelligent method + if (oc->x > 0 && oc->y > 0) { + output->x = oc->x; + output->y = oc->y; + } else { + unsigned int x = 0; + len = root_container.children->length; + for (i = 0; i < len; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c->type == C_OUTPUT) { + unsigned int cx = c->width + c->x; + if (cx > x) { + x = cx; + } } - sway_log(L_DEBUG, "So we're going to use it"); - ws_name = strdup(wso->workspace); - break; } + output->x = x; } } - if (!ws_name) { - ws_name = workspace_next_name(); - } + // Add as child to root + add_child(&root_container, output); // create and initilize default workspace - swayc_t *ws = new_workspace(output, ws_name); + swayc_t *ws = new_workspace(output, NULL); ws->is_focused = true; - free(ws_name); - return output; } swayc_t *new_workspace(swayc_t *output, const char *name) { - if (!ASSERT_NONNULL(output)) { - return NULL; + swayc_t *ws = NULL; + struct workspace_output *wsop; + if (name) { + // Find existing workspace with same name. + // or workspace found by special name + if ((ws = workspace_by_name(name))) { + return ws; + } + // Find matching output from config + if (!output) { + if ((wsop = wsop_find_workspace(name))) { + int i, len = root_container.children->length; + for (i = 0; i < len; ++i) { + swayc_t *op = root_container.children->items[i]; + if (strcasecmp(op->name, wsop->output) == 0) { + output = op; + goto find_wsop_end; + } + } + } + // Set output to active_output if there is no output. + output = swayc_active_output(); + find_wsop_end:; + } + } else { + // No name or output, use active_output + if (!output) { + output = swayc_active_output(); + } + // search for available output name + if (!(name = workspace_output_open_name(output))) { + // otherwise just use simple next name + name = workspace_next_name(); |
