diff options
-rw-r--r-- | include/config.h | 8 | ||||
-rw-r--r-- | include/container.h | 2 | ||||
-rw-r--r-- | include/focus.h | 36 | ||||
-rw-r--r-- | include/handlers.h | 5 | ||||
-rw-r--r-- | include/layout.h | 2 | ||||
-rw-r--r-- | include/movement.h | 17 | ||||
-rw-r--r-- | sway/commands.c | 22 | ||||
-rw-r--r-- | sway/config.c | 2 | ||||
-rw-r--r-- | sway/container.c | 49 | ||||
-rw-r--r-- | sway/focus.c | 192 | ||||
-rw-r--r-- | sway/handlers.c | 362 | ||||
-rw-r--r-- | sway/layout.c | 75 | ||||
-rw-r--r-- | sway/log.c | 2 | ||||
-rw-r--r-- | sway/movement.c | 70 | ||||
-rw-r--r-- | sway/workspace.c | 50 |
15 files changed, 549 insertions, 345 deletions
diff --git a/include/config.h b/include/config.h index 38e93eb8..9243bf35 100644 --- a/include/config.h +++ b/include/config.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <stdint.h> | 4 | #include <stdint.h> |
5 | #include <wlc/wlc.h> | 5 | #include <wlc/wlc.h> |
6 | #include <xkbcommon/xkbcommon.h> | ||
6 | #include "list.h" | 7 | #include "list.h" |
7 | 8 | ||
8 | struct sway_variable { | 9 | struct sway_variable { |
@@ -32,16 +33,17 @@ struct sway_config { | |||
32 | list_t *cmd_queue; | 33 | list_t *cmd_queue; |
33 | list_t *workspace_outputs; | 34 | list_t *workspace_outputs; |
34 | struct sway_mode *current_mode; | 35 | struct sway_mode *current_mode; |
36 | uint32_t floating_mod; | ||
35 | 37 | ||
36 | // Flags | 38 | // Flags |
37 | bool focus_follows_mouse; | 39 | bool focus_follows_mouse; |
38 | bool mouse_warping; | 40 | bool mouse_warping; |
39 | bool active; | 41 | bool active; |
40 | bool failed; | 42 | bool failed; |
41 | bool reloading; | 43 | bool reloading; |
42 | }; | 44 | }; |
43 | 45 | ||
44 | bool load_config(); | 46 | bool load_config(void); |
45 | bool read_config(FILE *file, bool is_active); | 47 | bool read_config(FILE *file, bool is_active); |
46 | char *do_var_replacement(struct sway_config *config, char *str); | 48 | char *do_var_replacement(struct sway_config *config, char *str); |
47 | 49 | ||
diff --git a/include/container.h b/include/container.h index e395a55b..5f386368 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -45,6 +45,8 @@ struct sway_container { | |||
45 | 45 | ||
46 | bool is_floating; | 46 | bool is_floating; |
47 | 47 | ||
48 | bool is_focused; | ||
49 | |||
48 | int weight; | 50 | int weight; |
49 | 51 | ||
50 | char *name; | 52 | char *name; |
diff --git a/include/focus.h b/include/focus.h new file mode 100644 index 00000000..185910f3 --- /dev/null +++ b/include/focus.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _SWAY_FOCUS_H | ||
2 | #define _SWAY_FOCUS_H | ||
3 | #include "container.h" | ||
4 | |||
5 | enum movement_direction { | ||
6 | MOVE_LEFT, | ||
7 | MOVE_RIGHT, | ||
8 | MOVE_UP, | ||
9 | MOVE_DOWN, | ||
10 | MOVE_PARENT | ||
11 | }; | ||
12 | |||
13 | //focused_container - the container found by following the `focused` pointer | ||
14 | //from a given container to a container with `is_focused` boolean set | ||
15 | //--- | ||
16 | //focused_view - the container found by following the `focused` pointer from a | ||
17 | //given container to a view. | ||
18 | //--- | ||
19 | |||
20 | swayc_t *get_focused_container(swayc_t *parent); | ||
21 | swayc_t *get_focused_view(swayc_t *parent); | ||
22 | |||
23 | void set_focused_container(swayc_t *container); | ||
24 | void set_focused_container_for(swayc_t *ancestor, swayc_t *container); | ||
25 | |||
26 | //lock focused container/view. locked by windows with OVERRIDE attribute | ||
27 | //and unlocked when they are destroyed | ||
28 | |||
29 | extern bool locked_container_focus; | ||
30 | extern bool locked_view_focus; | ||
31 | |||
32 | |||
33 | bool move_focus(enum movement_direction direction); | ||
34 | |||
35 | #endif | ||
36 | |||
diff --git a/include/handlers.h b/include/handlers.h index d1742cce..6b642419 100644 --- a/include/handlers.h +++ b/include/handlers.h | |||
@@ -1,12 +1,13 @@ | |||
1 | #ifndef _SWAY_HANDLERS_H | 1 | #ifndef _SWAY_HANDLERS_H |
2 | #define _SWAY_HANDLERS_H | 2 | #define _SWAY_HANDLERS_H |
3 | 3 | #include "container.h" | |
4 | #include <stdbool.h> | 4 | #include <stdbool.h> |
5 | #include <wlc/wlc.h> | 5 | #include <wlc/wlc.h> |
6 | 6 | ||
7 | extern struct wlc_interface interface; | 7 | extern struct wlc_interface interface; |
8 | extern uint32_t keys_pressed[32]; | ||
8 | 9 | ||
9 | //set focus to current pointer location and return focused container | 10 | //set focus to current pointer location and return focused container |
10 | swayc_t *focus_pointer(void); | 11 | swayc_t *container_under_pointer(void); |
11 | 12 | ||
12 | #endif | 13 | #endif |
diff --git a/include/layout.h b/include/layout.h index a7f43fda..26d00ce4 100644 --- a/include/layout.h +++ b/include/layout.h | |||
@@ -13,7 +13,7 @@ void add_child(swayc_t *parent, swayc_t *child); | |||
13 | //Returns parent container which needs to be rearranged. | 13 | //Returns parent container which needs to be rearranged. |
14 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child); | 14 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child); |
15 | swayc_t *replace_child(swayc_t *child, swayc_t *new_child); | 15 | swayc_t *replace_child(swayc_t *child, swayc_t *new_child); |
16 | swayc_t *remove_child(swayc_t *parent, swayc_t *child); | 16 | swayc_t *remove_child(swayc_t *child); |
17 | 17 | ||
18 | //Layout | 18 | //Layout |
19 | void arrange_windows(swayc_t *container, int width, int height); | 19 | void arrange_windows(swayc_t *container, int width, int height); |
diff --git a/include/movement.h b/include/movement.h deleted file mode 100644 index dd701877..00000000 --- a/include/movement.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | #ifndef _SWAY_MOVEMENT_H | ||
2 | #define _SWAY_MOVEMENT_H | ||
3 | |||
4 | #include <wlc/wlc.h> | ||
5 | #include "list.h" | ||
6 | |||
7 | enum movement_direction { | ||
8 | MOVE_LEFT, | ||
9 | MOVE_RIGHT, | ||
10 | MOVE_UP, | ||
11 | MOVE_DOWN, | ||
12 | MOVE_PARENT | ||
13 | }; | ||
14 | |||
15 | bool move_focus(enum movement_direction direction); | ||
16 | |||
17 | #endif | ||
diff --git a/sway/commands.c b/sway/commands.c index 642fa3ce..7e9169e8 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <ctype.h> | 8 | #include <ctype.h> |
9 | #include "stringop.h" | 9 | #include "stringop.h" |
10 | #include "layout.h" | 10 | #include "layout.h" |
11 | #include "movement.h" | 11 | #include "focus.h" |
12 | #include "log.h" | 12 | #include "log.h" |
13 | #include "workspace.h" | 13 | #include "workspace.h" |
14 | #include "commands.h" | 14 | #include "commands.h" |
@@ -171,6 +171,10 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) { | |||
171 | } | 171 | } |
172 | 172 | ||
173 | static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | 173 | static bool cmd_floating(struct sway_config *config, int argc, char **argv) { |
174 | if (!checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1)) { | ||
175 | return false; | ||
176 | } | ||
177 | |||
174 | if (strcasecmp(argv[0], "toggle") == 0) { | 178 | if (strcasecmp(argv[0], "toggle") == 0) { |
175 | swayc_t *view = get_focused_container(&root_container); | 179 | swayc_t *view = get_focused_container(&root_container); |
176 | // Prevent running floating commands on things like workspaces | 180 | // Prevent running floating commands on things like workspaces |
@@ -215,11 +219,12 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | |||
215 | view->is_floating = false; | 219 | view->is_floating = false; |
216 | active_workspace->focused = NULL; | 220 | active_workspace->focused = NULL; |
217 | // Get the properly focused container, and add in the view there | 221 | // Get the properly focused container, and add in the view there |
218 | swayc_t *focused = focus_pointer(); | 222 | swayc_t *focused = container_under_pointer(); |
219 | // If focused is null, it's because the currently focused container is a workspace | 223 | // If focused is null, it's because the currently focused container is a workspace |
220 | if (focused == NULL) { | 224 | if (focused == NULL) { |
221 | focused = active_workspace; | 225 | focused = active_workspace; |
222 | } | 226 | } |
227 | set_focused_container(focused); | ||
223 | 228 | ||
224 | sway_log(L_DEBUG, "Non-floating focused container is %p", focused); | 229 | sway_log(L_DEBUG, "Non-floating focused container is %p", focused); |
225 | 230 | ||
@@ -232,7 +237,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | |||
232 | add_sibling(focused, view); | 237 | add_sibling(focused, view); |
233 | } | 238 | } |
234 | // Refocus on the view once its been put back into the layout | 239 | // Refocus on the view once its been put back into the layout |
235 | focus_view(view); | 240 | set_focused_container(view); |
236 | arrange_windows(active_workspace, -1, -1); | 241 | arrange_windows(active_workspace, -1, -1); |
237 | return true; | 242 | return true; |
238 | } | 243 | } |
@@ -241,6 +246,14 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | |||
241 | return true; | 246 | return true; |
242 | } | 247 | } |
243 | 248 | ||
249 | static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) { | ||
250 | if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { | ||
251 | return false; | ||
252 | } | ||
253 | config->floating_mod = xkb_keysym_from_name(argv[0], XKB_KEYSYM_CASE_INSENSITIVE); | ||
254 | return true; | ||
255 | } | ||
256 | |||
244 | static bool cmd_focus(struct sway_config *config, int argc, char **argv) { | 257 | static bool cmd_focus(struct sway_config *config, int argc, char **argv) { |
245 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { | 258 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { |
246 | return false; | 259 | return false; |
@@ -345,7 +358,7 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay | |||
345 | else { | 358 | else { |
346 | sway_log(L_DEBUG, "Adding new container around current focused container"); | 359 | sway_log(L_DEBUG, "Adding new container around current focused container"); |
347 | swayc_t *parent = new_container(focused, layout); | 360 | swayc_t *parent = new_container(focused, layout); |
348 | focus_view(focused); | 361 | set_focused_container(focused); |
349 | arrange_windows(parent, -1, -1); | 362 | arrange_windows(parent, -1, -1); |
350 | } | 363 | } |
351 | 364 | ||
@@ -465,6 +478,7 @@ static struct cmd_handler handlers[] = { | |||
465 | { "exec_always", cmd_exec_always }, | 478 | { "exec_always", cmd_exec_always }, |
466 | { "exit", cmd_exit }, | 479 | { "exit", cmd_exit }, |
467 | { "floating", cmd_floating }, | 480 | { "floating", cmd_floating }, |
481 | { "floating_modifier", cmd_floating_mod }, | ||
468 | { "focus", cmd_focus }, | 482 | { "focus", cmd_focus }, |
469 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 483 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
470 | { "fullscreen", cmd_fullscreen }, | 484 | { "fullscreen", cmd_fullscreen }, |
diff --git a/sway/config.c b/sway/config.c index e2d10d28..95d605a3 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -126,7 +126,7 @@ static char* get_config_path() { | |||
126 | return NULL; | 126 | return NULL; |
127 | } | 127 | } |
128 | 128 | ||
129 | bool load_config() { | 129 | bool load_config(void) { |
130 | sway_log(L_INFO, "Loading config"); | 130 | sway_log(L_INFO, "Loading config"); |
131 | 131 | ||
132 | char *path = get_config_path(); | 132 | char *path = get_config_path(); |
diff --git a/sway/container.c b/sway/container.c index 3534721d..2b9f7554 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -27,10 +27,7 @@ static void free_swayc(swayc_t *c) { | |||
27 | list_free(c->children); | 27 | list_free(c->children); |
28 | } | 28 | } |
29 | if (c->parent) { | 29 | if (c->parent) { |
30 | if (c->parent->focused == c) { | 30 | remove_child(c); |
31 | c->parent->focused = NULL; | ||
32 | } | ||
33 | remove_child(c->parent, c); | ||
34 | } | 31 | } |
35 | if (c->name) { | 32 | if (c->name) { |
36 | free(c->name); | 33 | free(c->name); |
@@ -39,17 +36,11 @@ static void free_swayc(swayc_t *c) { | |||
39 | } | 36 | } |
40 | 37 | ||
41 | /* New containers */ | 38 | /* New containers */ |
42 | static void add_output_widths(swayc_t *container, void *_width) { | ||
43 | int *width = _width; | ||
44 | if (container->type == C_OUTPUT) { | ||
45 | *width += container->width; | ||
46 | } | ||
47 | } | ||
48 | 39 | ||
49 | swayc_t *new_output(wlc_handle handle) { | 40 | swayc_t *new_output(wlc_handle handle) { |
50 | const struct wlc_size* size = wlc_output_get_resolution(handle); | 41 | const struct wlc_size* size = wlc_output_get_resolution(handle); |
51 | const char *name = wlc_output_get_name(handle); | 42 | const char *name = wlc_output_get_name(handle); |
52 | sway_log(L_DEBUG, "Added output %u %s", (unsigned int)handle, name); | 43 | sway_log(L_DEBUG, "Added output %lu:%s", handle, name); |
53 | 44 | ||
54 | swayc_t *output = new_swayc(C_OUTPUT); | 45 | swayc_t *output = new_swayc(C_OUTPUT); |
55 | output->width = size->w; | 46 | output->width = size->w; |
@@ -59,9 +50,12 @@ swayc_t *new_output(wlc_handle handle) { | |||
59 | 50 | ||
60 | add_child(&root_container, output); | 51 | add_child(&root_container, output); |
61 | 52 | ||
62 | //TODO something with this | 53 | //TODO still dont know why this is here? |
63 | int total_width = 0; | 54 | // int total_width = 0; |
64 | container_map(&root_container, add_output_widths, &total_width); | 55 | // int i; |
56 | // for (i = 0; i < root_container.children->length; ++i) { | ||
57 | // total_width += ((swayc_t*)root_container.children->items[i])->width; | ||
58 | // } | ||
65 | 59 | ||
66 | //Create workspace | 60 | //Create workspace |
67 | char *ws_name = NULL; | 61 | char *ws_name = NULL; |
@@ -79,7 +73,10 @@ swayc_t *new_output(wlc_handle handle) { | |||
79 | if (!ws_name) { | 73 | if (!ws_name) { |
80 | ws_name = workspace_next_name(); | 74 | ws_name = workspace_next_name(); |
81 | } | 75 | } |
82 | new_workspace(output, ws_name); | 76 | //create and initilize default workspace |
77 | swayc_t *ws = new_workspace(output, ws_name); | ||
78 | ws->is_focused = true; | ||
79 | |||
83 | free(ws_name); | 80 | free(ws_name); |
84 | 81 | ||
85 | return output; | 82 | return output; |
@@ -118,6 +115,11 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | |||
118 | //reorder focus | 115 | //reorder focus |
119 | cont->focused = workspace->focused; | 116 | cont->focused = workspace->focused; |
120 | workspace->focused = cont; | 117 | workspace->focused = cont; |
118 | //set all children focu to container | ||
119 | int i; | ||
120 | for (i = 0; i < workspace->children->length; ++i) { | ||
121 | ((swayc_t *)workspace->children->items[i])->parent = cont; | ||
122 | } | ||
121 | //Swap children | 123 | //Swap children |
122 | list_t *tmp_list = workspace->children; | 124 | list_t *tmp_list = workspace->children; |
123 | workspace->children = cont->children; | 125 | workspace->children = cont->children; |
@@ -139,14 +141,15 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { | |||
139 | } | 141 | } |
140 | 142 | ||
141 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | 143 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { |
142 | const char *title = wlc_view_get_title(handle); | 144 | const char *title = wlc_view_get_title(handle); |
143 | swayc_t *view = new_swayc(C_VIEW); | 145 | swayc_t *view = new_swayc(C_VIEW); |
144 | sway_log(L_DEBUG, "Adding new view %u:%s to container %p %d", | 146 | sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d", |
145 | (unsigned int)handle, title, sibling, sibling?sibling->type:0); | 147 | handle, title, sibling, sibling ? sibling->type : 0); |
146 | //Setup values | 148 | //Setup values |
147 | view->handle = handle; | 149 | view->handle = handle; |
148 | view->name = title ? strdup(title) : NULL; | 150 | view->name = title ? strdup(title) : NULL; |
149 | view->visible = true; | 151 | view->visible = true; |
152 | view->is_focused = true; | ||
150 | 153 | ||
151 | view->desired_width = -1; | 154 | view->desired_width = -1; |
152 | view->desired_height = -1; | 155 | view->desired_height = -1; |
@@ -168,8 +171,8 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | |||
168 | swayc_t *new_floating_view(wlc_handle handle) { | 171 | swayc_t *new_floating_view(wlc_handle handle) { |
169 | const char *title = wlc_view_get_title(handle); | 172 | const char *title = wlc_view_get_title(handle); |
170 | swayc_t *view = new_swayc(C_VIEW); | 173 | swayc_t *view = new_swayc(C_VIEW); |
171 | sway_log(L_DEBUG, "Adding new view %u:%s as a floating view", | 174 | sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view", |
172 | (unsigned int)handle, title); | 175 | handle, wlc_view_get_type(handle), title); |
173 | //Setup values | 176 | //Setup values |
174 | view->handle = handle; | 177 | view->handle = handle; |
175 | view->name = title ? strdup(title) : NULL; | 178 | view->name = title ? strdup(title) : NULL; |
@@ -197,12 +200,13 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
197 | return view; | 200 | return view; |
198 | } | 201 | } |
199 | 202 | ||
203 | /* Destroy container */ | ||
200 | 204 | ||
201 | swayc_t *destroy_output(swayc_t *output) { | 205 | swayc_t *destroy_output(swayc_t *output) { |
202 | if (output->children->length == 0) { | 206 | if (output->children->length == 0) { |
203 | //TODO move workspaces to other outputs | 207 | //TODO move workspaces to other outputs |
204 | } | 208 | } |
205 | sway_log(L_DEBUG, "OUTPUT: Destroying output '%u'", (unsigned int)output->handle); | 209 | sway_log(L_DEBUG, "OUTPUT: Destroying output '%lu'", output->handle); |
206 | free_swayc(output); | 210 | free_swayc(output); |
207 | return &root_container; | 211 | return &root_container; |
208 | } | 212 | } |
@@ -244,7 +248,6 @@ swayc_t *destroy_view(swayc_t *view) { | |||
244 | if (parent->type == C_CONTAINER) { | 248 | if (parent->type == C_CONTAINER) { |
245 | return destroy_container(parent); | 249 | return destroy_container(parent); |
246 | } | 250 | } |
247 | |||
248 | return parent; | 251 | return parent; |
249 | } | 252 | } |
250 | 253 | ||
@@ -300,3 +303,5 @@ void set_view_visibility(swayc_t *view, void *data) { | |||
300 | } | 303 | } |
301 | view->visible = (*p == 2); | 304 | view->visible = (*p == 2); |
302 | } | 305 | } |
306 | |||
307 | |||
diff --git a/sway/focus.c b/sway/focus.c new file mode 100644 index 00000000..14d27184 --- /dev/null +++ b/sway/focus.c | |||
@@ -0,0 +1,192 @@ | |||
1 | #include <wlc/wlc.h> | ||
2 | |||
3 | #include "focus.h" | ||
4 | #include "log.h" | ||
5 | #include "workspace.h" | ||
6 | |||
7 | bool locked_container_focus = false; | ||
8 | bool locked_view_focus = false; | ||
9 | |||
10 | //switches parent focus to c. will switch it accordingly | ||
11 | //TODO, everything needs a handle, so we can set front/back position properly | ||
12 | static void update_focus(swayc_t *c) { | ||
13 | //Handle if focus switches | ||
14 | swayc_t *parent = c->parent; | ||
15 | if (parent->focused != c) { | ||
16 | switch (c->type) { | ||
17 | case C_ROOT: return; | ||
18 | case C_OUTPUT: | ||
19 | wlc_output_focus(c->parent->handle); | ||
20 | break; | ||
21 | //switching workspaces | ||
22 | case C_WORKSPACE: | ||
23 | if (parent->focused) { | ||
24 | swayc_t *ws = parent->focused; | ||
25 | //hide visibility of old workspace | ||
26 | uint32_t mask = 1; | ||
27 | container_map(ws, set_view_visibility, &mask); | ||
28 | //set visibility of new workspace | ||
29 | mask = 2; | ||
30 | container_map(c, set_view_visibility, &mask); | ||
31 | wlc_output_set_mask(parent->handle, 2); | ||
32 | destroy_workspace(ws); | ||
33 | } | ||
34 | active_workspace = c; | ||
35 | break; | ||
36 | default: | ||
37 | case C_VIEW: | ||
38 | case C_CONTAINER: | ||
39 | //TODO whatever to do when container changes | ||
40 | //for example, stacked and tabbing change stuff. | ||
41 | break; | ||
42 | } | ||
43 | } | ||
44 | c->parent->focused = c; | ||
45 | } | ||
46 | |||
47 | bool move_focus(enum movement_direction direction) { | ||
48 | if (locked_container_focus) { | ||
49 | return false; | ||
50 | } | ||
51 | swayc_t *current = get_focused_container(&root_container); | ||
52 | swayc_t *parent = current->parent; | ||
53 | |||
54 | if (direction == MOVE_PARENT) { | ||
55 | if (parent->type == C_OUTPUT) { | ||
56 | sway_log(L_DEBUG, "Focus cannot move to parent"); | ||
57 | return false; | ||
58 | } else { | ||
59 | sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld", | ||
60 | current, current->handle, parent, parent->handle); | ||
61 | set_focused_container(parent); | ||
62 | return true; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | while (true) { | ||
67 | sway_log(L_DEBUG, "Moving focus away from %p", current); | ||
68 | |||
69 | // Test if we can even make a difference here | ||
70 | bool can_move = false; | ||
71 | int diff = 0; | ||
72 | if (direction == MOVE_LEFT || direction == MOVE_RIGHT) { | ||
73 | if (parent->layout == L_HORIZ || parent->type == C_ROOT) { | ||
74 | can_move = true; | ||
75 | diff = direction == MOVE_LEFT ? -1 : 1; | ||
76 | } | ||
77 | } else { | ||
78 | if (parent->layout == L_VERT) { | ||
79 | can_move = true; | ||
80 | diff = direction == MOVE_UP ? -1 : 1; | ||
81 | } | ||
82 | } | ||
83 | sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no"); | ||
84 | if (can_move) { | ||
85 | int i; | ||
86 | for (i = 0; i < parent->children->length; ++i) { | ||
87 | swayc_t *child = parent->children->items[i]; | ||
88 | if (child == current) { | ||
89 | break; | ||
90 | } | ||
91 | } | ||
92 | int desired = i + diff; | ||
93 | sway_log(L_DEBUG, "Moving from %d to %d", i, desired); | ||
94 | if (desired < 0 || desired >= parent->children->length) { | ||
95 | can_move = false; | ||
96 | } else { | ||
97 | swayc_t *newview = parent->children->items[desired]; | ||
98 | set_focused_container(get_focused_view(newview)); | ||
99 | return true; | ||
100 | } | ||
101 | } | ||
102 | if (!can_move) { | ||
103 | sway_log(L_DEBUG, "Can't move at current level, moving up tree"); | ||
104 | current = parent; | ||
105 | parent = parent->parent; | ||
106 | if (!parent) { | ||
107 | // Nothing we can do | ||
108 | return false; | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | swayc_t *get_focused_container(swayc_t *parent) { | ||
115 | while (parent && !parent->is_focused) { | ||
116 | parent = parent->focused; | ||
117 | } | ||
118 | //just incase | ||
119 | if (parent == NULL) { | ||
120 | sway_log(L_DEBUG, "get_focused_container unable to find container"); | ||
121 | return active_workspace; | ||
122 | } | ||
123 | return parent; | ||
124 | } | ||
125 | |||
126 | void set_focused_container(swayc_t *c) { | ||
127 | if (locked_container_focus || !c) { | ||
128 | return; | ||
129 | } | ||
130 | sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); | ||
131 | if (c->type != C_ROOT && c->type != C_OUTPUT) { | ||
132 | c->is_focused = true; | ||
133 | } | ||
134 | swayc_t *prev_view = get_focused_view(&root_container); | ||
135 | swayc_t *p = c; | ||
136 | while (p != &root_container) { | ||
137 | update_focus(p); | ||
138 | p = p->parent; | ||
139 | p->is_focused = false; | ||
140 | } | ||
141 | if (!locked_view_focus) { | ||
142 | p = get_focused_view(c); | ||
143 | //Set focus to p | ||
144 | if (p && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { | ||
145 | if (prev_view) { | ||
146 | wlc_view_set_state(prev_view->handle, WLC_BIT_ACTIVATED, false); | ||
147 | } | ||
148 | wlc_view_focus(p->handle); | ||
149 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | |||
154 | void set_focused_container_for(swayc_t *a, swayc_t *c) { | ||
155 | if (locked_container_focus || !c) { | ||
156 | return; | ||
157 | } | ||
158 | swayc_t *find = c; | ||
159 | //Ensure that a is an ancestor of c | ||
160 | while (find != a && (find = find->parent)) { | ||
161 | if (find == &root_container) { | ||
162 | return; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", | ||
167 | a, a->handle, c, c->handle); | ||
168 | |||
169 | c->is_focused = true; | ||
170 | swayc_t *p = c; | ||
171 | while (p != a) { | ||
172 | update_focus(p); | ||
173 | p = p->parent; | ||
174 | p->is_focused = false; | ||
175 | } | ||
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 | } | ||
185 | |||
186 | swayc_t *get_focused_view(swayc_t *parent) { | ||
187 | while (parent && parent->type != C_VIEW) { | ||
188 | parent = parent->focused; | ||
189 | } | ||
190 | return parent; | ||
191 | } | ||
192 | |||
diff --git a/sway/handlers.c b/sway/handlers.c index e17aefee..0157d466 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -3,18 +3,23 @@ | |||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <wlc/wlc.h> | 4 | #include <wlc/wlc.h> |
5 | #include <ctype.h> | 5 | #include <ctype.h> |
6 | #include "layout.h" | 6 | |
7 | #include "handlers.h" | ||
7 | #include "log.h" | 8 | #include "log.h" |
9 | #include "layout.h" | ||
8 | #include "config.h" | 10 | #include "config.h" |
9 | #include "commands.h" | 11 | #include "commands.h" |
10 | #include "handlers.h" | ||
11 | #include "stringop.h" | 12 | #include "stringop.h" |
12 | #include "workspace.h" | 13 | #include "workspace.h" |
13 | #include "container.h" | 14 | #include "container.h" |
15 | #include "focus.h" | ||
16 | |||
17 | uint32_t keys_pressed[32]; | ||
14 | 18 | ||
15 | static struct wlc_origin mouse_origin; | 19 | static struct wlc_origin mouse_origin; |
16 | //Keyboard input is being overrided by window (dmenu) | 20 | |
17 | static bool override_redirect = false; | 21 | static bool m1_held = false; |
22 | static bool m2_held = false; | ||
18 | 23 | ||
19 | static bool pointer_test(swayc_t *view, void *_origin) { | 24 | static bool pointer_test(swayc_t *view, void *_origin) { |
20 | const struct wlc_origin *origin = _origin; | 25 | const struct wlc_origin *origin = _origin; |
@@ -23,27 +28,60 @@ static bool pointer_test(swayc_t *view, void *_origin) { | |||
23 | while (parent->type != C_OUTPUT) { | 28 | while (parent->type != C_OUTPUT) { |
24 | parent = parent->parent; | 29 | parent = parent->parent; |
25 | } | 30 | } |
26 | if (view->type == C_VIEW && origin->x >= view->x && origin->y >= view->y | 31 | if (origin->x >= view->x && origin->y >= view->y |
27 | && origin->x < view->x + view->width && origin->y < view->y + view->height | 32 | && origin->x < view->x + view->width && origin->y < view->y + view->height |
28 | && view->visible && parent == root_container.focused) { | 33 | && view->visible && parent == root_container.focused) { |
29 | return true; | 34 | return true; |
30 | } | 35 | } |
31 | return false; | 36 | return false; |
32 | } | 37 | } |
33 | 38 | ||
34 | swayc_t *focus_pointer(void) { | 39 | swayc_t *container_under_pointer(void) { |
35 | swayc_t *focused = get_focused_container(&root_container); | 40 | //root.output->workspace |
36 | if (!(wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) { | 41 | if (!root_container.focused || !root_container.focused->focused) { |
37 | swayc_t *pointer = find_container(&root_container, pointer_test, &mouse_origin); | 42 | return NULL; |
38 | if (pointer && focused != pointer) { | 43 | } |
39 | unfocus_all(&root_container); | 44 | swayc_t *lookup = root_container.focused->focused; |
40 | focus_view(pointer); | 45 | //Case of empty workspace |
41 | } else if (!focused) { | 46 | if (lookup->children == 0) { |
42 | focus_view(active_workspace); | 47 | return NULL; |
48 | } | ||
49 | while (lookup->type != C_VIEW) { | ||
50 | int i; | ||
51 | int len; | ||
52 | //if tabbed/stacked go directly to focused container, otherwise search | ||
53 | //children | ||
54 | if (lookup->layout == L_TABBED || lookup->layout == L_STACKED) { | ||
55 | lookup = lookup->focused; | ||
56 | continue; | ||
57 | } | ||
58 | //if workspace, search floating | ||
59 | if (lookup->type == C_WORKSPACE) { | ||
60 | len = lookup->floating->length; | ||
61 | for (i = 0; i < len; ++i) { | ||
62 | if (pointer_test(lookup->floating->items[i], &mouse_origin)) { | ||
63 | lookup = lookup->floating->items[i]; | ||
64 | break; | ||
65 | } | ||
66 | } | ||
67 | if (i < len) { | ||
68 | continue; | ||
69 | } | ||
70 | } | ||
71 | //search children | ||
72 | len = lookup->children->length; | ||
73 | for (i = 0; i < len; ++i) { | ||
74 | if (pointer_test(lookup->children->items[i], &mouse_origin)) { | ||
75 | lookup = lookup->children->items[i]; | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | //when border and titles are done, this could happen | ||
80 | if (i == len) { | ||
81 | break; | ||
43 | } | 82 | } |
44 | focused = pointer; | ||
45 | } | 83 | } |
46 | return focused; | 84 | return lookup; |
47 | } | 85 | } |
48 | 86 | ||
49 | static bool handle_output_created(wlc_handle output) { | 87 | static bool handle_output_created(wlc_handle output) { |
@@ -81,90 +119,77 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_ | |||
81 | 119 | ||
82 | static void handle_output_focused(wlc_handle output, bool focus) { | 120 | static void handle_output_focused(wlc_handle output, bool focus) { |
83 | swayc_t *c = get_swayc_for_handle(output, &root_container); | 121 | swayc_t *c = get_swayc_for_handle(output, &root_container); |
84 | if (!c) return; | 122 | //if for some reason this output doesnt exist, create it. |
123 | if (!c) { | ||
124 | handle_output_created(output); | ||
125 | } | ||
85 | if (focus) { | 126 | if (focus) { |
86 | unfocus_all(&root_container); | 127 | set_focused_container(c); |
87 | focus_view(c); | ||
88 | } | 128 | } |
89 | } | 129 | } |
90 | 130 | ||
91 | static bool handle_view_created(wlc_handle handle) { | 131 | static bool handle_view_created(wlc_handle handle) { |
92 | swayc_t *focused = get_focused_container(&root_container); | 132 | swayc_t *focused = get_focused_container(&root_container); |
93 | uint32_t type = wlc_view_get_type(handle); | 133 | swayc_t *newview = NULL; |
94 | // If override_redirect/unmanaged/popup/modal/splach | 134 | switch (wlc_view_get_type(handle)) { |
95 | if (type) { | 135 | //regular view created regularly |
96 | sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type); | 136 | case 0: |
97 | wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); | 137 | newview = new_view(focused, handle); |
98 | if (type & WLC_BIT_UNMANAGED) { | ||
99 | return true; | ||
100 | } | ||
101 | // For things like Dmenu | ||
102 | if (type & WLC_BIT_OVERRIDE_REDIRECT) { | ||
103 | override_redirect = true; | ||
104 | wlc_view_focus(handle); | ||
105 | } | ||
106 | |||
107 | // Float popups | ||
108 | if (type & WLC_BIT_POPUP) { | ||
109 | swayc_t *view = new_floating_view(handle); | ||
110 | wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, false); | ||
111 | focus_view(view); | ||
112 | arrange_windows(active_workspace, -1, -1); | ||
113 | } | ||
114 | } else { | ||
115 | swayc_t *view = new_view(focused, handle); | ||
116 | //Set maximize flag for windows. | ||
117 | //TODO: floating windows have this unset | ||
118 | wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); | 138 | wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); |
119 | unfocus_all(&root_container); | 139 | break; |
120 | focus_view(view); | 140 | //takes keyboard focus |
121 | arrange_windows(view->parent, -1, -1); | 141 | case WLC_BIT_OVERRIDE_REDIRECT: |
142 | sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle); | ||
143 | locked_view_focus = true; | ||
144 | wlc_view_focus(handle); | ||
145 | wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); | ||
146 | wlc_view_bring_to_front(handle); | ||
147 | break; | ||
148 | //Takes container focus | ||
149 | case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: | ||
150 | sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle); | ||
151 | wlc_view_bring_to_front(handle); | ||
152 | locked_container_focus = true; | ||
153 | break; | ||
154 | //set modals as floating containers | ||
155 | case WLC_BIT_MODAL: | ||
156 | wlc_view_bring_to_front(handle); | ||
157 | newview = new_floating_view(handle); | ||
158 | case WLC_BIT_POPUP: | ||
159 | break; | ||
122 | } | 160 | } |
123 | if (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { | 161 | if (newview) { |
124 | unfocus_all(&root_container); | 162 | set_focused_container(newview); |
125 | focus_view(focused); | 163 | arrange_windows(newview->parent, -1, -1); |
126 | arrange_windows(focused, -1, -1); | ||
127 | } | 164 | } |
128 | return true; | 165 | return true; |
129 | } | 166 | } |
130 | 167 | ||
131 | static void handle_view_destroyed(wlc_handle handle) { | 168 | static void handle_view_destroyed(wlc_handle handle) { |
132 | sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle); | 169 | sway_log(L_DEBUG, "Destroying window %lu", handle); |
133 | |||
134 | // Properly handle unmanaged views | ||
135 | uint32_t type = wlc_view_get_type(handle); | ||
136 | if (type) { | ||
137 | wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); | ||
138 | sway_log(L_DEBUG,"Unmanaged window of type %x was destroyed", type); | ||
139 | if (type & WLC_BIT_UNMANAGED) { | ||
140 | // We need to call focus_view() on focus_pointer because unmanaged windows | ||
141 | // do not alter the focus structure of the container tree. This makes focus_pointer() | ||
142 | // think that it doesn't need to do anything, so we manually focus the result. | ||
143 | focus_view(focus_pointer()); | ||
144 | return; | ||
145 | } | ||
146 | |||
147 | if (type & WLC_BIT_OVERRIDE_REDIRECT) { | ||
148 | override_redirect = false; | ||
149 | focus_view(focus_pointer()); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | // WLC_BIT_POPUP doesn't need to be dealt with since it's | ||
154 | // treated as a floating view. | ||
155 | } | ||
156 | |||
157 | swayc_t *view = get_swayc_for_handle(handle, &root_container); | 170 | swayc_t *view = get_swayc_for_handle(handle, &root_container); |
158 | swayc_t *parent; | ||
159 | swayc_t *focused = get_focused_container(&root_container); | 171 | swayc_t *focused = get_focused_container(&root_container); |
160 | 172 | ||
161 | if (view) { | 173 | switch (wlc_view_get_type(handle)) { |
162 | parent = destroy_view(view); | 174 | //regular view created regularly |
163 | arrange_windows(parent, -1, -1); | 175 | case 0: |
164 | } | 176 | case WLC_BIT_MODAL: |
165 | if (!focused || focused == view) { | 177 | if (view) { |
166 | focus_pointer(); | 178 | swayc_t *parent = destroy_view(view); |
179 | arrange_windows(parent, -1, -1); | ||
180 | } | ||
181 | break; | ||
182 | //takes keyboard focus | ||
183 | case WLC_BIT_OVERRIDE_REDIRECT: | ||
184 | locked_view_focus = false; | ||
185 | break; | ||
186 | //Takes container focus | ||
187 | case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: | ||
188 | locked_container_focus = false; | ||
189 | case WLC_BIT_POPUP: | ||
190 | break; | ||
167 | } | 191 | } |
192 | set_focused_container(get_focused_view(&root_container)); | ||
168 | } | 193 | } |
169 | 194 | ||
170 | static void handle_view_focus(wlc_handle view, bool focus) { | 195 | static void handle_view_focus(wlc_handle view, bool focus) { |
@@ -172,6 +197,8 @@ static void handle_view_focus(wlc_handle view, bool focus) { | |||
172 | } | 197 | } |
173 | 198 | ||
174 | static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) { | 199 | static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) { |
200 | sway_log(L_DEBUG, "geometry request %d x %d : %d x %d", | ||
201 | geometry->origin.x, geometry->origin.y, geometry->size.w,geometry->size.h); | ||
175 | // If the view is floating, then apply the geometry. | 202 | // If the view is floating, then apply the geometry. |
176 | // Otherwise save the desired width/height for the view. | 203 | // Otherwise save the desired width/height for the view. |
177 | // This will not do anything for the time being as WLC improperly sends geometry requests | 204 | // This will not do anything for the time being as WLC improperly sends geometry requests |
@@ -186,33 +213,32 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo | |||
186 | view->x = geometry->origin.x; | 213 | view->x = geometry->origin.x; |
187 | view->y = geometry->origin.y; | 214 | view->y = geometry->origin.y; |
188 | arrange_windows(view->parent, -1, -1); | 215 | arrange_windows(view->parent, -1, -1); |
189 | } | 216 | } |
190 | } | 217 | } |
191 | } | 218 | } |
192 | 219 | ||
193 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { | 220 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { |
221 | swayc_t *c = NULL; | ||
194 | switch(state) { | 222 | switch(state) { |
195 | case WLC_BIT_FULLSCREEN: | 223 | case WLC_BIT_FULLSCREEN: |
196 | { | 224 | //I3 just lets it become fullscreen |
197 | //I3 just lets it become fullscreen | 225 | wlc_view_set_state(view, state, toggle); |
198 | wlc_view_set_state(view,state,toggle); | 226 | c = get_swayc_for_handle(view, &root_container); |
199 | swayc_t *c = get_swayc_for_handle(view, &root_container); | 227 | sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle); |
200 | sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle); | 228 | if (c) { |
201 | if (c) { | 229 | arrange_windows(c->parent, -1, -1); |
202 | arrange_windows(c->parent, -1, -1); | 230 | //Set it as focused window for that workspace if its going |
203 | //Set it as focused window for that workspace if its going | 231 | //fullscreen |
204 | //fullscreen | 232 | if (toggle) { |
205 | if (toggle) { | 233 | swayc_t *ws = c; |
206 | swayc_t *ws = c; | 234 | while (ws->type != C_WORKSPACE) { |
207 | while (ws->type != C_WORKSPACE) { | 235 | ws = ws->parent; |
208 | ws = ws->parent; | ||
209 | } | ||
210 | //Set ws focus to c | ||
211 | focus_view_for(ws, c); | ||
212 | } | 236 | } |
237 | //Set ws focus to c | ||
238 | set_focused_container_for(ws, c); | ||
213 | } | 239 | } |
214 | break; | ||
215 | } | 240 | } |
241 | break; | ||
216 | case WLC_BIT_MAXIMIZED: | 242 | case WLC_BIT_MAXIMIZED: |
217 | case WLC_BIT_RESIZING: | 243 | case WLC_BIT_RESIZING: |
218 | case WLC_BIT_MOVING: | 244 | case WLC_BIT_MOVING: |
@@ -226,11 +252,10 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s | |||
226 | static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers | 252 | static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers |
227 | *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) { | 253 | *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) { |
228 | enum { QSIZE = 32 }; | 254 | enum { QSIZE = 32 }; |
229 | if (override_redirect) { | 255 | if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) { |
230 | return false; | 256 | return false; |
231 | } | 257 | } |
232 | static uint8_t head = 0; | 258 | static uint8_t head = 0; |
233 | static uint32_t array[QSIZE]; | ||
234 | bool cmd_success = false; | 259 | bool cmd_success = false; |
235 | 260 | ||
236 | struct sway_mode *mode = config->current_mode; | 261 | struct sway_mode *mode = config->current_mode; |
@@ -239,13 +264,13 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
239 | 264 | ||
240 | //Find key, if it has been pressed | 265 | //Find key, if it has been pressed |
241 | int mid = 0; | 266 | int mid = 0; |
242 | while (mid < head && array[mid] != sym) { | 267 | while (mid < head && keys_pressed[mid] != sym) { |
243 | ++mid; | 268 | ++mid; |
244 | } | 269 | } |
245 | if (state == WLC_KEY_STATE_PRESSED && mid == head && head + 1 < QSIZE) { | 270 | if (state == WLC_KEY_STATE_PRESSED && mid == head && head + 1 < QSIZE) { |
246 | array[head++] = sym; | 271 | keys_pressed[head++] = sym; |
247 | } else if (state == WLC_KEY_STATE_RELEASED && mid < head) { | 272 | } else if (state == WLC_KEY_STATE_RELEASED && mid < head) { |
248 | memmove(array + mid, array + mid + 1, sizeof*array * (--head - mid)); | 273 | memmove(keys_pressed + mid, keys_pressed + mid + 1, sizeof*keys_pressed * (--head - mid)); |
249 | } | 274 | } |
250 | // TODO: reminder to check conflicts with mod+q+a versus mod+q | 275 | // TODO: reminder to check conflicts with mod+q+a versus mod+q |
251 | int i; | 276 | int i; |
@@ -260,7 +285,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
260 | xkb_keysym_t *key = binding->keys->items[j]; | 285 | xkb_keysym_t *key = binding->keys->items[j]; |
261 | uint8_t k; | 286 | uint8_t k; |
262 | for (k = 0; k < head; ++k) { | 287 | for (k = 0; k < head; ++k) { |
263 | if (array[k] == *key) { | 288 | if (keys_pressed[k] == *key) { |
264 | match = true; | 289 | match = true; |
265 | break; | 290 | break; |
266 | } | 291 | } |
@@ -271,12 +296,12 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
271 | } | 296 | } |
272 | 297 | ||
273 | if (match) { | 298 | if (match) { |
274 | //Remove matched keys from array | 299 | //Remove matched keys from keys_pressed |
275 | int j; | 300 | int j; |
276 | for (j = 0; j < binding->keys->length; ++j) { | 301 | for (j = 0; j < binding->keys->length; ++j) { |
277 | uint8_t k; | 302 | uint8_t k; |
278 | for (k = 0; k < head; ++k) { | 303 | for (k = 0; k < head; ++k) { |
279 | memmove(array + k, array + k + 1, sizeof*array * (--head - k)); | 304 | memmove(keys_pressed + k, keys_pressed + k + 1, sizeof*keys_pressed * (--head - k)); |
280 | break; | 305 | break; |
281 | } | 306 | } |
282 | } | 307 | } |
@@ -291,13 +316,100 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
291 | return cmd_success; | 316 | return cmd_success; |
292 | } | 317 | } |
293 | 318 | ||
294 | static bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct wlc_origin *origin) { | 319 | static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { |
295 | static wlc_handle prev_view = 0; | 320 | static struct wlc_origin prev_pos; |
321 | static wlc_handle prev_handle = 0; | ||
296 | mouse_origin = *origin; | 322 | mouse_origin = *origin; |
297 | if (config->focus_follows_mouse && prev_view != view) { | 323 | bool changed_floating = false; |
298 | focus_pointer(); | 324 | int i = 0; |
325 | // Do checks to determine if proper keys are being held | ||
326 | swayc_t *view = active_workspace->focused; | ||
327 | if (m1_held) { | ||
328 | if (view->is_floating) { | ||
329 | while (keys_pressed[i++]) { | ||
330 | if (keys_pressed[i] == config->floating_mod) { | ||
331 | int dx = mouse_origin.x - prev_pos.x; | ||
332 | int dy = mouse_origin.y - prev_pos.y; | ||
333 | sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); | ||
334 | sway_log(L_DEBUG, "Moving: dx: %d, dy: %d", dx, dy); | ||
335 | |||
336 | view->x += dx; | ||
337 | view->y += dy; | ||
338 | changed_floating = true; | ||
339 | break; | ||
340 | } | ||
341 | } | ||
342 | } | ||
343 | } else if (m2_held) { | ||
344 | if (view->is_floating) { | ||
345 | while (keys_pressed[i++]) { | ||
346 | if (keys_pressed[i] == config->floating_mod) { | ||
347 | int dx = mouse_origin.x - prev_pos.x; | ||
348 | int dy = mouse_origin.y - prev_pos.y; | ||
349 | sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); | ||
350 | sway_log(L_INFO, "Moving: dx: %d, dy: %d", dx, dy); | ||
351 | |||
352 | // Move and resize the view based on the dx/dy and mouse position | ||
353 | int midway_x = view->x + view->width/2; | ||
354 | int midway_y = view->y + view->height/2; | ||
355 | |||
356 | if (dx < 0) { | ||
357 | changed_floating = true; | ||
358 | if (mouse_origin.x > midway_x) { | ||
359 | sway_log(L_INFO, "Downsizing view to the left"); | ||
360 | view->width += dx; | ||
361 | } else { | ||
362 | sway_log(L_INFO, "Upsizing view to the left"); | ||
363 | view->x += dx; | ||
364 | view->width -= dx; | ||
365 | } | ||
366 | } else if (dx > 0){ | ||
367 | changed_floating = true; | ||
368 | if (mouse_origin.x > midway_x) { | ||
369 | sway_log(L_INFO, "Upsizing to the right"); | ||
370 | view->width += dx; | ||
371 | } else { | ||
372 | sway_log(L_INFO, "Downsizing to the right"); | ||
373 | view->x += dx; | ||
374 | view->width -= dx; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | if (dy < 0) { | ||
379 | changed_floating = true; | ||
380 | if (mouse_origin.y > midway_y) { | ||
381 | sway_log(L_INFO, "Downsizing view to the top"); | ||
382 | view->height += dy; | ||
383 | } else { | ||
384 | sway_log(L_INFO, "Upsizing the view to the top"); | ||
385 | view->y += dy; | ||
386 | view->height -= dy; | ||
387 | } | ||
388 | } else if (dy > 0) { | ||
389 | changed_floating = true; | ||
390 | if (mouse_origin.y > midway_y) { | ||
391 | sway_log(L_INFO, "Upsizing to the bottom"); | ||
392 | view->height += dy; | ||
393 | } else { | ||
394 | sway_log(L_INFO, "Downsizing to the bottom"); | ||
395 | view->y += dy; | ||
396 | view->height -= dy; | ||
397 | } | ||
398 | } | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | } | ||
404 | if (config->focus_follows_mouse && prev_handle != handle) { | ||
405 | set_focused_container(container_under_pointer()); | ||
406 | } | ||
407 | prev_handle = handle; | ||
408 | prev_pos = mouse_origin; | ||
409 | if (changed_floating) { | ||
410 | arrange_windows(view, -1, -1); | ||
411 | return true; | ||
299 | } | 412 | } |
300 | prev_view = view; | ||
301 | return false; | 413 | return false; |
302 | } | 414 | } |
303 | 415 | ||
@@ -305,8 +417,24 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w | |||
305 | uint32_t button, enum wlc_button_state state) { | 417 | uint32_t button, enum wlc_button_state state) { |
306 | swayc_t *focused = get_focused_container(&root_container); | 418 | swayc_t *focused = get_focused_container(&root_container); |
307 | if (state == WLC_BUTTON_STATE_PRESSED) { | 419 | if (state == WLC_BUTTON_STATE_PRESSED) { |
308 | swayc_t *pointer = focus_pointer(); | 420 | sway_log(L_DEBUG, "Mouse button %u pressed", button); |
421 | if (button == 272) { | ||
422 | m1_held = true; | ||
423 | } | ||
424 | if (button == 273) { | ||
425 | m2_held = true; | ||
426 | } | ||
427 | swayc_t *pointer = container_under_pointer(); | ||
428 | set_focused_container(pointer); | ||
309 | return (pointer && pointer != focused); | 429 | return (pointer && pointer != focused); |
430 | } else { | ||
431 | sway_log(L_DEBUG, "Mouse button %u released", button); | ||
432 | if (button == 272) { | ||
433 | m1_held = false; | ||
434 | } | ||
435 | if (button == 273) { | ||
436 | m2_held = false; | ||
437 | } | ||
310 | } | 438 | } |
311 | return false; | 439 | return false; |
312 | } | 440 | } |
diff --git a/sway/layout.c b/sway/layout.c index f4079d4b..8ff5c4b7 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -31,9 +31,6 @@ void add_child(swayc_t *parent, swayc_t *child) { | |||
31 | child->width, child->height, parent, parent->type, parent->width, parent->height); | 31 | child->width, child->height, parent, parent->type, parent->width, parent->height); |
32 | list_add(parent->children, child); | 32 | list_add(parent->children, child); |
33 | child->parent = parent; | 33 | child->parent = parent; |
34 | if (parent->focused == NULL) { | ||
35 | parent->focused = child; | ||
36 | } | ||
37 | } | 34 | } |
38 | 35 | ||
39 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { | 36 | swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { |
@@ -63,8 +60,9 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { | |||
63 | return parent; | 60 | return parent; |
64 | } | 61 | } |
65 | 62 | ||
66 | swayc_t *remove_child(swayc_t *parent, swayc_t *child) { | 63 | swayc_t *remove_child(swayc_t *child) { |
67 | int i; | 64 | int i; |
65 | swayc_t *parent = child->parent; | ||
68 | // Special case for floating views | 66 | // Special case for floating views |
69 | if (child->is_floating) { | 67 | if (child->is_floating) { |
70 | for (i = 0; i < parent->floating->length; ++i) { | 68 | for (i = 0; i < parent->floating->length; ++i) { |
@@ -82,7 +80,11 @@ swayc_t *remove_child(swayc_t *parent, swayc_t *child) { | |||
82 | } | 80 | } |
83 | } | 81 | } |
84 | if (parent->focused == child) { | 82 | if (parent->focused == child) { |
85 | parent->focused = NULL; | 83 | if (parent->children->length > 0) { |
84 | parent->focused = parent->children->items[i?i-1:0]; | ||
85 | } else { | ||
86 | parent->focused = NULL; | ||
87 | } | ||
86 | } | 88 | } |
87 | return parent; | 89 | return parent; |
88 | } | 90 | } |
@@ -206,7 +208,7 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
206 | // Arrage floating layouts for workspaces last | 208 | // Arrage floating layouts for workspaces last |
207 | if (container->type == C_WORKSPACE) { | 209 | if (container->type == C_WORKSPACE) { |
208 | for (i = 0; i < container->floating->length; ++i) { | 210 | for (i = 0; i < container->floating->length; ++i) { |
209 | swayc_t *view = ((swayc_t *)container->floating->items[i]); | 211 | swayc_t *view = container->floating->items[i]; |
210 | // Set the geometry | 212 | // Set the geometry |
211 | struct wlc_geometry geometry = { | 213 | struct wlc_geometry geometry = { |
212 | .origin = { | 214 | .origin = { |
@@ -262,64 +264,3 @@ swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { | |||
262 | return NULL; | 264 | return NULL; |
263 | } | 265 | } |
264 | 266 | ||
265 | swayc_t *get_focused_container(swayc_t *parent) { | ||
266 | if (parent->focused == NULL) { | ||
267 | return parent; | ||
268 | } | ||
269 | return get_focused_container(parent->focused); | ||
270 | } | ||
271 | |||
272 | void unfocus_all(swayc_t *container) { | ||
273 | if (container->children == NULL) { | ||
274 | return; | ||
275 | } | ||
276 | int i; | ||
277 | for (i = 0; i < container->children->length; ++i) { | ||
278 | swayc_t *view = container->children->items[i]; | ||
279 | if (view->type == C_VIEW) { | ||
280 | wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, false); | ||
281 | } else { | ||
282 | unfocus_all(view); | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | |||
287 | void focus_view(swayc_t *view) { | ||
288 | if (!view) { | ||
289 | return; | ||
290 | } | ||
291 | sway_log(L_DEBUG, "Setting focus for %p:%ld", view, view->handle); | ||
292 | swayc_t *c = view; | ||
293 | //Set focus from root to view | ||
294 | while (c != &root_container) { | ||
295 | c->parent->focused = c; | ||
296 | c = c->parent; | ||
297 | } | ||
298 | //Set output | ||
299 | wlc_output_focus(c->focused->handle); | ||
300 | //get focus for views focused window | ||
301 | while (view && view->type != C_VIEW) { | ||
302 | view = view->focused; | ||
303 | } | ||
304 | if (view) { | ||
305 | wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, true); | ||
306 | wlc_view_focus(view->handle); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | void focus_view_for(swayc_t *top, swayc_t *view) { | ||
311 | swayc_t *find = view; | ||
312 | //Make sure top is a ancestor of view | ||
313 | while (find != top) { | ||
314 | if (find == &root_container) { | ||
315 | return; | ||
316 | } | ||
317 | find = find->parent; | ||
318 | } | ||
319 | //Set focus for top to go to view | ||
320 | while (view != top) { | ||
321 | view->parent->focused = view; | ||
322 | view = view->parent; | ||
323 | } | ||
324 | } | ||
325 | |||
@@ -8,7 +8,7 @@ | |||
8 | int colored = 1; | 8 | int colored = 1; |
9 | int v = 0; | 9 | int v = 0; |
10 | 10 | ||
11 | const char *verbosity_colors[] = { | 11 | static const char *verbosity_colors[] = { |
12 | "", // L_SILENT | 12 | "", // L_SILENT |
13 | "\x1B[1;31m", // L_ERROR | 13 | "\x1B[1;31m", // L_ERROR |
14 | "\x1B[1;34m", // L_INFO | 14 | "\x1B[1;34m", // L_INFO |
diff --git a/sway/movement.c b/sway/movement.c deleted file mode 100644 index 12726392..00000000 --- a/sway/movement.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <stdbool.h> | ||
3 | #include "list.h" | ||
4 | #include "log.h" | ||
5 | #include "layout.h" | ||
6 | #include "movement.h" | ||
7 | |||
8 | bool move_focus(enum movement_direction direction) { | ||
9 | swayc_t *current = get_focused_container(&root_container); | ||
10 | swayc_t *parent = current->parent; | ||
11 | |||
12 | if (direction == MOVE_PARENT) { | ||
13 | if (parent->type == C_OUTPUT) { | ||
14 | sway_log(L_DEBUG, "Focus cannot move to parent"); | ||
15 | return false; | ||
16 | } else { | ||
17 | sway_log(L_DEBUG, "Moving focus away from %p to %p", current, parent); | ||
18 | unfocus_all(parent->parent); | ||
19 | focus_view(parent); | ||
20 | return true; | ||
21 | } | ||
22 | } | ||
23 | |||
24 | while (true) { | ||
25 | sway_log(L_DEBUG, "Moving focus away from %p", current); | ||
26 | |||
27 | // Test if we can even make a difference here | ||
28 | bool can_move = false; | ||
29 | int diff = 0; | ||
30 | if (direction == MOVE_LEFT || direction == MOVE_RIGHT) { | ||
31 | if (parent->layout == L_HORIZ || parent->type == C_ROOT) { | ||
32 | can_move = true; | ||
33 | diff = direction == MOVE_LEFT ? -1 : 1; | ||
34 | } | ||
35 | } else { | ||
36 | if (parent->layout == L_VERT) { | ||
37 | can_move = true; | ||
38 | diff = direction == MOVE_UP ? -1 : 1; | ||
39 | } | ||
40 | } | ||
41 | sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no"); | ||
42 | if (can_move) { | ||
43 | int i; | ||
44 | for (i = 0; i < parent->children->length; ++i) { | ||
45 | swayc_t *child = parent->children->items[i]; | ||
46 | if (child == current) { | ||
47 | break; | ||
48 | } | ||
49 | } | ||
50 | int desired = i + diff; | ||
51 | sway_log(L_DEBUG, "Moving from %d to %d", i, desired); | ||
52 | if (desired < 0 || desired >= parent->children->length) { | ||
53 | can_move = false; | ||
54 | } else { | ||
55 | unfocus_all(&root_container); | ||
56 | focus_view(parent->children->items[desired]); | ||
57 | return true; | ||
58 | } | ||
59 | } | ||
60 | if (!can_move) { | ||
61 | sway_log(L_DEBUG, "Can't move at current level, moving up tree"); | ||
62 | current = parent; | ||
63 | parent = parent->parent; | ||
64 | if (!parent) { | ||
65 | // Nothing we can do | ||
66 | return false; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | } | ||
diff --git a/sway/workspace.c b/sway/workspace.c index df646445..bc0fa2c8 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "handlers.h" | 9 | #include "handlers.h" |
10 | #include "config.h" | 10 | #include "config.h" |
11 | #include "stringop.h" | 11 | #include "stringop.h" |
12 | #include "focus.h" | ||
12 | 13 | ||
13 | swayc_t *active_workspace = NULL; | 14 | swayc_t *active_workspace = NULL; |
14 | 15 | ||
@@ -173,64 +174,33 @@ void workspace_prev() { | |||
173 | } | 174 | } |
174 | 175 | ||
175 | void workspace_switch(swayc_t *workspace) { | 176 | void workspace_switch(swayc_t *workspace) { |
176 | swayc_t *ws_output = workspace->parent; | 177 | set_focused_container(workspace); |
177 | while (ws_output->type != C_OUTPUT) { | ||
178 | ws_output = ws_output->parent; | ||
179 | } | ||
180 | // The current workspace of the output our target workspace is in | ||
181 | swayc_t *focused_workspace = ws_output->focused; | ||
182 | if (workspace != focused_workspace && focused_workspace) { | ||
183 | sway_log(L_DEBUG, "workspace: changing from '%s' to '%s'", focused_workspace->name, workspace->name); | ||
184 | uint32_t mask = 1; | ||
185 | |||
186 | // set all c_views in the old workspace to the invisible mask if the workspace | ||
187 | // is in the same output & c_views in the new workspace to the visible mask | ||
188 | container_map(focused_workspace, set_view_visibility, &mask); | ||
189 | mask = 2; | ||
190 | container_map(workspace, set_view_visibility, &mask); | ||
191 | wlc_output_set_mask(ws_output->handle, 2); | ||
192 | |||
193 | destroy_workspace(focused_workspace); | ||
194 | } | ||
195 | unfocus_all(&root_container); | ||
196 | focus_view(workspace); | ||
197 | |||
198 | // focus the output this workspace is on | ||
199 | swayc_t *output = workspace->parent; | ||
200 | sway_log(L_DEBUG, "Switching focus to output %p (%d)", output, output->type); | ||
201 | while (output && output->type != C_OUTPUT) { | ||
202 | output = output->parent; | ||
203 | } | ||
204 | if (output) { | ||
205 | sway_log(L_DEBUG, "Switching focus to output %p (%d)", output, output->type); | ||
206 | wlc_output_focus(output->handle); | ||
207 | } | ||
208 | active_workspace = workspace; | 178 | active_workspace = workspace; |
209 | } | 179 | } |
210 | 180 | ||
211 | /* XXX:DEBUG:XXX */ | 181 | /* XXX:DEBUG:XXX */ |
212 | static void container_log(const swayc_t *c) { | 182 | static void container_log(const swayc_t *c) { |
213 | fprintf(stderr, "focus:%c|", | 183 | fprintf(stderr, "focus:%c|", |
214 | c == get_focused_container(&root_container) ? 'F' : //Focused | 184 | c->is_focused ? 'F' : //Focused |
215 | c == active_workspace ? 'W' : //active workspace | 185 | c == active_workspace ? 'W' : //active workspace |
216 | c == &root_container ? 'R' : //root | 186 | c == &root_container ? 'R' : //root |
217 | 'X');//not any others | 187 | 'X');//not any others |
218 | fprintf(stderr,"(%p)",c); | 188 | fprintf(stderr,"(%p)",c); |
219 | fprintf(stderr,"(p:%p)",c->parent); | 189 | fprintf(stderr,"(p:%p)",c->parent); |
220 | fprintf(stderr,"(f:%p)",c->focused); | 190 | fprintf(stderr,"(f:%p)",c->focused); |
191 | fprintf(stderr,"(h:%ld)",c->handle); | ||
221 | fprintf(stderr,"Type:"); | 192 | fprintf(stderr,"Type:"); |
222 | fprintf(stderr, | 193 | fprintf(stderr, |
223 | c->type == C_ROOT ? "Root|" : | 194 | c->type == C_ROOT ? "Root|" : |
224 | c->type == C_OUTPUT ? "Output|" : | 195 | c->type == C_OUTPUT ? "Output|" : |
225 | c->type == C_WORKSPACE ? "Workspace|" : | 196 | c->type == C_WORKSPACE ? "Workspace|" : |
226 | c->type == C_CONTAINER ? "Container|" : | 197 | c->type == C_CONTAINER ? "Container|" : |
227 | c->type == C_VIEW ? "View|" : | 198 | c->type == C_VIEW ? "View|" : "Unknown|"); |
228 | "Unknown|"); | ||
229 | fprintf(stderr,"layout:"); | 199 | fprintf(stderr,"layout:"); |
230 | fprintf(stderr, | 200 | fprintf(stderr, |
231 | c->layout == L_NONE ? "NONE|" : | 201 | c->layout == L_NONE ? "NONE|" : |
232 | c->layout == L_HORIZ ? "Horiz|": | 202 | c->layout == L_HORIZ ? "Horiz|": |
233 | c->layout == L_VERT ? "Vert|": | 203 | c->layout == L_VERT ? "Vert|": |
234 | c->layout == L_STACKED ? "Stacked|": | 204 | c->layout == L_STACKED ? "Stacked|": |
235 | c->layout == L_FLOATING ? "Floating|": | 205 | c->layout == L_FLOATING ? "Floating|": |
236 | "Unknown|"); | 206 | "Unknown|"); |