diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | include/container.h | 11 | ||||
-rw-r--r-- | include/input_state.h | 1 | ||||
-rw-r--r-- | include/stringop.h | 1 | ||||
-rw-r--r-- | sway-xorg.desktop | 5 | ||||
-rw-r--r-- | sway.desktop | 5 | ||||
-rw-r--r-- | sway/commands.c | 5 | ||||
-rw-r--r-- | sway/config.c | 3 | ||||
-rw-r--r-- | sway/container.c | 138 | ||||
-rw-r--r-- | sway/handlers.c | 15 | ||||
-rw-r--r-- | sway/input_state.c | 7 | ||||
-rw-r--r-- | sway/ipc.c | 92 | ||||
-rw-r--r-- | sway/layout.c | 10 | ||||
-rw-r--r-- | sway/stringop.c | 39 | ||||
-rw-r--r-- | sway/workspace.c | 4 |
15 files changed, 273 insertions, 71 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d190cd8b..3ed6fc02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -69,3 +69,11 @@ INSTALL( | |||
69 | FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sway.5 | 69 | FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sway.5 |
70 | DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man5 | 70 | DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man5 |
71 | ) | 71 | ) |
72 | |||
73 | INSTALL( | ||
74 | FILES ${PROJECT_SOURCE_DIR}/sway.desktop | ||
75 | DESTINATION ${CMAKE_INSTALL_PREFIX}/share/wayland-sessions/) | ||
76 | |||
77 | INSTALL( | ||
78 | FILES ${PROJECT_SOURCE_DIR}/sway-xorg.desktop | ||
79 | DESTINATION ${CMAKE_INSTALL_PREFIX}/share/xsessions/) | ||
diff --git a/include/container.h b/include/container.h index d3026011..3598067c 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -55,6 +55,7 @@ struct sway_container { | |||
55 | struct sway_container *focused; | 55 | struct sway_container *focused; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | // Container Creation | ||
58 | 59 | ||
59 | swayc_t *new_output(wlc_handle handle); | 60 | swayc_t *new_output(wlc_handle handle); |
60 | swayc_t *new_workspace(swayc_t *output, const char *name); | 61 | swayc_t *new_workspace(swayc_t *output, const char *name); |
@@ -65,13 +66,23 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle); | |||
65 | // Creates view as a new floating view which is in the active workspace | 66 | // Creates view as a new floating view which is in the active workspace |
66 | swayc_t *new_floating_view(wlc_handle handle); | 67 | swayc_t *new_floating_view(wlc_handle handle); |
67 | 68 | ||
69 | // Container Destroying | ||
68 | 70 | ||
69 | swayc_t *destroy_output(swayc_t *output); | 71 | swayc_t *destroy_output(swayc_t *output); |
70 | // Destroys workspace if empty and returns parent pointer, else returns NULL | 72 | // Destroys workspace if empty and returns parent pointer, else returns NULL |
71 | swayc_t *destroy_workspace(swayc_t *workspace); | 73 | swayc_t *destroy_workspace(swayc_t *workspace); |
74 | // Destroyes container and all parent container if they are empty, returns | ||
75 | // topmost non-empty parent. returns NULL otherwise | ||
72 | swayc_t *destroy_container(swayc_t *container); | 76 | swayc_t *destroy_container(swayc_t *container); |
77 | // Destroys view and all empty parent containers. return topmost non-empty | ||
78 | // parent | ||
73 | swayc_t *destroy_view(swayc_t *view); | 79 | swayc_t *destroy_view(swayc_t *view); |
74 | 80 | ||
81 | // Container Lookup | ||
82 | |||
83 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); | ||
84 | swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); | ||
85 | |||
75 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); | 86 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); |
76 | void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); | 87 | void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); |
77 | 88 | ||
diff --git a/include/input_state.h b/include/input_state.h index 7119c68b..27dd6cff 100644 --- a/include/input_state.h +++ b/include/input_state.h | |||
@@ -48,6 +48,7 @@ extern struct pointer_state { | |||
48 | 48 | ||
49 | void start_floating(swayc_t *view); | 49 | void start_floating(swayc_t *view); |
50 | void reset_floating(swayc_t *view); | 50 | void reset_floating(swayc_t *view); |
51 | void input_init(void); | ||
51 | 52 | ||
52 | #endif | 53 | #endif |
53 | 54 | ||
diff --git a/include/stringop.h b/include/stringop.h index a5346829..4300f9ed 100644 --- a/include/stringop.h +++ b/include/stringop.h | |||
@@ -10,5 +10,6 @@ char *code_strchr(const char *string, char delimiter); | |||
10 | char *code_strstr(const char *haystack, const char *needle); | 10 | char *code_strstr(const char *haystack, const char *needle); |
11 | int unescape_string(char *string); | 11 | int unescape_string(char *string); |
12 | char *join_args(char **argv, int argc); | 12 | char *join_args(char **argv, int argc); |
13 | char *join_list(list_t *list, char *separator); | ||
13 | 14 | ||
14 | #endif | 15 | #endif |
diff --git a/sway-xorg.desktop b/sway-xorg.desktop new file mode 100644 index 00000000..e93a4284 --- /dev/null +++ b/sway-xorg.desktop | |||
@@ -0,0 +1,5 @@ | |||
1 | [Desktop Entry] | ||
2 | Name=Sway (Xorg) | ||
3 | Comment=SirCmpwn's Wayland window manager | ||
4 | Exec=sway | ||
5 | Type=Application | ||
diff --git a/sway.desktop b/sway.desktop new file mode 100644 index 00000000..98c9af29 --- /dev/null +++ b/sway.desktop | |||
@@ -0,0 +1,5 @@ | |||
1 | [Desktop Entry] | ||
2 | Name=Sway | ||
3 | Comment=SirCmpwn's Wayland window manager | ||
4 | Exec=sway | ||
5 | Type=Application | ||
diff --git a/sway/commands.c b/sway/commands.c index 0f743b4e..d1bbdc89 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -390,7 +390,6 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) { | |||
390 | return false; | 390 | return false; |
391 | } | 391 | } |
392 | swayc_t *parent = get_focused_container(&root_container); | 392 | swayc_t *parent = get_focused_container(&root_container); |
393 | |||
394 | while (parent->type == C_VIEW) { | 393 | while (parent->type == C_VIEW) { |
395 | parent = parent->parent; | 394 | parent = parent->parent; |
396 | } | 395 | } |
@@ -665,9 +664,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { | |||
665 | // Resize workspace if going from fullscreen -> notfullscreen | 664 | // Resize workspace if going from fullscreen -> notfullscreen |
666 | // otherwise just resize container | 665 | // otherwise just resize container |
667 | if (current) { | 666 | if (current) { |
668 | while (container->type != C_WORKSPACE) { | 667 | container = swayc_parent_by_type(container, C_WORKSPACE); |
669 | container = container->parent; | ||
670 | } | ||
671 | } | 668 | } |
672 | // Only resize container when going into fullscreen | 669 | // Only resize container when going into fullscreen |
673 | arrange_windows(container, -1, -1); | 670 | arrange_windows(container, -1, -1); |
diff --git a/sway/config.c b/sway/config.c index 9f65e8a2..0afb0205 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "commands.h" | 9 | #include "commands.h" |
10 | #include "config.h" | 10 | #include "config.h" |
11 | #include "layout.h" | 11 | #include "layout.h" |
12 | #include "input_state.h" | ||
12 | 13 | ||
13 | struct sway_config *config; | 14 | struct sway_config *config; |
14 | 15 | ||
@@ -147,6 +148,8 @@ _continue: | |||
147 | bool load_config(const char *file) { | 148 | bool load_config(const char *file) { |
148 | sway_log(L_INFO, "Loading config"); | 149 | sway_log(L_INFO, "Loading config"); |
149 | 150 | ||
151 | input_init(); | ||
152 | |||
150 | char *path; | 153 | char *path; |
151 | if (file != NULL) { | 154 | if (file != NULL) { |
152 | path = strdup(file); | 155 | path = strdup(file); |
diff --git a/sway/container.c b/sway/container.c index 4559a5f5..7ccc2e09 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include "layout.h" | 8 | #include "layout.h" |
9 | #include "log.h" | 9 | #include "log.h" |
10 | 10 | ||
11 | #define ASSERT_NONNULL(PTR) \ | ||
12 | sway_assert (PTR, "%s: " #PTR "must be non-null", __func__) | ||
11 | 13 | ||
12 | static swayc_t *new_swayc(enum swayc_types type) { | 14 | static swayc_t *new_swayc(enum swayc_types type) { |
13 | swayc_t *c = calloc(1, sizeof(swayc_t)); | 15 | swayc_t *c = calloc(1, sizeof(swayc_t)); |
@@ -20,37 +22,40 @@ static swayc_t *new_swayc(enum swayc_types type) { | |||
20 | return c; | 22 | return c; |
21 | } | 23 | } |
22 | 24 | ||
23 | static void free_swayc(swayc_t *c) { | 25 | static void free_swayc(swayc_t *cont) { |
26 | if (!ASSERT_NONNULL(cont)) { | ||
27 | return; | ||
28 | } | ||
24 | // TODO does not properly handle containers with children, | 29 | // TODO does not properly handle containers with children, |
25 | // TODO but functions that call this usually check for that | 30 | // TODO but functions that call this usually check for that |
26 | if (c->children) { | 31 | if (cont->children) { |
27 | if (c->children->length) { | 32 | if (cont->children->length) { |
28 | int i; | 33 | int i; |
29 | for (i = 0; i < c->children->length; ++i) { | 34 | for (i = 0; i < cont->children->length; ++i) { |
30 | free_swayc(c->children->items[i]); | 35 | free_swayc(cont->children->items[i]); |
31 | } | 36 | } |
32 | } | 37 | } |
33 | list_free(c->children); | 38 | list_free(cont->children); |
34 | } | 39 | } |
35 | if (c->floating) { | 40 | if (cont->floating) { |
36 | if (c->floating->length) { | 41 | if (cont->floating->length) { |
37 | int i; | 42 | int i; |
38 | for (i = 0; i < c->floating->length; ++i) { | 43 | for (i = 0; i < cont->floating->length; ++i) { |
39 | free_swayc(c->floating->items[i]); | 44 | free_swayc(cont->floating->items[i]); |
40 | } | 45 | } |
41 | } | 46 | } |
42 | list_free(c->floating); | 47 | list_free(cont->floating); |
43 | } | 48 | } |
44 | if (c->parent) { | 49 | if (cont->parent) { |
45 | remove_child(c); | 50 | remove_child(cont); |
46 | } | 51 | } |
47 | if (c->name) { | 52 | if (cont->name) { |
48 | free(c->name); | 53 | free(cont->name); |
49 | } | 54 | } |
50 | free(c); | 55 | free(cont); |
51 | } | 56 | } |
52 | 57 | ||
53 | /* New containers */ | 58 | // New containers |
54 | 59 | ||
55 | static bool workspace_test(swayc_t *view, void *name) { | 60 | static bool workspace_test(swayc_t *view, void *name) { |
56 | return strcasecmp(view->name, (char *)name) == 0; | 61 | return strcasecmp(view->name, (char *)name) == 0; |
@@ -103,6 +108,9 @@ swayc_t *new_output(wlc_handle handle) { | |||
103 | } | 108 | } |
104 | 109 | ||
105 | swayc_t *new_workspace(swayc_t *output, const char *name) { | 110 | swayc_t *new_workspace(swayc_t *output, const char *name) { |
111 | if (!ASSERT_NONNULL(output)) { | ||
112 | return NULL; | ||
113 | } | ||
106 | sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); | 114 | sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); |
107 | swayc_t *workspace = new_swayc(C_WORKSPACE); | 115 | swayc_t *workspace = new_swayc(C_WORKSPACE); |
108 | 116 | ||
@@ -120,6 +128,9 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { | |||
120 | } | 128 | } |
121 | 129 | ||
122 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | 130 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { |
131 | if (!ASSERT_NONNULL(child)) { | ||
132 | return NULL; | ||
133 | } | ||
123 | swayc_t *cont = new_swayc(C_CONTAINER); | 134 | swayc_t *cont = new_swayc(C_CONTAINER); |
124 | 135 | ||
125 | sway_log(L_DEBUG, "creating container %p around %p", cont, child); | 136 | sway_log(L_DEBUG, "creating container %p around %p", cont, child); |
@@ -162,6 +173,9 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | |||
162 | } | 173 | } |
163 | 174 | ||
164 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | 175 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { |
176 | if (!ASSERT_NONNULL(sibling)) { | ||
177 | return NULL; | ||
178 | } | ||
165 | const char *title = wlc_view_get_title(handle); | 179 | const char *title = wlc_view_get_title(handle); |
166 | swayc_t *view = new_swayc(C_VIEW); | 180 | swayc_t *view = new_swayc(C_VIEW); |
167 | sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d", | 181 | sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d", |
@@ -172,14 +186,14 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | |||
172 | view->visible = true; | 186 | view->visible = true; |
173 | view->is_focused = true; | 187 | view->is_focused = true; |
174 | // Setup geometry | 188 | // Setup geometry |
189 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); | ||
175 | view->width = 0; | 190 | view->width = 0; |
176 | view->height = 0; | 191 | view->height = 0; |
192 | view->desired_width = geometry->size.w; | ||
193 | view->desired_height = geometry->size.h; | ||
177 | 194 | ||
178 | view->gaps = config->gaps_inner; | 195 | view->gaps = config->gaps_inner; |
179 | 196 | ||
180 | view->desired_width = -1; | ||
181 | view->desired_height = -1; | ||
182 | |||
183 | view->is_floating = false; | 197 | view->is_floating = false; |
184 | 198 | ||
185 | if (sibling->type == C_WORKSPACE) { | 199 | if (sibling->type == C_WORKSPACE) { |
@@ -225,9 +239,12 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
225 | return view; | 239 | return view; |
226 | } | 240 | } |
227 | 241 | ||
228 | /* Destroy container */ | 242 | // Destroy container |
229 | 243 | ||
230 | swayc_t *destroy_output(swayc_t *output) { | 244 | swayc_t *destroy_output(swayc_t *output) { |
245 | if (!ASSERT_NONNULL(output)) { | ||
246 | return NULL; | ||
247 | } | ||
231 | if (output->children->length == 0) { | 248 | if (output->children->length == 0) { |
232 | // TODO move workspaces to other outputs | 249 | // TODO move workspaces to other outputs |
233 | } | 250 | } |
@@ -237,23 +254,21 @@ swayc_t *destroy_output(swayc_t *output) { | |||
237 | } | 254 | } |
238 | 255 | ||
239 | swayc_t *destroy_workspace(swayc_t *workspace) { | 256 | swayc_t *destroy_workspace(swayc_t *workspace) { |
257 | if (!ASSERT_NONNULL(workspace)) { | ||
258 | return NULL; | ||
259 | } | ||
240 | // NOTE: This is called from elsewhere without checking children length | 260 | // NOTE: This is called from elsewhere without checking children length |
241 | // TODO move containers to other workspaces? | 261 | // TODO move containers to other workspaces? |
242 | // for now just dont delete | 262 | // for now just dont delete |
243 | 263 | ||
244 | // Do not destroy this if it's the last workspace on this output | 264 | // Do not destroy this if it's the last workspace on this output |
245 | swayc_t *output = workspace->parent; | 265 | swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); |
246 | while (output && output->type != C_OUTPUT) { | 266 | if (output && output->children->length == 1) { |
247 | output = output->parent; | 267 | return NULL; |
248 | } | ||
249 | if (output) { | ||
250 | if (output->children->length == 1) { | ||
251 | return NULL; | ||
252 | } | ||
253 | } | 268 | } |
254 | 269 | ||
255 | if (workspace->children->length == 0) { | 270 | if (workspace->children->length == 0) { |
256 | sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); | 271 | sway_log(L_DEBUG, "%s: '%s'", __func__, workspace->name); |
257 | swayc_t *parent = workspace->parent; | 272 | swayc_t *parent = workspace->parent; |
258 | free_swayc(workspace); | 273 | free_swayc(workspace); |
259 | return parent; | 274 | return parent; |
@@ -262,6 +277,9 @@ swayc_t *destroy_workspace(swayc_t *workspace) { | |||
262 | } | 277 | } |
263 | 278 | ||
264 | swayc_t *destroy_container(swayc_t *container) { | 279 | swayc_t *destroy_container(swayc_t *container) { |
280 | if (!ASSERT_NONNULL(container)) { | ||
281 | return NULL; | ||
282 | } | ||
265 | while (container->children->length == 0 && container->type == C_CONTAINER) { | 283 | while (container->children->length == 0 && container->type == C_CONTAINER) { |
266 | sway_log(L_DEBUG, "Container: Destroying container '%p'", container); | 284 | sway_log(L_DEBUG, "Container: Destroying container '%p'", container); |
267 | swayc_t *parent = container->parent; | 285 | swayc_t *parent = container->parent; |
@@ -272,8 +290,7 @@ swayc_t *destroy_container(swayc_t *container) { | |||
272 | } | 290 | } |
273 | 291 | ||
274 | swayc_t *destroy_view(swayc_t *view) { | 292 | swayc_t *destroy_view(swayc_t *view) { |
275 | if (view == NULL) { | 293 | if (!ASSERT_NONNULL(view)) { |
276 | sway_log(L_DEBUG, "Warning: NULL passed into destroy_view"); | ||
277 | return NULL; | 294 | return NULL; |
278 | } | 295 | } |
279 | sway_log(L_DEBUG, "Destroying view '%p'", view); | 296 | sway_log(L_DEBUG, "Destroying view '%p'", view); |
@@ -287,6 +304,34 @@ swayc_t *destroy_view(swayc_t *view) { | |||
287 | return parent; | 304 | return parent; |
288 | } | 305 | } |
289 | 306 | ||
307 | // Container lookup | ||
308 | |||
309 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { | ||
310 | if (!ASSERT_NONNULL(container)) { | ||
311 | return NULL; | ||
312 | } | ||
313 | if (!sway_assert(type < C_TYPES && type >= C_ROOT, "%s: invalid type", __func__)) { | ||
314 | return NULL; | ||
315 | } | ||
316 | do { | ||
317 | container = container->parent; | ||
318 | } while(container && container->type != type); | ||
319 | return container; | ||
320 | } | ||
321 | |||
322 | swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) { | ||
323 | if (!ASSERT_NONNULL(container)) { | ||
324 | return NULL; | ||
325 | } | ||
326 | if (!sway_assert(layout < L_LAYOUTS && layout >= L_NONE, "%s: invalid layout", __func__)) { | ||
327 | return NULL; | ||
328 | } | ||
329 | do { | ||
330 | container = container->parent; | ||
331 | } while (container && container->layout != layout); | ||
332 | return container; | ||
333 | } | ||
334 | |||
290 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | 335 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { |
291 | if (!container->children) { | 336 | if (!container->children) { |
292 | return NULL; | 337 | return NULL; |
@@ -316,25 +361,27 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da | |||
316 | } | 361 | } |
317 | 362 | ||
318 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | 363 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { |
319 | if (!container || !container->children || !container->children->length) { | 364 | if (container && container->children && container->children->length) { |
320 | return; | 365 | int i; |
321 | } | 366 | for (i = 0; i < container->children->length; ++i) { |
322 | int i; | 367 | swayc_t *child = container->children->items[i]; |
323 | for (i = 0; i < container->children->length; ++i) { | ||
324 | swayc_t *child = container->children->items[i]; | ||
325 | f(child, data); | ||
326 | container_map(child, f, data); | ||
327 | } | ||
328 | if (container->type == C_WORKSPACE) { | ||
329 | for (i = 0; i < container->floating->length; ++i) { | ||
330 | swayc_t *child = container->floating->items[i]; | ||
331 | f(child, data); | 368 | f(child, data); |
332 | container_map(child, f, data); | 369 | container_map(child, f, data); |
333 | } | 370 | } |
371 | if (container->type == C_WORKSPACE) { | ||
372 | for (i = 0; i < container->floating->length; ++i) { | ||
373 | swayc_t *child = container->floating->items[i]; | ||
374 | f(child, data); | ||
375 | container_map(child, f, data); | ||
376 | } | ||
377 | } | ||
334 | } | 378 | } |
335 | } | 379 | } |
336 | 380 | ||
337 | void set_view_visibility(swayc_t *view, void *data) { | 381 | void set_view_visibility(swayc_t *view, void *data) { |
382 | if (!ASSERT_NONNULL(view)) { | ||
383 | return; | ||
384 | } | ||
338 | uint32_t *p = data; | 385 | uint32_t *p = data; |
339 | if (view->type == C_VIEW) { | 386 | if (view->type == C_VIEW) { |
340 | wlc_view_set_mask(view->handle, *p); | 387 | wlc_view_set_mask(view->handle, *p); |
@@ -348,6 +395,9 @@ void set_view_visibility(swayc_t *view, void *data) { | |||
348 | } | 395 | } |
349 | 396 | ||
350 | void reset_gaps(swayc_t *view, void *data) { | 397 | void reset_gaps(swayc_t *view, void *data) { |
398 | if (!ASSERT_NONNULL(view)) { | ||
399 | return; | ||
400 | } | ||
351 | if (view->type == C_OUTPUT) { | 401 | if (view->type == C_OUTPUT) { |
352 | view->gaps = config->gaps_outer; | 402 | view->gaps = config->gaps_outer; |
353 | } | 403 | } |
diff --git a/sway/handlers.c b/sway/handlers.c index 571dd2a6..53eae439 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -21,10 +21,7 @@ static struct wlc_origin mouse_origin; | |||
21 | static bool pointer_test(swayc_t *view, void *_origin) { | 21 | static bool pointer_test(swayc_t *view, void *_origin) { |
22 | const struct wlc_origin *origin = _origin; | 22 | const struct wlc_origin *origin = _origin; |
23 | // Determine the output that the view is under | 23 | // Determine the output that the view is under |
24 | swayc_t *parent = view; | 24 | swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); |
25 | while (parent->type != C_OUTPUT) { | ||
26 | parent = parent->parent; | ||
27 | } | ||
28 | if (origin->x >= view->x && origin->y >= view->y | 25 | if (origin->x >= view->x && origin->y >= view->y |
29 | && origin->x < view->x + view->width && origin->y < view->y + view->height | 26 | && origin->x < view->x + view->width && origin->y < view->y + view->height |
30 | && view->visible && parent == root_container.focused) { | 27 | && view->visible && parent == root_container.focused) { |
@@ -192,10 +189,7 @@ static bool handle_view_created(wlc_handle handle) { | |||
192 | 189 | ||
193 | if (newview) { | 190 | if (newview) { |
194 | set_focused_container(newview); | 191 | set_focused_container(newview); |
195 | swayc_t *output = newview->parent; | 192 | swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT); |
196 | while (output && output->type != C_OUTPUT) { | ||
197 | output = output->parent; | ||
198 | } | ||
199 | arrange_windows(output, -1, -1); | 193 | arrange_windows(output, -1, -1); |
200 | } | 194 | } |
201 | return true; | 195 | return true; |
@@ -263,10 +257,7 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s | |||
263 | arrange_windows(c->parent, -1, -1); | 257 | arrange_windows(c->parent, -1, -1); |
264 | // Set it as focused window for that workspace if its going fullscreen | 258 | // Set it as focused window for that workspace if its going fullscreen |
265 | if (toggle) { | 259 | if (toggle) { |
266 | swayc_t *ws = c; | 260 | swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE); |
267 | while (ws->type != C_WORKSPACE) { | ||
268 | ws = ws->parent; | ||
269 | } | ||
270 | // Set ws focus to c | 261 | // Set ws focus to c |
271 | set_focused_container_for(ws, c); | 262 | set_focused_container_for(ws, c); |
272 | } | 263 | } |
diff --git a/sway/input_state.c b/sway/input_state.c index e592cfc1..ef5d6df0 100644 --- a/sway/input_state.c +++ b/sway/input_state.c | |||
@@ -8,6 +8,13 @@ | |||
8 | 8 | ||
9 | static keycode key_state_array[KEY_STATE_MAX_LENGTH]; | 9 | static keycode key_state_array[KEY_STATE_MAX_LENGTH]; |
10 | 10 | ||
11 | void input_init(void) { | ||
12 | int i; | ||
13 | for (i = 0; i < KEY_STATE_MAX_LENGTH; ++i) { | ||
14 | key_state_array[i] = 0; | ||
15 | } | ||
16 | } | ||
17 | |||
11 | static uint8_t find_key(keycode key) { | 18 | static uint8_t find_key(keycode key) { |
12 | int i; | 19 | int i; |
13 | for (i = 0; i < KEY_STATE_MAX_LENGTH; ++i) { | 20 | for (i = 0; i < KEY_STATE_MAX_LENGTH; ++i) { |
@@ -11,10 +11,13 @@ | |||
11 | #include <stropts.h> | 11 | #include <stropts.h> |
12 | #include <sys/ioctl.h> | 12 | #include <sys/ioctl.h> |
13 | #include <fcntl.h> | 13 | #include <fcntl.h> |
14 | #include <ctype.h> | ||
14 | #include "ipc.h" | 15 | #include "ipc.h" |
15 | #include "log.h" | 16 | #include "log.h" |
16 | #include "config.h" | 17 | #include "config.h" |
17 | #include "commands.h" | 18 | #include "commands.h" |
19 | #include "list.h" | ||
20 | #include "stringop.h" | ||
18 | 21 | ||
19 | static int ipc_socket = -1; | 22 | static int ipc_socket = -1; |
20 | static struct wlc_event_source *ipc_event_source = NULL; | 23 | static struct wlc_event_source *ipc_event_source = NULL; |
@@ -37,6 +40,10 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); | |||
37 | void ipc_client_disconnect(struct ipc_client *client); | 40 | void ipc_client_disconnect(struct ipc_client *client); |
38 | void ipc_client_handle_command(struct ipc_client *client); | 41 | void ipc_client_handle_command(struct ipc_client *client); |
39 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); | 42 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); |
43 | void ipc_get_workspaces_callback(swayc_t *container, void *data); | ||
44 | void ipc_get_outputs_callback(swayc_t *container, void *data); | ||
45 | |||
46 | char *json_list(list_t *items); | ||
40 | 47 | ||
41 | void ipc_init(void) { | 48 | void ipc_init(void) { |
42 | ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); | 49 | ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); |
@@ -195,6 +202,26 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
195 | ipc_send_reply(client, reply, (uint32_t) length); | 202 | ipc_send_reply(client, reply, (uint32_t) length); |
196 | break; | 203 | break; |
197 | } | 204 | } |
205 | case IPC_GET_WORKSPACES: | ||
206 | { | ||
207 | list_t *workspaces = create_list(); | ||
208 | container_map(&root_container, ipc_get_workspaces_callback, workspaces); | ||
209 | char *json = json_list(workspaces); | ||
210 | free_flat_list(workspaces); | ||
211 | ipc_send_reply(client, json, strlen(json)); | ||
212 | free(json); | ||
213 | break; | ||
214 | } | ||
215 | case IPC_GET_OUTPUTS: | ||
216 | { | ||
217 | list_t *outputs = create_list(); | ||
218 | container_map(&root_container, ipc_get_outputs_callback, outputs); | ||
219 | char *json = json_list(outputs); | ||
220 | free_flat_list(outputs); | ||
221 | ipc_send_reply(client, json, strlen(json)); | ||
222 | free(json); | ||
223 | break; | ||
224 | } | ||
198 | default: | 225 | default: |
199 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); | 226 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); |
200 | ipc_client_disconnect(client); | 227 | ipc_client_disconnect(client); |
@@ -227,3 +254,68 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
227 | 254 | ||
228 | return true; | 255 | return true; |
229 | } | 256 | } |
257 | |||
258 | char *json_list(list_t *items) { | ||
259 | char *json_elements = join_list(items, ","); | ||
260 | size_t len = strlen(json_elements); | ||
261 | char *json = malloc(len + 3); | ||
262 | json[0] = '['; | ||
263 | memcpy(json + 1, json_elements, len); | ||
264 | json[len+1] = ']'; | ||
265 | json[len+2] = '\0'; | ||
266 | free(json_elements); | ||
267 | return json; | ||
268 | } | ||
269 | |||
270 | void ipc_get_workspaces_callback(swayc_t *container, void *data) { | ||
271 | if (container->type == C_WORKSPACE) { | ||
272 | char *json = malloc(512); // Output should usually be around 180 chars | ||
273 | int num = isdigit(container->name[0]) ? atoi(container->name) : -1; | ||
274 | // TODO: escape the name (quotation marks, unicode) | ||
275 | sprintf(json, | ||
276 | "{" | ||
277 | "\"num\":%d," | ||
278 | "\"name\":\"%s\"," | ||
279 | "\"visible\":%s," | ||
280 | "\"focused\":%s," | ||
281 | "\"rect\":{" | ||
282 | "\"x\":%d," | ||
283 | "\"y\":%d," | ||
284 | "\"width\":%d," | ||
285 | "\"height\":%d" | ||
286 | "}," | ||
287 | "\"output\":\"%s\"," | ||
288 | "\"urgent\":%s" | ||
289 | "}", | ||
290 | num, container->name, container->visible ? "true" : "false", container->is_focused ? "true" : "false", | ||
291 | container->x, container->y, container->width, container->height, | ||
292 | container->parent->name, "false" // TODO: urgent hint | ||
293 | ); | ||
294 | list_add((list_t *)data, json); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | void ipc_get_outputs_callback(swayc_t *container, void *data) { | ||
299 | if (container->type == C_OUTPUT) { | ||
300 | char *json = malloc(512); // Output should usually be around 130 chars | ||
301 | // TODO: escape the name (quotation marks, unicode) | ||
302 | sprintf(json, | ||
303 | "{" | ||
304 | "\"name\":\"%s\"," | ||
305 | "\"active\":%s," | ||
306 | "\"primary\":%s," | ||
307 | "\"rect\":{" | ||
308 | "\"x\":%d," | ||
309 | "\"y\":%d," | ||
310 | "\"width\":%d," | ||
311 | "\"height\":%d" | ||
312 | "}," | ||
313 | "\"current_workspace\":\"%s\"" | ||
314 | "}", | ||
315 | container->name, "true", "false", // TODO: active, primary | ||
316 | container->x, container->y, container->width, container->height, | ||
317 | container->focused ? container->focused->name : "" | ||
318 | ); | ||
319 | list_add((list_t *)data, json); | ||
320 | } | ||
321 | } | ||
diff --git a/sway/layout.c b/sway/layout.c index 12b27987..35aa4942 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -161,10 +161,7 @@ void arrange_windows(swayc_t *container, double width, double height) { | |||
161 | } | 161 | } |
162 | }; | 162 | }; |
163 | if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { | 163 | if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { |
164 | swayc_t *parent = container; | 164 | swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT); |
165 | while (parent->type != C_OUTPUT) { | ||
166 | parent = parent->parent; | ||
167 | } | ||
168 | geometry.origin.x = 0; | 165 | geometry.origin.x = 0; |
169 | geometry.origin.y = 0; | 166 | geometry.origin.y = 0; |
170 | geometry.size.w = parent->width; | 167 | geometry.size.w = parent->width; |
@@ -263,10 +260,7 @@ void arrange_windows(swayc_t *container, double width, double height) { | |||
263 | } | 260 | } |
264 | }; | 261 | }; |
265 | if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { | 262 | if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { |
266 | swayc_t *parent = view; | 263 | swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); |
267 | while (parent->type != C_OUTPUT) { | ||
268 | parent = parent->parent; | ||
269 | } | ||
270 | geometry.origin.x = 0; | 264 | geometry.origin.x = 0; |
271 | geometry.origin.y = 0; | 265 | geometry.origin.y = 0; |
272 | geometry.size.w = parent->width; | 266 | geometry.size.w = parent->width; |
diff --git a/sway/stringop.c b/sway/stringop.c index 1dff97bf..c39e2c34 100644 --- a/sway/stringop.c +++ b/sway/stringop.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include "string.h" | 4 | #include "string.h" |
5 | #include "list.h" | 5 | #include "list.h" |
6 | #include <strings.h> | 6 | #include <strings.h> |
7 | #include <log.h> | ||
7 | 8 | ||
8 | /* Note: This returns 8 characters for trimmed_start per tab character. */ | 9 | /* Note: This returns 8 characters for trimmed_start per tab character. */ |
9 | char *strip_whitespace(char *_str, int *trimmed_start) { | 10 | char *strip_whitespace(char *_str, int *trimmed_start) { |
@@ -197,3 +198,41 @@ char *join_args(char **argv, int argc) { | |||
197 | res[len - 1] = '\0'; | 198 | res[len - 1] = '\0'; |
198 | return res; | 199 | return res; |
199 | } | 200 | } |
201 | |||
202 | /* | ||
203 | * Join a list of strings, adding separator in between. Separator can be NULL. | ||
204 | */ | ||
205 | char *join_list(list_t *list, char *separator) { | ||
206 | if (!sway_assert(list != NULL, "list != NULL") || list->length == 0) { | ||
207 | return NULL; | ||
208 | } | ||
209 | |||
210 | size_t len = 1; // NULL terminator | ||
211 | size_t sep_len = 0; | ||
212 | if (separator != NULL) { | ||
213 | sep_len = strlen(separator); | ||
214 | len += (list->length - 1) * sep_len; | ||
215 | } | ||
216 | |||
217 | for (int i = 0; i < list->length; i++) { | ||
218 | len += strlen(list->items[i]); | ||
219 | } | ||
220 | |||
221 | char *res = malloc(len); | ||
222 | |||
223 | char *p = res + strlen(list->items[0]); | ||
224 | strcpy(res, list->items[0]); | ||
225 | |||
226 | for (int i = 1; i < list->length; i++) { | ||
227 | if (sep_len) { | ||
228 | memcpy(p, separator, sep_len); | ||
229 | p += sep_len; | ||
230 | } | ||
231 | strcpy(p, list->items[i]); | ||
232 | p += strlen(list->items[i]); | ||
233 | } | ||
234 | |||
235 | *p = '\0'; | ||
236 | |||
237 | return res; | ||
238 | } | ||
diff --git a/sway/workspace.c b/sway/workspace.c index 0f44d3b0..d436da8e 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -75,9 +75,7 @@ char *workspace_next_name(void) { | |||
75 | 75 | ||
76 | swayc_t *workspace_create(const char* name) { | 76 | swayc_t *workspace_create(const char* name) { |
77 | swayc_t *parent = get_focused_container(&root_container); | 77 | swayc_t *parent = get_focused_container(&root_container); |
78 | while (parent->type != C_OUTPUT) { | 78 | parent = swayc_parent_by_type(parent, C_OUTPUT); |
79 | parent = parent->parent; | ||
80 | } | ||
81 | return new_workspace(parent, name); | 79 | return new_workspace(parent, name); |
82 | } | 80 | } |
83 | 81 | ||