diff options
-rw-r--r-- | sway/commands.c | 93 | ||||
-rw-r--r-- | sway/container.c | 205 | ||||
-rw-r--r-- | sway/container.h | 63 | ||||
-rw-r--r-- | sway/handlers.c | 84 | ||||
-rw-r--r-- | sway/handlers.h | 3 | ||||
-rw-r--r-- | sway/layout.c | 273 | ||||
-rw-r--r-- | sway/layout.h | 55 | ||||
-rw-r--r-- | sway/movement.c | 8 | ||||
-rw-r--r-- | sway/workspace.c | 28 | ||||
-rw-r--r-- | sway/workspace.h | 2 |
10 files changed, 491 insertions, 323 deletions
diff --git a/sway/commands.c b/sway/commands.c index cae35237..a0a95eef 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -228,33 +228,25 @@ static bool cmd_set(struct sway_config *config, int argc, char **argv) { | |||
228 | } | 228 | } |
229 | 229 | ||
230 | static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) { | 230 | static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) { |
231 | char *name = layout == L_VERT ? "splitv": | 231 | char *name = layout == L_VERT ? "splitv" : |
232 | layout == L_HORIZ ? "splith":"split"; | 232 | layout == L_HORIZ ? "splith" : "split"; |
233 | if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) { | 233 | if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) { |
234 | return false; | 234 | return false; |
235 | } | 235 | } |
236 | swayc_t *focused = get_focused_container(&root_container); | 236 | swayc_t *focused = get_focused_container(&root_container); |
237 | |||
238 | /* Case that focus is on an empty workspace. change its layout */ | ||
237 | if (focused->type == C_WORKSPACE) { | 239 | if (focused->type == C_WORKSPACE) { |
238 | sway_log(L_DEBUG, "Dont split workspaces"); | 240 | focused->layout = layout; |
239 | if (focused->children->length == 0) { | 241 | return true; |
240 | focused->layout = layout; | 242 | } |
241 | } | 243 | /* Case of no siblings. change parent layout */ |
244 | if (focused->parent->children->length == 1) { | ||
245 | focused->parent->layout = layout; | ||
242 | return true; | 246 | return true; |
243 | } | 247 | } |
244 | swayc_t *parent = focused->parent; | 248 | /* regular case where new split container is build around focused container */ |
245 | sway_log(L_DEBUG, "Splitting %p vertically with %p", parent, focused); | 249 | swayc_t *parent = new_container(focused, layout); |
246 | int index = remove_container_from_parent(parent, focused); | ||
247 | swayc_t *new_container = create_container(parent, -1); | ||
248 | new_container->layout = layout; | ||
249 | new_container->weight = focused->weight; | ||
250 | new_container->width = focused->width; | ||
251 | new_container->height = focused->height; | ||
252 | new_container->x = focused->x; | ||
253 | new_container->y = focused->y; | ||
254 | focused->weight = 1; | ||
255 | focused->parent = new_container; | ||
256 | list_insert(parent->children, index, new_container); | ||
257 | list_add(new_container->children, focused); | ||
258 | focus_view(focused); | 250 | focus_view(focused); |
259 | arrange_windows(parent, -1, -1); | 251 | arrange_windows(parent, -1, -1); |
260 | return true; | 252 | return true; |
@@ -302,15 +294,72 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) { | |||
302 | swayc_t *workspace = workspace_find_by_name(argv[0]); | 294 | swayc_t *workspace = workspace_find_by_name(argv[0]); |
303 | if (!workspace) { | 295 | if (!workspace) { |
304 | workspace = workspace_create(argv[0]); | 296 | workspace = workspace_create(argv[0]); |
305 | } else sway_log(L_DEBUG, "workspace exists, all ok"); | 297 | } |
306 | |||
307 | workspace_switch(workspace); | 298 | workspace_switch(workspace); |
308 | return true; | 299 | return true; |
309 | } | 300 | } |
310 | 301 | ||
302 | /* XXX:DEBUG:XXX */ | ||
303 | static void container_log(const swayc_t *c) { | ||
304 | fprintf(stderr, "focus:%c|", | ||
305 | c == get_focused_container(&root_container) ? 'F' : //Focused | ||
306 | c == active_workspace ? 'W' : //active workspace | ||
307 | c == &root_container ? 'R' : //root | ||
308 | 'X');//not any others | ||
309 | fprintf(stderr,"(%p)",c); | ||
310 | fprintf(stderr,"(p:%p)",c->parent); | ||
311 | fprintf(stderr,"(f:%p)",c->focused); | ||
312 | fprintf(stderr,"Type:"); | ||
313 | fprintf(stderr, | ||
314 | c->type == C_ROOT ? "Root|" : | ||
315 | c->type == C_OUTPUT ? "Output|" : | ||
316 | c->type == C_WORKSPACE ? "Workspace|" : | ||
317 | c->type == C_CONTAINER ? "Container|" : | ||
318 | c->type == C_VIEW ? "View|" : | ||
319 | "Unknown|"); | ||
320 | fprintf(stderr,"layout:"); | ||
321 | fprintf(stderr, | ||
322 | c->layout == L_NONE ? "NONE|" : | ||
323 | c->layout == L_HORIZ ? "Horiz|": | ||
324 | c->layout == L_VERT ? "Vert|": | ||
325 | c->layout == L_STACKED ? "Stacked|": | ||
326 | c->layout == L_FLOATING ? "Floating|": | ||
327 | "Unknown|"); | ||
328 | fprintf(stderr, "w:%d|h:%d|", c->width, c->height); | ||
329 | fprintf(stderr, "x:%d|y:%d|", c->x, c->y); | ||
330 | fprintf(stderr, "vis:%c|", c->visible?'t':'f'); | ||
331 | fprintf(stderr, "wgt:%d|", c->weight); | ||
332 | fprintf(stderr, "name:%.16s|", c->name); | ||
333 | fprintf(stderr, "children:%d\n",c->children?c->children->length:0); | ||
334 | } | ||
335 | void layout_log(const swayc_t *c, int depth) { | ||
336 | int i; | ||
337 | int e = c->children?c->children->length:0; | ||
338 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
339 | container_log(c); | ||
340 | if (e) { | ||
341 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
342 | fprintf(stderr,"(\n"); | ||
343 | for (i = 0; i < e; ++i) { | ||
344 | layout_log(c->children->items[i], depth + 1); | ||
345 | } | ||
346 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
347 | fprintf(stderr,")\n"); | ||
348 | } | ||
349 | } | ||
350 | bool cmd_debug_print_layout(struct sway_config *config, int argc, char **argv) { | ||
351 | fprintf(stderr,"root:%p\nactive workspace:%p\n",&root_container, active_workspace); | ||
352 | layout_log(&root_container, 0); | ||
353 | return true; | ||
354 | } | ||
355 | /* XXX:DEBUG:XXX */ | ||
356 | |||
311 | /* Keep alphabetized */ | 357 | /* Keep alphabetized */ |
312 | static struct cmd_handler handlers[] = { | 358 | static struct cmd_handler handlers[] = { |
313 | { "bindsym", cmd_bindsym }, | 359 | { "bindsym", cmd_bindsym }, |
360 | //DEBUG | ||
361 | { "debug_print_layout", cmd_debug_print_layout }, | ||
362 | //DEBUG | ||
314 | { "exec", cmd_exec }, | 363 | { "exec", cmd_exec }, |
315 | { "exec_always", cmd_exec_always }, | 364 | { "exec_always", cmd_exec_always }, |
316 | { "exit", cmd_exit }, | 365 | { "exit", cmd_exit }, |
diff --git a/sway/container.c b/sway/container.c index c637daca..1c17e92f 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -1,18 +1,213 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <stdbool.h> | ||
3 | #include <strings.h> | ||
1 | #include "container.h" | 4 | #include "container.h" |
5 | #include "workspace.h" | ||
2 | #include "layout.h" | 6 | #include "layout.h" |
7 | #include "log.h" | ||
3 | 8 | ||
4 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | 9 | |
10 | static swayc_t *new_swayc(enum swayc_types type) { | ||
11 | swayc_t *c = calloc(1, sizeof(swayc_t)); | ||
12 | c->handle = -1; | ||
13 | c->layout = L_NONE; | ||
14 | c->type = type; | ||
15 | c->weight = 1; | ||
16 | if (type != C_VIEW) { | ||
17 | c->children = create_list(); | ||
18 | } | ||
19 | return c; | ||
20 | } | ||
21 | |||
22 | static void free_swayc(swayc_t *c) { | ||
23 | //TODO does not properly handle containers with children, | ||
24 | //TODO but functions that call this usually check for that | ||
25 | if (c->children) { | ||
26 | list_free(c->children); | ||
27 | } | ||
28 | if (c->parent) { | ||
29 | remove_child(c->parent, c); | ||
30 | } | ||
31 | free(c); | ||
32 | } | ||
33 | |||
34 | /* New containers */ | ||
35 | static void add_output_widths(swayc_t *container, void *_width) { | ||
36 | int *width = _width; | ||
37 | if (container->type == C_OUTPUT) { | ||
38 | *width += container->width; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | swayc_t *new_output(wlc_handle handle) { | ||
43 | sway_log(L_DEBUG, "Added output %d", handle); | ||
44 | const struct wlc_size* size = wlc_output_get_resolution(handle); | ||
45 | |||
46 | swayc_t *output = new_swayc(C_OUTPUT); | ||
47 | output->width = size->w; | ||
48 | output->height = size->h; | ||
49 | output->handle = handle; | ||
50 | |||
51 | add_child(&root_container, output); | ||
52 | |||
53 | //TODO something with this | ||
54 | int total_width = 0; | ||
55 | container_map(&root_container, add_output_widths, &total_width); | ||
56 | |||
57 | //Create workspace | ||
58 | char *ws_name = workspace_next_name(); | ||
59 | new_workspace(output, ws_name); | ||
60 | free(ws_name); | ||
61 | |||
62 | return output; | ||
63 | } | ||
64 | |||
65 | swayc_t *new_workspace(swayc_t * output, const char *name) { | ||
66 | sway_log(L_DEBUG, "Added workspace %s for output %d", name, output->handle); | ||
67 | swayc_t *workspace = new_swayc(C_WORKSPACE); | ||
68 | |||
69 | workspace->layout = L_HORIZ; // TODO:default layout | ||
70 | workspace->width = output->width; | ||
71 | workspace->height = output->height; | ||
72 | workspace->name = strdup(name); | ||
73 | workspace->visible = true; | ||
74 | |||
75 | add_child(output, workspace); | ||
76 | return workspace; | ||
77 | } | ||
78 | |||
79 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | ||
80 | swayc_t *cont = new_swayc(C_CONTAINER); | ||
81 | |||
82 | sway_log(L_DEBUG, "creating container %p around %p", cont, child); | ||
83 | |||
84 | cont->layout = layout; | ||
85 | cont->width = child->width; | ||
86 | cont->height = child->height; | ||
87 | cont->x = child->x; | ||
88 | cont->y = child->y; | ||
89 | cont->visible = child->visible; | ||
90 | |||
91 | swayc_t *parent = replace_child(child, cont); | ||
92 | if (parent) { | ||
93 | add_child(cont, child); | ||
94 | } | ||
95 | return cont; | ||
96 | } | ||
97 | |||
98 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | ||
99 | const uint32_t type = wlc_view_get_type(handle); | ||
100 | const char *title = wlc_view_get_title(handle); | ||
101 | /* Skip if unmanaged window */ | ||
102 | if ((type & WLC_BIT_OVERRIDE_REDIRECT) || (type & WLC_BIT_UNMANAGED) || | ||
103 | (type & WLC_BIT_POPUP) || (type & WLC_BIT_MODAL) || (type & WLC_BIT_SPLASH)) { | ||
104 | sway_log(L_DEBUG, "Leaving view %d:%s alone (unmanaged)", handle, title); | ||
105 | return NULL; | ||
106 | } | ||
107 | |||
108 | swayc_t *view = new_swayc(C_VIEW); | ||
109 | sway_log(L_DEBUG, "Adding new view %d:%s:%d to container %p %d", | ||
110 | handle, title, type, sibling, sibling?sibling->type:0); | ||
111 | //Setup values | ||
112 | view->handle = handle; | ||
113 | view->name = strdup(title); | ||
114 | view->visible = true; | ||
115 | |||
116 | //Case of focused workspace, just create as child of it | ||
117 | if (sibling->type == C_WORKSPACE) { | ||
118 | add_child(sibling, view); | ||
119 | } | ||
120 | //Regular case, create as sibling of current container | ||
121 | else { | ||
122 | add_sibling(sibling, view); | ||
123 | } | ||
124 | return view; | ||
125 | } | ||
126 | |||
127 | |||
128 | swayc_t *destroy_output(swayc_t *output) { | ||
129 | if (output->children->length == 0) { | ||
130 | //TODO move workspaces to other outputs | ||
131 | } | ||
132 | sway_log(L_DEBUG, "OUTPUT: Destroying output '%d'", output->handle); | ||
133 | free_swayc(output); | ||
134 | return &root_container; | ||
135 | } | ||
136 | |||
137 | swayc_t *destroy_workspace(swayc_t *workspace) { | ||
138 | //TODO move containers to other workspaces? | ||
139 | //for now just dont delete | ||
140 | if (workspace->children->length == 0) { | ||
141 | sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); | ||
142 | swayc_t *parent = workspace->parent; | ||
143 | free_swayc(workspace); | ||
144 | return parent; | ||
145 | } | ||
146 | return NULL; | ||
147 | } | ||
148 | |||
149 | swayc_t *destroy_container(swayc_t *container) { | ||
150 | while (container->children->length == 0 && container->type == C_CONTAINER) { | ||
151 | sway_log(L_DEBUG, "Container: Destroying container '%p'", container); | ||
152 | swayc_t *parent = container->parent; | ||
153 | free_swayc(container); | ||
154 | |||
155 | if (parent->focused == container) { | ||
156 | parent->focused = NULL; | ||
157 | } | ||
158 | container = parent; | ||
159 | } | ||
160 | return container; | ||
161 | } | ||
162 | |||
163 | swayc_t *destroy_view(swayc_t *view) { | ||
164 | if (view == NULL) { | ||
165 | sway_log(L_DEBUG, "Warning: NULL passed into destroy_view"); | ||
166 | return NULL; | ||
167 | } | ||
168 | sway_log(L_DEBUG, "Destroying view '%p'", view); | ||
169 | swayc_t *parent = view->parent; | ||
170 | free_swayc(view); | ||
171 | |||
172 | if (parent->focused == view) { | ||
173 | parent->focused = NULL; | ||
174 | } | ||
175 | //Destroy empty containers | ||
176 | if (parent->type == C_CONTAINER) { | ||
177 | return destroy_container(parent); | ||
178 | } | ||
179 | return parent; | ||
180 | } | ||
181 | |||
182 | |||
183 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | ||
5 | if (!container->children) { | 184 | if (!container->children) { |
185 | return NULL; | ||
186 | } | ||
187 | int i; | ||
188 | for (i = 0; i < container->children->length; ++i) { | ||
189 | swayc_t *child = container->children->items[i]; | ||
190 | if (test(child, data)) { | ||
191 | return child; | ||
192 | } else { | ||
193 | swayc_t *_ = find_container(child, test, data); | ||
194 | if (_) { | ||
195 | return _; | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | return NULL; | ||
200 | } | ||
201 | |||
202 | void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { | ||
203 | if (!container->children || !container->children->length) { | ||
6 | return; | 204 | return; |
7 | } | 205 | } |
8 | int i; | 206 | int i; |
9 | for (i = 0; i < container->children->length; ++i) { | 207 | for (i = 0; i < container->children->length; ++i) { |
10 | swayc_t *child = container->children->items[i]; | 208 | swayc_t *child = container->children->items[i]; |
11 | f(child, data); | 209 | f(child, data); |
12 | 210 | container_map(child, f, data); | |
13 | if (child->children) { | ||
14 | container_map(child, f, data); | ||
15 | } | ||
16 | } | 211 | } |
17 | } | 212 | } |
18 | 213 | ||
diff --git a/sway/container.h b/sway/container.h index d853661c..a54e016a 100644 --- a/sway/container.h +++ b/sway/container.h | |||
@@ -1,8 +1,71 @@ | |||
1 | #ifndef _SWAY_CONTAINER_H | 1 | #ifndef _SWAY_CONTAINER_H |
2 | #define _SWAY_CONTAINER_H | 2 | #define _SWAY_CONTAINER_H |
3 | #include <wlc/wlc.h> | ||
4 | typedef struct sway_container swayc_t; | ||
3 | 5 | ||
4 | #include "layout.h" | 6 | #include "layout.h" |
5 | 7 | ||
8 | enum swayc_types{ | ||
9 | C_ROOT, | ||
10 | C_OUTPUT, | ||
11 | C_WORKSPACE, | ||
12 | C_CONTAINER, | ||
13 | C_VIEW, | ||
14 | //Keep last | ||
15 | C_TYPES, | ||
16 | }; | ||
17 | |||
18 | enum swayc_layouts{ | ||
19 | L_NONE, | ||
20 | L_HORIZ, | ||
21 | L_VERT, | ||
22 | L_STACKED, | ||
23 | L_TABBED, | ||
24 | L_FLOATING, | ||
25 | //Keep last | ||
26 | L_LAYOUTS, | ||
27 | }; | ||
28 | |||
29 | struct sway_container { | ||
30 | wlc_handle handle; | ||
31 | |||
32 | enum swayc_types type; | ||
33 | |||
34 | enum swayc_layouts layout; | ||
35 | |||
36 | // Not including borders or margins | ||
37 | int width, height; | ||
38 | |||
39 | int x, y; | ||
40 | |||
41 | bool visible; | ||
42 | |||
43 | int weight; | ||
44 | |||
45 | char *name; | ||
46 | |||
47 | list_t *children; | ||
48 | |||
49 | struct sway_container *parent; | ||
50 | struct sway_container *focused; | ||
51 | }; | ||
52 | |||
53 | |||
54 | swayc_t *new_output(wlc_handle handle); | ||
55 | swayc_t *new_workspace(swayc_t * output, const char *name); | ||
56 | //Creates container Around child (parent child) -> (parent (container child)) | ||
57 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); | ||
58 | //Creates view as a sibling of current focused container, or as child of a workspace | ||
59 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle); | ||
60 | |||
61 | |||
62 | swayc_t *destroy_output(swayc_t *output); | ||
63 | //destroys workspace if empty and returns parent pointer, else returns NULL | ||
64 | swayc_t *destroy_workspace(swayc_t *workspace); | ||
65 | swayc_t *destroy_container(swayc_t *container); | ||
66 | swayc_t *destroy_view(swayc_t *view); | ||
67 | |||
68 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); | ||
6 | void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); | 69 | void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); |
7 | 70 | ||
8 | #endif | 71 | #endif |
diff --git a/sway/handlers.c b/sway/handlers.c index 48c6cbf7..393a2181 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -9,14 +9,53 @@ | |||
9 | #include "commands.h" | 9 | #include "commands.h" |
10 | #include "handlers.h" | 10 | #include "handlers.h" |
11 | #include "stringop.h" | 11 | #include "stringop.h" |
12 | #include "workspace.h" | ||
13 | |||
14 | static struct wlc_origin mouse_origin; | ||
15 | |||
16 | static bool pointer_test(swayc_t *view, void *_origin) { | ||
17 | const struct wlc_origin *origin = _origin; | ||
18 | if (view->type == C_VIEW && origin->x >= view->x && origin->y >= view->y | ||
19 | && origin->x < view->x + view->width && origin->y < view->y + view->height | ||
20 | && view->visible) { | ||
21 | return true; | ||
22 | } | ||
23 | return false; | ||
24 | } | ||
25 | |||
26 | void focus_pointer(void) { | ||
27 | swayc_t *focused = find_container(&root_container, pointer_test, &mouse_origin); | ||
28 | if (focused) { | ||
29 | sway_log(L_DEBUG, "Switching focus to %p", focused); | ||
30 | unfocus_all(&root_container); | ||
31 | focus_view(focused); | ||
32 | } else { | ||
33 | focus_view(active_workspace); | ||
34 | } | ||
35 | } | ||
12 | 36 | ||
13 | static bool handle_output_created(wlc_handle output) { | 37 | static bool handle_output_created(wlc_handle output) { |
14 | add_output(output); | 38 | swayc_t *op = new_output(output); |
39 | |||
40 | //Switch to workspace if we need to | ||
41 | if (active_workspace == NULL) { | ||
42 | swayc_t *ws = op->children->items[0]; | ||
43 | workspace_switch(ws); | ||
44 | } | ||
15 | return true; | 45 | return true; |
16 | } | 46 | } |
17 | 47 | ||
18 | static void handle_output_destroyed(wlc_handle output) { | 48 | static void handle_output_destroyed(wlc_handle output) { |
19 | destroy_output(output); | 49 | int i; |
50 | list_t *list = root_container.children; | ||
51 | for (i = 0; i < list->length; ++i) { | ||
52 | if (((swayc_t *)list->items[i])->handle == output) { | ||
53 | break; | ||
54 | } | ||
55 | } | ||
56 | if (i < list->length) { | ||
57 | destroy_output(list->items[i]); | ||
58 | } | ||
20 | } | 59 | } |
21 | 60 | ||
22 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { | 61 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { |
@@ -37,14 +76,33 @@ static void handle_output_focused(wlc_handle output, bool focus) { | |||
37 | } | 76 | } |
38 | } | 77 | } |
39 | 78 | ||
40 | static bool handle_view_created(wlc_handle view) { | 79 | static bool handle_view_created(wlc_handle handle) { |
41 | add_view(view); | 80 | swayc_t *container = get_focused_container(&root_container); |
81 | swayc_t *view = new_view(container, handle); | ||
82 | unfocus_all(&root_container); | ||
83 | if (view) { | ||
84 | focus_view(view); | ||
85 | arrange_windows(view->parent, -1, -1); | ||
86 | } else { //Unmanaged view | ||
87 | wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); | ||
88 | wlc_view_focus(handle); | ||
89 | } | ||
42 | return true; | 90 | return true; |
43 | } | 91 | } |
44 | 92 | ||
45 | static void handle_view_destroyed(wlc_handle view) { | 93 | static void handle_view_destroyed(wlc_handle handle) { |
46 | sway_log(L_DEBUG, "Destroying window %d", view); | 94 | sway_log(L_DEBUG, "Destroying window %d", handle); |
47 | destroy_view(get_swayc_for_handle(view, &root_container)); | 95 | swayc_t *view = get_swayc_for_handle(handle, &root_container); |
96 | swayc_t *parent; | ||
97 | swayc_t *focused = get_focused_container(&root_container); | ||
98 | |||
99 | if (view) { | ||
100 | parent = destroy_view(view); | ||
101 | arrange_windows(parent, -1, -1); | ||
102 | } | ||
103 | if (!focused || focused == view) { | ||
104 | focus_pointer(); | ||
105 | } | ||
48 | } | 106 | } |
49 | 107 | ||
50 | static void handle_view_focus(wlc_handle view, bool focus) { | 108 | static void handle_view_focus(wlc_handle view, bool focus) { |
@@ -121,18 +179,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
121 | return cmd_success; | 179 | return cmd_success; |
122 | } | 180 | } |
123 | 181 | ||
124 | bool pointer_test(swayc_t *view, void *_origin) { | ||
125 | const struct wlc_origin *origin = _origin; | ||
126 | if (view->type == C_VIEW && origin->x >= view->x && origin->y >= view->y | ||
127 | && origin->x < view->x + view->width && origin->y < view->y + view->height | ||
128 | && view->visible) { | ||
129 | return true; | ||
130 | } | ||
131 | return false; | ||
132 | } | ||
133 | |||
134 | struct wlc_origin mouse_origin; | ||
135 | |||
136 | static bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct wlc_origin *origin) { | 182 | static bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct wlc_origin *origin) { |
137 | mouse_origin = *origin; | 183 | mouse_origin = *origin; |
138 | if (!config->focus_follows_mouse) { | 184 | if (!config->focus_follows_mouse) { |
diff --git a/sway/handlers.h b/sway/handlers.h index 798b3b50..b8b171c3 100644 --- a/sway/handlers.h +++ b/sway/handlers.h | |||
@@ -6,4 +6,7 @@ | |||
6 | 6 | ||
7 | extern struct wlc_interface interface; | 7 | extern struct wlc_interface interface; |
8 | 8 | ||
9 | //set focus to current pointer location | ||
10 | void focus_pointer(void); | ||
11 | |||
9 | #endif | 12 | #endif |
diff --git a/sway/layout.c b/sway/layout.c index ccf29f34..0db4dc4d 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -9,25 +9,75 @@ | |||
9 | 9 | ||
10 | swayc_t root_container; | 10 | swayc_t root_container; |
11 | 11 | ||
12 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | 12 | void init_layout(void) { |
13 | if (!container->children) { | 13 | root_container.type = C_ROOT; |
14 | root_container.layout = L_NONE; | ||
15 | root_container.children = create_list(); | ||
16 | root_container.handle = -1; | ||
17 | } | ||
18 | |||
19 | static int index_child(swayc_t *parent, swayc_t *child) { | ||
20 | int i; | ||
21 | for (i = 0; i < parent->children->length; ++i) { | ||
22 | if (parent->children->items[i] == child) { | ||
23 | break; | ||
24 | } | ||
25 | } | ||
26 | return i; | ||
27 | } | ||
28 | |||
29 | void add_child(swayc_t *parent, swayc_t *child) { | ||
30 | sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, | ||
31 | child->width, child->height, parent, parent->type, parent->width, parent->height); | ||
32 | list_add(parent->children, child); | ||
33 | child->parent = parent; | ||
34 | if(parent->focused == NULL) { | ||
35 | parent->focused = child; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { | ||
40 | swayc_t *parent = sibling->parent; | ||
41 | int i = index_child(parent, sibling); | ||
42 | if (i == parent->children->length) { | ||
43 | --i; | ||
44 | } | ||
45 | list_insert(parent->children, i+1, child); | ||
46 | child->parent = parent; | ||
47 | return child->parent; | ||
48 | } | ||
49 | |||
50 | swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { | ||
51 | swayc_t *parent = child->parent; | ||
52 | if (parent == NULL) { | ||
14 | return NULL; | 53 | return NULL; |
15 | } | 54 | } |
55 | int i = index_child(parent, child); | ||
56 | parent->children->items[i] = new_child; | ||
57 | new_child->parent = child->parent; | ||
58 | |||
59 | if (child->parent->focused == child) { | ||
60 | child->parent->focused = new_child; | ||
61 | } | ||
62 | child->parent = NULL; | ||
63 | return parent; | ||
64 | } | ||
65 | |||
66 | swayc_t *remove_child(swayc_t *parent, swayc_t *child) { | ||
16 | int i; | 67 | int i; |
17 | for (i = 0; i < container->children->length; ++i) { | 68 | for (i = 0; i < parent->children->length; ++i) { |
18 | swayc_t *child = container->children->items[i]; | 69 | if (parent->children->items[i] == child) { |
19 | if (test(child, data)) { | 70 | list_del(parent->children, i); |
20 | return child; | 71 | break; |
21 | } else { | ||
22 | swayc_t *_ = find_container(child, test, data); | ||
23 | if (_) { | ||
24 | return _; | ||
25 | } | ||
26 | } | 72 | } |
27 | } | 73 | } |
28 | return NULL; | 74 | if (parent->focused == child) { |
75 | parent->focused = NULL; | ||
76 | } | ||
77 | return parent; | ||
29 | } | 78 | } |
30 | 79 | ||
80 | |||
31 | void arrange_windows(swayc_t *container, int width, int height) { | 81 | void arrange_windows(swayc_t *container, int width, int height) { |
32 | int i; | 82 | int i; |
33 | if (width == -1 || height == -1) { | 83 | if (width == -1 || height == -1) { |
@@ -131,25 +181,6 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
131 | } | 181 | } |
132 | } | 182 | } |
133 | 183 | ||
134 | void init_layout(void) { | ||
135 | root_container.type = C_ROOT; | ||
136 | root_container.layout = L_NONE; | ||
137 | root_container.children = create_list(); | ||
138 | root_container.handle = -1; | ||
139 | } | ||
140 | |||
141 | void free_swayc(swayc_t *container) { | ||
142 | // NOTE: Does not handle moving children into a different container | ||
143 | if (container->parent) { | ||
144 | remove_container_from_parent(container->parent, container); | ||
145 | } | ||
146 | list_free(container->children); | ||
147 | if (container->name) { | ||
148 | free(container->name); | ||
149 | } | ||
150 | free(container); | ||
151 | } | ||
152 | |||
153 | swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { | 184 | swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { |
154 | if (parent->children == NULL) { | 185 | if (parent->children == NULL) { |
155 | return NULL; | 186 | return NULL; |
@@ -176,99 +207,6 @@ swayc_t *get_focused_container(swayc_t *parent) { | |||
176 | return get_focused_container(parent->focused); | 207 | return get_focused_container(parent->focused); |
177 | } | 208 | } |
178 | 209 | ||
179 | void add_view(wlc_handle view_handle) { | ||
180 | const uint32_t type = wlc_view_get_type(view_handle); | ||
181 | const char *title = wlc_view_get_title(view_handle); | ||
182 | if ((type & WLC_BIT_OVERRIDE_REDIRECT) || (type & WLC_BIT_UNMANAGED) || (type & | ||
183 | WLC_BIT_POPUP) || (type & WLC_BIT_MODAL) || (type & WLC_BIT_SPLASH)) { | ||
184 | sway_log(L_DEBUG, "Leaving view %d:%s alone (unmanaged)", view_handle, title); | ||
185 | unfocus_all(&root_container); | ||
186 | wlc_view_set_state(view_handle, WLC_BIT_ACTIVATED, true); | ||
187 | wlc_view_focus(view_handle); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | swayc_t *parent = get_focused_container(&root_container); | ||
192 | sway_log(L_DEBUG, "Adding new view %d:%s:%d under container %p %d", view_handle, title, type, parent, parent->type); | ||
193 | |||
194 | while (parent->type == C_VIEW) { | ||
195 | parent = parent->parent; | ||
196 | } | ||
197 | |||
198 | swayc_t *view = calloc(1, sizeof(swayc_t)); | ||
199 | view->weight = 1; | ||
200 | view->layout = L_NONE; | ||
201 | view->handle = view_handle; | ||
202 | view->parent = parent; | ||
203 | view->type = C_VIEW; | ||
204 | view->visible = true; | ||
205 | if (title) { | ||
206 | view->name = malloc(strlen(title) + 1); | ||
207 | strcpy(view->name, title); | ||
208 | } | ||
209 | add_child(parent, view); | ||
210 | |||
211 | unfocus_all(&root_container); | ||
212 | focus_view(view); | ||
213 | |||
214 | arrange_windows(parent, -1, -1); | ||
215 | } | ||
216 | |||
217 | int remove_container_from_parent(swayc_t *parent, swayc_t *container) { | ||
218 | int i; | ||
219 | for (i = 0; i < parent->children->length; ++i) { | ||
220 | if (parent->children->items[i] == container) { | ||
221 | list_del(parent->children, i); | ||
222 | break; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | if (parent->focused == container) { | ||
227 | parent->focused = NULL; | ||
228 | } | ||
229 | |||
230 | return i; | ||
231 | } | ||
232 | |||
233 | void destroy_view(swayc_t *view) { | ||
234 | if (view == NULL) { | ||
235 | sway_log(L_DEBUG, "Warning: NULL passed into destroy_view"); | ||
236 | return; | ||
237 | } | ||
238 | sway_log(L_DEBUG, "Destroying container %p", view); | ||
239 | swayc_t *parent = view->parent; | ||
240 | if (!parent) { | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | int i; | ||
245 | for (i = 0; i < parent->children->length; ++i) { | ||
246 | if (parent->children->items[i] == view) { | ||
247 | list_del(parent->children, i); | ||
248 | break; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | free_swayc(view); | ||
253 | |||
254 | if (parent->focused == view) { | ||
255 | parent->focused = NULL; | ||
256 | } | ||
257 | |||
258 | unfocus_all(&root_container); | ||
259 | if (parent->children->length != 0) { | ||
260 | focus_view(parent->children->items[0]); | ||
261 | } else { | ||
262 | focus_view(parent); | ||
263 | } | ||
264 | |||
265 | arrange_windows(parent, -1, -1); | ||
266 | |||
267 | if (parent->children->length == 0 && parent->type == C_CONTAINER) { | ||
268 | destroy_view(parent); | ||
269 | } | ||
270 | } | ||
271 | |||
272 | void unfocus_all(swayc_t *container) { | 210 | void unfocus_all(swayc_t *container) { |
273 | if (container->children == NULL) { | 211 | if (container->children == NULL) { |
274 | return; | 212 | return; |
@@ -285,85 +223,16 @@ void unfocus_all(swayc_t *container) { | |||
285 | } | 223 | } |
286 | 224 | ||
287 | void focus_view(swayc_t *view) { | 225 | void focus_view(swayc_t *view) { |
288 | sway_log(L_DEBUG, "Setting focus for %p", view); | 226 | sway_log(L_DEBUG, "Setting focus to %p", view); |
289 | if (view == &root_container) { | 227 | if (view->type == C_VIEW) { |
290 | // Propegate wayland focus down | 228 | wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, true); |
291 | swayc_t *child = view->focused; | 229 | wlc_view_bring_to_front(view->handle); |
292 | while (child && child->type != C_VIEW) { | 230 | wlc_view_focus(view->handle); |
293 | child = child->focused; | ||
294 | } | ||
295 | if (child) { | ||
296 | wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, true); | ||
297 | wlc_view_focus(child->handle); | ||
298 | } | ||
299 | return; | ||
300 | } | ||
301 | view->parent->focused = view; | ||
302 | focus_view(view->parent); | ||
303 | } | ||
304 | |||
305 | void add_child(swayc_t *parent, swayc_t *child) { | ||
306 | sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, | ||
307 | child->width, child->height, parent, parent->type, parent->width, parent->height); | ||
308 | list_add(parent->children, child); | ||
309 | } | ||
310 | |||
311 | swayc_t *create_container(swayc_t *parent, wlc_handle handle) { | ||
312 | swayc_t *c = calloc(1, sizeof(swayc_t)); | ||
313 | c->weight = 1; | ||
314 | c->handle = handle; | ||
315 | c->parent = parent; | ||
316 | c->layout = L_NONE; | ||
317 | c->type = C_CONTAINER; | ||
318 | c->children = create_list(); | ||
319 | return c; | ||
320 | } | ||
321 | |||
322 | void add_output_widths(swayc_t *container, void *_width) { | ||
323 | int *width = _width; | ||
324 | if (container->type == C_OUTPUT) { | ||
325 | *width += container->width; | ||
326 | } | 231 | } |
327 | } | 232 | // Propagete focus up |
328 | 233 | while (view != &root_container) { | |
329 | void add_output(wlc_handle output) { | 234 | view->parent->focused = view; |
330 | sway_log(L_DEBUG, "Adding output %d", output); | 235 | view = view->parent; |
331 | const struct wlc_size* size = wlc_output_get_resolution(output); | ||
332 | |||
333 | swayc_t *container = create_container(&root_container, output); | ||
334 | container->type = C_OUTPUT; | ||
335 | container->width = size->w; | ||
336 | container->height = size->h; | ||
337 | add_child(&root_container, container); | ||
338 | |||
339 | int total_width = 0; | ||
340 | container_map(&root_container, add_output_widths, &total_width); | ||
341 | |||
342 | swayc_t *workspace = create_container(container, -1); | ||
343 | workspace->type = C_WORKSPACE; | ||
344 | workspace->name = workspace_next_name(); | ||
345 | workspace->width = size->w; // TODO: gaps | ||
346 | workspace->height = size->h; | ||
347 | workspace->layout = L_HORIZ; // TODO: Get default layout from config | ||
348 | add_child(container, workspace); | ||
349 | sway_log(L_DEBUG, "Added workspace %s for output %d", workspace->name, output); | ||
350 | |||
351 | if (root_container.focused == NULL) { | ||
352 | workspace_switch(workspace); | ||
353 | unfocus_all(&root_container); | ||
354 | focus_view(workspace); | ||
355 | } | 236 | } |
356 | } | 237 | } |
357 | 238 | ||
358 | void destroy_output(wlc_handle output) { | ||
359 | sway_log(L_DEBUG, "Destroying output %d", output); | ||
360 | int i; | ||
361 | for (i = 0; i < root_container.children->length; ++i) { | ||
362 | swayc_t *c = root_container.children->items[i]; | ||
363 | if (c->handle == output) { | ||
364 | list_del(root_container.children, i); | ||
365 | free_swayc(c); | ||
366 | return; | ||
367 | } | ||
368 | } | ||
369 | } | ||
diff --git a/sway/layout.h b/sway/layout.h index b4769e08..a136f917 100644 --- a/sway/layout.h +++ b/sway/layout.h | |||
@@ -3,62 +3,23 @@ | |||
3 | 3 | ||
4 | #include <wlc/wlc.h> | 4 | #include <wlc/wlc.h> |
5 | #include "list.h" | 5 | #include "list.h" |
6 | 6 | #include "container.h" | |
7 | struct sway_container { | ||
8 | wlc_handle handle; | ||
9 | |||
10 | enum { | ||
11 | C_ROOT, | ||
12 | C_OUTPUT, | ||
13 | C_WORKSPACE, | ||
14 | C_CONTAINER, | ||
15 | C_VIEW | ||
16 | } type; | ||
17 | |||
18 | enum { | ||
19 | L_NONE, | ||
20 | L_HORIZ, | ||
21 | L_VERT, | ||
22 | L_STACKED, | ||
23 | L_TABBED, | ||
24 | L_FLOATING | ||
25 | } layout; | ||
26 | |||
27 | // Not including borders or margins | ||
28 | int width, height; | ||
29 | |||
30 | int x, y; | ||
31 | |||
32 | bool visible; | ||
33 | |||
34 | int weight; | ||
35 | |||
36 | char *name; | ||
37 | |||
38 | list_t *children; | ||
39 | |||
40 | struct sway_container *parent; | ||
41 | struct sway_container *focused; | ||
42 | }; | ||
43 | |||
44 | typedef struct sway_container swayc_t; | ||
45 | 7 | ||
46 | extern swayc_t root_container; | 8 | extern swayc_t root_container; |
47 | 9 | ||
48 | void init_layout(void); | 10 | void init_layout(void); |
11 | |||
49 | void add_child(swayc_t *parent, swayc_t *child); | 12 | void add_child(swayc_t *parent, swayc_t *child); |
50 | void add_output(wlc_handle output); | 13 | //Returns parent container wihch needs to be rearranged. |
51 | void destroy_output(wlc_handle output); | 14 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child); |
52 | void destroy_view(swayc_t *view); | 15 | swayc_t *replace_child(swayc_t *child, swayc_t *new_child); |
53 | void add_view(wlc_handle view); | 16 | swayc_t *remove_child(swayc_t *parent, swayc_t *child); |
17 | |||
54 | void unfocus_all(swayc_t *container); | 18 | void unfocus_all(swayc_t *container); |
55 | void focus_view(swayc_t *view); | 19 | void focus_view(swayc_t *view); |
56 | void arrange_windows(swayc_t *container, int width, int height); | 20 | void arrange_windows(swayc_t *container, int width, int height); |
57 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); | ||
58 | swayc_t *get_focused_container(swayc_t *parent); | 21 | swayc_t *get_focused_container(swayc_t *parent); |
59 | int remove_container_from_parent(swayc_t *parent, swayc_t *container); | 22 | |
60 | swayc_t *create_container(swayc_t *parent, wlc_handle handle); | ||
61 | void free_swayc(swayc_t *container); | ||
62 | swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent); | 23 | swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent); |
63 | 24 | ||
64 | #endif | 25 | #endif |
diff --git a/sway/movement.c b/sway/movement.c index 166e6508..de987679 100644 --- a/sway/movement.c +++ b/sway/movement.c | |||
@@ -10,14 +10,12 @@ bool move_focus(enum movement_direction direction) { | |||
10 | swayc_t *parent = current->parent; | 10 | swayc_t *parent = current->parent; |
11 | 11 | ||
12 | if (direction == MOVE_PARENT) { | 12 | if (direction == MOVE_PARENT) { |
13 | current = parent; | 13 | if (parent->type == C_OUTPUT) { |
14 | parent = parent->parent; | ||
15 | if (parent->type == C_ROOT) { | ||
16 | sway_log(L_DEBUG, "Focus cannot move to parent"); | 14 | sway_log(L_DEBUG, "Focus cannot move to parent"); |
17 | return false; | 15 | return false; |
18 | } else { | 16 | } else { |
19 | sway_log(L_DEBUG, "Moving focus away from %p", current); | 17 | sway_log(L_DEBUG, "Moving focus away from %p to %p", current, parent); |
20 | unfocus_all(parent); | 18 | unfocus_all(parent->parent); |
21 | focus_view(parent); | 19 | focus_view(parent); |
22 | return true; | 20 | return true; |
23 | } | 21 | } |
diff --git a/sway/workspace.c b/sway/workspace.c index 906d0c5d..88596dfe 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "list.h" | 6 | #include "list.h" |
7 | #include "log.h" | 7 | #include "log.h" |
8 | #include "container.h" | 8 | #include "container.h" |
9 | #include "handlers.h" | ||
9 | #include "config.h" | 10 | #include "config.h" |
10 | #include "stringop.h" | 11 | #include "stringop.h" |
11 | 12 | ||
@@ -71,16 +72,7 @@ swayc_t *workspace_create(const char* name) { | |||
71 | while(parent->type != C_OUTPUT) { | 72 | while(parent->type != C_OUTPUT) { |
72 | parent = parent->parent; | 73 | parent = parent->parent; |
73 | } | 74 | } |
74 | 75 | return new_workspace(parent, name); | |
75 | swayc_t *workspace = create_container(parent, -1); | ||
76 | workspace->type = C_WORKSPACE; | ||
77 | workspace->name = strdup(name); | ||
78 | workspace->width = parent->width; | ||
79 | workspace->height = parent->height; | ||
80 | workspace->layout = L_HORIZ; // todo: thing | ||
81 | |||
82 | add_child(parent, workspace); | ||
83 | return workspace; | ||
84 | } | 76 | } |
85 | 77 | ||
86 | bool workspace_by_name(swayc_t *view, void *data) { | 78 | bool workspace_by_name(swayc_t *view, void *data) { |
@@ -88,23 +80,13 @@ bool workspace_by_name(swayc_t *view, void *data) { | |||
88 | (strcasecmp(view->name, (char *) data) == 0); | 80 | (strcasecmp(view->name, (char *) data) == 0); |
89 | } | 81 | } |
90 | 82 | ||
91 | bool workspace_destroy(swayc_t *workspace) { | ||
92 | //Dont destroy if there are children | ||
93 | if (workspace->children->length) { | ||
94 | return false; | ||
95 | } | ||
96 | sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); | ||
97 | free_swayc(workspace); | ||
98 | return true; | ||
99 | } | ||
100 | |||
101 | void set_mask(swayc_t *view, void *data) { | 83 | void set_mask(swayc_t *view, void *data) { |
102 | uint32_t *p = data; | 84 | uint32_t *p = data; |
103 | 85 | ||
104 | if(view->type == C_VIEW) { | 86 | if(view->type == C_VIEW) { |
105 | wlc_view_set_mask(view->handle, *p); | 87 | wlc_view_set_mask(view->handle, *p); |
106 | view->visible = (*p == 2); | ||
107 | } | 88 | } |
89 | view->visible = (*p == 2); | ||
108 | } | 90 | } |
109 | 91 | ||
110 | swayc_t *workspace_find_by_name(const char* name) { | 92 | swayc_t *workspace_find_by_name(const char* name) { |
@@ -123,9 +105,9 @@ void workspace_switch(swayc_t *workspace) { | |||
123 | container_map(workspace, set_mask, &mask); | 105 | container_map(workspace, set_mask, &mask); |
124 | 106 | ||
125 | wlc_output_set_mask(wlc_get_focused_output(), 2); | 107 | wlc_output_set_mask(wlc_get_focused_output(), 2); |
126 | unfocus_all(active_workspace); | 108 | unfocus_all(&root_container); |
127 | focus_view(workspace); | 109 | focus_view(workspace); |
128 | workspace_destroy(active_workspace); | 110 | destroy_workspace(active_workspace); |
129 | } | 111 | } |
130 | active_workspace = workspace; | 112 | active_workspace = workspace; |
131 | } | 113 | } |
diff --git a/sway/workspace.h b/sway/workspace.h index 19f0d4c1..523ce633 100644 --- a/sway/workspace.h +++ b/sway/workspace.h | |||
@@ -5,6 +5,8 @@ | |||
5 | #include "list.h" | 5 | #include "list.h" |
6 | #include "layout.h" | 6 | #include "layout.h" |
7 | 7 | ||
8 | extern swayc_t *active_workspace; | ||
9 | |||
8 | char *workspace_next_name(void); | 10 | char *workspace_next_name(void); |
9 | swayc_t *workspace_create(const char*); | 11 | swayc_t *workspace_create(const char*); |
10 | swayc_t *workspace_find_by_name(const char*); | 12 | swayc_t *workspace_find_by_name(const char*); |