aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md46
-rw-r--r--include/stringop.h4
-rw-r--r--sway/commands.c8
-rw-r--r--sway/config.c5
-rw-r--r--sway/container.c51
-rw-r--r--sway/focus.c79
-rw-r--r--sway/handlers.c42
-rw-r--r--sway/layout.c62
-rw-r--r--sway/stringop.c52
-rw-r--r--sway/workspace.c55
10 files changed, 262 insertions, 142 deletions
diff --git a/README.md b/README.md
index 8c312984..a51a0a86 100644
--- a/README.md
+++ b/README.md
@@ -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 4i3-compatible window manager for [Wayland](http://wayland.freedesktop.org/).
5sway is a **work in progress** i3-compatible window manager for 5Read 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
10Chat on #sway on irc.freenode.net
11
12## Rationale 9## Rationale
13 10
14I use i3 on xorg. Wayland is coming, and [i3way](http://i3way.org/) still has 11I 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
22sway is not supported by many distributions yet. Here's a list of packages
23available for you to install:
24 24
25Install [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
29Dependencies: 29Install 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
36Compiling: 36Run these commands:
37 37
38 cmake . 38 cmake .
39 make 39 make
40 # sudo make install 40 sudo make install
41
42Binary shows up in `./bin` (or `/usr/local/bin` if you `make install`).
43 41
44## Configuration 42## Configuration
45 43
46 mkdir ~/.config/sway 44If you already use i3, then copy your i3 config to `~/.config/sway/config` and
47 cp ~/.config/i3/config ~/.config/sway/ 45it'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.
49Or if you don't already use i3:
50
51 mkdir ~/.config/sway
52 cp /etc/sway/config ~/.config/sway/
53
54Edit to your liking.
55
56[See also](http://i3wm.org/docs/)
57 47
58## Running 48## Running
59 49
50Run this from a tty (instead of starting x):
51
60 sway 52 sway
61 53
62If you run this while xorg is running, it'll run inside of an x window (useful 54If you run it from within x, it will spawn x windows instead of using your
63for testing). Otherwise, it'll run wayland properly. 55hardware 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
5void strip_whitespace(char *str); 5char *strip_whitespace(char *str, int *trimmed_start);
6void strip_comments(char *str); 6char *strip_comments(char *str);
7list_t *split_string(const char *str, const char *delims); 7list_t *split_string(const char *str, const char *delims);
8void free_flat_list(list_t *list); 8void free_flat_list(list_t *list);
9char *code_strchr(const char *string, char delimiter); 9char *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
23static void free_swayc(swayc_t *c) { 24static 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
56static bool workspace_test(swayc_t *view, void *name) {
57 return strcasecmp(view->name, (char *)name);
58}
59
40swayc_t *new_output(wlc_handle handle) { 60swayc_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
273void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { 309void 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
285void set_view_visibility(swayc_t *view, void *data) { 328void 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
186swayc_t *get_focused_view(swayc_t *parent) { 217swayc_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
111static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { 119static 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
414static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, 429static 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
10swayc_t root_container; 11swayc_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. */
10void strip_whitespace(char *str) { 9char *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
35void strip_comments(char *str) { 34char *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
53list_t *split_string(const char *str, const char *delims) { 53list_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
176void workspace_switch(swayc_t *workspace) { 176void 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 */
182static void container_log(const swayc_t *c) { 187static 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}
214void layout_log(const swayc_t *c, int depth) { 219void 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}