diff options
author | Drew DeVault <sir@cmpwn.com> | 2015-09-12 10:29:11 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2015-09-12 10:29:11 -0400 |
commit | 9c8f1fb9649c5673cd6b42230c0784f099a62db7 (patch) | |
tree | bb5eccfddb8b8d56e387327908490daeca2c42a7 | |
parent | Merge pull request #177 from taiyu-len/master (diff) | |
parent | visible values (diff) | |
download | sway-9c8f1fb9649c5673cd6b42230c0784f099a62db7.tar.gz sway-9c8f1fb9649c5673cd6b42230c0784f099a62db7.tar.zst sway-9c8f1fb9649c5673cd6b42230c0784f099a62db7.zip |
Merge pull request #179 from taiyu-len/master
new_workspace null behavior + testmap functions + regex
-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 @@ | |||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include "config.h" | 4 | #include "config.h" |
5 | 5 | ||
6 | typedef enum cmd_status { | ||
7 | CMD_SUCCESS, | ||
8 | CMD_FAILURE, | ||
9 | CMD_DEFER, | ||
10 | } sway_cmd(char *criteria, int argc, char **argv); | ||
11 | |||
6 | struct cmd_handler { | 12 | struct cmd_handler { |
7 | char *command; | 13 | const char*command; |
8 | enum cmd_status { | 14 | sway_cmd *handle; |
9 | CMD_SUCCESS, | ||
10 | CMD_FAILURE, | ||
11 | CMD_DEFER, | ||
12 | } (*handle)(int argc, char **argv); | ||
13 | }; | 15 | }; |
14 | 16 | ||
15 | enum cmd_status handle_command(char *command); | 17 | enum cmd_status handle_command(char *command); |
16 | // Handles commands during config | 18 | // Handles commands during config |
17 | enum cmd_status config_command(char *command); | 19 | enum cmd_status config_command(char *command); |
18 | 20 | ||
19 | void remove_view_from_scratchpad(); | 21 | void remove_view_from_scratchpad(swayc_t *view); |
20 | 22 | ||
21 | #endif | 23 | #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); | |||
63 | bool read_config(FILE *file, bool is_active); | 63 | bool read_config(FILE *file, bool is_active); |
64 | char *do_var_replacement(char *str); | 64 | char *do_var_replacement(char *str); |
65 | 65 | ||
66 | // Find workspace_output from config by workspace or output name | ||
67 | struct workspace_output *wsop_find_workspace(const char *); | ||
68 | struct workspace_output *wsop_find_output(const char *); | ||
69 | |||
66 | extern struct sway_config *config; | 70 | extern struct sway_config *config; |
67 | 71 | ||
68 | #endif | 72 | #endif |
diff --git a/include/container.h b/include/container.h index a9b95229..b164af95 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -2,29 +2,25 @@ | |||
2 | #define _SWAY_CONTAINER_H | 2 | #define _SWAY_CONTAINER_H |
3 | #include <wlc/wlc.h> | 3 | #include <wlc/wlc.h> |
4 | typedef struct sway_container swayc_t; | 4 | typedef struct sway_container swayc_t; |
5 | |||
6 | #include "layout.h" | 5 | #include "layout.h" |
7 | 6 | ||
8 | enum swayc_types{ | 7 | enum swayc_types { |
9 | C_ROOT, | 8 | C_ROOT = 1 << 0, |
10 | C_OUTPUT, | 9 | C_OUTPUT = 1 << 1, |
11 | C_WORKSPACE, | 10 | C_WORKSPACE = 1 << 2, |
12 | C_CONTAINER, | 11 | C_CONTAINER = 1 << 3, |
13 | C_VIEW, | 12 | C_VIEW = 1 << 4, |
14 | // Keep last | 13 | C_TYPES = 5, |
15 | C_TYPES, | ||
16 | }; | 14 | }; |
17 | 15 | ||
18 | 16 | enum swayc_layouts { | |
19 | enum swayc_layouts{ | 17 | L_NONE = 1 << 0, |
20 | L_NONE, | 18 | L_HORIZ = 1 << 1, |
21 | L_HORIZ, | 19 | L_VERT = 1 << 2, |
22 | L_VERT, | 20 | L_STACKED = 1 << 3, |
23 | L_STACKED, | 21 | L_TABBED = 1 << 4, |
24 | L_TABBED, | 22 | L_FLOATING = 1 << 5, |
25 | L_FLOATING, | 23 | L_LAYOUTS = 6, |
26 | // Keep last | ||
27 | L_LAYOUTS, | ||
28 | }; | 24 | }; |
29 | 25 | ||
30 | struct sway_container { | 26 | struct sway_container { |
@@ -35,13 +31,16 @@ struct sway_container { | |||
35 | 31 | ||
36 | // Not including borders or margins | 32 | // Not including borders or margins |
37 | double width, height; | 33 | double width, height; |
34 | double x, y; | ||
38 | 35 | ||
39 | // Used for setting floating geometry | 36 | // Used for setting floating geometry |
40 | int desired_width, desired_height; | 37 | int desired_width, desired_height; |
41 | 38 | ||
42 | double x, y; | 39 | enum visibility_mask { |
40 | INVISIBLE = false, | ||
41 | VISIBLE = true, | ||
42 | } visible; | ||
43 | 43 | ||
44 | bool visible; | ||
45 | bool is_floating; | 44 | bool is_floating; |
46 | bool is_focused; | 45 | bool is_focused; |
47 | 46 | ||
@@ -56,70 +55,120 @@ struct sway_container { | |||
56 | struct sway_container *focused; | 55 | struct sway_container *focused; |
57 | }; | 56 | }; |
58 | 57 | ||
59 | enum visibility_mask { | 58 | // swayc Creation |
60 | VISIBLE = 1 | ||
61 | }; | ||
62 | |||
63 | // Container Creation | ||
64 | 59 | ||
60 | /* Creates and returns new, or an already created output. | ||
61 | * If it creates a new output, it also creates a workspace using | ||
62 | * `new_workspace(outputname, NULL);` */ | ||
65 | swayc_t *new_output(wlc_handle handle); | 63 | swayc_t *new_output(wlc_handle handle); |
64 | |||
65 | /* Creates workspace with given name, under given output. | ||
66 | * If workspace with that name already exists, returns that workspace | ||
67 | * If name is NULL, it will choose a name automatically. | ||
68 | * If output is NULL, it will choose an output automatically. */ | ||
66 | swayc_t *new_workspace(swayc_t *output, const char *name); | 69 | swayc_t *new_workspace(swayc_t *output, const char *name); |
70 | |||
67 | // Creates container Around child (parent child) -> (parent (container child)) | 71 | // Creates container Around child (parent child) -> (parent (container child)) |
68 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); | 72 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); |
73 | |||
69 | // Creates view as a sibling of current focused container, or as child of a workspace | 74 | // Creates view as a sibling of current focused container, or as child of a workspace |
70 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle); | 75 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle); |
76 | |||
71 | // Creates view as a new floating view which is in the active workspace | 77 | // Creates view as a new floating view which is in the active workspace |
72 | swayc_t *new_floating_view(wlc_handle handle); | 78 | swayc_t *new_floating_view(wlc_handle handle); |
73 | 79 | ||
74 | // Container Destroying | 80 | // Container Destroying |
75 | 81 | // Destroys output and moves workspaces to another output | |
76 | swayc_t *destroy_output(swayc_t *output); | 82 | swayc_t *destroy_output(swayc_t *output); |
83 | |||
77 | // Destroys workspace if empty and returns parent pointer, else returns NULL | 84 | // Destroys workspace if empty and returns parent pointer, else returns NULL |
78 | swayc_t *destroy_workspace(swayc_t *workspace); | 85 | swayc_t *destroy_workspace(swayc_t *workspace); |
86 | |||
79 | // Destroyes container and all parent container if they are empty, returns | 87 | // Destroyes container and all parent container if they are empty, returns |
80 | // topmost non-empty parent. returns NULL otherwise | 88 | // topmost non-empty parent. returns NULL otherwise |
81 | swayc_t *destroy_container(swayc_t *container); | 89 | swayc_t *destroy_container(swayc_t *container); |
90 | |||
82 | // Destroys view and all empty parent containers. return topmost non-empty | 91 | // Destroys view and all empty parent containers. return topmost non-empty |
83 | // parent | 92 | // parent |
84 | swayc_t *destroy_view(swayc_t *view); | 93 | swayc_t *destroy_view(swayc_t *view); |
85 | 94 | ||
86 | // Container Lookup | 95 | // Container Mapping and testing functions |
96 | typedef bool swayc_test_func(swayc_t *view, void *data); | ||
97 | typedef void swayc_map_func(swayc_t *view, void *data); | ||
98 | |||
99 | // Returns the first swayc that matches test() | ||
100 | swayc_t *swayc_by_test_r(swayc_t *root, swayc_test_func test, void *data); | ||
101 | swayc_t *swayc_by_test(swayc_test_func test, void *data); | ||
102 | |||
103 | // Calls func for all children. | ||
104 | void swayc_map_r(swayc_t *root, swayc_map_func func, void *data); | ||
105 | void swayc_map(swayc_map_func func, void *data); | ||
106 | |||
107 | |||
108 | // Call func on container if test passes | ||
109 | void swayc_map_by_test_r(swayc_t *root, | ||
110 | swayc_map_func func, swayc_test_func test, | ||
111 | void *funcdata, void *testdata); | ||
112 | void swayc_map_by_test( | ||
113 | swayc_map_func func, swayc_test_func test, | ||
114 | void *funcdata, void *testdata); | ||
115 | |||
116 | // Map functions | ||
117 | swayc_map_func set_gaps; | ||
118 | swayc_map_func add_gaps; | ||
119 | |||
120 | // Test functions | ||
121 | // generic swayc tests | ||
122 | swayc_test_func test_name; | ||
123 | swayc_test_func test_name_regex; | ||
124 | swayc_test_func test_layout; | ||
125 | swayc_test_func test_type; | ||
126 | swayc_test_func test_visibility; | ||
127 | swayc_test_func test_handle; | ||
128 | |||
129 | // C_VIEW tests | ||
130 | // See wlc_view_*_bit enums | ||
131 | swayc_test_func test_view_state; | ||
132 | swayc_test_func test_view_type; | ||
133 | swayc_test_func test_view_title; | ||
134 | swayc_test_func test_view_class; | ||
135 | swayc_test_func test_view_appid; | ||
136 | swayc_test_func test_view_title_regex; | ||
137 | swayc_test_func test_view_class_regex; | ||
138 | swayc_test_func test_view_appid_regex; | ||
139 | |||
140 | // functions for test_*_regex | ||
141 | void *compile_regex(const char *regex); | ||
142 | void free_regex(void *); | ||
143 | |||
144 | // these take a NULL terminated array of test_list struct. | ||
145 | struct test_list { swayc_test_func *test; void *data ; }; | ||
146 | swayc_test_func test_and; | ||
147 | swayc_test_func test_or; | ||
87 | 148 | ||
88 | swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); | ||
89 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); | 149 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); |
90 | swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); | 150 | swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); |
91 | // Follow focused until type/layout | 151 | // Follow focused until type/layout |
92 | swayc_t *swayc_focus_by_type(swayc_t *container, enum swayc_types); | 152 | swayc_t *swayc_focus_by_type(swayc_t *container, enum swayc_types); |
93 | swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts); | 153 | swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts); |
94 | 154 | ||
95 | |||
96 | swayc_t *swayc_by_handle(wlc_handle handle); | ||
97 | swayc_t *swayc_by_name(const char *name); | ||
98 | swayc_t *swayc_active_output(void); | 155 | swayc_t *swayc_active_output(void); |
99 | swayc_t *swayc_active_workspace(void); | 156 | swayc_t *swayc_active_workspace(void); |
100 | swayc_t *swayc_active_workspace_for(swayc_t *view); | 157 | swayc_t *swayc_active_workspace_for(swayc_t *view); |
101 | 158 | ||
102 | // Container information | 159 | // Container information |
103 | 160 | // if `parent` is the parent of `child` | |
104 | bool swayc_is_fullscreen(swayc_t *view); | ||
105 | bool swayc_is_active(swayc_t *view); | ||
106 | // Is `parent` the parent of `child` | ||
107 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child); | 161 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child); |
108 | // Is `child` a child of `parent` | 162 | // If `child` is a child of `parent` |
109 | bool swayc_is_child_of(swayc_t *child, swayc_t *parent); | 163 | bool swayc_is_child_of(swayc_t *child, swayc_t *parent); |
110 | // Return gap of specified container | 164 | // Return gap of specified container |
111 | int swayc_gap(swayc_t *container); | 165 | int swayc_gap(swayc_t *container); |
112 | 166 | ||
113 | // Mapping functions | 167 | bool swayc_is_fullscreen(swayc_t *view); |
114 | 168 | bool swayc_is_active(swayc_t *view); | |
115 | void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); | ||
116 | 169 | ||
117 | // Mappings | ||
118 | void set_view_visibility(swayc_t *view, void *data); | ||
119 | // Set or add to gaps | ||
120 | void set_gaps(swayc_t *view, void *amount); | ||
121 | void add_gaps(swayc_t *view, void *amount); | ||
122 | 170 | ||
171 | // Specialized mapping functions | ||
123 | void update_visibility(swayc_t *container); | 172 | void update_visibility(swayc_t *container); |
124 | 173 | ||
125 | #endif | 174 | #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); | |||
19 | char *code_strchr(const char *string, char delimiter); | 19 | char *code_strchr(const char *string, char delimiter); |
20 | char *code_strstr(const char *haystack, const char *needle); | 20 | char *code_strstr(const char *haystack, const char *needle); |
21 | int unescape_string(char *string); | 21 | int unescape_string(char *string); |
22 | char *join_args(char **argv, int argc); | 22 | char *join_args(int argc, char **argv); |
23 | char *join_list(list_t *list, char *separator); | 23 | char *join_list(list_t *list, char *separator); |
24 | 24 | ||
25 | char *strdup(const char *); | 25 | 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 @@ | |||
7 | 7 | ||
8 | extern char *prev_workspace_name; | 8 | extern char *prev_workspace_name; |
9 | 9 | ||
10 | char *workspace_next_name(void); | 10 | // Search for available workspace name on output from config |
11 | swayc_t *workspace_create(const char*); | 11 | const char *workspace_output_open_name(swayc_t *output); |
12 | // Search for any available workspace name | ||
13 | const char *workspace_next_name(void); | ||
14 | |||
15 | |||
12 | swayc_t *workspace_by_name(const char*); | 16 | swayc_t *workspace_by_name(const char*); |
13 | void workspace_switch(swayc_t*); | 17 | void workspace_switch(swayc_t*); |
14 | swayc_t *workspace_output_next(); | 18 | swayc_t *workspace_output_next(void); |
15 | swayc_t *workspace_next(); | 19 | swayc_t *workspace_next(void); |
16 | swayc_t *workspace_output_prev(); | 20 | swayc_t *workspace_output_prev(void); |
17 | swayc_t *workspace_prev(); | 21 | swayc_t *workspace_prev(void); |
18 | 22 | ||
19 | #endif | 23 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index e79746ae..3ed0c8db 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -21,6 +21,35 @@ | |||
21 | swayc_t *sp_view; | 21 | swayc_t *sp_view; |
22 | int sp_index = 0; | 22 | int sp_index = 0; |
23 | 23 | ||
24 | // Commands | ||
25 | static sway_cmd cmd_bindsym; | ||
26 | static sway_cmd cmd_orientation; | ||
27 | static sway_cmd cmd_exec; | ||
28 | static sway_cmd cmd_exec_always; | ||
29 | static sway_cmd cmd_exit; | ||
30 | static sway_cmd cmd_floating; | ||
31 | static sway_cmd cmd_floating_mod; | ||
32 | static sway_cmd cmd_focus; | ||
33 | static sway_cmd cmd_focus_follows_mouse; | ||
34 | static sway_cmd cmd_for_window; | ||
35 | static sway_cmd cmd_fullscreen; | ||
36 | static sway_cmd cmd_gaps; | ||
37 | static sway_cmd cmd_kill; | ||
38 | static sway_cmd cmd_layout; | ||
39 | static sway_cmd cmd_log_colors; | ||
40 | static sway_cmd cmd_mode; | ||
41 | static sway_cmd cmd_move; | ||
42 | static sway_cmd cmd_output; | ||
43 | static sway_cmd cmd_reload; | ||
44 | static sway_cmd cmd_resize; | ||
45 | static sway_cmd cmd_scratchpad; | ||
46 | static sway_cmd cmd_set; | ||
47 | static sway_cmd cmd_split; | ||
48 | static sway_cmd cmd_splith; | ||
49 | static sway_cmd cmd_splitv; | ||
50 | static sway_cmd cmd_workspace; | ||
51 | static sway_cmd cmd_ws_auto_back_and_forth; | ||
52 | |||
24 | static struct modifier_key { | 53 | static struct modifier_key { |
25 | char *name; | 54 | char *name; |
26 | uint32_t mod; | 55 | uint32_t mod; |
@@ -94,7 +123,7 @@ static int bindsym_sort(const void *_lbind, const void *_rbind) { | |||
94 | return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); | 123 | return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); |
95 | } | 124 | } |
96 | 125 | ||
97 | static enum cmd_status cmd_bindsym(int argc, char **argv) { | 126 | enum cmd_status cmd_bindsym(char *criteria, int argc, char **argv) { |
98 | if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1) | 127 | if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1) |
99 | || !config->reading) { | 128 | || !config->reading) { |
100 | return CMD_FAILURE; | 129 | return CMD_FAILURE; |
@@ -103,7 +132,7 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) { | |||
103 | struct sway_binding *binding = malloc(sizeof(struct sway_binding)); | 132 | struct sway_binding *binding = malloc(sizeof(struct sway_binding)); |
104 | binding->keys = create_list(); | 133 | binding->keys = create_list(); |
105 | binding->modifiers = 0; | 134 | binding->modifiers = 0; |
106 | binding->command = join_args(argv + 1, argc - 1); | 135 | binding->command = join_args(argc - 1, argv + 1); |
107 | 136 | ||
108 | list_t *split = split_string(argv[0], "+"); | 137 | list_t *split = split_string(argv[0], "+"); |
109 | int i; | 138 | int i; |
@@ -144,7 +173,7 @@ static enum cmd_status cmd_bindsym(int argc, char **argv) { | |||
144 | return CMD_SUCCESS; | 173 | return CMD_SUCCESS; |
145 | } | 174 | } |
146 | 175 | ||
147 | static enum cmd_status cmd_exec_always(int argc, char **argv) { | 176 | enum cmd_status cmd_exec_always(char *criteria, int argc, char **argv) { |
148 | if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { | 177 | if (!checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0)) { |
149 | return CMD_FAILURE; | 178 | return CMD_FAILURE; |
150 | } | 179 | } |
@@ -160,7 +189,7 @@ static enum cmd_status cmd_exec_always(int argc, char **argv) { | |||
160 | } | 189 | } |
161 | /* Child process */ | 190 | /* Child process */ |
162 | if (pid == 0) { | 191 | if (pid == 0) { |
163 | char *args = join_args(argv, argc); | 192 | char *args = join_args(argc, argv); |
164 | sway_log(L_DEBUG, "Executing %s", args); | 193 | sway_log(L_DEBUG, "Executing %s", args); |
165 | execl("/bin/sh", "sh", "-c", args, (char *)NULL); | 194 | execl("/bin/sh", "sh", "-c", args, (char *)NULL); |
166 | /* Execl doesnt return unless failure */ | 195 | /* Execl doesnt return unless failure */ |
@@ -172,17 +201,17 @@ static enum cmd_status cmd_exec_always(int argc, char **argv) { | |||
172 | return CMD_SUCCESS; | 201 | return CMD_SUCCESS; |
173 | } | 202 | } |
174 | 203 | ||
175 | static enum cmd_status cmd_exec(int argc, char **argv) { | 204 | enum cmd_status cmd_exec(char *criteria, int argc, char **argv) { |
176 | if (!config->active) { | 205 | if (!config->active) { |
177 | return CMD_DEFER; | 206 | return CMD_DEFER; |
178 | } | 207 | } |
179 | if (config->reloading) { | 208 | if (config->reloading) { |
180 | char *args = join_args(argv, argc); | 209 | char *args = join_args(argc, argv); |
181 | sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); | 210 | sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); |
182 | free(args); | 211 | free(args); |
183 | return CMD_SUCCESS; | 212 | return CMD_SUCCESS; |
184 | } | 213 | } |
185 | return cmd_exec_always(argc, argv); | 214 | return cmd_exec_always(criteria, argc, argv); |
186 | } | 215 | } |
187 | 216 | ||
188 | static void kill_views(swayc_t *container, void *data) { | 217 | static void kill_views(swayc_t *container, void *data) { |
@@ -191,18 +220,19 @@ static void kill_views(swayc_t *container, void *data) { | |||
191 | } | 220 | } |
192 | } | 221 | } |
193 | 222 | ||
194 | static enum cmd_status cmd_exit(int argc, char **argv) { | 223 | enum cmd_status cmd_exit(char *criteria, int argc, char **argv) { |
224 | (void) argv; | ||
195 | if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0) | 225 | if (!checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0) |
196 | || config->reading || !config->active) { | 226 | || config->reading || !config->active) { |
197 | return CMD_FAILURE; | 227 | return CMD_FAILURE; |
198 | } | 228 | } |
199 | // Close all views | 229 | // Close all views |
200 | container_map(&root_container, kill_views, NULL); | 230 | swayc_map(kill_views, NULL); |
201 | sway_terminate(); | 231 | sway_terminate(); |
202 | return CMD_SUCCESS; | 232 | return CMD_SUCCESS; |
203 | } | 233 | } |
204 | 234 | ||
205 | static enum cmd_status cmd_floating(int argc, char **argv) { | 235 | enum cmd_status cmd_floating(char *criteria, int argc, char **argv) { |
206 | if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1) | 236 | if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1) |
207 | || config->reading || !config->active) { | 237 | || config->reading || !config->active) { |
208 | return CMD_FAILURE; | 238 | return CMD_FAILURE; |
@@ -264,7 +294,7 @@ static enum cmd_status cmd_floating(int argc, char **argv) { | |||
264 | return CMD_SUCCESS; | 294 | return CMD_SUCCESS; |
265 | } | 295 | } |
266 | 296 | ||
267 | static enum cmd_status cmd_floating_mod(int argc, char **argv) { | 297 | enum cmd_status cmd_floating_mod(char *criteria, int argc, char **argv) { |
268 | if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1) | 298 | if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1) |
269 | || !config->reading) { | 299 | || !config->reading) { |
270 | return CMD_FAILURE; | 300 | return CMD_FAILURE; |
@@ -289,7 +319,7 @@ static enum cmd_status cmd_floating_mod(int argc, char **argv) { | |||
289 | return CMD_SUCCESS; | 319 | return CMD_SUCCESS; |
290 | } | 320 | } |
291 | 321 | ||
292 | static enum cmd_status cmd_focus(int argc, char **argv) { | 322 | enum cmd_status cmd_focus(char *criteria, int argc, char **argv) { |
293 | static int floating_toggled_index = 0; | 323 | static int floating_toggled_index = 0; |
294 | static int tiled_toggled_index = 0; | 324 | static int tiled_toggled_index = 0; |
295 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1) | 325 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1) |
@@ -347,7 +377,7 @@ static enum cmd_status cmd_focus(int argc, char **argv) { | |||
347 | return CMD_SUCCESS; | 377 | return CMD_SUCCESS; |
348 | } | 378 | } |
349 | 379 | ||
350 | static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) { | 380 | enum cmd_status cmd_focus_follows_mouse(char *criteria, int argc, char **argv) { |
351 | if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { | 381 | if (!checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1)) { |
352 | return CMD_FAILURE; | 382 | return CMD_FAILURE; |
353 | } | 383 | } |
@@ -356,6 +386,21 @@ static enum cmd_status cmd_focus_follows_mouse(int argc, char **argv) { | |||
356 | return CMD_SUCCESS; | 386 | return CMD_SUCCESS; |
357 | } | 387 | } |
358 | 388 | ||
389 | static void debug_for_window(swayc_t *view, void *data) { | ||
390 | layout_log(view, 0); | ||
391 | } | ||
392 | |||
393 | enum cmd_status cmd_for_window(char *criteria, int argc, char **argv) { | ||
394 | if (!checkarg(argc, "for_window", EXPECTED_AT_LEAST, 1)) { | ||
395 | return CMD_FAILURE; | ||
396 | } | ||
397 | //TODO | ||
398 | void *re = compile_regex(argv[0]); | ||
399 | swayc_map_by_test(debug_for_window, test_view_title_regex, NULL, re); | ||
400 | free_regex(re); | ||
401 | return CMD_FAILURE; | ||
402 | } | ||
403 | |||
359 | static void hide_view_in_scratchpad(swayc_t *sp_view) { | 404 | static void hide_view_in_scratchpad(swayc_t *sp_view) { |
360 | if(sp_view == NULL) { | 405 | if(sp_view == NULL) { |
361 | return; | 406 | return; |
@@ -372,7 +417,7 @@ static void hide_view_in_scratchpad(swayc_t *sp_view) { | |||
372 | set_focused_container(container_under_pointer()); | 417 | set_focused_container(container_under_pointer()); |
373 | } | 418 | } |
374 | 419 | ||
375 | static enum cmd_status cmd_mode(int argc, char **argv) { | 420 | enum cmd_status cmd_mode(char *criteria, int argc, char **argv) { |
376 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { | 421 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1)) { |
377 | return CMD_FAILURE; | 422 | return CMD_FAILURE; |
378 | } | 423 | } |
@@ -381,7 +426,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { | |||
381 | return CMD_FAILURE; | 426 | return CMD_FAILURE; |
382 | } | 427 | } |
383 | 428 | ||
384 | char *mode_name = join_args(argv, argc - mode_make); | 429 | char *mode_name = join_args(argc - mode_make, argv); |
385 | struct sway_mode *mode = NULL; | 430 | struct sway_mode *mode = NULL; |
386 | // Find mode | 431 | // Find mode |
387 | int i, len = config->modes->length; | 432 | int i, len = config->modes->length; |
@@ -411,7 +456,7 @@ static enum cmd_status cmd_mode(int argc, char **argv) { | |||
411 | return CMD_SUCCESS; | 456 | return CMD_SUCCESS; |
412 | } | 457 | } |
413 | 458 | ||
414 | static enum cmd_status cmd_move(int argc, char **argv) { | 459 | enum cmd_status cmd_move(char *criteria, int argc, char **argv) { |
415 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1) | 460 | if (!checkarg(argc, "move", EXPECTED_AT_LEAST, 1) |
416 | || config->reading || !config->active) { | 461 | || config->reading || !config->active) { |
417 | return CMD_FAILURE; | 462 | return CMD_FAILURE; |
@@ -444,11 +489,7 @@ static enum cmd_status cmd_move(int argc, char **argv) { | |||
444 | // move "container to workspace number x" | 489 | // move "container to workspace number x" |
445 | ws_name = argv[4]; | 490 | ws_name = argv[4]; |
446 | } | 491 | } |
447 | 492 | swayc_t *ws = new_workspace(NULL, ws_name); | |
448 | swayc_t *ws = workspace_by_name(ws_name); | ||
449 | if (ws == NULL) { | ||
450 | ws = workspace_create(ws_name); | ||
451 | } | ||
452 | move_container_to(view, get_focused_container(ws)); | 493 | move_container_to(view, get_focused_container(ws)); |
453 | } else if (strcasecmp(argv[0], "scratchpad") == 0) { | 494 | } else if (strcasecmp(argv[0], "scratchpad") == 0) { |
454 | if (view->type != C_CONTAINER && view->type != C_VIEW) { | 495 | if (view->type != C_CONTAINER && view->type != C_VIEW) { |
@@ -482,7 +523,7 @@ static enum cmd_status cmd_move(int argc, char **argv) { | |||
482 | return CMD_SUCCESS; | 523 | return CMD_SUCCESS; |
483 | } | 524 | } |
484 | 525 | ||
485 | static enum cmd_status cmd_orientation(int argc, char **argv) { | 526 | enum cmd_status cmd_orientation(char *criteria, int argc, char **argv) { |
486 | if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1) | 527 | if (!checkarg(argc, "orientation", EXPECTED_EQUAL_TO, 1) |
487 | || !config->reading) { | 528 | || !config->reading) { |
488 | return CMD_FAILURE; | 529 | return CMD_FAILURE; |
@@ -499,7 +540,7 @@ static enum cmd_status cmd_orientation(int argc, char **argv) { | |||
499 | return CMD_SUCCESS; | 540 | return CMD_SUCCESS; |
500 | } | 541 | } |
501 | 542 | ||
502 | static enum cmd_status cmd_output(int argc, char **argv) { | 543 | enum cmd_status cmd_output(char *criteria, int argc, char **argv) { |
503 | if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { | 544 | if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { |
504 | return CMD_FAILURE; | 545 | return CMD_FAILURE; |
505 | } | 546 | } |
@@ -564,7 +605,7 @@ static enum cmd_status cmd_output(int argc, char **argv) { | |||
564 | return CMD_SUCCESS; | 605 | return CMD_SUCCESS; |
565 | } | 606 | } |
566 | 607 | ||
567 | static enum cmd_status cmd_gaps(int argc, char **argv) { | 608 | enum cmd_status cmd_gaps(char *criteria, int argc, char **argv) { |
568 | if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { | 609 | if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { |
569 | return CMD_FAILURE; | 610 | return CMD_FAILURE; |
570 | } | 611 | } |
@@ -698,15 +739,14 @@ static enum cmd_status cmd_gaps(int argc, char **argv) { | |||
698 | top = &root_container; | 739 | top = &root_container; |
699 | } | 740 | } |
700 | int top_gap = top->gaps; | 741 | int top_gap = top->gaps; |
701 | container_map(top, method == SET ? set_gaps : add_gaps, &amount); | 742 | swayc_map_r(top, method == SET ? set_gaps : add_gaps, &amount); |
702 | top->gaps = top_gap; | 743 | top->gaps = top_gap; |
703 | arrange_windows(top, -1, -1); | 744 | arrange_windows(top, -1, -1); |
704 | } | 745 | } |
705 | |||
706 | return CMD_SUCCESS; | 746 | return CMD_SUCCESS; |
707 | } | 747 | } |
708 | 748 | ||
709 | static enum cmd_status cmd_kill(int argc, char **argv) { | 749 | enum cmd_status cmd_kill(char *criteria, int argc, char **argv) { |
710 | if (config->reading || !config->active) { | 750 | if (config->reading || !config->active) { |
711 | return CMD_FAILURE; | 751 | return CMD_FAILURE; |
712 | } | 752 | } |
@@ -715,7 +755,7 @@ static enum cmd_status cmd_kill(int argc, char **argv) { | |||
715 | return CMD_SUCCESS; | 755 | return CMD_SUCCESS; |
716 | } | 756 | } |
717 | 757 | ||
718 | static enum cmd_status cmd_layout(int argc, char **argv) { | 758 | enum cmd_status cmd_layout(char *criteria, int argc, char **argv) { |
719 | if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0) | 759 | if (!checkarg(argc, "layout", EXPECTED_MORE_THAN, 0) |
720 | || config->reading || !config->active) { | 760 | || config->reading || !config->active) { |
721 | return CMD_FAILURE; | 761 | return CMD_FAILURE; |
@@ -741,7 +781,7 @@ static enum cmd_status cmd_layout(int argc, char **argv) { | |||
741 | return CMD_SUCCESS; | 781 | return CMD_SUCCESS; |
742 | } | 782 | } |
743 | 783 | ||
744 | static enum cmd_status cmd_reload(int argc, char **argv) { | 784 | enum cmd_status cmd_reload(char *criteria, int argc, char **argv) { |
745 | if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0) | 785 | if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0) |
746 | || config->reading | 786 | || config->reading |
747 | || !load_config(NULL)) { | 787 | || !load_config(NULL)) { |
@@ -751,7 +791,7 @@ static enum cmd_status cmd_reload(int argc, char **argv) { | |||
751 | return CMD_SUCCESS; | 791 | return CMD_SUCCESS; |
752 | } | 792 | } |
753 | 793 | ||
754 | static enum cmd_status cmd_resize(int argc, char **argv) { | 794 | enum cmd_status cmd_resize(char *criteria, int argc, char **argv) { |
755 | if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3) | 795 | if (!checkarg(argc, "resize", EXPECTED_AT_LEAST, 3) |
756 | || config->reading || !config->active) { | 796 | || config->reading || !config->active) { |
757 | return CMD_FAILURE; | 797 | return CMD_FAILURE; |
@@ -781,7 +821,7 @@ static enum cmd_status cmd_resize(int argc, char **argv) { | |||
781 | return CMD_SUCCESS; | 821 | return CMD_SUCCESS; |
782 | } | 822 | } |
783 | 823 | ||
784 | static swayc_t *fetch_view_from_scratchpad() { | 824 | static swayc_t *fetch_view_from_scratchpad(void) { |
785 | if (sp_index >= scratchpad->length) { | 825 | if (sp_index >= scratchpad->length) { |
786 | sp_index = 0; | 826 | sp_index = 0; |
787 | } | 827 | } |
@@ -826,7 +866,7 @@ void remove_view_from_scratchpad(swayc_t *view) { | |||
826 | } | 866 | } |
827 | } | 867 | } |
828 | 868 | ||
829 | static enum cmd_status cmd_scratchpad(int argc, char **argv) { | 869 | enum cmd_status cmd_scratchpad(char *criteria, int argc, char **argv) { |
830 | if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1) | 870 | if (!checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1) |
831 | || config->reading || !config->active) { | 871 | || config->reading || !config->active) { |
832 | return CMD_FAILURE; | 872 | return CMD_FAILURE; |
@@ -860,7 +900,7 @@ static int compare_set(const void *_l, const void *_r) { | |||
860 | return strlen((*r)->name) - strlen((*l)->name); | 900 | return strlen((*r)->name) - strlen((*l)->name); |
861 | } | 901 | } |
862 | 902 | ||
863 | static enum cmd_status cmd_set(int argc, char **argv) { | 903 | enum cmd_status cmd_set(char *criteria, int argc, char **argv) { |
864 | if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2) | 904 | if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2) |
865 | || !config->reading) { | 905 | || !config->reading) { |
866 | return CMD_FAILURE; | 906 | return CMD_FAILURE; |
@@ -883,11 +923,11 @@ static enum cmd_status cmd_set(int argc, char **argv) { | |||
883 | list_add(config->symbols, var); | 923 | list_add(config->symbols, var); |
884 | list_sort(config->symbols, compare_set); | 924 | list_sort(config->symbols, compare_set); |
885 | } | 925 | } |
886 | var->value = join_args(argv + 1, argc - 1); | 926 | var->value = join_args(argc - 1, argv + 1); |
887 | return CMD_SUCCESS; | 927 | return CMD_SUCCESS; |
888 | } | 928 | } |
889 | 929 | ||
890 | static enum cmd_status _do_split(int argc, char **argv, int layout) { | 930 | static enum cmd_status _do_split(char *criteria, int argc, char **argv, int layout) { |
891 | char *name = layout == L_VERT ? "splitv" : | 931 | char *name = layout == L_VERT ? "splitv" : |
892 | layout == L_HORIZ ? "splith" : "split"; | 932 | layout == L_HORIZ ? "splith" : "split"; |
893 | if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0) | 933 | if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0) |
@@ -919,16 +959,16 @@ static enum cmd_status _do_split(int argc, char **argv, int layout) { | |||
919 | return CMD_SUCCESS; | 959 | return CMD_SUCCESS; |
920 | } | 960 | } |
921 | 961 | ||
922 | static enum cmd_status cmd_split(int argc, char **argv) { | 962 | enum cmd_status cmd_split(char *criteria, int argc, char **argv) { |
923 | if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1) | 963 | if (!checkarg(argc, "split", EXPECTED_EQUAL_TO, 1) |
924 | || config->reading || !config->active) { | 964 | || config->reading || !config->active) { |
925 | return CMD_FAILURE; | 965 | return CMD_FAILURE; |
926 | } | 966 | } |
927 | 967 | ||
928 | if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { | 968 | if (strcasecmp(argv[0], "v") == 0 || strcasecmp(argv[0], "vertical") == 0) { |
929 | _do_split(argc - 1, argv + 1, L_VERT); | 969 | _do_split(criteria, argc - 1, argv + 1, L_VERT); |
930 | } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { | 970 | } else if (strcasecmp(argv[0], "h") == 0 || strcasecmp(argv[0], "horizontal") == 0) { |
931 | _do_split(argc - 1, argv + 1, L_HORIZ); | 971 | _do_split(criteria, argc - 1, argv + 1, L_HORIZ); |
932 | } else { | 972 | } else { |
933 | sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); | 973 | sway_log(L_ERROR, "Invalid split command (expected either horiziontal or vertical)."); |
934 | return CMD_FAILURE; | 974 | return CMD_FAILURE; |
@@ -936,15 +976,15 @@ static enum cmd_status cmd_split(int argc, char **argv) { | |||
936 | return CMD_SUCCESS; | 976 | return CMD_SUCCESS; |
937 | } | 977 | } |
938 | 978 | ||
939 | static enum cmd_status cmd_splitv(int argc, char **argv) { | 979 | enum cmd_status cmd_splitv(char *criteria, int argc, char **argv) { |
940 | return _do_split(argc, argv, L_VERT); | 980 | return _do_split(criteria, argc, argv, L_VERT); |
941 | } | 981 | } |
942 | 982 | ||
943 | static enum cmd_status cmd_splith(int argc, char **argv) { | 983 | enum cmd_status cmd_splith(char *criteria, int argc, char **argv) { |
944 | return _do_split(argc, argv, L_HORIZ); | 984 | return _do_split(criteria, argc, argv, L_HORIZ); |
945 | } | 985 | } |
946 | 986 | ||
947 | static enum cmd_status cmd_log_colors(int argc, char **argv) { | 987 | enum cmd_status cmd_log_colors(char *criteria, int argc, char **argv) { |
948 | if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1) | 988 | if (!checkarg(argc, "log_colors", EXPECTED_EQUAL_TO, 1) |
949 | || !config->reading) { | 989 | || !config->reading) { |
950 | return CMD_FAILURE; | 990 | return CMD_FAILURE; |
@@ -960,7 +1000,7 @@ static enum cmd_status cmd_log_colors(int argc, char **argv) { | |||
960 | return CMD_SUCCESS; | 1000 | return CMD_SUCCESS; |
961 | } | 1001 | } |
962 | 1002 | ||
963 | static enum cmd_status cmd_fullscreen(int argc, char **argv) { | 1003 | enum cmd_status cmd_fullscreen(char *criteria, int argc, char **argv) { |
964 | if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0) | 1004 | if (!checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0) |
965 | || config->reading || !config->active) { | 1005 | || config->reading || !config->active) { |
966 | return CMD_FAILURE; | 1006 | return CMD_FAILURE; |
@@ -980,7 +1020,7 @@ static enum cmd_status cmd_fullscreen(int argc, char **argv) { | |||
980 | return CMD_SUCCESS; | 1020 | return CMD_SUCCESS; |
981 | } | 1021 | } |
982 | 1022 | ||
983 | static enum cmd_status cmd_workspace(int argc, char **argv) { | 1023 | enum cmd_status cmd_workspace(char *criteria, int argc, char **argv) { |
984 | if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { | 1024 | if (!checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1)) { |
985 | return CMD_FAILURE; | 1025 | return CMD_FAILURE; |
986 | } | 1026 | } |
@@ -989,28 +1029,7 @@ static enum cmd_status cmd_workspace(int argc, char **argv) { | |||
989 | if (config->reading || !config->active) { | 1029 | if (config->reading || !config->active) { |
990 | return CMD_DEFER; | 1030 | return CMD_DEFER; |
991 | } | 1031 | } |
992 | // Handle workspace next/prev | 1032 | workspace_switch(new_workspace(NULL, argv[0])); |
993 | swayc_t *ws = NULL; | ||
994 | if (strcasecmp(argv[0], "next") == 0) { | ||
995 | ws = workspace_next(); | ||
996 | } else if (strcasecmp(argv[0], "prev") == 0) { | ||
997 | ws = workspace_prev(); | ||
998 | } else if (strcasecmp(argv[0], "next_on_output") == 0) { | ||
999 | ws = workspace_output_next(); | ||
1000 | } else if (strcasecmp(argv[0], "prev_on_output") == 0) { | ||
1001 | ws = workspace_output_prev(); | ||
1002 | } else if (strcasecmp(argv[0], "back_and_forth") == 0) { | ||
1003 | if (prev_workspace_name) { | ||
1004 | if (!(ws = workspace_by_name(prev_workspace_name))) { | ||
1005 | ws = workspace_create(prev_workspace_name); | ||
1006 | } | ||
1007 | } | ||
1008 | } else { | ||
1009 | if (!(ws= workspace_by_name(argv[0]))) { | ||
1010 | ws = workspace_create(argv[0]); | ||
1011 | } | ||
1012 | } | ||
1013 | workspace_switch(ws); | ||
1014 | } else { | 1033 | } else { |
1015 | if (strcasecmp(argv[1], "output") == 0) { | 1034 | if (strcasecmp(argv[1], "output") == 0) { |
1016 | if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3)) { | 1035 | if (!checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3)) { |
@@ -1021,15 +1040,12 @@ static enum cmd_status cmd_workspace(int argc, char **argv) { | |||
1021 | wso->workspace = strdup(argv[0]); | 1040 | wso->workspace = strdup(argv[0]); |
1022 | wso->output = strdup(argv[2]); | 1041 | wso->output = strdup(argv[2]); |
1023 | list_add(config->workspace_outputs, wso); | 1042 | list_add(config->workspace_outputs, wso); |
1024 | if (!config->reading) { | ||
1025 | // TODO: Move workspace to output. (dont do so when reloading) | ||
1026 | } | ||
1027 | } | 1043 | } |
1028 | } | 1044 | } |
1029 | return CMD_SUCCESS; | 1045 | return CMD_SUCCESS; |
1030 | } | 1046 | } |
1031 | 1047 | ||
1032 | static enum cmd_status cmd_ws_auto_back_and_forth(int argc, char **argv) { | 1048 | enum cmd_status cmd_ws_auto_back_and_forth(char *criteria, int argc, char **argv) { |
1033 | if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { | 1049 | if (!checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1)) { |
1034 | return CMD_FAILURE; | 1050 | return CMD_FAILURE; |
1035 | } | 1051 | } |
@@ -1044,7 +1060,7 @@ static enum cmd_status cmd_ws_auto_back_and_forth(int argc, char **argv) { | |||
1044 | } | 1060 | } |
1045 | 1061 | ||
1046 | /* Keep alphabetized */ | 1062 | /* Keep alphabetized */ |
1047 | static struct cmd_handler handlers[] = { | 1063 | static const struct cmd_handler handlers[] = { |
1048 | { "bindsym", cmd_bindsym }, | 1064 | { "bindsym", cmd_bindsym }, |
1049 | { "default_orientation", cmd_orientation }, | 1065 | { "default_orientation", cmd_orientation }, |
1050 | { "exec", cmd_exec }, | 1066 | { "exec", cmd_exec }, |
@@ -1054,6 +1070,7 @@ static struct cmd_handler handlers[] = { | |||
1054 | { "floating_modifier", cmd_floating_mod }, | 1070 | { "floating_modifier", cmd_floating_mod }, |
1055 | { "focus", cmd_focus }, | 1071 | { "focus", cmd_focus }, |
1056 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 1072 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
1073 | { "for_window", cmd_for_window }, | ||
1057 | { "fullscreen", cmd_fullscreen }, | 1074 | { "fullscreen", cmd_fullscreen }, |
1058 | { "gaps", cmd_gaps }, | 1075 | { "gaps", cmd_gaps }, |
1059 | { "kill", cmd_kill }, | 1076 | { "kill", cmd_kill }, |
@@ -1090,6 +1107,7 @@ static struct cmd_handler *find_handler(char *line) { | |||
1090 | enum cmd_status handle_command(char *exec) { | 1107 | enum cmd_status handle_command(char *exec) { |
1091 | sway_log(L_INFO, "Handling command '%s'", exec); | 1108 | sway_log(L_INFO, "Handling command '%s'", exec); |
1092 | int argc; | 1109 | int argc; |
1110 | char *criteria = NULL; | ||
1093 | char **argv = split_args(exec, &argc); | 1111 | char **argv = split_args(exec, &argc); |
1094 | enum cmd_status status = CMD_FAILURE; | 1112 | enum cmd_status status = CMD_FAILURE; |
1095 | struct cmd_handler *handler; | 1113 | struct cmd_handler *handler; |
@@ -1097,7 +1115,7 @@ enum cmd_status handle_command(char *exec) { | |||
1097 | return status; | 1115 | return status; |
1098 | } | 1116 | } |
1099 | if ((handler = find_handler(argv[0])) == NULL | 1117 | if ((handler = find_handler(argv[0])) == NULL |
1100 | || (status = handler->handle(argc - 1, argv + 1)) != CMD_SUCCESS) { | 1118 | || (status = handler->handle(criteria, argc - 1, argv + 1)) != CMD_SUCCESS) { |
1101 | sway_log(L_ERROR, "Command failed: %s", argv[0]); | 1119 | sway_log(L_ERROR, "Command failed: %s", argv[0]); |
1102 | } | 1120 | } |
1103 | free_argv(argc, argv); | 1121 | free_argv(argc, argv); |
@@ -1108,6 +1126,7 @@ enum cmd_status config_command(char *exec) { | |||
1108 | sway_log(L_INFO, "handling config command '%s'", exec); | 1126 | sway_log(L_INFO, "handling config command '%s'", exec); |
1109 | int argc; | 1127 | int argc; |
1110 | char **argv = split_args(exec, &argc); | 1128 | char **argv = split_args(exec, &argc); |
1129 | char *criteria = NULL; | ||
1111 | enum cmd_status status = CMD_FAILURE; | 1130 | enum cmd_status status = CMD_FAILURE; |
1112 | struct cmd_handler *handler; | 1131 | struct cmd_handler *handler; |
1113 | if (!argc) { | 1132 | if (!argc) { |
@@ -1127,7 +1146,7 @@ enum cmd_status config_command(char *exec) { | |||
1127 | for (; i < e; ++i) { | 1146 | for (; i < e; ++i) { |
1128 | argv[i] = do_var_replacement(argv[i]); | 1147 | argv[i] = do_var_replacement(argv[i]); |
1129 | } | 1148 | } |
1130 | status = handler->handle(argc - 1, argv + 1); | 1149 | status = handler->handle(criteria, argc - 1, argv + 1); |
1131 | if (status == CMD_FAILURE) { | 1150 | if (status == CMD_FAILURE) { |
1132 | sway_log(L_ERROR, "Config load failed for line `%s'", exec); | 1151 | sway_log(L_ERROR, "Config load failed for line `%s'", exec); |
1133 | } else if (status == CMD_DEFER) { | 1152 | } 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) { | |||
286 | } | 286 | } |
287 | return str; | 287 | return str; |
288 | } | 288 | } |
289 | |||
290 | struct workspace_output *wsop_find_workspace(const char *name) { | ||
291 | int i, len = config->workspace_outputs->length; | ||
292 | struct workspace_output *wsop; | ||
293 | for (i = 0; i < len; ++i) { | ||
294 | wsop = config->workspace_outputs->items[i]; | ||
295 | if (strcasecmp(wsop->workspace, name) == 0) { | ||
296 | return wsop; | ||
297 | } | ||
298 | } | ||
299 | return NULL; | ||
300 | } | ||
301 | |||
302 | struct workspace_output *wsop_find_output(const char *name) { | ||
303 | int i, len = config->workspace_outputs->length; | ||
304 | struct workspace_output *wsop; | ||
305 | for (i = 0; i < len; ++i) { | ||
306 | wsop = config->workspace_outputs->items[i]; | ||
307 | if (strcasecmp(wsop->output, name) == 0) { | ||
308 | return wsop; | ||
309 | } | ||
310 | } | ||
311 | return NULL; | ||
312 | } | ||
313 | |||
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 @@ | |||
1 | #include <stdlib.h> | 1 | #include <stdlib.h> |
2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
3 | #include <strings.h> | 3 | #include <strings.h> |
4 | #include <pcre.h> | ||
4 | #include "config.h" | 5 | #include "config.h" |
5 | #include "container.h" | 6 | #include "container.h" |
6 | #include "workspace.h" | 7 | #include "workspace.h" |
@@ -53,26 +54,30 @@ static void free_swayc(swayc_t *cont) { | |||
53 | // New containers | 54 | // New containers |
54 | 55 | ||
55 | swayc_t *new_output(wlc_handle handle) { | 56 | swayc_t *new_output(wlc_handle handle) { |
56 | const struct wlc_size *size = wlc_output_get_resolution(handle); | ||
57 | const char *name = wlc_output_get_name(handle); | 57 | const char *name = wlc_output_get_name(handle); |
58 | int i, len; | ||
59 | |||
58 | // Find current outputs to see if this already exists | 60 | // Find current outputs to see if this already exists |
59 | { | 61 | if (name) { |
60 | int i, len = root_container.children->length; | 62 | len = root_container.children->length; |
61 | for (i = 0; i < len; ++i) { | 63 | for (i = 0; i < len; ++i) { |
62 | swayc_t *op = root_container.children->items[i]; | 64 | swayc_t *op = root_container.children->items[i]; |
63 | const char *op_name = op->name; | 65 | if (strcmp(op->name, name) == 0) { |
64 | if (op_name && name && strcmp(op_name, name) == 0) { | 66 | sway_log(L_DEBUG, "restoring output %lu:%s", handle, op->name); |
65 | sway_log(L_DEBUG, "restoring output %lu:%s", handle, op_name); | ||
66 | return op; | 67 | return op; |
67 | } | 68 | } |
68 | } | 69 | } |
70 | } else { | ||
71 | sway_log(L_ERROR, "Output has no given name"); | ||
72 | return NULL; | ||
69 | } | 73 | } |
70 | 74 | ||
71 | sway_log(L_DEBUG, "Added output %lu:%s", handle, name); | 75 | sway_log(L_DEBUG, "Adding output %lu:%s", handle, name); |
72 | 76 | ||
77 | // Find output config | ||
73 | struct output_config *oc = NULL; | 78 | struct output_config *oc = NULL; |
74 | int i; | 79 | len = config->output_configs->length; |
75 | for (i = 0; i < config->output_configs->length; ++i) { | 80 | for (i = 0; i < len; ++i) { |
76 | oc = config->output_configs->items[i]; | 81 | oc = config->output_configs->items[i]; |
77 | if (strcasecmp(name, oc->name) == 0) { | 82 | if (strcasecmp(name, oc->name) == 0) { |
78 | sway_log(L_DEBUG, "Matched output config for %s", name); | 83 | sway_log(L_DEBUG, "Matched output config for %s", name); |
@@ -86,77 +91,88 @@ swayc_t *new_output(wlc_handle handle) { | |||
86 | } | 91 | } |
87 | 92 | ||
88 | swayc_t *output = new_swayc(C_OUTPUT); | 93 | swayc_t *output = new_swayc(C_OUTPUT); |
89 | if (oc && oc->width != -1 && oc->height != -1) { | ||
90 | output->width = oc->width; | ||
91 | output->height = oc->height; | ||
92 | struct wlc_size new_size = { .w = oc->width, .h = oc->height }; | ||
93 | wlc_output_set_resolution(handle, &new_size); | ||
94 | } else { | ||
95 | output->width = size->w; | ||
96 | output->height = size->h; | ||
97 | } | ||
98 | output->handle = handle; | 94 | output->handle = handle; |
99 | output->name = name ? strdup(name) : NULL; | 95 | output->name = name ? strdup(name) : NULL; |
100 | |||
101 | // Find position for it | ||
102 | if (oc && oc->x != -1 && oc->y != -1) { | ||
103 | sway_log(L_DEBUG, "Set %s position to %d, %d", name, oc->x, oc->y); | ||
104 | output->x = oc->x; | ||
105 | output->y = oc->y; | ||
106 | } else { | ||
107 | int x = 0; | ||
108 | for (i = 0; i < root_container.children->length; ++i) { | ||
109 | swayc_t *c = root_container.children->items[i]; | ||
110 | if (c->type == C_OUTPUT) { | ||
111 | if (c->width + c->x > x) { | ||
112 | x = c->width + c->x; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | output->x = x; | ||
117 | } | ||
118 | 96 | ||
119 | add_child(&root_container, output); | 97 | if (oc) { |
120 | 98 | // Set output width/height | |
121 | // Create workspace | 99 | if (oc->width > 0 && oc->height > 0) { |
122 | char *ws_name = NULL; | 100 | output->width = oc->width; |
123 | if (name) { | 101 | output->height = oc->height; |
124 | for (i = 0; i < config->workspace_outputs->length; ++i) { | 102 | struct wlc_size geo = { .w = oc->width, .h = oc->height}; |
125 | struct workspace_output *wso = config->workspace_outputs->items[i]; | 103 | wlc_output_set_resolution(handle, &geo); |
126 | if (strcasecmp(wso->output, name) == 0) { | 104 | } else { |
127 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); | 105 | struct wlc_size geo = *wlc_output_get_resolution(handle); |
128 | // Check if any other workspaces are using this name | 106 | output->width = geo.w; |
129 | if (workspace_by_name(wso->workspace)) { | 107 | output->height = geo.h; |
130 | sway_log(L_DEBUG, "But it's already taken"); | 108 | } |
131 | break; | 109 | // find position in config or find where it should go |
110 | // TODO more intelligent method | ||
111 | if (oc->x > 0 && oc->y > 0) { | ||
112 | output->x = oc->x; | ||
113 | output->y = oc->y; | ||
114 | } else { | ||
115 | unsigned int x = 0; | ||
116 | len = root_container.children->length; | ||
117 | for (i = 0; i < len; ++i) { | ||
118 | swayc_t *c = root_container.children->items[i]; | ||
119 | if (c->type == C_OUTPUT) { | ||
120 | unsigned int cx = c->width + c->x; | ||
121 | if (cx > x) { | ||
122 | x = cx; | ||
123 | } | ||
132 | } | 124 | } |
133 | sway_log(L_DEBUG, "So we're going to use it"); | ||
134 | ws_name = strdup(wso->workspace); | ||
135 | break; | ||
136 | } | 125 | } |
126 | output->x = x; | ||
137 | } | 127 | } |
138 | } | 128 | } |
139 | if (!ws_name) { | 129 | // Add as child to root |
140 | ws_name = workspace_next_name(); | 130 | add_child(&root_container, output); |
141 | } | ||
142 | 131 | ||
143 | // create and initilize default workspace | 132 | // create and initilize default workspace |
144 | swayc_t *ws = new_workspace(output, ws_name); | 133 | swayc_t *ws = new_workspace(output, NULL); |
145 | ws->is_focused = true; | 134 | ws->is_focused = true; |
146 | 135 | ||
147 | free(ws_name); | ||
148 | |||
149 | return output; | 136 | return output; |
150 | } | 137 | } |
151 | 138 | ||
152 | swayc_t *new_workspace(swayc_t *output, const char *name) { | 139 | swayc_t *new_workspace(swayc_t *output, const char *name) { |
153 | if (!ASSERT_NONNULL(output)) { | 140 | swayc_t *ws = NULL; |
154 | return NULL; | 141 | struct workspace_output *wsop; |
142 | if (name) { | ||
143 | // Find existing workspace with same name. | ||
144 | // or workspace found by special name | ||
145 | if ((ws = workspace_by_name(name))) { | ||
146 | return ws; | ||
147 | } | ||
148 | // Find matching output from config | ||
149 | if (!output) { | ||
150 | if ((wsop = wsop_find_workspace(name))) { | ||
151 | int i, len = root_container.children->length; | ||
152 | for (i = 0; i < len; ++i) { | ||
153 | swayc_t *op = root_container.children->items[i]; | ||
154 | if (strcasecmp(op->name, wsop->output) == 0) { | ||
155 | output = op; | ||
156 | goto find_wsop_end; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | // Set output to active_output if there is no output. | ||
161 | output = swayc_active_output(); | ||
162 | find_wsop_end:; | ||
163 | } | ||
164 | } else { | ||
165 | // No name or output, use active_output | ||
166 | if (!output) { | ||
167 | output = swayc_active_output(); | ||
168 | } | ||
169 | // search for available output name | ||
170 | if (!(name = workspace_output_open_name(output))) { | ||
171 | // otherwise just use simple next name | ||
172 | name = workspace_next_name(); | ||
173 | } | ||
155 | } | 174 | } |
156 | sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); | ||
157 | swayc_t *workspace = new_swayc(C_WORKSPACE); | 175 | swayc_t *workspace = new_swayc(C_WORKSPACE); |
158 | |||
159 | // TODO: default_layout | ||
160 | if (config->default_layout != L_NONE) { | 176 | if (config->default_layout != L_NONE) { |
161 | workspace->layout = config->default_layout; | 177 | workspace->layout = config->default_layout; |
162 | } else if (config->default_orientation != L_NONE) { | 178 | } else if (config->default_orientation != L_NONE) { |
@@ -374,7 +390,7 @@ swayc_t *destroy_view(swayc_t *view) { | |||
374 | // Container lookup | 390 | // Container lookup |
375 | 391 | ||
376 | 392 | ||
377 | swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | 393 | swayc_t *swayc_by_test_r(swayc_t *container, swayc_test_func test, void *data) { |
378 | if (!container->children) { | 394 | if (!container->children) { |
379 | return NULL; | 395 | return NULL; |
380 | } | 396 | } |
@@ -393,7 +409,7 @@ swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *dat | |||
393 | if (test(child, data)) { | 409 | if (test(child, data)) { |
394 | return child; | 410 | return child; |
395 | } else { | 411 | } else { |
396 | swayc_t *res = swayc_by_test(child, test, data); | 412 | swayc_t *res = swayc_by_test_r(child, test, data); |
397 | if (res) { | 413 | if (res) { |
398 | return res; | 414 | return res; |
399 | } | 415 | } |
@@ -401,18 +417,193 @@ swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *dat | |||
401 | } | 417 | } |
402 | return NULL; | 418 | return NULL; |
403 | } | 419 | } |
420 | swayc_t *swayc_by_test(swayc_test_func test, void *data) { | ||
421 | return swayc_by_test_r(&root_container, test, data); | ||
422 | } | ||
423 | |||
424 | void swayc_map_r(swayc_t *container, swayc_map_func f, void *data) { | ||
425 | if (container) { | ||
426 | f(container, data); | ||
427 | int i; | ||
428 | if (container->children) { | ||
429 | for (i = 0; i < container->children->length; ++i) { | ||
430 | swayc_t *child = container->children->items[i]; | ||
431 | swayc_map_r(child, f, data); | ||
432 | } | ||
433 | } | ||
434 | if (container->floating) { | ||
435 | for (i = 0; i < container->floating->length; ++i) { | ||
436 | swayc_t *child = container->floating->items[i]; | ||
437 | swayc_map_r(child, f, data); | ||
438 | } | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | void swayc_map(swayc_map_func f, void *data) { | ||
443 | swayc_map_r(&root_container, f, data); | ||
444 | } | ||
445 | |||
446 | void swayc_map_by_test_r(swayc_t *container, | ||
447 | swayc_map_func func, swayc_test_func test, | ||
448 | void *funcdata, void *testdata) { | ||
449 | if (container) { | ||
450 | if (test(container, testdata)) { | ||
451 | func(container, funcdata); | ||
452 | } | ||
453 | int i; | ||
454 | if (container->children) { | ||
455 | for (i = 0; i < container->children->length; ++i) { | ||
456 | swayc_t *child = container->children->items[i]; | ||
457 | swayc_map_by_test_r(child, func, test, funcdata, testdata); | ||
458 | } | ||
459 | } | ||
460 | if (container->floating) { | ||
461 | for (i = 0; i < container->floating->length; ++i) { | ||
462 | swayc_t *child = container->floating->items[i]; | ||
463 | swayc_map_by_test_r(child, func, test, funcdata, testdata); | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | void swayc_map_by_test( | ||
469 | swayc_map_func func, swayc_test_func test, | ||
470 | void *funcdata, void *testdata) { | ||
471 | swayc_map_by_test_r(&root_container, func, test, funcdata, testdata); | ||
472 | } | ||
473 | |||
474 | |||
475 | |||
476 | // Map functions | ||
477 | void set_gaps(swayc_t *view, void *_data) { | ||
478 | int *data = _data; | ||
479 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { | ||
480 | view->gaps = *data; | ||
481 | } | ||
482 | } | ||
404 | 483 | ||
405 | static bool test_name(swayc_t *view, void *data) { | 484 | void add_gaps(swayc_t *view, void *_data) { |
406 | if (!view && !view->name) { | 485 | int *data = _data; |
407 | return false; | 486 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { |
487 | if ((view->gaps += *data) < 0) { | ||
488 | view->gaps = 0; | ||
489 | } | ||
408 | } | 490 | } |
409 | return strcmp(view->name, data) == 0; | ||
410 | } | 491 | } |
411 | 492 | ||
412 | swayc_t *swayc_by_name(const char *name) { | 493 | // Test functions |
413 | return swayc_by_test(&root_container, test_name, (void *)name); | 494 | bool test_name(swayc_t *view, void *data) { |
495 | return view->name && strcmp(view->name, data) == 0; | ||
414 | } | 496 | } |
415 | 497 | ||
498 | // test_name_regex | ||
499 | struct test_name_regex { | ||
500 | pcre *reg; | ||
501 | pcre_extra *regext; | ||
502 | }; | ||
503 | |||
504 | void *compile_regex(const char *pattern) { | ||
505 | struct test_name_regex *regex = malloc(sizeof *regex); | ||
506 | const char *error; | ||
507 | int erroffset; | ||
508 | if (!(regex->reg = pcre_compile(pattern, 0, &error, &erroffset, NULL))) { | ||
509 | sway_log(L_ERROR, "Regex compilation failed:%s:%s", pattern, error); | ||
510 | free(regex); | ||
511 | return NULL; | ||
512 | } | ||
513 | regex->regext = pcre_study(regex->reg, 0, &error); | ||
514 | if (error) { | ||
515 | sway_log(L_DEBUG, "Regex study failed:%s:%s", pattern, error); | ||
516 | } | ||
517 | return regex; | ||
518 | } | ||
519 | |||
520 | void free_regex(void *_regex) { | ||
521 | struct test_name_regex *regex = _regex; | ||
522 | pcre_free(regex->reg); | ||
523 | pcre_free_study(regex->regext); | ||
524 | free(regex); | ||
525 | } | ||
526 | |||
527 | static bool exec_regex(const char *pattern, struct test_name_regex *regex) { | ||
528 | int ovector[300]; | ||
529 | return 0 < pcre_exec(regex->reg, regex->regext, pattern, | ||
530 | strlen(pattern), 0, 0, ovector, 300); | ||
531 | } | ||
532 | |||
533 | bool test_name_regex(swayc_t *view, void *data) { | ||
534 | return view->name && exec_regex(view->name, data); | ||
535 | } | ||
536 | bool test_layout(swayc_t *view, void *data) { | ||
537 | return view->layout & *(enum swayc_layouts *)data; | ||
538 | } | ||
539 | bool test_type(swayc_t *view, void *data) { | ||
540 | return view->layout & *(enum swayc_types *)data; | ||
541 | } | ||
542 | bool test_visibility(swayc_t *view, void *data) { | ||
543 | return view->visible == *(bool *)data; | ||
544 | } | ||
545 | bool test_handle(swayc_t *view, void *data) { | ||
546 | return view->handle == *(wlc_handle *)data; | ||
547 | } | ||
548 | |||
549 | // C_VIEW tests | ||
550 | bool test_view_state(swayc_t *view, void *data) { | ||
551 | return view->type == C_VIEW | ||
552 | && wlc_view_get_state(view->handle) & *(int *)data; | ||
553 | } | ||
554 | bool test_view_type(swayc_t *view, void *data) { | ||
555 | return view->type == C_VIEW | ||
556 | && wlc_view_get_type(view->handle) & *(int *)data; | ||
557 | } | ||
558 | bool test_view_title(swayc_t *view, void *data) { | ||
559 | return view->type == C_VIEW | ||
560 | && strcmp(view->name, data) == 0; | ||
561 | } | ||
562 | bool test_view_class(swayc_t *view, void *data) { | ||
563 | return view->type == C_VIEW | ||
564 | && strcmp(wlc_view_get_class(view->handle), data) == 0; | ||
565 | } | ||
566 | bool test_view_appid(swayc_t *view, void *data) { | ||
567 | return view->type == C_VIEW | ||
568 | && strcmp(wlc_view_get_app_id(view->handle), data) == 0; | ||
569 | } | ||
570 | bool test_view_title_regex(swayc_t *view, void *data) { | ||
571 | return view->type == C_VIEW | ||
572 | && exec_regex(view->name, data); | ||
573 | } | ||
574 | bool test_view_class_regex(swayc_t *view, void *data) { | ||
575 | return view->type == C_VIEW | ||
576 | && exec_regex(wlc_view_get_class(view->handle), data); | ||
577 | } | ||
578 | bool test_view_appid_regex(swayc_t *view, void *data) { | ||
579 | return view->type == C_VIEW | ||
580 | && exec_regex(wlc_view_get_app_id(view->handle), data); | ||
581 | } | ||
582 | |||
583 | // Fancy test combiners | ||
584 | bool test_and(swayc_t *view, void *data) { | ||
585 | struct test_list *list = data; | ||
586 | while (list->test) { | ||
587 | if (!list->test(view, list->data)) { | ||
588 | return false; | ||
589 | } | ||
590 | ++list; | ||
591 | } | ||
592 | return true; | ||
593 | } | ||
594 | bool test_or(swayc_t *view, void *data) { | ||
595 | struct test_list *list = data; | ||
596 | while (list->test) { | ||
597 | if (list->test(view, list->data)) { | ||
598 | return true; | ||
599 | } | ||
600 | ++list; | ||
601 | } | ||
602 | return false; | ||
603 | } | ||
604 | |||
605 | // Focus|parent lookup | ||
606 | |||
416 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { | 607 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { |
417 | if (!ASSERT_NONNULL(container)) { | 608 | if (!ASSERT_NONNULL(container)) { |
418 | return NULL; | 609 | return NULL; |
@@ -465,42 +656,6 @@ swayc_t *swayc_focus_by_layout(swayc_t *container, enum swayc_layouts layout) { | |||
465 | return container; | 656 | return container; |
466 | } | 657 | } |
467 | 658 | ||
468 | |||
469 | static swayc_t *_swayc_by_handle_helper(wlc_handle handle, swayc_t *parent) { | ||
470 | if (!parent || !parent->children) { | ||
471 | return NULL; | ||
472 | } | ||
473 | int i, len; | ||
474 | swayc_t **child; | ||
475 | if (parent->type == C_WORKSPACE) { | ||
476 | len = parent->floating->length; | ||
477 | child = (swayc_t **)parent->floating->items; | ||
478 | for (i = 0; i < len; ++i, ++child) { | ||
479 | if ((*child)->handle == handle) { | ||
480 | return *child; | ||
481 | } | ||
482 | } | ||
483 | } | ||
484 | |||
485 | len = parent->children->length; | ||
486 | child = (swayc_t**)parent->children->items; | ||
487 | for (i = 0; i < len; ++i, ++child) { | ||
488 | if ((*child)->handle == handle) { | ||
489 | return *child; | ||
490 | } else { | ||
491 | swayc_t *res; | ||
492 | if ((res = _swayc_by_handle_helper(handle, *child))) { | ||
493 | return res; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | return NULL; | ||
498 | } | ||
499 | |||
500 | swayc_t *swayc_by_handle(wlc_handle handle) { | ||
501 | return _swayc_by_handle_helper(handle, &root_container); | ||
502 | } | ||
503 | |||
504 | swayc_t *swayc_active_output(void) { | 659 | swayc_t *swayc_active_output(void) { |
505 | return root_container.focused; | 660 | return root_container.focused; |
506 | } | 661 | } |
@@ -533,11 +688,13 @@ swayc_t *swayc_active_workspace_for(swayc_t *cont) { | |||
533 | // Container information | 688 | // Container information |
534 | 689 | ||
535 | bool swayc_is_fullscreen(swayc_t *view) { | 690 | bool swayc_is_fullscreen(swayc_t *view) { |
536 | return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN); | 691 | return view && view->type == C_VIEW |
692 | && wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN; | ||
537 | } | 693 | } |
538 | 694 | ||
539 | bool swayc_is_active(swayc_t *view) { | 695 | bool swayc_is_active(swayc_t *view) { |
540 | return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_ACTIVATED); | 696 | return view && view->type == C_VIEW |
697 | && wlc_view_get_state(view->handle) & WLC_BIT_ACTIVATED; | ||
541 | } | 698 | } |
542 | 699 | ||
543 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child) { | 700 | bool swayc_is_parent_of(swayc_t *parent, swayc_t *child) { |
@@ -566,25 +723,6 @@ int swayc_gap(swayc_t *container) { | |||
566 | 723 | ||
567 | // Mapping | 724 | // Mapping |
568 | 725 | ||
569 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | ||
570 | if (container) { | ||
571 | f(container, data); | ||
572 | int i; | ||
573 | if (container->children) { | ||
574 | for (i = 0; i < container->children->length; ++i) { | ||
575 | swayc_t *child = container->children->items[i]; | ||
576 | container_map(child, f, data); | ||
577 | } | ||
578 | } | ||
579 | if (container->floating) { | ||
580 | for (i = 0; i < container->floating->length; ++i) { | ||
581 | swayc_t *child = container->floating->items[i]; | ||
582 | container_map(child, f, data); | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | void update_visibility_output(swayc_t *container, wlc_handle output) { | 726 | void update_visibility_output(swayc_t *container, wlc_handle output) { |
589 | // Inherit visibility | 727 | // Inherit visibility |
590 | swayc_t *parent = container->parent; | 728 | swayc_t *parent = container->parent; |
@@ -653,24 +791,3 @@ void update_visibility(swayc_t *container) { | |||
653 | } | 791 | } |
654 | } | 792 | } |
655 | 793 | ||
656 | void set_gaps(swayc_t *view, void *_data) { | ||
657 | int *data = _data; | ||
658 | if (!ASSERT_NONNULL(view)) { | ||
659 | return; | ||
660 | } | ||
661 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { | ||
662 | view->gaps = *data; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | void add_gaps(swayc_t *view, void *_data) { | ||
667 | int *data = _data; | ||
668 | if (!ASSERT_NONNULL(view)) { | ||
669 | return; | ||
670 | } | ||
671 | if (view->type == C_WORKSPACE || view->type == C_VIEW) { | ||
672 | if ((view->gaps += *data) < 0) { | ||
673 | view->gaps = 0; | ||
674 | } | ||
675 | } | ||
676 | } | ||
diff --git a/sway/handlers.c b/sway/handlers.c index 096df53c..1a8138f8 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -126,7 +126,7 @@ static void handle_output_destroyed(wlc_handle output) { | |||
126 | 126 | ||
127 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { | 127 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { |
128 | sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); | 128 | sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); |
129 | swayc_t *c = swayc_by_handle(output); | 129 | swayc_t *c = swayc_by_test(test_handle, &output); |
130 | if (!c) return; | 130 | if (!c) return; |
131 | c->width = to->w; | 131 | c->width = to->w; |
132 | c->height = to->h; | 132 | c->height = to->h; |
@@ -134,7 +134,7 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_ | |||
134 | } | 134 | } |
135 | 135 | ||
136 | static void handle_output_focused(wlc_handle output, bool focus) { | 136 | static void handle_output_focused(wlc_handle output, bool focus) { |
137 | swayc_t *c = swayc_by_handle(output); | 137 | swayc_t *c = swayc_by_test(test_handle, &output); |
138 | // if for some reason this output doesnt exist, create it. | 138 | // if for some reason this output doesnt exist, create it. |
139 | if (!c) { | 139 | if (!c) { |
140 | handle_output_created(output); | 140 | handle_output_created(output); |
@@ -152,7 +152,7 @@ static bool handle_view_created(wlc_handle handle) { | |||
152 | 152 | ||
153 | // Get parent container, to add view in | 153 | // Get parent container, to add view in |
154 | if (parent) { | 154 | if (parent) { |
155 | focused = swayc_by_handle(parent); | 155 | focused = swayc_by_test(test_handle, &parent); |
156 | } | 156 | } |
157 | if (!focused || focused->type == C_OUTPUT) { | 157 | if (!focused || focused->type == C_OUTPUT) { |
158 | focused = get_focused_container(&root_container); | 158 | focused = get_focused_container(&root_container); |
@@ -221,7 +221,7 @@ static bool handle_view_created(wlc_handle handle) { | |||
221 | 221 | ||
222 | static void handle_view_destroyed(wlc_handle handle) { | 222 | static void handle_view_destroyed(wlc_handle handle) { |
223 | sway_log(L_DEBUG, "Destroying window %lu", handle); | 223 | sway_log(L_DEBUG, "Destroying window %lu", handle); |
224 | swayc_t *view = swayc_by_handle(handle); | 224 | swayc_t *view = swayc_by_test(test_handle, &handle); |
225 | 225 | ||
226 | // destroy views by type | 226 | // destroy views by type |
227 | switch (wlc_view_get_type(handle)) { | 227 | switch (wlc_view_get_type(handle)) { |
@@ -258,7 +258,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo | |||
258 | // If the view is floating, then apply the geometry. | 258 | // If the view is floating, then apply the geometry. |
259 | // Otherwise save the desired width/height for the view. | 259 | // Otherwise save the desired width/height for the view. |
260 | // This will not do anything for the time being as WLC improperly sends geometry requests | 260 | // This will not do anything for the time being as WLC improperly sends geometry requests |
261 | swayc_t *view = swayc_by_handle(handle); | 261 | swayc_t *view = swayc_by_test(test_handle, &handle); |
262 | if (view) { | 262 | if (view) { |
263 | view->desired_width = geometry->size.w; | 263 | view->desired_width = geometry->size.w; |
264 | view->desired_height = geometry->size.h; | 264 | view->desired_height = geometry->size.h; |
@@ -274,7 +274,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo | |||
274 | } | 274 | } |
275 | 275 | ||
276 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { | 276 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { |
277 | swayc_t *c = swayc_by_handle(view); | 277 | swayc_t *c = swayc_by_test(test_handle, &view); |
278 | switch (state) { | 278 | switch (state) { |
279 | case WLC_BIT_FULLSCREEN: | 279 | case WLC_BIT_FULLSCREEN: |
280 | // i3 just lets it become fullscreen | 280 | // i3 just lets it become fullscreen |
@@ -207,7 +207,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
207 | case IPC_GET_WORKSPACES: | 207 | case IPC_GET_WORKSPACES: |
208 | { | 208 | { |
209 | json_object *workspaces = json_object_new_array(); | 209 | json_object *workspaces = json_object_new_array(); |
210 | container_map(&root_container, ipc_get_workspaces_callback, workspaces); | 210 | swayc_map(ipc_get_workspaces_callback, workspaces); |
211 | const char *json_string = json_object_to_json_string(workspaces); | 211 | const char *json_string = json_object_to_json_string(workspaces); |
212 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 212 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
213 | json_object_put(workspaces); // free | 213 | json_object_put(workspaces); // free |
@@ -216,7 +216,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
216 | case IPC_GET_OUTPUTS: | 216 | case IPC_GET_OUTPUTS: |
217 | { | 217 | { |
218 | json_object *outputs = json_object_new_array(); | 218 | json_object *outputs = json_object_new_array(); |
219 | container_map(&root_container, ipc_get_outputs_callback, outputs); | 219 | swayc_map(ipc_get_outputs_callback, outputs); |
220 | const char *json_string = json_object_to_json_string(outputs); | 220 | const char *json_string = json_object_to_json_string(outputs); |
221 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 221 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
222 | json_object_put(outputs); // free | 222 | json_object_put(outputs); // free |
diff --git a/sway/stringop.c b/sway/stringop.c index 191e40c8..54faf74c 100644 --- a/sway/stringop.c +++ b/sway/stringop.c | |||
@@ -258,7 +258,7 @@ int unescape_string(char *string) { | |||
258 | return len - shift; | 258 | return len - shift; |
259 | } | 259 | } |
260 | 260 | ||
261 | char *join_args(char **argv, int argc) { | 261 | char *join_args(int argc, char **argv) { |
262 | int len = 0, i; | 262 | int len = 0, i; |
263 | for (i = 0; i < argc; ++i) { | 263 | for (i = 0; i < argc; ++i) { |
264 | len += strlen(argv[i]) + 1; | 264 | len += strlen(argv[i]) + 1; |
diff --git a/sway/workspace.c b/sway/workspace.c index 658f79bc..80141f71 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -15,7 +15,26 @@ | |||
15 | 15 | ||
16 | char *prev_workspace_name = NULL; | 16 | char *prev_workspace_name = NULL; |
17 | 17 | ||
18 | char *workspace_next_name(void) { | 18 | static swayc_t *workspace_by_name_only(const char *name); |
19 | |||
20 | const char *workspace_output_open_name(swayc_t *output) { | ||
21 | struct workspace_output *wsop; | ||
22 | int i, len = config->workspace_outputs->length; | ||
23 | // Search config for output | ||
24 | for (i = 0; i < len; ++i) { | ||
25 | wsop = config->workspace_outputs->items[i]; | ||
26 | // Find matching outputs | ||
27 | if (strcasecmp(wsop->output, output->name)) { | ||
28 | // Check if workspace is available and use that name | ||
29 | if (!workspace_by_name(wsop->workspace)) { | ||
30 | return wsop->workspace; | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | return NULL; | ||
35 | } | ||
36 | |||
37 | const char *workspace_next_name(void) { | ||
19 | sway_log(L_DEBUG, "Workspace: Generating new name"); | 38 | sway_log(L_DEBUG, "Workspace: Generating new name"); |
20 | int i; | 39 | int i; |
21 | int l = 1; | 40 | int l = 1; |
@@ -25,42 +44,29 @@ char *workspace_next_name(void) { | |||
25 | 44 | ||
26 | for (i = 0; i < mode->bindings->length; ++i) { | 45 | for (i = 0; i < mode->bindings->length; ++i) { |
27 | struct sway_binding *binding = mode->bindings->items[i]; | 46 | struct sway_binding *binding = mode->bindings->items[i]; |
28 | const char* command = binding->command; | 47 | const char *command = binding->command; |
29 | list_t *args = split_string(command, " "); | 48 | const char *ws = "workspace"; |
30 | 49 | const int wslen = sizeof("workspace") - 1; | |
31 | if (strcmp("workspace", args->items[0]) == 0 && args->length > 1) { | 50 | if (strncmp(ws, command, wslen) == 0) { |
32 | sway_log(L_DEBUG, "Got valid workspace command for target: '%s'", (char *)args->items[1]); | 51 | command += wslen; |
33 | char* target = malloc(strlen(args->items[1]) + 1); | 52 | // Skip whitespace |
34 | strcpy(target, args->items[1]); | 53 | command += strspn(command, whitespace); |
35 | while (*target == ' ' || *target == '\t') | 54 | // make sure its not a special command |
36 | target++; | 55 | if (strcmp(command, "next") == 0 |
37 | 56 | || strcmp(command, "prev") == 0 | |
38 | // Make sure that the command references an actual workspace | 57 | || strcmp(command, "next_on_output") == 0 |
39 | // not a command about workspaces | 58 | || strcmp(command, "prev_on_output") == 0 |
40 | if (strcmp(target, "next") == 0 || | 59 | || strcmp(command, "number") == 0 |
41 | strcmp(target, "prev") == 0 || | 60 | || strcmp(command, "back_and_forth") == 0 |
42 | strcmp(target, "next_on_output") == 0 || | 61 | || strcmp(command, "current") == 0 |
43 | strcmp(target, "prev_on_output") == 0 || | 62 | // Or if it already exists |
44 | strcmp(target, "number") == 0 || | 63 | || workspace_by_name_only(command)) { |
45 | strcmp(target, "back_and_forth") == 0 || | ||
46 | strcmp(target, "current") == 0) | ||
47 | { | ||
48 | free_flat_list(args); | ||
49 | continue; | 64 | continue; |
65 | } else { | ||
66 | // otherwise we found it | ||
67 | return command; | ||
50 | } | 68 | } |
51 | |||
52 | // Make sure that the workspace doesn't already exist | ||
53 | if (workspace_by_name(target)) { | ||
54 | free_flat_list(args); | ||
55 | continue; | ||
56 | } | ||
57 | |||
58 | free_flat_list(args); | ||
59 | |||
60 | sway_log(L_DEBUG, "Workspace: Found free name %s", target); | ||
61 | return target; | ||
62 | } | 69 | } |
63 | free_flat_list(args); | ||
64 | } | 70 | } |
65 | // As a fall back, get the current number of active workspaces | 71 | // As a fall back, get the current number of active workspaces |
66 | // and return that + 1 for the next workspace's name | 72 | // and return that + 1 for the next workspace's name |
@@ -75,55 +81,40 @@ char *workspace_next_name(void) { | |||
75 | return name; | 81 | return name; |
76 | } | 82 | } |
77 | 83 | ||
78 | swayc_t *workspace_create(const char* name) { | 84 | swayc_t *workspace_by_name_only(const char *name) { |
79 | swayc_t *parent; | 85 | int i, len = root_container.children->length; |
80 | // Search for workspace<->output pair | 86 | for (i = 0; i < len; ++i) { |
81 | int i, e = config->workspace_outputs->length; | 87 | swayc_t *op = root_container.children->items[i]; |
82 | for (i = 0; i < e; ++i) { | 88 | int i, len = op->children->length; |
83 | struct workspace_output *wso = config->workspace_outputs->items[i]; | 89 | for (i = 0; i < len; ++i) { |
84 | if (strcasecmp(wso->workspace, name) == 0) | 90 | swayc_t *ws = op->children->items[i]; |
85 | { | 91 | if (strcasecmp(ws->name, name) == 0) { |
86 | // Find output to use if it exists | 92 | return ws; |
87 | e = root_container.children->length; | ||
88 | for (i = 0; i < e; ++i) { | ||
89 | parent = root_container.children->items[i]; | ||
90 | if (strcmp(parent->name, wso->output) == 0) { | ||
91 | return new_workspace(parent, name); | ||
92 | } | ||
93 | } | 93 | } |
94 | break; | ||
95 | } | 94 | } |
96 | } | 95 | } |
97 | // Otherwise create a new one | 96 | return NULL; |
98 | parent = get_focused_container(&root_container); | ||
99 | parent = swayc_parent_by_type(parent, C_OUTPUT); | ||
100 | return new_workspace(parent, name); | ||
101 | } | ||
102 | |||
103 | static bool _workspace_by_name(swayc_t *view, void *data) { | ||
104 | return (view->type == C_WORKSPACE) && | ||
105 | (strcasecmp(view->name, (char *) data) == 0); | ||
106 | } | 97 | } |
107 | 98 | ||
108 | swayc_t *workspace_by_name(const char* name) { | 99 | swayc_t *workspace_by_name(const char* name) { |
109 | if (strcmp(name, "prev") == 0) { | 100 | if (strcmp(name, "prev") == 0) { |
110 | return workspace_prev(); | 101 | return workspace_prev(); |
111 | } | 102 | } else if (!strcmp(name, "prev_on_output")) { |
112 | else if (strcmp(name, "prev_on_output") == 0) { | ||
113 | return workspace_output_prev(); | 103 | return workspace_output_prev(); |
114 | } | 104 | } else if (!strcmp(name, "next")) { |
115 | else if (strcmp(name, "next") == 0) { | ||
116 | return workspace_next(); | 105 | return workspace_next(); |
117 | } | 106 | } else if (!strcmp(name, "next_on_output")) { |
118 | else if (strcmp(name, "next_on_output") == 0) { | ||
119 | return workspace_output_next(); | 107 | return workspace_output_next(); |
120 | } | 108 | } else if (!strcmp(name, "current")) { |
121 | else if (strcmp(name, "current") == 0) { | ||
122 | return swayc_active_workspace(); | 109 | return swayc_active_workspace(); |
110 | } else if (!strcmp(name, "back_and_forth")) { | ||
111 | if (prev_workspace_name) { | ||
112 | name = prev_workspace_name; | ||
113 | } else { // If there is no prev workspace name. just return current | ||
114 | return swayc_active_workspace(); | ||
115 | } | ||
123 | } | 116 | } |
124 | else { | 117 | return workspace_by_name_only(name); |
125 | return swayc_by_test(&root_container, _workspace_by_name, (void *) name); | ||
126 | } | ||
127 | } | 118 | } |
128 | 119 | ||
129 | /** | 120 | /** |
@@ -181,19 +172,19 @@ swayc_t *workspace_prev_next_impl(swayc_t *workspace, bool next) { | |||
181 | return NULL; | 172 | return NULL; |
182 | } | 173 | } |
183 | 174 | ||
184 | swayc_t *workspace_output_next() { | 175 | swayc_t *workspace_output_next(void) { |
185 | return workspace_output_prev_next_impl(swayc_active_output(), true); | 176 | return workspace_output_prev_next_impl(swayc_active_output(), true); |
186 | } | 177 | } |
187 | 178 | ||
188 | swayc_t *workspace_next() { | 179 | swayc_t *workspace_next(void) { |
189 | return workspace_prev_next_impl(swayc_active_workspace(), true); | 180 | return workspace_prev_next_impl(swayc_active_workspace(), true); |
190 | } | 181 | } |
191 | 182 | ||
192 | swayc_t *workspace_output_prev() { | 183 | swayc_t *workspace_output_prev(void) { |
193 | return workspace_output_prev_next_impl(swayc_active_output(), false); | 184 | return workspace_output_prev_next_impl(swayc_active_output(), false); |
194 | } | 185 | } |
195 | 186 | ||
196 | swayc_t *workspace_prev() { | 187 | swayc_t *workspace_prev(void) { |
197 | return workspace_prev_next_impl(swayc_active_workspace(), false); | 188 | return workspace_prev_next_impl(swayc_active_workspace(), false); |
198 | } | 189 | } |
199 | 190 | ||
@@ -202,17 +193,17 @@ void workspace_switch(swayc_t *workspace) { | |||
202 | return; | 193 | return; |
203 | } | 194 | } |
204 | swayc_t *active_ws = swayc_active_workspace(); | 195 | swayc_t *active_ws = swayc_active_workspace(); |
205 | if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { | 196 | // set workspace to prev_workspace |
206 | swayc_t *new_ws = workspace_by_name(prev_workspace_name); | 197 | if (config->auto_back_and_forth && active_ws == workspace) { |
207 | workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); | 198 | workspace = new_workspace(NULL, "back_and_forth"); |
208 | } | 199 | } |
209 | 200 | ||
201 | // set prev workspace name | ||
210 | if (!prev_workspace_name | 202 | if (!prev_workspace_name |
211 | || (strcmp(prev_workspace_name, active_ws->name) | 203 | || (strcmp(prev_workspace_name, active_ws->name) |
212 | && active_ws != workspace)) { | 204 | && active_ws != workspace)) { |
213 | free(prev_workspace_name); | 205 | free(prev_workspace_name); |
214 | prev_workspace_name = malloc(strlen(active_ws->name)+1); | 206 | prev_workspace_name = strdup(active_ws->name); |
215 | strcpy(prev_workspace_name, active_ws->name); | ||
216 | } | 207 | } |
217 | 208 | ||
218 | sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); | 209 | sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); |