diff options
-rw-r--r-- | README.md | 46 | ||||
-rw-r--r-- | include/stringop.h | 4 | ||||
-rw-r--r-- | sway/commands.c | 8 | ||||
-rw-r--r-- | sway/config.c | 5 | ||||
-rw-r--r-- | sway/container.c | 51 | ||||
-rw-r--r-- | sway/focus.c | 79 | ||||
-rw-r--r-- | sway/handlers.c | 42 | ||||
-rw-r--r-- | sway/layout.c | 62 | ||||
-rw-r--r-- | sway/stringop.c | 52 | ||||
-rw-r--r-- | sway/workspace.c | 55 |
10 files changed, 262 insertions, 142 deletions
@@ -1,14 +1,11 @@ | |||
1 | # sway | 1 | # sway |
2 | 2 | ||
3 | "**S**irCmpwn's **Way**land window manager" | 3 | "**S**irCmpwn's **Way**land window manager" is a **work in progress** |
4 | 4 | i3-compatible window manager for [Wayland](http://wayland.freedesktop.org/). | |
5 | sway is a **work in progress** i3-compatible window manager for | 5 | Read the [FAQ](https://github.com/SirCmpwn/sway/wiki). |
6 | [Wayland](http://wayland.freedesktop.org/). | ||
7 | 6 | ||
8 | ![](https://sr.ht/qxGE.png) | 7 | ![](https://sr.ht/qxGE.png) |
9 | 8 | ||
10 | Chat on #sway on irc.freenode.net | ||
11 | |||
12 | ## Rationale | 9 | ## Rationale |
13 | 10 | ||
14 | I use i3 on xorg. Wayland is coming, and [i3way](http://i3way.org/) still has | 11 | I use i3 on xorg. Wayland is coming, and [i3way](http://i3way.org/) still has |
@@ -20,44 +17,39 @@ zero lines of source code after two years. | |||
20 | 17 | ||
21 | ## Installation | 18 | ## Installation |
22 | 19 | ||
23 | ### Arch Linux | 20 | ### From Packages |
21 | |||
22 | sway is not supported by many distributions yet. Here's a list of packages | ||
23 | available for you to install: | ||
24 | 24 | ||
25 | Install [aur/sway-git](https://aur.archlinux.org/packages/sway-git/). | 25 | * [Arch Linux](https://aur.archlinux.org/packages/sway-git/). |
26 | 26 | ||
27 | ### Manual | 27 | ### Compiling from Source |
28 | 28 | ||
29 | Dependencies: | 29 | Install dependencies: |
30 | 30 | ||
31 | * cmake | 31 | * cmake |
32 | * [wlc](https://github.com/Cloudef/wlc) | 32 | * [wlc](https://github.com/Cloudef/wlc) |
33 | * xwayland | 33 | * xwayland |
34 | * asciidoc | 34 | * asciidoc |
35 | 35 | ||
36 | Compiling: | 36 | Run these commands: |
37 | 37 | ||
38 | cmake . | 38 | cmake . |
39 | make | 39 | make |
40 | # sudo make install | 40 | sudo make install |
41 | |||
42 | Binary shows up in `./bin` (or `/usr/local/bin` if you `make install`). | ||
43 | 41 | ||
44 | ## Configuration | 42 | ## Configuration |
45 | 43 | ||
46 | mkdir ~/.config/sway | 44 | If you already use i3, then copy your i3 config to `~/.config/sway/config` and |
47 | cp ~/.config/i3/config ~/.config/sway/ | 45 | it'll work out of the box. Otherwise, copy `/etc/sway/config` to |
48 | 46 | `~/.config/sway/config`. Run `man 5 sway` for information on the configuration. | |
49 | Or if you don't already use i3: | ||
50 | |||
51 | mkdir ~/.config/sway | ||
52 | cp /etc/sway/config ~/.config/sway/ | ||
53 | |||
54 | Edit to your liking. | ||
55 | |||
56 | [See also](http://i3wm.org/docs/) | ||
57 | 47 | ||
58 | ## Running | 48 | ## Running |
59 | 49 | ||
50 | Run this from a tty (instead of starting x): | ||
51 | |||
60 | sway | 52 | sway |
61 | 53 | ||
62 | If you run this while xorg is running, it'll run inside of an x window (useful | 54 | If you run it from within x, it will spawn x windows instead of using your |
63 | for testing). Otherwise, it'll run wayland properly. | 55 | hardware directly (useful for development). |
diff --git a/include/stringop.h b/include/stringop.h index 03387345..a5346829 100644 --- a/include/stringop.h +++ b/include/stringop.h | |||
@@ -2,8 +2,8 @@ | |||
2 | #define _SWAY_STRINGOP_H | 2 | #define _SWAY_STRINGOP_H |
3 | #include "list.h" | 3 | #include "list.h" |
4 | 4 | ||
5 | void strip_whitespace(char *str); | 5 | char *strip_whitespace(char *str, int *trimmed_start); |
6 | void strip_comments(char *str); | 6 | char *strip_comments(char *str); |
7 | list_t *split_string(const char *str, const char *delims); | 7 | list_t *split_string(const char *str, const char *delims); |
8 | void free_flat_list(list_t *list); | 8 | void free_flat_list(list_t *list); |
9 | char *code_strchr(const char *string, char delimiter); | 9 | char *code_strchr(const char *string, char delimiter); |
diff --git a/sway/commands.c b/sway/commands.c index 19704064..9a3ea5d6 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -413,7 +413,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { | |||
413 | return false; | 413 | return false; |
414 | } | 414 | } |
415 | 415 | ||
416 | swayc_t *container = get_focused_container(&root_container); | 416 | swayc_t *container = get_focused_view(&root_container); |
417 | bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0; | 417 | bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0; |
418 | wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); | 418 | wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); |
419 | //Resize workspace if going from fullscreen -> notfullscreen | 419 | //Resize workspace if going from fullscreen -> notfullscreen |
@@ -512,7 +512,7 @@ static char **split_directive(char *line, int *argc) { | |||
512 | if (!*line) return parts; | 512 | if (!*line) return parts; |
513 | 513 | ||
514 | int in_string = 0, in_character = 0; | 514 | int in_string = 0, in_character = 0; |
515 | int i, j; | 515 | int i, j, _; |
516 | for (i = 0, j = 0; line[i]; ++i) { | 516 | for (i = 0, j = 0; line[i]; ++i) { |
517 | if (line[i] == '\\') { | 517 | if (line[i] == '\\') { |
518 | ++i; | 518 | ++i; |
@@ -525,7 +525,7 @@ static char **split_directive(char *line, int *argc) { | |||
525 | char *item = malloc(i - j + 1); | 525 | char *item = malloc(i - j + 1); |
526 | strncpy(item, line + j, i - j); | 526 | strncpy(item, line + j, i - j); |
527 | item[i - j] = '\0'; | 527 | item[i - j] = '\0'; |
528 | strip_whitespace(item); | 528 | item = strip_whitespace(item, &_); |
529 | if (item[0] == '\0') { | 529 | if (item[0] == '\0') { |
530 | free(item); | 530 | free(item); |
531 | } else { | 531 | } else { |
@@ -543,7 +543,7 @@ static char **split_directive(char *line, int *argc) { | |||
543 | char *item = malloc(i - j + 1); | 543 | char *item = malloc(i - j + 1); |
544 | strncpy(item, line + j, i - j); | 544 | strncpy(item, line + j, i - j); |
545 | item[i - j] = '\0'; | 545 | item[i - j] = '\0'; |
546 | strip_whitespace(item); | 546 | item = strip_whitespace(item, &_); |
547 | if (*argc == capacity) { | 547 | if (*argc == capacity) { |
548 | capacity++; | 548 | capacity++; |
549 | parts = realloc(parts, sizeof(char *) * capacity); | 549 | parts = realloc(parts, sizeof(char *) * capacity); |
diff --git a/sway/config.c b/sway/config.c index 6d39839d..f1de6080 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -186,9 +186,10 @@ bool read_config(FILE *file, bool is_active) { | |||
186 | int temp_depth = 0; // Temporary: skip all config sections with depth | 186 | int temp_depth = 0; // Temporary: skip all config sections with depth |
187 | 187 | ||
188 | while (!feof(file)) { | 188 | while (!feof(file)) { |
189 | int _; | ||
189 | char *line = read_line(file); | 190 | char *line = read_line(file); |
190 | strip_comments(line); | 191 | line = strip_comments(line); |
191 | strip_whitespace(line); | 192 | line = strip_whitespace(line, &_); |
192 | if (!line[0]) { | 193 | if (!line[0]) { |
193 | goto _continue; | 194 | goto _continue; |
194 | } | 195 | } |
diff --git a/sway/container.c b/sway/container.c index e679e823..62c5bda0 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include "config.h" | 4 | #include "config.h" |
5 | #include "container.h" | 5 | #include "container.h" |
6 | #include "workspace.h" | 6 | #include "workspace.h" |
7 | #include "focus.h" | ||
7 | #include "layout.h" | 8 | #include "layout.h" |
8 | #include "log.h" | 9 | #include "log.h" |
9 | 10 | ||
@@ -21,11 +22,26 @@ static swayc_t *new_swayc(enum swayc_types type) { | |||
21 | } | 22 | } |
22 | 23 | ||
23 | static void free_swayc(swayc_t *c) { | 24 | static void free_swayc(swayc_t *c) { |
24 | //TODO does not properly handle containers with children, | 25 | // TODO does not properly handle containers with children, |
25 | //TODO but functions that call this usually check for that | 26 | // TODO but functions that call this usually check for that |
26 | if (c->children) { | 27 | if (c->children) { |
28 | if (c->children->length) { | ||
29 | int i; | ||
30 | for (i = 0; i < c->children->length; ++i) { | ||
31 | free_swayc(c->children->items[i]); | ||
32 | } | ||
33 | } | ||
27 | list_free(c->children); | 34 | list_free(c->children); |
28 | } | 35 | } |
36 | if (c->floating) { | ||
37 | if (c->floating->length) { | ||
38 | int i; | ||
39 | for (i = 0; i < c->floating->length; ++i) { | ||
40 | free_swayc(c->floating->items[i]); | ||
41 | } | ||
42 | } | ||
43 | list_free(c->floating); | ||
44 | } | ||
29 | if (c->parent) { | 45 | if (c->parent) { |
30 | remove_child(c); | 46 | remove_child(c); |
31 | } | 47 | } |
@@ -37,6 +53,10 @@ static void free_swayc(swayc_t *c) { | |||
37 | 53 | ||
38 | /* New containers */ | 54 | /* New containers */ |
39 | 55 | ||
56 | static bool workspace_test(swayc_t *view, void *name) { | ||
57 | return strcasecmp(view->name, (char *)name); | ||
58 | } | ||
59 | |||
40 | swayc_t *new_output(wlc_handle handle) { | 60 | swayc_t *new_output(wlc_handle handle) { |
41 | const struct wlc_size* size = wlc_output_get_resolution(handle); | 61 | const struct wlc_size* size = wlc_output_get_resolution(handle); |
42 | const char *name = wlc_output_get_name(handle); | 62 | const char *name = wlc_output_get_name(handle); |
@@ -58,6 +78,10 @@ swayc_t *new_output(wlc_handle handle) { | |||
58 | struct workspace_output *wso = config->workspace_outputs->items[i]; | 78 | struct workspace_output *wso = config->workspace_outputs->items[i]; |
59 | if (strcasecmp(wso->output, name) == 0) { | 79 | if (strcasecmp(wso->output, name) == 0) { |
60 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); | 80 | sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); |
81 | // Check if any other workspaces are using this name | ||
82 | if (find_container(&root_container, workspace_test, wso->workspace)) { | ||
83 | break; | ||
84 | } | ||
61 | ws_name = strdup(wso->workspace); | 85 | ws_name = strdup(wso->workspace); |
62 | break; | 86 | break; |
63 | } | 87 | } |
@@ -186,7 +210,7 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
186 | list_add(active_workspace->floating, view); | 210 | list_add(active_workspace->floating, view); |
187 | view->parent = active_workspace; | 211 | view->parent = active_workspace; |
188 | if (active_workspace->focused == NULL) { | 212 | if (active_workspace->focused == NULL) { |
189 | active_workspace->focused = view; | 213 | set_focused_container_for(active_workspace, view); |
190 | } | 214 | } |
191 | return view; | 215 | return view; |
192 | } | 216 | } |
@@ -206,6 +230,18 @@ swayc_t *destroy_workspace(swayc_t *workspace) { | |||
206 | // NOTE: This is called from elsewhere without checking children length | 230 | // NOTE: This is called from elsewhere without checking children length |
207 | // TODO move containers to other workspaces? | 231 | // TODO move containers to other workspaces? |
208 | // for now just dont delete | 232 | // for now just dont delete |
233 | |||
234 | // Do not destroy this if it's the last workspace on this output | ||
235 | swayc_t *output = workspace->parent; | ||
236 | while (output && output->type != C_OUTPUT) { | ||
237 | output = output->parent; | ||
238 | } | ||
239 | if (output) { | ||
240 | if (output->children->length == 1) { | ||
241 | return NULL; | ||
242 | } | ||
243 | } | ||
244 | |||
209 | if (workspace->children->length == 0) { | 245 | if (workspace->children->length == 0) { |
210 | sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); | 246 | sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); |
211 | swayc_t *parent = workspace->parent; | 247 | swayc_t *parent = workspace->parent; |
@@ -271,7 +307,7 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da | |||
271 | } | 307 | } |
272 | 308 | ||
273 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | 309 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { |
274 | if (!container->children || !container->children->length) { | 310 | if (!container || !container->children || !container->children->length) { |
275 | return; | 311 | return; |
276 | } | 312 | } |
277 | int i; | 313 | int i; |
@@ -280,6 +316,13 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi | |||
280 | f(child, data); | 316 | f(child, data); |
281 | container_map(child, f, data); | 317 | container_map(child, f, data); |
282 | } | 318 | } |
319 | if (container->type == C_WORKSPACE) { | ||
320 | for (i = 0; i < container->floating->length; ++i) { | ||
321 | swayc_t *child = container->floating->items[i]; | ||
322 | f(child, data); | ||
323 | container_map(child, f, data); | ||
324 | } | ||
325 | } | ||
283 | } | 326 | } |
284 | 327 | ||
285 | void set_view_visibility(swayc_t *view, void *data) { | 328 | void set_view_visibility(swayc_t *view, void *data) { |
diff --git a/sway/focus.c b/sway/focus.c index 99cb2570..628316dd 100644 --- a/sway/focus.c +++ b/sway/focus.c | |||
@@ -14,11 +14,15 @@ static void update_focus(swayc_t *c) { | |||
14 | swayc_t *parent = c->parent; | 14 | swayc_t *parent = c->parent; |
15 | if (parent->focused != c) { | 15 | if (parent->focused != c) { |
16 | switch (c->type) { | 16 | switch (c->type) { |
17 | // Shouldnt happen | ||
17 | case C_ROOT: return; | 18 | case C_ROOT: return; |
19 | |||
20 | // Case where output changes | ||
18 | case C_OUTPUT: | 21 | case C_OUTPUT: |
19 | wlc_output_focus(c->parent->handle); | 22 | wlc_output_focus(c->handle); |
20 | break; | 23 | break; |
21 | // switching workspaces | 24 | |
25 | // Case where workspace changes | ||
22 | case C_WORKSPACE: | 26 | case C_WORKSPACE: |
23 | if (parent->focused) { | 27 | if (parent->focused) { |
24 | swayc_t *ws = parent->focused; | 28 | swayc_t *ws = parent->focused; |
@@ -29,10 +33,12 @@ static void update_focus(swayc_t *c) { | |||
29 | mask = 2; | 33 | mask = 2; |
30 | container_map(c, set_view_visibility, &mask); | 34 | container_map(c, set_view_visibility, &mask); |
31 | wlc_output_set_mask(parent->handle, 2); | 35 | wlc_output_set_mask(parent->handle, 2); |
36 | c->parent->focused = c; | ||
32 | destroy_workspace(ws); | 37 | destroy_workspace(ws); |
33 | } | 38 | } |
34 | active_workspace = c; | 39 | active_workspace = c; |
35 | break; | 40 | break; |
41 | |||
36 | default: | 42 | default: |
37 | case C_VIEW: | 43 | case C_VIEW: |
38 | case C_CONTAINER: | 44 | case C_CONTAINER: |
@@ -49,6 +55,10 @@ bool move_focus(enum movement_direction direction) { | |||
49 | return false; | 55 | return false; |
50 | } | 56 | } |
51 | swayc_t *current = get_focused_container(&root_container); | 57 | swayc_t *current = get_focused_container(&root_container); |
58 | if (current->type == C_VIEW | ||
59 | && wlc_view_get_state(current->handle) & WLC_BIT_FULLSCREEN) { | ||
60 | return false; | ||
61 | } | ||
52 | swayc_t *parent = current->parent; | 62 | swayc_t *parent = current->parent; |
53 | 63 | ||
54 | if (direction == MOVE_PARENT) { | 64 | if (direction == MOVE_PARENT) { |
@@ -128,23 +138,39 @@ void set_focused_container(swayc_t *c) { | |||
128 | return; | 138 | return; |
129 | } | 139 | } |
130 | sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); | 140 | sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); |
131 | if (c->type != C_ROOT && c->type != C_OUTPUT) { | 141 | |
132 | c->is_focused = true; | 142 | // Find previous focused view, and the new focused view, if they are the same return |
143 | swayc_t *focused = get_focused_view(&root_container); | ||
144 | swayc_t *workspace = active_workspace; | ||
145 | if (focused == get_focused_view(c)) { | ||
146 | return; | ||
133 | } | 147 | } |
134 | swayc_t *prev_view = get_focused_view(&root_container); | 148 | |
149 | // update container focus from here to root, making necessary changes along | ||
150 | // the way | ||
135 | swayc_t *p = c; | 151 | swayc_t *p = c; |
136 | while (p != &root_container) { | 152 | while (p != &root_container) { |
137 | update_focus(p); | 153 | update_focus(p); |
138 | p = p->parent; | 154 | p = p->parent; |
139 | p->is_focused = false; | 155 | p->is_focused = false; |
140 | } | 156 | } |
141 | if (!locked_view_focus) { | 157 | |
142 | p = get_focused_view(c); | 158 | // if the workspace is the same, and previous focus is fullscreen, dont |
143 | // Set focus to p | 159 | // change focus |
144 | if (p && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { | 160 | if (workspace == active_workspace |
145 | if (prev_view) { | 161 | && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { |
146 | wlc_view_set_state(prev_view->handle, WLC_BIT_ACTIVATED, false); | 162 | return; |
147 | } | 163 | } |
164 | |||
165 | // get new focused view and set focus to it. | ||
166 | p = get_focused_view(c); | ||
167 | if (p->type == C_VIEW && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { | ||
168 | // unactivate previous focus | ||
169 | if (focused->type == C_VIEW) { | ||
170 | wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); | ||
171 | } | ||
172 | // activate current focus | ||
173 | if (p->type == C_VIEW) { | ||
148 | wlc_view_focus(p->handle); | 174 | wlc_view_focus(p->handle); |
149 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); | 175 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); |
150 | } | 176 | } |
@@ -156,12 +182,25 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { | |||
156 | return; | 182 | return; |
157 | } | 183 | } |
158 | swayc_t *find = c; | 184 | swayc_t *find = c; |
159 | //Ensure that a is an ancestor of c | 185 | // Ensure that a is an ancestor of c |
160 | while (find != a && (find = find->parent)) { | 186 | while (find != a && (find = find->parent)) { |
161 | if (find == &root_container) { | 187 | if (find == &root_container) { |
162 | return; | 188 | return; |
163 | } | 189 | } |
164 | } | 190 | } |
191 | // Check if we changing a parent container that will see chnage | ||
192 | bool effective = true; | ||
193 | while (find != &root_container) { | ||
194 | if (find->parent->focused != find) { | ||
195 | effective = false; | ||
196 | } | ||
197 | find = find->parent; | ||
198 | } | ||
199 | if (effective) { | ||
200 | // Go to set_focused_container | ||
201 | set_focused_container(c); | ||
202 | return; | ||
203 | } | ||
165 | 204 | ||
166 | sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", | 205 | sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", |
167 | a, a->handle, c, c->handle); | 206 | a, a->handle, c, c->handle); |
@@ -173,19 +212,17 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { | |||
173 | p = p->parent; | 212 | p = p->parent; |
174 | p->is_focused = false; | 213 | p->is_focused = false; |
175 | } | 214 | } |
176 | if (!locked_view_focus) { | ||
177 | p = get_focused_view(c); | ||
178 | // Set focus to p | ||
179 | if (p) { | ||
180 | wlc_view_focus(p->handle); | ||
181 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); | ||
182 | } | ||
183 | } | ||
184 | } | 215 | } |
185 | 216 | ||
186 | swayc_t *get_focused_view(swayc_t *parent) { | 217 | swayc_t *get_focused_view(swayc_t *parent) { |
187 | while (parent && parent->type != C_VIEW) { | 218 | while (parent && parent->type != C_VIEW) { |
219 | if (parent->type == C_WORKSPACE && parent->focused == NULL) { | ||
220 | return parent; | ||
221 | } | ||
188 | parent = parent->focused; | 222 | parent = parent->focused; |
189 | } | 223 | } |
224 | if (parent == NULL) { | ||
225 | return active_workspace; | ||
226 | } | ||
190 | return parent; | 227 | return parent; |
191 | } | 228 | } |
diff --git a/sway/handlers.c b/sway/handlers.c index cd97ab43..534b4e4f 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -57,14 +57,16 @@ swayc_t *container_under_pointer(void) { | |||
57 | } | 57 | } |
58 | // if workspace, search floating | 58 | // if workspace, search floating |
59 | if (lookup->type == C_WORKSPACE) { | 59 | if (lookup->type == C_WORKSPACE) { |
60 | len = lookup->floating->length; | 60 | i = len = lookup->floating->length; |
61 | for (i = 0; i < len; ++i) { | 61 | bool got_floating = false; |
62 | while (--i > -1) { | ||
62 | if (pointer_test(lookup->floating->items[i], &mouse_origin)) { | 63 | if (pointer_test(lookup->floating->items[i], &mouse_origin)) { |
63 | lookup = lookup->floating->items[i]; | 64 | lookup = lookup->floating->items[i]; |
65 | got_floating = true; | ||
64 | break; | 66 | break; |
65 | } | 67 | } |
66 | } | 68 | } |
67 | if (i < len) { | 69 | if (got_floating) { |
68 | continue; | 70 | continue; |
69 | } | 71 | } |
70 | } | 72 | } |
@@ -106,6 +108,12 @@ static void handle_output_destroyed(wlc_handle output) { | |||
106 | if (i < list->length) { | 108 | if (i < list->length) { |
107 | destroy_output(list->items[i]); | 109 | destroy_output(list->items[i]); |
108 | } | 110 | } |
111 | if (list->length == 0) { | ||
112 | active_workspace = NULL; | ||
113 | } else { | ||
114 | //switch to other outputs active workspace | ||
115 | workspace_switch(((swayc_t *)root_container.children->items[0])->focused); | ||
116 | } | ||
109 | } | 117 | } |
110 | 118 | ||
111 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { | 119 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { |
@@ -320,9 +328,12 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct | |||
320 | mouse_origin = *origin; | 328 | mouse_origin = *origin; |
321 | bool changed_floating = false; | 329 | bool changed_floating = false; |
322 | int i = 0; | 330 | int i = 0; |
331 | if (!active_workspace) { | ||
332 | return false; | ||
333 | } | ||
323 | // Do checks to determine if proper keys are being held | 334 | // Do checks to determine if proper keys are being held |
324 | swayc_t *view = active_workspace->focused; | 335 | swayc_t *view = active_workspace->focused; |
325 | if (m1_held) { | 336 | if (m1_held && view) { |
326 | if (view->is_floating) { | 337 | if (view->is_floating) { |
327 | while (keys_pressed[i++]) { | 338 | while (keys_pressed[i++]) { |
328 | if (keys_pressed[i] == config->floating_mod) { | 339 | if (keys_pressed[i] == config->floating_mod) { |
@@ -338,7 +349,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct | |||
338 | } | 349 | } |
339 | } | 350 | } |
340 | } | 351 | } |
341 | } else if (m2_held) { | 352 | } else if (m2_held && view) { |
342 | if (view->is_floating) { | 353 | if (view->is_floating) { |
343 | while (keys_pressed[i++]) { | 354 | while (keys_pressed[i++]) { |
344 | if (keys_pressed[i] == config->floating_mod) { | 355 | if (keys_pressed[i] == config->floating_mod) { |
@@ -400,7 +411,11 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct | |||
400 | } | 411 | } |
401 | } | 412 | } |
402 | if (config->focus_follows_mouse && prev_handle != handle) { | 413 | if (config->focus_follows_mouse && prev_handle != handle) { |
403 | set_focused_container(container_under_pointer()); | 414 | //Dont change focus if fullscreen |
415 | swayc_t *focused = get_focused_view(view); | ||
416 | if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) { | ||
417 | set_focused_container(container_under_pointer()); | ||
418 | } | ||
404 | } | 419 | } |
405 | prev_handle = handle; | 420 | prev_handle = handle; |
406 | prev_pos = mouse_origin; | 421 | prev_pos = mouse_origin; |
@@ -414,6 +429,10 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct | |||
414 | static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, | 429 | static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, |
415 | uint32_t button, enum wlc_button_state state) { | 430 | uint32_t button, enum wlc_button_state state) { |
416 | swayc_t *focused = get_focused_container(&root_container); | 431 | swayc_t *focused = get_focused_container(&root_container); |
432 | //dont change focus if fullscreen | ||
433 | if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { | ||
434 | return false; | ||
435 | } | ||
417 | if (state == WLC_BUTTON_STATE_PRESSED) { | 436 | if (state == WLC_BUTTON_STATE_PRESSED) { |
418 | sway_log(L_DEBUG, "Mouse button %u pressed", button); | 437 | sway_log(L_DEBUG, "Mouse button %u pressed", button); |
419 | if (button == 272) { | 438 | if (button == 272) { |
@@ -424,6 +443,17 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w | |||
424 | } | 443 | } |
425 | swayc_t *pointer = container_under_pointer(); | 444 | swayc_t *pointer = container_under_pointer(); |
426 | set_focused_container(pointer); | 445 | set_focused_container(pointer); |
446 | if (pointer->is_floating) { | ||
447 | int i; | ||
448 | for (i = 0; i < pointer->parent->floating->length; i++) { | ||
449 | if (pointer->parent->floating->items[i] == pointer) { | ||
450 | list_del(pointer->parent->floating, i); | ||
451 | list_add(pointer->parent->floating, pointer); | ||
452 | break; | ||
453 | } | ||
454 | } | ||
455 | arrange_windows(pointer->parent, -1, -1); | ||
456 | } | ||
427 | return (pointer && pointer != focused); | 457 | return (pointer && pointer != focused); |
428 | } else { | 458 | } else { |
429 | sway_log(L_DEBUG, "Mouse button %u released", button); | 459 | sway_log(L_DEBUG, "Mouse button %u released", button); |
diff --git a/sway/layout.c b/sway/layout.c index e2ea46a7..105359d2 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -1,11 +1,12 @@ | |||
1 | #include <stdlib.h> | 1 | #include <stdlib.h> |
2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
3 | #include <wlc/wlc.h> | 3 | #include <wlc/wlc.h> |
4 | #include "list.h" | ||
5 | #include "log.h" | ||
6 | #include "layout.h" | 4 | #include "layout.h" |
5 | #include "log.h" | ||
6 | #include "list.h" | ||
7 | #include "container.h" | 7 | #include "container.h" |
8 | #include "workspace.h" | 8 | #include "workspace.h" |
9 | #include "focus.h" | ||
9 | 10 | ||
10 | swayc_t root_container; | 11 | swayc_t root_container; |
11 | 12 | ||
@@ -79,9 +80,10 @@ swayc_t *remove_child(swayc_t *child) { | |||
79 | } | 80 | } |
80 | } | 81 | } |
81 | } | 82 | } |
83 | //Set focused to new container | ||
82 | if (parent->focused == child) { | 84 | if (parent->focused == child) { |
83 | if (parent->children->length > 0) { | 85 | if (parent->children->length > 0) { |
84 | parent->focused = parent->children->items[i?i-1:0]; | 86 | set_focused_container_for(parent, parent->children->items[i?i-1:0]); |
85 | } else { | 87 | } else { |
86 | parent->focused = NULL; | 88 | parent->focused = NULL; |
87 | } | 89 | } |
@@ -209,26 +211,42 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
209 | if (container->type == C_WORKSPACE) { | 211 | if (container->type == C_WORKSPACE) { |
210 | for (i = 0; i < container->floating->length; ++i) { | 212 | for (i = 0; i < container->floating->length; ++i) { |
211 | swayc_t *view = container->floating->items[i]; | 213 | swayc_t *view = container->floating->items[i]; |
212 | // Set the geometry | 214 | if (view->type == C_VIEW) { |
213 | struct wlc_geometry geometry = { | 215 | // Set the geometry |
214 | .origin = { | 216 | struct wlc_geometry geometry = { |
215 | .x = view->x, | 217 | .origin = { |
216 | .y = view->y | 218 | .x = view->x, |
217 | }, | 219 | .y = view->y |
218 | .size = { | 220 | }, |
219 | .w = view->width, | 221 | .size = { |
220 | .h = view->height | 222 | .w = view->width, |
223 | .h = view->height | ||
224 | } | ||
225 | }; | ||
226 | if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { | ||
227 | swayc_t *parent = view; | ||
228 | while (parent->type != C_OUTPUT) { | ||
229 | parent = parent->parent; | ||
230 | } | ||
231 | geometry.origin.x = 0; | ||
232 | geometry.origin.y = 0; | ||
233 | geometry.size.w = parent->width; | ||
234 | geometry.size.h = parent->height; | ||
235 | wlc_view_set_geometry(view->handle, &geometry); | ||
236 | wlc_view_bring_to_front(view->handle); | ||
237 | } else { | ||
238 | wlc_view_set_geometry(view->handle, &geometry); | ||
239 | view->width = width; | ||
240 | view->height = height; | ||
241 | // Bring the views to the front in order of the list, the list | ||
242 | // will be kept up to date so that more recently focused views | ||
243 | // have higher indexes | ||
244 | // This is conditional on there not being a fullscreen view in the workspace | ||
245 | if (!container->focused | ||
246 | || !(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) { | ||
247 | wlc_view_bring_to_front(view->handle); | ||
248 | } | ||
221 | } | 249 | } |
222 | }; | ||
223 | wlc_view_set_geometry(view->handle, &geometry); | ||
224 | |||
225 | // Bring the views to the front in order of the list, the list | ||
226 | // will be kept up to date so that more recently focused views | ||
227 | // have higher indexes | ||
228 | // This is conditional on there not being a fullscreen view in the workspace | ||
229 | if (!container->focused | ||
230 | || !(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) { | ||
231 | wlc_view_bring_to_front(view->handle); | ||
232 | } | 250 | } |
233 | } | 251 | } |
234 | } | 252 | } |
diff --git a/sway/stringop.c b/sway/stringop.c index 00cc32b8..1dff97bf 100644 --- a/sway/stringop.c +++ b/sway/stringop.c | |||
@@ -1,38 +1,37 @@ | |||
1 | #include "stringop.h" | ||
1 | #include <stdlib.h> | 2 | #include <stdlib.h> |
2 | #include <stdio.h> | 3 | #include <stdio.h> |
3 | #include <strings.h> | ||
4 | #include <ctype.h> | ||
5 | #include "stringop.h" | ||
6 | #include "string.h" | 4 | #include "string.h" |
7 | #include "list.h" | 5 | #include "list.h" |
6 | #include <strings.h> | ||
8 | 7 | ||
9 | /* Note: This returns 8 characters for trimmed_start per tab character. */ | 8 | /* Note: This returns 8 characters for trimmed_start per tab character. */ |
10 | void strip_whitespace(char *str) { | 9 | char *strip_whitespace(char *_str, int *trimmed_start) { |
11 | int shift = 0; | 10 | *trimmed_start = 0; |
12 | int bpair = 1; | 11 | if (*_str == '\0') |
13 | int in_str = 0, in_ch = 0; | 12 | return _str; |
14 | while (*str) { | 13 | char *strold = _str; |
15 | str[-shift] = str[0]; | 14 | while (*_str == ' ' || *_str == '\t') { |
16 | if (*str == '"' && !in_ch) { | 15 | if (*_str == '\t') { |
17 | in_str = !in_str; | 16 | *trimmed_start += 8; |
18 | } else if (*str == '\'' && !in_str) { | 17 | } else { |
19 | in_ch = !in_ch; | 18 | *trimmed_start += 1; |
20 | } else if (!in_ch && !in_str) { | ||
21 | if (isblank(*str)) { | ||
22 | if (bpair) { | ||
23 | ++shift; | ||
24 | } | ||
25 | bpair=1; | ||
26 | } else { | ||
27 | bpair = 0; | ||
28 | } | ||
29 | } | 19 | } |
30 | ++str; | 20 | _str++; |
31 | } | 21 | } |
32 | str[-shift-bpair] = 0; | 22 | char *str = malloc(strlen(_str) + 1); |
23 | strcpy(str, _str); | ||
24 | free(strold); | ||
25 | int i; | ||
26 | for (i = 0; str[i] != '\0'; ++i); | ||
27 | do { | ||
28 | i--; | ||
29 | } while (i >= 0 && (str[i] == ' ' || str[i] == '\t')); | ||
30 | str[i + 1] = '\0'; | ||
31 | return str; | ||
33 | } | 32 | } |
34 | 33 | ||
35 | void strip_comments(char *str) { | 34 | char *strip_comments(char *str) { |
36 | int in_string = 0, in_character = 0; | 35 | int in_string = 0, in_character = 0; |
37 | int i = 0; | 36 | int i = 0; |
38 | while (str[i] != '\0') { | 37 | while (str[i] != '\0') { |
@@ -41,13 +40,14 @@ void strip_comments(char *str) { | |||
41 | } else if (str[i] == '\'' && !in_string) { | 40 | } else if (str[i] == '\'' && !in_string) { |
42 | in_character = !in_character; | 41 | in_character = !in_character; |
43 | } else if (!in_character && !in_string) { | 42 | } else if (!in_character && !in_string) { |
44 | if (str[i] == '#') { | 43 | if (str[i] == '#' && i == 0) { |
45 | str[i] = '\0'; | 44 | str[i] = '\0'; |
46 | break; | 45 | break; |
47 | } | 46 | } |
48 | } | 47 | } |
49 | ++i; | 48 | ++i; |
50 | } | 49 | } |
50 | return str; | ||
51 | } | 51 | } |
52 | 52 | ||
53 | list_t *split_string(const char *str, const char *delims) { | 53 | list_t *split_string(const char *str, const char *delims) { |
diff --git a/sway/workspace.c b/sway/workspace.c index bc0fa2c8..05a669fe 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -174,36 +174,41 @@ void workspace_prev() { | |||
174 | } | 174 | } |
175 | 175 | ||
176 | void workspace_switch(swayc_t *workspace) { | 176 | void workspace_switch(swayc_t *workspace) { |
177 | set_focused_container(workspace); | 177 | if (!workspace) { |
178 | return; | ||
179 | } | ||
180 | sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); | ||
181 | set_focused_container(get_focused_view(workspace)); | ||
182 | arrange_windows(workspace, -1, -1); | ||
178 | active_workspace = workspace; | 183 | active_workspace = workspace; |
179 | } | 184 | } |
180 | 185 | ||
181 | /* XXX:DEBUG:XXX */ | 186 | /* XXX:DEBUG:XXX */ |
182 | static void container_log(const swayc_t *c) { | 187 | static void container_log(const swayc_t *c) { |
183 | fprintf(stderr, "focus:%c|", | 188 | fprintf(stderr, "focus:%c|", |
184 | c->is_focused ? 'F' : //Focused | 189 | c->is_focused ? 'F' : //Focused |
185 | c == active_workspace ? 'W' : //active workspace | 190 | c == active_workspace ? 'W' : //active workspace |
186 | c == &root_container ? 'R' : //root | 191 | c == &root_container ? 'R' : //root |
187 | 'X');//not any others | 192 | 'X');//not any others |
188 | fprintf(stderr,"(%p)",c); | 193 | fprintf(stderr,"(%p)",c); |
189 | fprintf(stderr,"(p:%p)",c->parent); | 194 | fprintf(stderr,"(p:%p)",c->parent); |
190 | fprintf(stderr,"(f:%p)",c->focused); | 195 | fprintf(stderr,"(f:%p)",c->focused); |
191 | fprintf(stderr,"(h:%ld)",c->handle); | 196 | fprintf(stderr,"(h:%ld)",c->handle); |
192 | fprintf(stderr,"Type:"); | 197 | fprintf(stderr,"Type:"); |
193 | fprintf(stderr, | 198 | fprintf(stderr, |
194 | c->type == C_ROOT ? "Root|" : | 199 | c->type == C_ROOT ? "Root|" : |
195 | c->type == C_OUTPUT ? "Output|" : | 200 | c->type == C_OUTPUT ? "Output|" : |
196 | c->type == C_WORKSPACE ? "Workspace|" : | 201 | c->type == C_WORKSPACE ? "Workspace|" : |
197 | c->type == C_CONTAINER ? "Container|" : | 202 | c->type == C_CONTAINER ? "Container|" : |
198 | c->type == C_VIEW ? "View|" : "Unknown|"); | 203 | c->type == C_VIEW ? "View|" : "Unknown|"); |
199 | fprintf(stderr,"layout:"); | 204 | fprintf(stderr,"layout:"); |
200 | fprintf(stderr, | 205 | fprintf(stderr, |
201 | c->layout == L_NONE ? "NONE|" : | 206 | c->layout == L_NONE ? "NONE|" : |
202 | c->layout == L_HORIZ ? "Horiz|": | 207 | c->layout == L_HORIZ ? "Horiz|": |
203 | c->layout == L_VERT ? "Vert|": | 208 | c->layout == L_VERT ? "Vert|": |
204 | c->layout == L_STACKED ? "Stacked|": | 209 | c->layout == L_STACKED ? "Stacked|": |
205 | c->layout == L_FLOATING ? "Floating|": | 210 | c->layout == L_FLOATING ? "Floating|": |
206 | "Unknown|"); | 211 | "Unknown|"); |
207 | fprintf(stderr, "w:%d|h:%d|", c->width, c->height); | 212 | fprintf(stderr, "w:%d|h:%d|", c->width, c->height); |
208 | fprintf(stderr, "x:%d|y:%d|", c->x, c->y); | 213 | fprintf(stderr, "x:%d|y:%d|", c->x, c->y); |
209 | fprintf(stderr, "vis:%c|", c->visible?'t':'f'); | 214 | fprintf(stderr, "vis:%c|", c->visible?'t':'f'); |
@@ -212,30 +217,24 @@ static void container_log(const swayc_t *c) { | |||
212 | fprintf(stderr, "children:%d\n",c->children?c->children->length:0); | 217 | fprintf(stderr, "children:%d\n",c->children?c->children->length:0); |
213 | } | 218 | } |
214 | void layout_log(const swayc_t *c, int depth) { | 219 | void layout_log(const swayc_t *c, int depth) { |
215 | int i; | 220 | int i, d; |
216 | int e = c->children?c->children->length:0; | 221 | int e = c->children ? c->children->length : 0; |
217 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
218 | container_log(c); | 222 | container_log(c); |
219 | if (e) { | 223 | if (e) { |
220 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
221 | fprintf(stderr,"(\n"); | ||
222 | for (i = 0; i < e; ++i) { | 224 | for (i = 0; i < e; ++i) { |
225 | fputc('|',stderr); | ||
226 | for (d = 0; d < depth; ++d) fputc('-', stderr); | ||
223 | layout_log(c->children->items[i], depth + 1); | 227 | layout_log(c->children->items[i], depth + 1); |
224 | } | 228 | } |
225 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
226 | fprintf(stderr,")\n"); | ||
227 | } | 229 | } |
228 | if (c->type == C_WORKSPACE) { | 230 | if (c->type == C_WORKSPACE) { |
229 | e = c->floating?c->floating->length:0; | 231 | e = c->floating?c->floating->length:0; |
230 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
231 | if (e) { | 232 | if (e) { |
232 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
233 | fprintf(stderr,"(\n"); | ||
234 | for (i = 0; i < e; ++i) { | 233 | for (i = 0; i < e; ++i) { |
234 | fputc('|',stderr); | ||
235 | for (d = 0; d < depth; ++d) fputc('-', stderr); | ||
235 | layout_log(c->floating->items[i], depth + 1); | 236 | layout_log(c->floating->items[i], depth + 1); |
236 | } | 237 | } |
237 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
238 | fprintf(stderr,")\n"); | ||
239 | } | 238 | } |
240 | } | 239 | } |
241 | } | 240 | } |