From 7bbb102e2d49e90f70fa8a954febb091a4d8bb81 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 10:45:40 -0700 Subject: [PATCH 01/42] reset floating view on floating_mod repress --- sway/handlers.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sway/handlers.c b/sway/handlers.c index 71691d7db..46d1fff55 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -91,6 +91,31 @@ swayc_t *container_under_pointer(void) { return lookup; } +static struct wlc_geometry saved_floating; + +static void start_floating(swayc_t *view) { + if (view->is_floating) { + saved_floating.origin.x = view->x; + saved_floating.origin.y = view->y; + saved_floating.size.w = view->width; + saved_floating.size.h = view->height; + } +} + +static void reset_floating(swayc_t *view) { + if (view->is_floating) { + view->x = saved_floating.origin.x; + view->y = saved_floating.origin.y; + view->width = saved_floating.size.w; + view->height = saved_floating.size.h; + arrange_windows(view->parent, -1, -1); + } + dragging = resizing = false; + lock_left = lock_right = lock_top = lock_bottom = false; +} + +/* Handles */ + static bool handle_output_created(wlc_handle output) { swayc_t *op = new_output(output); @@ -291,6 +316,10 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } bool cmd_success = false; + if ((modifiers->mods & config->floating_mod) && (dragging||resizing)) { + reset_floating(get_focused_view(&root_container)); + } + struct sway_mode *mode = config->current_mode; // Lowercase if necessary sym = tolower(sym); @@ -500,6 +529,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w lock_top = !lock_bottom; lock_right = origin->x < midway_x; lock_left = !lock_right; + start_floating(pointer); } //Dont want pointer sent to window while dragging or resizing return (dragging || resizing); From e53a95c60d281ab751e05f4af43eb117ab0880be Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 11:15:13 -0700 Subject: [PATCH 02/42] style --- sway/handlers.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 46d1fff55..f7d5386a5 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -258,7 +258,7 @@ static void handle_view_focus(wlc_handle view, bool focus) { static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry *geometry) { sway_log(L_DEBUG, "geometry request %d x %d : %d x %d", - geometry->origin.x, geometry->origin.y, geometry->size.w,geometry->size.h); + geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h); // If the view is floating, then apply the geometry. // Otherwise save the desired width/height for the view. // This will not do anything for the time being as WLC improperly sends geometry requests @@ -279,12 +279,12 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { swayc_t *c = NULL; - switch(state) { + switch (state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen wlc_view_set_state(view, state, toggle); c = get_swayc_for_handle(view, &root_container); - sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle); + sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle); if (c) { arrange_windows(c->parent, -1, -1); // Set it as focused window for that workspace if its going fullscreen @@ -316,7 +316,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } bool cmd_success = false; - if ((modifiers->mods & config->floating_mod) && (dragging||resizing)) { + if ((modifiers->mods & config->floating_mod) && (dragging || resizing)) { reset_floating(get_focused_view(&root_container)); } From c29214f348cef5951eeece3b60383993eaaca305 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Wed, 19 Aug 2015 14:14:54 -0500 Subject: [PATCH 03/42] Minor style fix --- sway/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/handlers.c b/sway/handlers.c index f7d5386a5..7b82fd032 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -423,7 +423,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; } - } else if (dx > 0){ + } else if (dx > 0) { if (mouse_origin.x > midway_x && !lock_right) { changed_floating = true; view->width += dx; From 48a983316c01d9ccd9fdd7aab56ee4e779654915 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 13:02:29 -0700 Subject: [PATCH 04/42] floating mode_toggle --- sway/commands.c | 11 +++++++++++ sway/handlers.c | 3 +++ 2 files changed, 14 insertions(+) diff --git a/sway/commands.c b/sway/commands.c index aafa51f33..f87ab0e5a 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -231,6 +231,17 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { return true; } set_focused_container(view); + } else if (strcasecmp(argv[0], "mode_toggle") == 0) { + if (get_focused_view(active_workspace)->is_floating) { + if (active_workspace->children->length > 0) { + set_focused_container(get_focused_view(active_workspace->children->items[0])); + } + } else { + if (active_workspace->floating->length > 0) { + swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length-1]; + set_focused_container(get_focused_view(floating)); + } + } } return true; diff --git a/sway/handlers.c b/sway/handlers.c index 7b82fd032..75adf7dd6 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -316,6 +316,9 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } bool cmd_success = false; + sway_log(L_DEBUG, "modifier %x: state %d: key %d, sym: %d", + modifiers->mods, state, key, sym); + if ((modifiers->mods & config->floating_mod) && (dragging || resizing)) { reset_floating(get_focused_view(&root_container)); } From 6cc29ebbf53503a2ea72545fcdd495f5c1a89dfc Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 13:10:58 -0700 Subject: [PATCH 05/42] man page update --- sway.5.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway.5.txt b/sway.5.txt index b03fb73ed..9c40558bc 100644 --- a/sway.5.txt +++ b/sway.5.txt @@ -41,6 +41,9 @@ Commands **floating** toggle:: Toggles the "floating" status of the focused view. +**floating** mode_toggle:: + Toggles focus between floating view and tiled view. + **focus** :: Direction may be one of _up_, _down_, _left_, _right_, or _parent_. The directional focus commands will move the focus in that direction. The parent From 269d6ba4ea9d317b4dfae640acce4d5ff142ef84 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 13:27:06 -0700 Subject: [PATCH 06/42] fixed --- sway/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/handlers.c b/sway/handlers.c index 75adf7dd6..344edd076 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -319,7 +319,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier sway_log(L_DEBUG, "modifier %x: state %d: key %d, sym: %d", modifiers->mods, state, key, sym); - if ((modifiers->mods & config->floating_mod) && (dragging || resizing)) { + if (state == WLC_KEY_STATE_PRESSED && (dragging || resizing)) { reset_floating(get_focused_view(&root_container)); } From a31f23f90c7259f48dcd02eaef08449a226460cd Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 15:22:55 -0700 Subject: [PATCH 07/42] fixed active_workspace update on focus change --- sway/focus.c | 2 ++ sway/handlers.c | 11 +++++++++-- sway/workspace.c | 1 - 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/sway/focus.c b/sway/focus.c index 7023d37dc..f76b2d9a6 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -20,6 +20,8 @@ static void update_focus(swayc_t *c) { // Case where output changes case C_OUTPUT: wlc_output_focus(c->handle); + //Set new workspace to the outputs focused workspace + active_workspace = c->focused; break; // Case where workspace changes diff --git a/sway/handlers.c b/sway/handlers.c index 344edd076..241890038 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -179,8 +179,14 @@ static bool handle_view_created(wlc_handle handle) { if (!focused || focused->type == C_OUTPUT) { focused = get_focused_container(&root_container); } - sway_log(L_DEBUG, "creating view %ld with type %x, state %x, with parent %ld", - handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent); + sway_log(L_DEBUG, "handle:%ld type:%x state:%x parent:%ld " + "mask:%d (x:%d y:%d w:%d h:%d) title:%s " + "class:%s appid:%s", + handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent, + wlc_view_get_mask(handle), wlc_view_get_geometry(handle)->origin.x, + wlc_view_get_geometry(handle)->origin.y,wlc_view_get_geometry(handle)->size.w, + wlc_view_get_geometry(handle)->size.h, wlc_view_get_title(handle), + wlc_view_get_class(handle), wlc_view_get_app_id(handle)); // TODO properly figure out how each window should be handled. switch (wlc_view_get_type(handle)) { @@ -319,6 +325,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier sway_log(L_DEBUG, "modifier %x: state %d: key %d, sym: %d", modifiers->mods, state, key, sym); + //Revert floating container back to original position on keypress if (state == WLC_KEY_STATE_PRESSED && (dragging || resizing)) { reset_floating(get_focused_view(&root_container)); } diff --git a/sway/workspace.c b/sway/workspace.c index a690e3ae0..ec60c8e01 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -183,7 +183,6 @@ void workspace_switch(swayc_t *workspace) { return; } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); - active_workspace = workspace; set_focused_container(get_focused_view(workspace)); arrange_windows(workspace, -1, -1); } From b79a49a394ede1c07773dadab97b00a4c7b4d835 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 15:44:13 -0700 Subject: [PATCH 08/42] use enums for pointer click names --- sway/handlers.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 241890038..a6dbf94cb 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -503,6 +503,14 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct return false; } +enum pointer_values { + M_LEFT_CLICK = 272, + M_RIGHT_CLICK = 273, + M_SCROLL_CLICK = 274, + M_SCROLL_UP = 275, + M_SCROLL_DOWN = 276, +}; + static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) { swayc_t *focused = get_focused_container(&root_container); @@ -512,10 +520,10 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w } if (state == WLC_BUTTON_STATE_PRESSED) { sway_log(L_DEBUG, "Mouse button %u pressed", button); - if (button == 272) { + if (button == M_LEFT_CLICK) { m1_held = true; } - if (button == 273) { + if (button == M_RIGHT_CLICK) { m2_held = true; } swayc_t *pointer = container_under_pointer(); @@ -547,11 +555,11 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w return (pointer && pointer != focused); } else { sway_log(L_DEBUG, "Mouse button %u released", button); - if (button == 272) { + if (button == M_LEFT_CLICK) { m1_held = false; dragging = false; } - if (button == 273) { + if (button == M_RIGHT_CLICK) { m2_held = false; resizing = false; lock_top = lock_bottom = lock_left = lock_right = false; From 6f424ff6b82d86a174319ffd534e517b2ae6d367 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 16:15:17 -0700 Subject: [PATCH 09/42] fixed default active_workspace, and more use of set_focused_container_for(...) --- sway/container.c | 1 + sway/layout.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sway/container.c b/sway/container.c index 0a89f6344..0a75643dd 100644 --- a/sway/container.c +++ b/sway/container.c @@ -150,6 +150,7 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { // give them proper layouts cont->layout = workspace->layout; workspace->layout = layout; + set_focused_container_for(workspace, get_focused_view(workspace)); } else { // Or is built around container swayc_t *parent = replace_child(child, cont); if (parent) { diff --git a/sway/layout.c b/sway/layout.c index 7125ffc32..eb8391cec 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -33,8 +33,9 @@ void add_child(swayc_t *parent, swayc_t *child) { child->width, child->height, parent, parent->type, parent->width, parent->height); list_add(parent->children, child); child->parent = parent; + //set focus for this container if (parent->children->length == 1) { - parent->focused = child; + set_focused_container_for(parent, child); } } @@ -45,7 +46,7 @@ void add_floating(swayc_t *ws, swayc_t *child) { child->parent = ws; child->is_floating = true; if (!ws->focused) { - ws->focused = child; + set_focused_container_for(ws, child); } } @@ -70,7 +71,7 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { new_child->parent = child->parent; if (child->parent->focused == child) { - child->parent->focused = new_child; + set_focused_container_for(child->parent, new_child); } child->parent = NULL; return parent; From 74c9df0c0798bb9fcc6f616e393a9edb01f3d0cb Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 19:29:35 -0400 Subject: [PATCH 10/42] Fix error with workspace/output name matching --- sway/container.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sway/container.c b/sway/container.c index 0a75643dd..9c6b78e95 100644 --- a/sway/container.c +++ b/sway/container.c @@ -54,7 +54,7 @@ static void free_swayc(swayc_t *c) { /* New containers */ static bool workspace_test(swayc_t *view, void *name) { - return strcasecmp(view->name, (char *)name); + return strcasecmp(view->name, (char *)name) == 0; } swayc_t *new_output(wlc_handle handle) { @@ -81,8 +81,10 @@ swayc_t *new_output(wlc_handle handle) { sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output); // Check if any other workspaces are using this name if (find_container(&root_container, workspace_test, wso->workspace)) { + sway_log(L_DEBUG, "But it's already taken"); break; } + sway_log(L_DEBUG, "So we're going to use it"); ws_name = strdup(wso->workspace); break; } From c068f47ce392dab0374b619d6a501ab6974749cc Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Thu, 20 Aug 2015 02:10:45 +0200 Subject: [PATCH 11/42] Fix potential crash when toggling fullscreen mode --- sway/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/handlers.c b/sway/handlers.c index a6dbf94cb..0bb181cc3 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -290,8 +290,8 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s // i3 just lets it become fullscreen wlc_view_set_state(view, state, toggle); c = get_swayc_for_handle(view, &root_container); - sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle); if (c) { + sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle); arrange_windows(c->parent, -1, -1); // Set it as focused window for that workspace if its going fullscreen if (toggle) { From 22675b01118766c980d9c9c66453fb5d5318cdef Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Thu, 20 Aug 2015 02:17:46 +0200 Subject: [PATCH 12/42] Minor style fix --- sway/log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/log.c b/sway/log.c index 9b9a9dc00..44f6e3660 100644 --- a/sway/log.c +++ b/sway/log.c @@ -19,10 +19,10 @@ static const char *verbosity_colors[] = { void init_log(int verbosity) { v = verbosity; /* set FD_CLOEXEC flag to prevent programs called with exec to write into logs */ - int i, flag; + int i; int fd[] = { STDOUT_FILENO, STDIN_FILENO, STDERR_FILENO }; for (i = 0; i < 3; ++i) { - flag = fcntl(fd[i], F_GETFD); + int flag = fcntl(fd[i], F_GETFD); if (flag != -1) { fcntl(fd[i], F_SETFD, flag | FD_CLOEXEC); } From f85d0740a83c32f9ef4d7f73b3dd25cff3a6239a Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Thu, 20 Aug 2015 02:24:47 +0200 Subject: [PATCH 13/42] Fix potential memory leak --- sway/readline.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sway/readline.c b/sway/readline.c index dfdc3fe87..e75b183fe 100644 --- a/sway/readline.c +++ b/sway/readline.c @@ -17,18 +17,22 @@ char *read_line(FILE *file) { continue; } if (length == size) { - string = realloc(string, size *= 2); - if (!string) { + char *new_string = realloc(string, size *= 2); + if (!new_string) { + free(string); return NULL; } + string = new_string; } string[length++] = c; } if (length + 1 == size) { - string = realloc(string, length + 1); - if (!string) { + char *new_string = realloc(string, length + 1); + if (!new_string) { + free(string); return NULL; } + string = new_string; } string[length] = '\0'; return string; From 2dabca03f404b4c5f0275b39dc6d103a26d43663 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 19:55:40 -0400 Subject: [PATCH 14/42] Remove logging of all key presess This makes the logs a bit too hard to read --- sway/handlers.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 0bb181cc3..6889fb22a 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -322,9 +322,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } bool cmd_success = false; - sway_log(L_DEBUG, "modifier %x: state %d: key %d, sym: %d", - modifiers->mods, state, key, sym); - //Revert floating container back to original position on keypress if (state == WLC_KEY_STATE_PRESSED && (dragging || resizing)) { reset_floating(get_focused_view(&root_container)); From 84a778b688320ca535cee29f1b6c580ed7f36715 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 20:12:05 -0400 Subject: [PATCH 15/42] Improve key buffer handling --- sway/handlers.c | 59 +++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 6889fb22a..c789662ee 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -14,9 +14,8 @@ #include "container.h" #include "focus.h" -uint32_t keys_pressed[32]; -int keys_pressed_length = 0; - +#define KEY_CACHE_SIZE 32 +uint32_t keys_pressed[KEY_CACHE_SIZE]; static struct wlc_origin mouse_origin; @@ -284,12 +283,11 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo } static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { - swayc_t *c = NULL; + swayc_t *c = get_swayc_for_handle(view, &root_container); switch (state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen wlc_view_set_state(view, state, toggle); - c = get_swayc_for_handle(view, &root_container); if (c) { sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle); arrange_windows(c->parent, -1, -1); @@ -307,7 +305,9 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s case WLC_BIT_MAXIMIZED: case WLC_BIT_RESIZING: case WLC_BIT_MOVING: + break; case WLC_BIT_ACTIVATED: + sway_log(L_DEBUG, "View %p requested to be activated", c); break; } return; @@ -316,13 +316,12 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) { - enum { QSIZE = 32 }; if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) { return false; } bool cmd_success = false; - //Revert floating container back to original position on keypress + // Revert floating container back to original position on keypress if (state == WLC_KEY_STATE_PRESSED && (dragging || resizing)) { reset_floating(get_focused_view(&root_container)); } @@ -331,20 +330,23 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier // Lowercase if necessary sym = tolower(sym); - // Find key, if it has been pressed - int mid = 0; - while (mid < keys_pressed_length && keys_pressed[mid] != sym) { - ++mid; - } - //Add or remove key depending on state - if (state == WLC_KEY_STATE_PRESSED && mid == keys_pressed_length && keys_pressed_length + 1 < QSIZE) { - keys_pressed[keys_pressed_length++] = sym; - } else if (state == WLC_KEY_STATE_RELEASED && mid < keys_pressed_length) { - memmove(keys_pressed + mid, keys_pressed + mid + 1, sizeof*keys_pressed * (--keys_pressed_length - mid)); - keys_pressed[keys_pressed_length] = 0; - } - // TODO: reminder to check conflicts with mod+q+a versus mod+q int i; + + for (i = 0; i < KEY_CACHE_SIZE; ++i) { + if (state == WLC_KEY_STATE_PRESSED && keys_pressed[i] == 0) { + keys_pressed[i] = sym; + break; + } else if (state == WLC_KEY_STATE_RELEASED && keys_pressed[i] == sym) { + keys_pressed[i] = 0; + break; + } + } + if (i == KEY_CACHE_SIZE) { + sway_log(L_DEBUG, "Key buffer full!"); + return false; + } + + // TODO: reminder to check conflicts with mod+q+a versus mod+q for (i = 0; i < mode->bindings->length; ++i) { struct sway_binding *binding = mode->bindings->items[i]; @@ -354,8 +356,8 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier for (j = 0; j < binding->keys->length; ++j) { match = false; xkb_keysym_t *key = binding->keys->items[j]; - uint8_t k; - for (k = 0; k < keys_pressed_length; ++k) { + int k; + for (k = 0; k < KEY_CACHE_SIZE; ++k) { if (keys_pressed[k] == *key) { match = true; break; @@ -368,15 +370,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier if (match) { // Remove matched keys from keys_pressed - int j; - for (j = 0; j < binding->keys->length; ++j) { - uint8_t k; - for (k = 0; k < keys_pressed_length; ++k) { - memmove(keys_pressed + k, keys_pressed + k + 1, sizeof*keys_pressed * (--keys_pressed_length - k)); - keys_pressed[keys_pressed_length] = 0; - break; - } - } if (state == WLC_KEY_STATE_PRESSED) { cmd_success = handle_command(config, binding->command); } else if (state == WLC_KEY_STATE_RELEASED) { @@ -574,6 +567,10 @@ static void handle_wlc_ready(void) { } free_flat_list(config->cmd_queue); config->active = true; + + for (i = 0; i < KEY_CACHE_SIZE; ++i) { + keys_pressed[i] = 0; + } } From 1d8591d9026c19f5c308bed5961341b00aef69ca Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 20:52:52 -0400 Subject: [PATCH 16/42] Improve key handling somewhat XKB is fucking bullshit --- sway/handlers.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index c789662ee..18f1d13c6 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -316,6 +316,14 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) { + + static const uint32_t modifier_syms[] = { + XKB_KEY_Shift_L, XKB_KEY_Shift_R, XKB_KEY_Control_L, XKB_KEY_Control_R, + XKB_KEY_Caps_Lock, XKB_KEY_Shift_Lock, XKB_KEY_Meta_L, XKB_KEY_Meta_R, + XKB_KEY_Alt_L, XKB_KEY_Alt_R, XKB_KEY_Super_L, XKB_KEY_Super_R, + XKB_KEY_Hyper_L, XKB_KEY_Hyper_R + }; + if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) { return false; } @@ -327,12 +335,28 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } struct sway_mode *mode = config->current_mode; + + if (!isalnum(sym)) { + // God fucking dammit + return false; + } + // Lowercase if necessary sym = tolower(sym); int i; + bool mod = false; - for (i = 0; i < KEY_CACHE_SIZE; ++i) { + for (i = 0; i < sizeof(modifier_syms) / sizeof(uint32_t); ++i) { + if (modifier_syms[i] == sym) { + mod = true; + break; + } + } + + int total = 0; + for (i = 0; i < KEY_CACHE_SIZE && !mod; ++i) { + total += keys_pressed[i] != 0; if (state == WLC_KEY_STATE_PRESSED && keys_pressed[i] == 0) { keys_pressed[i] = sym; break; @@ -341,10 +365,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier break; } } - if (i == KEY_CACHE_SIZE) { - sway_log(L_DEBUG, "Key buffer full!"); - return false; - } // TODO: reminder to check conflicts with mod+q+a versus mod+q for (i = 0; i < mode->bindings->length; ++i) { From 29b6b2f37b3a3ec05c48c00103360b2297912e69 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Wed, 19 Aug 2015 19:57:24 -0500 Subject: [PATCH 17/42] Fixed mode_toggle --- sway/commands.c | 51 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index f87ab0e5a..f3553b038 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -231,19 +231,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { return true; } set_focused_container(view); - } else if (strcasecmp(argv[0], "mode_toggle") == 0) { - if (get_focused_view(active_workspace)->is_floating) { - if (active_workspace->children->length > 0) { - set_focused_container(get_focused_view(active_workspace->children->items[0])); - } - } else { - if (active_workspace->floating->length > 0) { - swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length-1]; - set_focused_container(get_focused_view(floating)); - } - } } - return true; } @@ -272,6 +260,8 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) } static bool cmd_focus(struct sway_config *config, int argc, char **argv) { + static int floating_toggled_index = 0; + static int tiled_toggled_index = 0; if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { return false; } @@ -285,7 +275,44 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) { return move_focus(MOVE_DOWN); } else if (strcasecmp(argv[0], "parent") == 0) { return move_focus(MOVE_PARENT); + } else if (strcasecmp(argv[0], "mode_toggle") == 0) { + int i; + swayc_t *focused = get_focused_view(active_workspace); + if (focused->is_floating) { + if (active_workspace->children->length > 0) { + for (i = 0;i < active_workspace->floating->length; i++) { + if (active_workspace->floating->items[i] == focused) { + floating_toggled_index = i; + break; + } + } + if (active_workspace->children->length > tiled_toggled_index) { + set_focused_container(get_focused_view(active_workspace->children->items[tiled_toggled_index])); + } else { + set_focused_container(get_focused_view(active_workspace->children->items[0])); + tiled_toggled_index = 0; + } + } + } else { + if (active_workspace->floating->length > 0) { + for (i = 0;i < active_workspace->children->length; i++) { + if (active_workspace->children->items[i] == focused) { + tiled_toggled_index = i; + break; + } + } + if (active_workspace->floating->length > floating_toggled_index) { + swayc_t *floating = active_workspace->floating->items[floating_toggled_index]; + set_focused_container(get_focused_view(floating)); + } else { + swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length - 1]; + set_focused_container(get_focused_view(floating)); + tiled_toggled_index = active_workspace->floating->length - 1; + } + } + } } + return true; } From e5d3074d702906f2da8f94d017fd687bebbc3d8e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 21:04:06 -0400 Subject: [PATCH 18/42] Whitelist a handful of characters for keys Ones that don't change when you hold shift --- sway/handlers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 18f1d13c6..d45340ad3 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -336,7 +336,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier struct sway_mode *mode = config->current_mode; - if (!isalnum(sym)) { + if (!isalnum(sym) && sym != ' ' && sym != XKB_KEY_Escape && sym != XKB_KEY_Tab) { // God fucking dammit return false; } @@ -391,7 +391,8 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier if (match) { // Remove matched keys from keys_pressed if (state == WLC_KEY_STATE_PRESSED) { - cmd_success = handle_command(config, binding->command); + handle_command(config, binding->command); + cmd_success = true; } else if (state == WLC_KEY_STATE_RELEASED) { // TODO: --released } From 4db89b5fe46e8e7dc741b0ccb9fa3d0708c6fa59 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 21:14:34 -0400 Subject: [PATCH 19/42] Deal with more xkb bullshit --- sway/handlers.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index d45340ad3..63db972e4 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -336,9 +336,11 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier struct sway_mode *mode = config->current_mode; - if (!isalnum(sym) && sym != ' ' && sym != XKB_KEY_Escape && sym != XKB_KEY_Tab) { - // God fucking dammit - return false; + if (sym < 70000 /* bullshit made up number */) { + if (!isalnum(sym) && sym != ' ' && sym != XKB_KEY_Escape && sym != XKB_KEY_Tab) { + // God fucking dammit + return false; + } } // Lowercase if necessary From 470b4dfbae146d83c0061b39534c16b5aad90f1c Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 18:59:27 -0700 Subject: [PATCH 20/42] key_state.ch, and command conflicts resolved --- include/key_state.h | 18 ++++++++++++++++ sway/commands.c | 17 ++++++++++++++- sway/handlers.c | 39 +++++++--------------------------- sway/key_state.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 32 deletions(-) create mode 100644 include/key_state.h create mode 100644 sway/key_state.c diff --git a/include/key_state.h b/include/key_state.h new file mode 100644 index 000000000..a8fa8d5e0 --- /dev/null +++ b/include/key_state.h @@ -0,0 +1,18 @@ +#ifndef _SWAY_KEY_STATE_H +#define _SWAY_KEY_STATE_H +#include +#include + +typedef uint32_t keycode; + +// returns true if key has been pressed, otherwise false +bool check_key(keycode key); + +// sets a key as pressed +void press_key(keycode key); + +// unsets a key as pressed +void release_key(keycode key); + +#endif + diff --git a/sway/commands.c b/sway/commands.c index f3553b038..66c05a0c6 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -76,6 +76,18 @@ static bool checkarg(int argc, char *name, enum expected_args type, int val) { return false; } +static int bindsym_sort(const void *_lbind, const void *_rbind) { + const struct sway_binding *lbind = *(void **)_lbind; + const struct sway_binding *rbind = *(void **)_rbind; + unsigned int lmod = 0, rmod = 0, i; + + //Count how any modifiers are pressed + for (i = 0; i < 8 * sizeof(lbind->modifiers); ++i) { + lmod += lbind->modifiers & 1 << i; + rmod += rbind->modifiers & 1 << i; + } + return (rbind->keys->length + rmod) - (lbind->keys->length + lmod); +} static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) { @@ -118,7 +130,10 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { list_free(split); // TODO: Check if there are other commands with this key binding - list_add(config->current_mode->bindings, binding); + struct sway_mode *mode = config->current_mode; + list_add(mode->bindings, binding); + qsort(mode->bindings->items, mode->bindings->length, + sizeof(mode->bindings->items[0]), bindsym_sort); sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command); return true; diff --git a/sway/handlers.c b/sway/handlers.c index 63db972e4..c9d7c7ac0 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -13,9 +13,7 @@ #include "workspace.h" #include "container.h" #include "focus.h" - -#define KEY_CACHE_SIZE 32 -uint32_t keys_pressed[KEY_CACHE_SIZE]; +#include "key_state.h" static struct wlc_origin mouse_origin; @@ -327,7 +325,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) { return false; } - bool cmd_success = false; // Revert floating container back to original position on keypress if (state == WLC_KEY_STATE_PRESSED && (dragging || resizing)) { @@ -356,16 +353,10 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } } - int total = 0; - for (i = 0; i < KEY_CACHE_SIZE && !mod; ++i) { - total += keys_pressed[i] != 0; - if (state == WLC_KEY_STATE_PRESSED && keys_pressed[i] == 0) { - keys_pressed[i] = sym; - break; - } else if (state == WLC_KEY_STATE_RELEASED && keys_pressed[i] == sym) { - keys_pressed[i] = 0; - break; - } + if (state == WLC_KEY_STATE_PRESSED) { + press_key(sym); + } else { // WLC_KEY_STATE_RELEASED + release_key(sym); } // TODO: reminder to check conflicts with mod+q+a versus mod+q @@ -376,32 +367,22 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier bool match; int j; for (j = 0; j < binding->keys->length; ++j) { - match = false; xkb_keysym_t *key = binding->keys->items[j]; - int k; - for (k = 0; k < KEY_CACHE_SIZE; ++k) { - if (keys_pressed[k] == *key) { - match = true; - break; - } - } - if (match == false) { + if ((match = check_key(*key)) == false) { break; } } - if (match) { - // Remove matched keys from keys_pressed if (state == WLC_KEY_STATE_PRESSED) { handle_command(config, binding->command); - cmd_success = true; + return true; } else if (state == WLC_KEY_STATE_RELEASED) { // TODO: --released } } } } - return cmd_success; + return false; } static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { @@ -590,10 +571,6 @@ static void handle_wlc_ready(void) { } free_flat_list(config->cmd_queue); config->active = true; - - for (i = 0; i < KEY_CACHE_SIZE; ++i) { - keys_pressed[i] = 0; - } } diff --git a/sway/key_state.c b/sway/key_state.c new file mode 100644 index 000000000..76561dbc0 --- /dev/null +++ b/sway/key_state.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "key_state.h" + +enum { KEY_STATE_MAX_LENGTH = 64 }; + +static keycode key_state_array[KEY_STATE_MAX_LENGTH]; +static uint8_t key_state_length = 0; + +static uint8_t find_key(keycode key) +{ + int i; + for (i = 0; i < key_state_length; ++i) + { + if (key_state_array[i] == key) + { + break; + } + } + return i; +} + +bool check_key(keycode key) +{ + return find_key(key) < key_state_length; +} + +void press_key(keycode key) +{ + // Check if key exists + if (!check_key(key)) + { + // Check that we dont exceed buffer length + if (key_state_length < KEY_STATE_MAX_LENGTH) { + key_state_array[key_state_length++] = key; + } + } +} + +void release_key(keycode key) +{ + uint8_t index = find_key(key); + if (index < key_state_length) + { + //shift it over and remove key + memmove(&key_state_array[index], + &key_state_array[index + 1], + sizeof(*key_state_array) * (--key_state_length - index)); + } +} From 5ff0619ca1cab044004df044c253c9170b8316c3 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 20:22:15 -0700 Subject: [PATCH 21/42] input state, find_container_in_direction --- include/focus.h | 4 +- include/input_state.h | 49 +++++++++++++++++++++++ include/key_state.h | 18 --------- include/layout.h | 2 + sway/commands.c | 1 - sway/focus.c | 74 ++++------------------------------ sway/handlers.c | 93 ++++++++++++++----------------------------- sway/input_state.c | 70 ++++++++++++++++++++++++++++++++ sway/key_state.c | 52 ------------------------ sway/layout.c | 51 ++++++++++++++++++++++++ 10 files changed, 211 insertions(+), 203 deletions(-) create mode 100644 include/input_state.h delete mode 100644 include/key_state.h create mode 100644 sway/input_state.c delete mode 100644 sway/key_state.c diff --git a/include/focus.h b/include/focus.h index 410ed1345..383993faf 100644 --- a/include/focus.h +++ b/include/focus.h @@ -1,7 +1,5 @@ #ifndef _SWAY_FOCUS_H #define _SWAY_FOCUS_H -#include "container.h" - enum movement_direction { MOVE_LEFT, MOVE_RIGHT, @@ -10,6 +8,8 @@ enum movement_direction { MOVE_PARENT }; +#include "container.h" + // focused_container - the container found by following the `focused` pointer // from a given container to a container with `is_focused` boolean set // --- diff --git a/include/input_state.h b/include/input_state.h new file mode 100644 index 000000000..782b4b19c --- /dev/null +++ b/include/input_state.h @@ -0,0 +1,49 @@ +#ifndef _SWAY_KEY_STATE_H +#define _SWAY_KEY_STATE_H +#include +#include +#include "container.h" + +/* Keyboard state */ + +typedef uint32_t keycode; + +// returns true if key has been pressed, otherwise false +bool check_key(keycode key); + +// sets a key as pressed +void press_key(keycode key); + +// unsets a key as pressed +void release_key(keycode key); + +/* Pointer state */ + +enum pointer_values { + M_LEFT_CLICK = 272, + M_RIGHT_CLICK = 273, + M_SCROLL_CLICK = 274, + M_SCROLL_UP = 275, + M_SCROLL_DOWN = 276, +}; + +extern struct pointer_state { + bool l_held; + bool r_held; + struct pointer_floating { + bool drag; + bool resize; + } floating; + struct pointer_lock { + bool left; + bool right; + bool top; + bool bottom; + } lock; +} pointer_state; + +void start_floating(swayc_t *view); +void reset_floating(swayc_t *view); + +#endif + diff --git a/include/key_state.h b/include/key_state.h deleted file mode 100644 index a8fa8d5e0..000000000 --- a/include/key_state.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _SWAY_KEY_STATE_H -#define _SWAY_KEY_STATE_H -#include -#include - -typedef uint32_t keycode; - -// returns true if key has been pressed, otherwise false -bool check_key(keycode key); - -// sets a key as pressed -void press_key(keycode key); - -// unsets a key as pressed -void release_key(keycode key); - -#endif - diff --git a/include/layout.h b/include/layout.h index 98fdb531f..75e72d2fe 100644 --- a/include/layout.h +++ b/include/layout.h @@ -4,6 +4,7 @@ #include #include "list.h" #include "container.h" +#include "focus.h" extern swayc_t root_container; @@ -26,5 +27,6 @@ void focus_view_for(swayc_t *ancestor, swayc_t *container); swayc_t *get_focused_container(swayc_t *parent); swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent); +swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir); #endif diff --git a/sway/commands.c b/sway/commands.c index 66c05a0c6..c4cf96a20 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -243,7 +243,6 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { } // Refocus on the view once its been put back into the layout arrange_windows(active_workspace, -1, -1); - return true; } set_focused_container(view); } diff --git a/sway/focus.c b/sway/focus.c index f76b2d9a6..1dbac0030 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -3,6 +3,7 @@ #include "focus.h" #include "log.h" #include "workspace.h" +#include "layout.h" bool locked_container_focus = false; bool locked_view_focus = false; @@ -53,74 +54,13 @@ static void update_focus(swayc_t *c) { } bool move_focus(enum movement_direction direction) { - if (locked_container_focus) { - return false; - } - swayc_t *current = get_focused_container(&root_container); - if (current->type == C_VIEW - && wlc_view_get_state(current->handle) & WLC_BIT_FULLSCREEN) { - return false; - } - swayc_t *parent = current->parent; - - if (direction == MOVE_PARENT) { - if (parent->type == C_OUTPUT) { - sway_log(L_DEBUG, "Focus cannot move to parent"); - return false; - } else { - sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld", - current, current->handle, parent, parent->handle); - set_focused_container(parent); - return true; - } - } - - while (true) { - sway_log(L_DEBUG, "Moving focus away from %p", current); - - // Test if we can even make a difference here - bool can_move = false; - int diff = 0; - if (direction == MOVE_LEFT || direction == MOVE_RIGHT) { - if (parent->layout == L_HORIZ || parent->type == C_ROOT) { - can_move = true; - diff = direction == MOVE_LEFT ? -1 : 1; - } - } else { - if (parent->layout == L_VERT) { - can_move = true; - diff = direction == MOVE_UP ? -1 : 1; - } - } - sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no"); - if (can_move) { - int i; - for (i = 0; i < parent->children->length; ++i) { - swayc_t *child = parent->children->items[i]; - if (child == current) { - break; - } - } - int desired = i + diff; - sway_log(L_DEBUG, "Moving from %d to %d", i, desired); - if (desired < 0 || desired >= parent->children->length) { - can_move = false; - } else { - swayc_t *newview = parent->children->items[desired]; - set_focused_container(get_focused_view(newview)); - return true; - } - } - if (!can_move) { - sway_log(L_DEBUG, "Can't move at current level, moving up tree"); - current = parent; - parent = parent->parent; - if (!parent) { - // Nothing we can do - return false; - } - } + swayc_t *view = get_swayc_in_direction( + get_focused_container(&root_container), direction); + if (view) { + set_focused_container(view); + return true; } + return false; } swayc_t *get_focused_container(swayc_t *parent) { diff --git a/sway/handlers.c b/sway/handlers.c index c9d7c7ac0..03a328354 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -13,16 +13,10 @@ #include "workspace.h" #include "container.h" #include "focus.h" -#include "key_state.h" +#include "input_state.h" static struct wlc_origin mouse_origin; -static bool m1_held = false; -static bool dragging = false; -static bool m2_held = false; -static bool resizing = false; -static bool lock_left, lock_right, lock_top, lock_bottom = false; - static bool pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; // Determine the output that the view is under @@ -88,29 +82,6 @@ swayc_t *container_under_pointer(void) { return lookup; } -static struct wlc_geometry saved_floating; - -static void start_floating(swayc_t *view) { - if (view->is_floating) { - saved_floating.origin.x = view->x; - saved_floating.origin.y = view->y; - saved_floating.size.w = view->width; - saved_floating.size.h = view->height; - } -} - -static void reset_floating(swayc_t *view) { - if (view->is_floating) { - view->x = saved_floating.origin.x; - view->y = saved_floating.origin.y; - view->width = saved_floating.size.w; - view->height = saved_floating.size.h; - arrange_windows(view->parent, -1, -1); - } - dragging = resizing = false; - lock_left = lock_right = lock_top = lock_bottom = false; -} - /* Handles */ static bool handle_output_created(wlc_handle output) { @@ -327,7 +298,8 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } // Revert floating container back to original position on keypress - if (state == WLC_KEY_STATE_PRESSED && (dragging || resizing)) { + if (state == WLC_KEY_STATE_PRESSED && + (pointer_state.floating.drag || pointer_state.floating.resize)) { reset_floating(get_focused_view(&root_container)); } @@ -396,7 +368,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct // Do checks to determine if proper keys are being held swayc_t *view = get_focused_view(active_workspace); uint32_t edge = 0; - if (dragging && view) { + if (pointer_state.floating.drag && view) { if (view->is_floating) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; @@ -404,7 +376,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct view->y += dy; changed_floating = true; } - } else if (resizing && view) { + } else if (pointer_state.floating.resize && view) { if (view->is_floating) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; @@ -415,24 +387,24 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct int midway_x = view->x + view->width/2; int midway_y = view->y + view->height/2; if (dx < 0) { - if (!lock_right) { + if (!pointer_state.lock.right) { if (view->width > min_sane_w) { changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } - } else if (mouse_origin.x < midway_x && !lock_left) { + } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) { changed_floating = true; view->x += dx; view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; } } else if (dx > 0) { - if (mouse_origin.x > midway_x && !lock_right) { + if (mouse_origin.x > midway_x && !pointer_state.lock.right) { changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; - } else if (!lock_left) { + } else if (!pointer_state.lock.left) { if (view->width > min_sane_w) { changed_floating = true; view->x += dx; @@ -443,24 +415,24 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } if (dy < 0) { - if (!lock_bottom) { + if (!pointer_state.lock.bottom) { if (view->height > min_sane_h) { changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } - } else if (mouse_origin.y < midway_y && !lock_top) { + } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) { changed_floating = true; view->y += dy; view->height -= dy; edge += WLC_RESIZE_EDGE_TOP; } } else if (dy > 0) { - if (mouse_origin.y > midway_y && !lock_bottom) { + if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) { changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; - } else if (!lock_top) { + } else if (!pointer_state.lock.top) { if (view->height > min_sane_h) { changed_floating = true; view->y += dy; @@ -474,7 +446,8 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct if (config->focus_follows_mouse && prev_handle != handle) { //Dont change focus if fullscreen swayc_t *focused = get_focused_view(view); - if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) && !(m1_held || m2_held)) { + if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) + && !(pointer_state.l_held || pointer_state.r_held)) { set_focused_container(container_under_pointer()); } } @@ -497,13 +470,6 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct return false; } -enum pointer_values { - M_LEFT_CLICK = 272, - M_RIGHT_CLICK = 273, - M_SCROLL_CLICK = 274, - M_SCROLL_UP = 275, - M_SCROLL_DOWN = 276, -}; static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) { @@ -515,10 +481,10 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w if (state == WLC_BUTTON_STATE_PRESSED) { sway_log(L_DEBUG, "Mouse button %u pressed", button); if (button == M_LEFT_CLICK) { - m1_held = true; + pointer_state.l_held = true; } if (button == M_RIGHT_CLICK) { - m2_held = true; + pointer_state.r_held = true; } swayc_t *pointer = container_under_pointer(); set_focused_container(pointer); @@ -533,30 +499,31 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w } arrange_windows(pointer->parent, -1, -1); if (modifiers->mods & config->floating_mod) { - dragging = m1_held; - resizing = m2_held; int midway_x = pointer->x + pointer->width/2; int midway_y = pointer->y + pointer->height/2; - lock_bottom = origin->y < midway_y; - lock_top = !lock_bottom; - lock_right = origin->x < midway_x; - lock_left = !lock_right; + + pointer_state.floating.drag = pointer_state.l_held; + pointer_state.floating.resize = pointer_state.r_held; + pointer_state.lock.bottom = origin->y < midway_y; + pointer_state.lock.top = !pointer_state.lock.bottom; + pointer_state.lock.right = origin->x < midway_x; + pointer_state.lock.left = !pointer_state.lock.right; start_floating(pointer); } //Dont want pointer sent to window while dragging or resizing - return (dragging || resizing); + return (pointer_state.floating.drag || pointer_state.floating.resize); } return (pointer && pointer != focused); } else { sway_log(L_DEBUG, "Mouse button %u released", button); if (button == M_LEFT_CLICK) { - m1_held = false; - dragging = false; + pointer_state.l_held = false; + pointer_state.floating.drag = false; } if (button == M_RIGHT_CLICK) { - m2_held = false; - resizing = false; - lock_top = lock_bottom = lock_left = lock_right = false; + pointer_state.r_held = false; + pointer_state.floating.resize = false; + pointer_state.lock = (struct pointer_lock){false ,false ,false ,false}; } } return false; diff --git a/sway/input_state.c b/sway/input_state.c new file mode 100644 index 000000000..0769c30f7 --- /dev/null +++ b/sway/input_state.c @@ -0,0 +1,70 @@ +#include +#include +#include + +#include "input_state.h" + +enum { KEY_STATE_MAX_LENGTH = 64 }; + +static keycode key_state_array[KEY_STATE_MAX_LENGTH]; +static uint8_t key_state_length = 0; + +static uint8_t find_key(keycode key) { + int i; + for (i = 0; i < key_state_length; ++i) { + if (key_state_array[i] == key) { + break; + } + } + return i; +} + +bool check_key(keycode key) { + return find_key(key) < key_state_length; +} + +void press_key(keycode key) { + // Check if key exists + if (!check_key(key)) { + // Check that we dont exceed buffer length + if (key_state_length < KEY_STATE_MAX_LENGTH) { + key_state_array[key_state_length++] = key; + } + } +} + +void release_key(keycode key) { + uint8_t index = find_key(key); + if (index < key_state_length) { + //shift it over and remove key + memmove(&key_state_array[index], + &key_state_array[index + 1], + sizeof(*key_state_array) * (--key_state_length - index)); + } +} + +struct pointer_state pointer_state = {0, 0, {0, 0}, {0, 0, 0, 0}}; + +static struct wlc_geometry saved_floating; + +void start_floating(swayc_t *view) { + if (view->is_floating) { + saved_floating.origin.x = view->x; + saved_floating.origin.y = view->y; + saved_floating.size.w = view->width; + saved_floating.size.h = view->height; + } +} + +void reset_floating(swayc_t *view) { + if (view->is_floating) { + view->x = saved_floating.origin.x; + view->y = saved_floating.origin.y; + view->width = saved_floating.size.w; + view->height = saved_floating.size.h; + arrange_windows(view->parent, -1, -1); + } + pointer_state.floating = (struct pointer_floating){0,0}; + pointer_state.lock = (struct pointer_lock){0,0,0,0}; +} + diff --git a/sway/key_state.c b/sway/key_state.c deleted file mode 100644 index 76561dbc0..000000000 --- a/sway/key_state.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include - -#include "key_state.h" - -enum { KEY_STATE_MAX_LENGTH = 64 }; - -static keycode key_state_array[KEY_STATE_MAX_LENGTH]; -static uint8_t key_state_length = 0; - -static uint8_t find_key(keycode key) -{ - int i; - for (i = 0; i < key_state_length; ++i) - { - if (key_state_array[i] == key) - { - break; - } - } - return i; -} - -bool check_key(keycode key) -{ - return find_key(key) < key_state_length; -} - -void press_key(keycode key) -{ - // Check if key exists - if (!check_key(key)) - { - // Check that we dont exceed buffer length - if (key_state_length < KEY_STATE_MAX_LENGTH) { - key_state_array[key_state_length++] = key; - } - } -} - -void release_key(keycode key) -{ - uint8_t index = find_key(key); - if (index < key_state_length) - { - //shift it over and remove key - memmove(&key_state_array[index], - &key_state_array[index + 1], - sizeof(*key_state_array) * (--key_state_length - index)); - } -} diff --git a/sway/layout.c b/sway/layout.c index eb8391cec..2a43671b9 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -298,3 +298,54 @@ swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { return NULL; } +swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) { + swayc_t *parent = container->parent; + + if (dir == MOVE_PARENT) { + if (parent->type == C_OUTPUT) { + return NULL; + } else { + return parent; + } + } + while (true) { + // Test if we can even make a difference here + bool can_move = false; + int diff = 0; + if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { + if (parent->layout == L_HORIZ || parent->type == C_ROOT) { + can_move = true; + diff = dir == MOVE_LEFT ? -1 : 1; + } + } else { + if (parent->layout == L_VERT) { + can_move = true; + diff = dir == MOVE_UP ? -1 : 1; + } + } + if (can_move) { + int i; + for (i = 0; i < parent->children->length; ++i) { + swayc_t *child = parent->children->items[i]; + if (child == container) { + break; + } + } + int desired = i + diff; + if (desired < 0 || desired >= parent->children->length) { + can_move = false; + } else { + return parent->children->items[desired]; + } + } + if (!can_move) { + sway_log(L_DEBUG, "Can't move at current level, moving up tree"); + container = parent; + parent = parent->parent; + if (!parent) { + // Nothing we can do + return NULL; + } + } + } +} From 66e82a68fc9d3264413a9d7b54813143ada61d20 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 20:28:05 -0700 Subject: [PATCH 22/42] small fix --- sway/focus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/focus.c b/sway/focus.c index 1dbac0030..48017fdf7 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -57,7 +57,7 @@ bool move_focus(enum movement_direction direction) { swayc_t *view = get_swayc_in_direction( get_focused_container(&root_container), direction); if (view) { - set_focused_container(view); + set_focused_container(get_focused_view(view)); return true; } return false; From 686780f12d40c788a29bfe552c892a802e805dca Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 20:29:24 -0700 Subject: [PATCH 23/42] another small fix to move_focus --- sway/focus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sway/focus.c b/sway/focus.c index 48017fdf7..a6ffe73f5 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -57,7 +57,11 @@ bool move_focus(enum movement_direction direction) { swayc_t *view = get_swayc_in_direction( get_focused_container(&root_container), direction); if (view) { - set_focused_container(get_focused_view(view)); + if (direction == MOVE_PARENT) { + set_focused_container(view); + } else { + set_focused_container(get_focused_view(view)); + } return true; } return false; From 1d9b73ed67d9c961cf14d3d2649c84ac0ead13df Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 20:31:28 -0700 Subject: [PATCH 24/42] remove debug message --- sway/layout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/layout.c b/sway/layout.c index 2a43671b9..f600cf495 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -339,7 +339,6 @@ swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) } } if (!can_move) { - sway_log(L_DEBUG, "Can't move at current level, moving up tree"); container = parent; parent = parent->parent; if (!parent) { From 3c124d9e7d56559ff6c82ac313cb7ee065bc839f Mon Sep 17 00:00:00 2001 From: KoffeinFlummi Date: Thu, 20 Aug 2015 08:46:06 +0200 Subject: [PATCH 25/42] Change gap behaviour to more closely match i3-gaps Previously, when only using inner gaps, the gap between a window at the edge of the output was only half the size of the gaps between views. Additionally, the gaps between the actual windows was twice as wide as it was on i3-gaps. --- sway/container.c | 2 +- sway/layout.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sway/container.c b/sway/container.c index 9c6b78e95..dee4028db 100644 --- a/sway/container.c +++ b/sway/container.c @@ -67,7 +67,7 @@ swayc_t *new_output(wlc_handle handle) { output->height = size->h; output->handle = handle; output->name = name ? strdup(name) : NULL; - output->gaps = config->gaps_outer; + output->gaps = config->gaps_outer + config->gaps_inner / 2; add_child(&root_container, output); diff --git a/sway/layout.c b/sway/layout.c index eb8391cec..e628c5edd 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -152,12 +152,12 @@ void arrange_windows(swayc_t *container, int width, int height) { { struct wlc_geometry geometry = { .origin = { - .x = container->x + container->gaps, - .y = container->y + container->gaps + .x = container->x + container->gaps / 2, + .y = container->y + container->gaps / 2 }, .size = { - .w = width - container->gaps * 2, - .h = height - container->gaps * 2 + .w = width - container->gaps, + .h = height - container->gaps } }; if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { From ba6034e8c8cd2bbe15f318e511817e0904633bb3 Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 04:24:39 -0700 Subject: [PATCH 26/42] changes --- sway.5.txt | 20 ++++++++++---------- sway/input_state.c | 18 ++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/sway.5.txt b/sway.5.txt index 9c40558bc..5bccbd12d 100644 --- a/sway.5.txt +++ b/sway.5.txt @@ -22,11 +22,11 @@ Commands -------- **bindsym** :: - Binds _key combo_ to execute _command_ when pressed. You may use XKB key names - here (**xev**(1) is a good tool for discovering them). An example bindsym - command would be _bindsym Mod1+Shift+f exec firefox_, which would execute - Firefox if the alt, shift, and F keys are pressed together. Any valid sway - command is eligible to be bound to a key combo. + Binds _key combo_ to execute _command_ when pressed. You may use XKB key + names here (**xev**(1) is a good tool for discovering them). An example + bindsym command would be _bindsym Mod1+Shift+f exec firefox_, which would + execute Firefox if the alt, shift, and F keys are pressed together. Any + valid sway command is eligible to be bound to a key combo. **exec** :: Executes _shell command_ with sh. @@ -41,9 +41,6 @@ Commands **floating** toggle:: Toggles the "floating" status of the focused view. -**floating** mode_toggle:: - Toggles focus between floating view and tiled view. - **focus** :: Direction may be one of _up_, _down_, _left_, _right_, or _parent_. The directional focus commands will move the focus in that direction. The parent @@ -51,6 +48,9 @@ Commands container, which is useful, for example, to open a sibling of the parent container, or to move the entire container around. +**focus** mode_toggle:: + Toggles focus between floating view and tiled view. + **focus_follows_mouse** :: If set to _yes_, the currently focused view will change as you move your mouse around the screen to the view that ends up underneath your mouse. @@ -86,10 +86,10 @@ Commands **fullscreen**:: Toggles fullscreen status for the focused view. -**gaps** **:: +**gaps** :: Adds _amount_ pixels between each view, and around each output. -**gaps** **:: +**gaps** :: Adds _amount_ pixels as an _inner_ or _outer_ gap, where the former affects spacing between views and the latter affects the space around each output. diff --git a/sway/input_state.c b/sway/input_state.c index 0769c30f7..51213b19e 100644 --- a/sway/input_state.c +++ b/sway/input_state.c @@ -4,14 +4,13 @@ #include "input_state.h" -enum { KEY_STATE_MAX_LENGTH = 64 }; +#define KEY_STATE_MAX_LENGTH 64 static keycode key_state_array[KEY_STATE_MAX_LENGTH]; -static uint8_t key_state_length = 0; static uint8_t find_key(keycode key) { int i; - for (i = 0; i < key_state_length; ++i) { + for (i = 0; i < KEY_STATE_MAX_LENGTH; ++i) { if (key_state_array[i] == key) { break; } @@ -20,26 +19,25 @@ static uint8_t find_key(keycode key) { } bool check_key(keycode key) { - return find_key(key) < key_state_length; + return find_key(key) < KEY_STATE_MAX_LENGTH; } void press_key(keycode key) { // Check if key exists if (!check_key(key)) { // Check that we dont exceed buffer length - if (key_state_length < KEY_STATE_MAX_LENGTH) { - key_state_array[key_state_length++] = key; + int insert = find_key(0); + if (insert < KEY_STATE_MAX_LENGTH) { + key_state_array[insert] = key; } } } void release_key(keycode key) { uint8_t index = find_key(key); - if (index < key_state_length) { + if (index < KEY_STATE_MAX_LENGTH) { //shift it over and remove key - memmove(&key_state_array[index], - &key_state_array[index + 1], - sizeof(*key_state_array) * (--key_state_length - index)); + key_state_array[index] = 0; } } From 85ae987515a9227bde15c736a941d5ee59e49dc3 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 20 Aug 2015 07:38:40 -0400 Subject: [PATCH 27/42] Fix compiler warning --- sway/handlers.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 03a328354..6c103b027 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -286,13 +286,6 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) { - static const uint32_t modifier_syms[] = { - XKB_KEY_Shift_L, XKB_KEY_Shift_R, XKB_KEY_Control_L, XKB_KEY_Control_R, - XKB_KEY_Caps_Lock, XKB_KEY_Shift_Lock, XKB_KEY_Meta_L, XKB_KEY_Meta_R, - XKB_KEY_Alt_L, XKB_KEY_Alt_R, XKB_KEY_Super_L, XKB_KEY_Super_R, - XKB_KEY_Hyper_L, XKB_KEY_Hyper_R - }; - if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) { return false; } @@ -316,14 +309,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier sym = tolower(sym); int i; - bool mod = false; - - for (i = 0; i < sizeof(modifier_syms) / sizeof(uint32_t); ++i) { - if (modifier_syms[i] == sym) { - mod = true; - break; - } - } if (state == WLC_KEY_STATE_PRESSED) { press_key(sym); From fbaa9111a8525daeef8a5534784da2f793917a36 Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 04:47:36 -0700 Subject: [PATCH 28/42] setup for resizable windows, drop weight --- include/container.h | 2 -- sway/commands.c | 1 + sway/container.c | 9 +++++- sway/layout.c | 75 +++++++++++++++++++++++++++++---------------- sway/log.c | 1 - 5 files changed, 58 insertions(+), 30 deletions(-) diff --git a/include/container.h b/include/container.h index 76ddec7ea..4f1877e32 100644 --- a/include/container.h +++ b/include/container.h @@ -44,8 +44,6 @@ struct sway_container { bool is_floating; bool is_focused; - int weight; - char *name; int gaps; diff --git a/sway/commands.c b/sway/commands.c index c4cf96a20..babefd020 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -242,6 +242,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { add_sibling(focused, view); } // Refocus on the view once its been put back into the layout + view->width = view->height = 0; arrange_windows(active_workspace, -1, -1); } set_focused_container(view); diff --git a/sway/container.c b/sway/container.c index 9c6b78e95..c9163784a 100644 --- a/sway/container.c +++ b/sway/container.c @@ -14,7 +14,6 @@ static swayc_t *new_swayc(enum swayc_types type) { c->handle = -1; c->layout = L_NONE; c->type = type; - c->weight = 1; if (type != C_VIEW) { c->children = create_list(); } @@ -172,6 +171,14 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->name = title ? strdup(title) : NULL; view->visible = true; view->is_focused = true; + //Setup geometry + view->width = sibling->parent->width; + view->height = sibling->parent->height; + if (sibling->parent->layout == L_HORIZ) { + view->width /= sibling->parent->children->length; + } else { + view->height /= sibling->parent->children->length; + } view->gaps = config->gaps_inner; diff --git a/sway/layout.c b/sway/layout.c index f600cf495..50a25442b 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -186,40 +186,63 @@ void arrange_windows(swayc_t *container, int width, int height) { break; } - double total_weight = 0; - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - total_weight += child->weight; - } - + x = y = 0; + double scale = 0; switch (container->layout) { case L_HORIZ: default: - sway_log(L_DEBUG, "Arranging %p horizontally", container); + //Calculate total width for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - double percent = child->weight / total_weight; - sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will receive %.2f of %d)", child, child->type, percent, width); - child->x = x + container->x; - child->y = y + container->y; - int w = width * percent; - int h = height; - arrange_windows(child, w, h); - x += w; + int *old_width = &((swayc_t *)container->children->items[i])->width; + if (*old_width == 0) { + if (container->children->length > 1) { + *old_width = width / (container->children->length - 1); + } else { + *old_width = width; + } + sway_log(L_DEBUG,"setting width as %d",*old_width); + } + scale += *old_width; + } + //Resize windows + if (scale > 0.1) { + scale = width / scale; + sway_log(L_DEBUG, "Arranging %p horizontally", container); + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, width, scale); + child->x = x + container->x; + child->y = y + container->y; + arrange_windows(child, child->width * scale, height); + x += child->width; + } } break; case L_VERT: - sway_log(L_DEBUG, "Arranging %p vertically", container); + //Calculate total height for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - double percent = child->weight / total_weight; - sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will receive %.2f of %d)", child, child->type, percent, width); - child->x = x + container->x; - child->y = y + container->y; - int w = width; - int h = height * percent; - arrange_windows(child, w, h); - y += h; + int *old_height = &((swayc_t *)container->children->items[i])->height; + if (container->children->length > 1) { + *old_height = height / (container->children->length - 1); + } else { + *old_height = height; + } + if (*old_height == 0) { + } + scale += *old_height; + } + //Resize + if (scale > 0.1) { + scale = height / scale; + sway_log(L_DEBUG, "Arranging %p vertically", container); + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, height, scale); + child->x = x + container->x; + child->y = y + container->y; + arrange_windows(child, width, child->height * scale); + y += child->height; + } } break; } diff --git a/sway/log.c b/sway/log.c index 44f6e3660..49a74e027 100644 --- a/sway/log.c +++ b/sway/log.c @@ -114,7 +114,6 @@ static void container_log(const swayc_t *c) { fprintf(stderr, "w:%d|h:%d|", c->width, c->height); fprintf(stderr, "x:%d|y:%d|", c->x, c->y); fprintf(stderr, "vis:%c|", c->visible?'t':'f'); - fprintf(stderr, "wgt:%d|", c->weight); fprintf(stderr, "name:%.16s|", c->name); fprintf(stderr, "children:%d\n",c->children?c->children->length:0); } From b76dcf6e0fb9cec1bc966b5a4ab764cd9c61bd48 Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 04:50:15 -0700 Subject: [PATCH 29/42] unnessesary log --- sway/layout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/layout.c b/sway/layout.c index 50a25442b..6a4f8b459 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -200,7 +200,6 @@ void arrange_windows(swayc_t *container, int width, int height) { } else { *old_width = width; } - sway_log(L_DEBUG,"setting width as %d",*old_width); } scale += *old_width; } From f6e002fb8b664d80ef10126f6a204ffbb2f192df Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 04:57:01 -0700 Subject: [PATCH 30/42] small fix, default width/height 0 --- sway/container.c | 9 ++------- sway/layout.c | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/sway/container.c b/sway/container.c index c9163784a..59dc9e62b 100644 --- a/sway/container.c +++ b/sway/container.c @@ -172,13 +172,8 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->visible = true; view->is_focused = true; //Setup geometry - view->width = sibling->parent->width; - view->height = sibling->parent->height; - if (sibling->parent->layout == L_HORIZ) { - view->width /= sibling->parent->children->length; - } else { - view->height /= sibling->parent->children->length; - } + view->width = 0; + view->height = 0; view->gaps = config->gaps_inner; diff --git a/sway/layout.c b/sway/layout.c index 6a4f8b459..192f09cf5 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -194,7 +194,7 @@ void arrange_windows(swayc_t *container, int width, int height) { //Calculate total width for (i = 0; i < container->children->length; ++i) { int *old_width = &((swayc_t *)container->children->items[i])->width; - if (*old_width == 0) { + if (*old_width <= 0) { if (container->children->length > 1) { *old_width = width / (container->children->length - 1); } else { @@ -221,12 +221,12 @@ void arrange_windows(swayc_t *container, int width, int height) { //Calculate total height for (i = 0; i < container->children->length; ++i) { int *old_height = &((swayc_t *)container->children->items[i])->height; + if (*old_height <= 0) { if (container->children->length > 1) { *old_height = height / (container->children->length - 1); } else { *old_height = height; } - if (*old_height == 0) { } scale += *old_height; } From f5fde7c45c04b02406eabc34cbb4248189c6a26e Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 05:06:22 -0700 Subject: [PATCH 31/42] style --- include/container.h | 4 ++-- sway/commands.c | 20 ++++++++++---------- sway/container.c | 4 ++-- sway/focus.c | 4 ++-- sway/handlers.c | 14 +++++++------- sway/input_state.c | 2 +- sway/layout.c | 12 ++++++------ sway/log.c | 8 ++++---- sway/workspace.c | 2 +- 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/include/container.h b/include/container.h index 4f1877e32..bd92058d6 100644 --- a/include/container.h +++ b/include/container.h @@ -11,7 +11,7 @@ enum swayc_types{ C_WORKSPACE, C_CONTAINER, C_VIEW, - //Keep last + // Keep last C_TYPES, }; @@ -22,7 +22,7 @@ enum swayc_layouts{ L_STACKED, L_TABBED, L_FLOATING, - //Keep last + // Keep last L_LAYOUTS, }; diff --git a/sway/commands.c b/sway/commands.c index babefd020..a3f74747b 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -81,7 +81,7 @@ static int bindsym_sort(const void *_lbind, const void *_rbind) { const struct sway_binding *rbind = *(void **)_rbind; unsigned int lmod = 0, rmod = 0, i; - //Count how any modifiers are pressed + // Count how any modifiers are pressed for (i = 0; i < 8 * sizeof(lbind->modifiers); ++i) { lmod += lbind->modifiers & 1 << i; rmod += rbind->modifiers & 1 << i; @@ -203,10 +203,10 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { } // Change from nonfloating to floating if (!view->is_floating) { - //Remove view from its current location + // Remove view from its current location destroy_container(remove_child(view)); - //and move it into workspace floating + // and move it into workspace floating add_floating(active_workspace,view); view->x = (active_workspace->width - view->width)/2; view->y = (active_workspace->height - view->height)/2; @@ -233,11 +233,11 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { sway_log(L_DEBUG, "Non-floating focused container is %p", focused); - //Case of focused workspace, just create as child of it + // Case of focused workspace, just create as child of it if (focused->type == C_WORKSPACE) { add_child(focused, view); } - //Regular case, create as sibling of current container + // Regular case, create as sibling of current container else { add_sibling(focused, view); } @@ -258,7 +258,7 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) list_t *split = split_string(argv[0], "+"); config->floating_mod = 0; - //set modifer keys + // set modifer keys for (i = 0; i < split->length; ++i) { for (j = 0; j < sizeof(modifiers) / sizeof(struct modifier_key); ++j) { if (strcasecmp(modifiers[j].name, split->items[i]) == 0) { @@ -508,14 +508,14 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { swayc_t *container = get_focused_view(&root_container); bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0; wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); - //Resize workspace if going from fullscreen -> notfullscreen - //otherwise just resize container + // Resize workspace if going from fullscreen -> notfullscreen + // otherwise just resize container if (current) { while (container->type != C_WORKSPACE) { container = container->parent; } } - //Only resize container when going into fullscreen + // Only resize container when going into fullscreen arrange_windows(container, -1, -1); return true; @@ -679,7 +679,7 @@ bool handle_command(struct sway_config *config, char *exec) { char **argv = split_directive(exec + strlen(handler->command), &argc); int i; - //Perform var subs on all parts of the command + // Perform var subs on all parts of the command for (i = 0; i < argc; ++i) { argv[i] = do_var_replacement(config, argv[i]); } diff --git a/sway/container.c b/sway/container.c index 59dc9e62b..7da33b481 100644 --- a/sway/container.c +++ b/sway/container.c @@ -171,7 +171,7 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->name = title ? strdup(title) : NULL; view->visible = true; view->is_focused = true; - //Setup geometry + // Setup geometry view->width = 0; view->height = 0; @@ -205,7 +205,7 @@ swayc_t *new_floating_view(wlc_handle handle) { // Set the geometry of the floating view const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); - //give it requested geometry, but place in center + // give it requested geometry, but place in center view->x = (active_workspace->width - geometry->size.w) / 2; view->y = (active_workspace->height- geometry->size.h) / 2; view->width = geometry->size.w; diff --git a/sway/focus.c b/sway/focus.c index a6ffe73f5..5008dbbf0 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -21,7 +21,7 @@ static void update_focus(swayc_t *c) { // Case where output changes case C_OUTPUT: wlc_output_focus(c->handle); - //Set new workspace to the outputs focused workspace + // Set new workspace to the outputs focused workspace active_workspace = c->focused; break; @@ -118,7 +118,7 @@ void set_focused_container(swayc_t *c) { // activate current focus if (p->type == C_VIEW) { wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); - //set focus if view_focus is unlocked + // set focus if view_focus is unlocked if (!locked_view_focus) { wlc_view_focus(p->handle); } diff --git a/sway/handlers.c b/sway/handlers.c index 03a328354..2f062911e 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -87,7 +87,7 @@ swayc_t *container_under_pointer(void) { static bool handle_output_created(wlc_handle output) { swayc_t *op = new_output(output); - //Switch to workspace if we need to + // Switch to workspace if we need to if (active_workspace == NULL) { swayc_t *ws = op->children->items[0]; workspace_switch(ws); @@ -109,7 +109,7 @@ static void handle_output_destroyed(wlc_handle output) { if (list->length == 0) { active_workspace = NULL; } else { - //switch to other outputs active workspace + // switch to other outputs active workspace workspace_switch(((swayc_t *)root_container.children->items[0])->focused); } } @@ -167,7 +167,7 @@ static bool handle_view_created(wlc_handle handle) { // Dmenu keeps viewfocus, but others with this flag dont, for now simulate // dmenu case WLC_BIT_OVERRIDE_REDIRECT: -// locked_view_focus = true; +// locked_view_focus = true; wlc_view_focus(handle); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); wlc_view_bring_to_front(handle); @@ -217,7 +217,7 @@ static void handle_view_destroyed(wlc_handle handle) { // DMENU has this flag, and takes view_focus, but other things with this // flag dont case WLC_BIT_OVERRIDE_REDIRECT: -// locked_view_focus = false; +// locked_view_focus = false; break; case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: locked_container_focus = false; @@ -444,7 +444,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } } if (config->focus_follows_mouse && prev_handle != handle) { - //Dont change focus if fullscreen + // Dont change focus if fullscreen swayc_t *focused = get_focused_view(view); if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) && !(pointer_state.l_held || pointer_state.r_held)) { @@ -474,7 +474,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) { swayc_t *focused = get_focused_container(&root_container); - //dont change focus if fullscreen + // dont change focus if fullscreen if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { return false; } @@ -510,7 +510,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w pointer_state.lock.left = !pointer_state.lock.right; start_floating(pointer); } - //Dont want pointer sent to window while dragging or resizing + // Dont want pointer sent to window while dragging or resizing return (pointer_state.floating.drag || pointer_state.floating.resize); } return (pointer && pointer != focused); diff --git a/sway/input_state.c b/sway/input_state.c index 51213b19e..a7f88d4a6 100644 --- a/sway/input_state.c +++ b/sway/input_state.c @@ -36,7 +36,7 @@ void press_key(keycode key) { void release_key(keycode key) { uint8_t index = find_key(key); if (index < KEY_STATE_MAX_LENGTH) { - //shift it over and remove key + // shift it over and remove key key_state_array[index] = 0; } } diff --git a/sway/layout.c b/sway/layout.c index 192f09cf5..4a9aa9073 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -33,7 +33,7 @@ void add_child(swayc_t *parent, swayc_t *child) { child->width, child->height, parent, parent->type, parent->width, parent->height); list_add(parent->children, child); child->parent = parent; - //set focus for this container + // set focus for this container if (parent->children->length == 1) { set_focused_container_for(parent, child); } @@ -97,7 +97,7 @@ swayc_t *remove_child(swayc_t *child) { } } } - //Set focused to new container + // Set focused to new container if (parent->focused == child) { if (parent->children->length > 0) { set_focused_container_for(parent, parent->children->items[i?i-1:0]); @@ -191,7 +191,7 @@ void arrange_windows(swayc_t *container, int width, int height) { switch (container->layout) { case L_HORIZ: default: - //Calculate total width + // Calculate total width for (i = 0; i < container->children->length; ++i) { int *old_width = &((swayc_t *)container->children->items[i])->width; if (*old_width <= 0) { @@ -203,7 +203,7 @@ void arrange_windows(swayc_t *container, int width, int height) { } scale += *old_width; } - //Resize windows + // Resize windows if (scale > 0.1) { scale = width / scale; sway_log(L_DEBUG, "Arranging %p horizontally", container); @@ -218,7 +218,7 @@ void arrange_windows(swayc_t *container, int width, int height) { } break; case L_VERT: - //Calculate total height + // Calculate total height for (i = 0; i < container->children->length; ++i) { int *old_height = &((swayc_t *)container->children->items[i])->height; if (*old_height <= 0) { @@ -230,7 +230,7 @@ void arrange_windows(swayc_t *container, int width, int height) { } scale += *old_height; } - //Resize + // Resize if (scale > 0.1) { scale = height / scale; sway_log(L_DEBUG, "Arranging %p vertically", container); diff --git a/sway/log.c b/sway/log.c index 49a74e027..2d633abb2 100644 --- a/sway/log.c +++ b/sway/log.c @@ -88,10 +88,10 @@ bool sway_assert(bool condition, const char* format, ...) { /* XXX:DEBUG:XXX */ static void container_log(const swayc_t *c) { fprintf(stderr, "focus:%c|", - c->is_focused ? 'F' : //Focused - c == active_workspace ? 'W' : //active workspace - c == &root_container ? 'R' : //root - 'X');//not any others + c->is_focused ? 'F' : // Focused + c == active_workspace ? 'W' : // active workspace + c == &root_container ? 'R' : // root + 'X');// not any others fprintf(stderr,"(%p)",c); fprintf(stderr,"(p:%p)",c->parent); fprintf(stderr,"(f:%p)",c->focused); diff --git a/sway/workspace.c b/sway/workspace.c index ec60c8e01..0f44d3b06 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -47,7 +47,7 @@ char *workspace_next_name(void) { continue; } - //Make sure that the workspace doesn't already exist + // Make sure that the workspace doesn't already exist if (workspace_find_by_name(target)) { list_free(args); continue; From 579fe70ed92ce65d5a761ebdbb6c458b5f919687 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 20 Aug 2015 08:37:09 -0400 Subject: [PATCH 32/42] Add command line parsing Closes #6 --- .gitignore | 1 + include/config.h | 2 +- sway/commands.c | 2 +- sway/config.c | 9 ++++-- sway/main.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 86 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index b7b3266c5..cf23d168d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ bin/ test/ build/ .lvimrc +config-debug diff --git a/include/config.h b/include/config.h index c47eb6831..c23c35096 100644 --- a/include/config.h +++ b/include/config.h @@ -46,7 +46,7 @@ struct sway_config { int gaps_outer; }; -bool load_config(void); +bool load_config(const char *file); bool read_config(FILE *file, bool is_active); char *do_var_replacement(struct sway_config *config, char *str); diff --git a/sway/commands.c b/sway/commands.c index a3f74747b..803d9a214 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -414,7 +414,7 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) { if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) { return false; } - if (!load_config()) { + if (!load_config(NULL)) { // TODO: Use config given from -c return false; } arrange_windows(&root_container, -1, -1); diff --git a/sway/config.c b/sway/config.c index 94bc2abb5..9f65e8a26 100644 --- a/sway/config.c +++ b/sway/config.c @@ -144,10 +144,15 @@ _continue: return test; } -bool load_config(void) { +bool load_config(const char *file) { sway_log(L_INFO, "Loading config"); - char *path = get_config_path(); + char *path; + if (file != NULL) { + path = strdup(file); + } else { + path = get_config_path(); + } if (path == NULL) { sway_log(L_ERROR, "Unable to find a config file!"); diff --git a/sway/main.c b/sway/main.c index 2db4604cc..4a7e13c13 100644 --- a/sway/main.c +++ b/sway/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "layout.h" #include "config.h" #include "log.h" @@ -12,23 +13,96 @@ static void sigchld_handle(int signal); int main(int argc, char **argv) { + static int verbose = 0, debug = 0, validate = 0; + + static struct option long_options[] = { + {"config", required_argument, NULL, 'c'}, + {"validate", no_argument, &validate, 1}, + {"debug", no_argument, &debug, 1}, + {"version", no_argument, NULL, 'v'}, + {"verbose", no_argument, &verbose, 1}, + {"get-socketpath", no_argument, NULL, 'p'}, + }; + /* Signal handling */ signal(SIGCHLD, sigchld_handle); setenv("WLC_DIM", "0", 0); + + FILE *devnull = fopen("/dev/null", "w"); + if (devnull) { + // NOTE: Does not work, see wlc issue #54 + wlc_set_log_file(devnull); + } + /* Changing code earlier than this point requires detailed review */ if (!wlc_init(&interface, argc, argv)) { return 1; } - init_log(L_DEBUG); // TODO: Control this with command line arg + char *config_path = NULL; + + int c; + while (1) { + int option_index = 0; + c = getopt_long(argc, argv, "CdvVpc:", long_options, &option_index); + if (c == -1) { + break; + } + switch (c) { + case 0: // Flag + break; + case 'c': // config + config_path = strdup(optarg); + break; + case 'C': // validate + validate = 1; + break; + case 'd': // debug + debug = 1; + break; + case 'v': // version + // todo + exit(0); + break; + case 'V': // verbose + verbose = 1; + break; + case 'p': // --get-socketpath + // TODO + break; + } + } + + if (debug) { + init_log(L_DEBUG); + wlc_set_log_file(stderr); + fclose(devnull); + devnull = NULL; + } else if (verbose || validate) { + init_log(L_INFO); + } else { + init_log(L_ERROR); + } + + if (validate) { + bool valid = load_config(config_path); + return valid ? 0 : 1; + } + init_layout(); - if (!load_config()) { + if (!load_config(config_path)) { sway_log(L_ERROR, "Error(s) loading config!"); } + if (config_path) { + free(config_path); + } wlc_run(); + if (devnull) { + fclose(devnull); + } return 0; } From 8981b48cd2cdd0a59c1546f2816587b303538d77 Mon Sep 17 00:00:00 2001 From: minus Date: Sun, 16 Aug 2015 20:24:18 +0200 Subject: [PATCH 33/42] very basic IPC implementation simply executes the received data as command --- include/ipc.h | 6 +++++ sway/ipc.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ sway/main.c | 3 +++ 3 files changed, 79 insertions(+) create mode 100644 include/ipc.h create mode 100644 sway/ipc.c diff --git a/include/ipc.h b/include/ipc.h new file mode 100644 index 000000000..aab9cf0c0 --- /dev/null +++ b/include/ipc.h @@ -0,0 +1,6 @@ +#ifndef _SWAY_IPC_H +#define _SWAY_IPC_H + +void init_ipc(void); + +#endif diff --git a/sway/ipc.c b/sway/ipc.c new file mode 100644 index 000000000..ac5246d2a --- /dev/null +++ b/sway/ipc.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "config.h" +#include "commands.h" + +static int ipc_socket = -1; + +int ipc_handle_connection(int fd, uint32_t mask, void *data); + +void init_ipc() { + ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); + if (ipc_socket == -1) { + sway_abort("Unable to create IPC socket"); + } + + struct sockaddr_un ipc_sockaddr = { + .sun_family = AF_UNIX, + // TODO: use a proper socket path + .sun_path = "/tmp/sway.sock" + }; + + unlink(ipc_sockaddr.sun_path); + if (bind(ipc_socket, (struct sockaddr *)&ipc_sockaddr, sizeof(ipc_sockaddr)) == -1) { + sway_abort("Unable to bind IPC socket"); + } + + if (listen(ipc_socket, 3) == -1) { + sway_abort("Unable to listen on IPC socket"); + } + + wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); +} + +int ipc_handle_connection(int /*fd*/, uint32_t /*mask*/, void */*data*/) { + int client_socket = accept(ipc_socket, NULL, NULL); + if (client_socket == -1) { + char error[256]; + strerror_r(errno, error, sizeof(error)); + sway_log(L_INFO, "Unable to accept IPC client connection: %s", error); + return 0; + } + + char buf[1024]; + if (recv(client_socket, buf, sizeof(buf), 0) == -1) { + char error[256]; + strerror_r(errno, error, sizeof(error)); + sway_log(L_INFO, "Unable to receive from IPC client: %s", error); + close(client_socket); + return 0; + } + + sway_log(L_INFO, "Executing IPC command: %s", buf); + + bool success = handle_command(config, buf); + snprintf(buf, sizeof(buf), "{\"success\":%s}\n", success ? "true" : "false"); + + if (send(client_socket, buf, strlen(buf), 0) == -1) { + char error[256]; + strerror_r(errno, error, sizeof(error)); + sway_log(L_INFO, "Unable to send to IPC client: %s", error); + } + + close(client_socket); + return 0; +} diff --git a/sway/main.c b/sway/main.c index 4a7e13c13..1af1278d2 100644 --- a/sway/main.c +++ b/sway/main.c @@ -9,6 +9,7 @@ #include "config.h" #include "log.h" #include "handlers.h" +#include "ipc.h" static void sigchld_handle(int signal); @@ -99,6 +100,8 @@ int main(int argc, char **argv) { free(config_path); } + init_ipc(); + wlc_run(); if (devnull) { fclose(devnull); From 5d99215469088790d9b07a2932fd266133c8dc0b Mon Sep 17 00:00:00 2001 From: minus Date: Sun, 16 Aug 2015 22:02:16 +0200 Subject: [PATCH 34/42] added i3-ipc support/parsing --- include/ipc.h | 11 +++++++ sway/ipc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index aab9cf0c0..25d2fc613 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -1,6 +1,17 @@ #ifndef _SWAY_IPC_H #define _SWAY_IPC_H +enum ipc_command_type { + IPC_COMMAND = 0, + IPC_GET_WORKSPACES = 1, + IPC_SUBSCRIBE = 2, + IPC_GET_OUTPUTS = 3, + IPC_GET_TREE = 4, + IPC_GET_MARKS = 5, + IPC_GET_BAR_CONFIG = 6, + IPC_GET_VERSION = 7, +}; + void init_ipc(void); #endif diff --git a/sway/ipc.c b/sway/ipc.c index ac5246d2a..1a0747882 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -2,15 +2,23 @@ #include #include #include +#include #include #include +#include +#include "ipc.h" #include "log.h" #include "config.h" #include "commands.h" static int ipc_socket = -1; +static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; + int ipc_handle_connection(int fd, uint32_t mask, void *data); +size_t ipc_handle_command(char **reply_data, char *data, ssize_t length); +size_t ipc_format_reply(char **data, enum ipc_command_type command_type, const char *payload, uint32_t payload_length); + void init_ipc() { ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); @@ -36,7 +44,8 @@ void init_ipc() { wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); } -int ipc_handle_connection(int /*fd*/, uint32_t /*mask*/, void */*data*/) { +int ipc_handle_connection(int fd, uint32_t mask, void *data) { + sway_log(L_DEBUG, "Event on IPC listening socket"); int client_socket = accept(ipc_socket, NULL, NULL); if (client_socket == -1) { char error[256]; @@ -46,7 +55,9 @@ int ipc_handle_connection(int /*fd*/, uint32_t /*mask*/, void */*data*/) { } char buf[1024]; - if (recv(client_socket, buf, sizeof(buf), 0) == -1) { + // Leave one byte of space at the end of the buffer for NULL terminator + ssize_t received = recv(client_socket, buf, sizeof(buf) - 1, 0); + if (received == -1) { char error[256]; strerror_r(errno, error, sizeof(error)); sway_log(L_INFO, "Unable to receive from IPC client: %s", error); @@ -54,17 +65,72 @@ int ipc_handle_connection(int /*fd*/, uint32_t /*mask*/, void */*data*/) { return 0; } - sway_log(L_INFO, "Executing IPC command: %s", buf); + char *reply_buf; + size_t reply_length = ipc_handle_command(&reply_buf, buf, received); + sway_log(L_DEBUG, "IPC reply: %s", reply_buf); - bool success = handle_command(config, buf); - snprintf(buf, sizeof(buf), "{\"success\":%s}\n", success ? "true" : "false"); - - if (send(client_socket, buf, strlen(buf), 0) == -1) { + if (send(client_socket, reply_buf, reply_length, 0) == -1) { char error[256]; strerror_r(errno, error, sizeof(error)); sway_log(L_INFO, "Unable to send to IPC client: %s", error); } + free(reply_buf); close(client_socket); return 0; } + +static const int ipc_header_size = sizeof(ipc_magic)+8; + +size_t ipc_handle_command(char **reply_data, char *data, ssize_t length) { + // See https://i3wm.org/docs/ipc.html for protocol details + + if (length < ipc_header_size) { + sway_log(L_DEBUG, "IPC data too short"); + return false; + } + + if (memcmp(data, ipc_magic, sizeof(ipc_magic)) != 0) { + sway_log(L_DEBUG, "IPC header check failed"); + return false; + } + + uint32_t payload_length = *(uint32_t *)&data[sizeof(ipc_magic)]; + uint32_t command_type = *(uint32_t *)&data[sizeof(ipc_magic)+4]; + + if (length != payload_length + ipc_header_size) { + // TODO: try to read enough data + sway_log(L_DEBUG, "IPC payload size mismatch"); + return false; + } + + switch (command_type) { + case IPC_COMMAND: + { + char *cmd = &data[ipc_header_size]; + data[ipc_header_size + payload_length] = '\0'; + bool success = handle_command(config, cmd); + char buf[64]; + int length = snprintf(buf, sizeof(buf), "{\"success\":%s}", success ? "true" : "false"); + return ipc_format_reply(reply_data, IPC_COMMAND, buf, (uint32_t) length); + } + default: + sway_log(L_INFO, "Unknown IPC command type %i", command_type); + return false; + } +} + +size_t ipc_format_reply(char **data, enum ipc_command_type command_type, const char *payload, uint32_t payload_length) { + assert(data); + assert(payload); + + size_t length = ipc_header_size + payload_length; + *data = malloc(length); + + memcpy(*data, ipc_magic, sizeof(ipc_magic)); + *(uint32_t *)&((*data)[sizeof(ipc_magic)]) = payload_length; + *(uint32_t *)&((*data)[sizeof(ipc_magic)+4]) = command_type; + memcpy(&(*data)[ipc_header_size], payload, payload_length); + + return length; +} From 773e85c681ee4faecf353de7066b536f1a50ff61 Mon Sep 17 00:00:00 2001 From: minus Date: Wed, 19 Aug 2015 01:35:01 +0200 Subject: [PATCH 35/42] properly handle IPC clients --- include/log.h | 1 + sway/ipc.c | 193 ++++++++++++++++++++++++++++++++++---------------- sway/log.c | 30 ++++++++ 3 files changed, 163 insertions(+), 61 deletions(-) diff --git a/include/log.h b/include/log.h index 7aea2ded4..47a83321d 100644 --- a/include/log.h +++ b/include/log.h @@ -13,6 +13,7 @@ typedef enum { void init_log(int verbosity); void sway_log_colors(int mode); void sway_log(int verbosity, const char* format, ...) __attribute__((format(printf,2,3))); +void sway_log_errno(int verbosity, char* format, ...) __attribute__((format(printf,2,3))); void sway_abort(const char* format, ...) __attribute__((format(printf,1,2))); bool sway_assert(bool condition, const char* format, ...) __attribute__((format(printf,2,3))); diff --git a/sway/ipc.c b/sway/ipc.c index 1a0747882..292d9593c 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -1,3 +1,5 @@ +// See https://i3wm.org/docs/ipc.html for protocol information + #include #include #include @@ -6,6 +8,8 @@ #include #include #include +#include +#include #include "ipc.h" #include "log.h" #include "config.h" @@ -15,10 +19,18 @@ static int ipc_socket = -1; static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; -int ipc_handle_connection(int fd, uint32_t mask, void *data); -size_t ipc_handle_command(char **reply_data, char *data, ssize_t length); -size_t ipc_format_reply(char **data, enum ipc_command_type command_type, const char *payload, uint32_t payload_length); +struct ipc_client { + struct wlc_event_source *event_source; + int fd; + uint32_t payload_length; + enum ipc_command_type current_command; +}; +int ipc_handle_connection(int fd, uint32_t mask, void *data); +int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); +void ipc_client_disconnect(struct ipc_client *client); +void ipc_client_handle_command(struct ipc_client *client); +bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); void init_ipc() { ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); @@ -46,91 +58,150 @@ void init_ipc() { int ipc_handle_connection(int fd, uint32_t mask, void *data) { sway_log(L_DEBUG, "Event on IPC listening socket"); - int client_socket = accept(ipc_socket, NULL, NULL); - if (client_socket == -1) { - char error[256]; - strerror_r(errno, error, sizeof(error)); - sway_log(L_INFO, "Unable to accept IPC client connection: %s", error); + assert(mask == WLC_EVENT_READABLE); + + int client_fd = accept(ipc_socket, NULL, NULL); + if (client_fd == -1) { + sway_log_errno(L_INFO, "Unable to accept IPC client connection"); return 0; } - char buf[1024]; - // Leave one byte of space at the end of the buffer for NULL terminator - ssize_t received = recv(client_socket, buf, sizeof(buf) - 1, 0); - if (received == -1) { - char error[256]; - strerror_r(errno, error, sizeof(error)); - sway_log(L_INFO, "Unable to receive from IPC client: %s", error); - close(client_socket); - return 0; - } + struct ipc_client* client = malloc(sizeof(struct ipc_client)); + client->payload_length = 0; + client->fd = client_fd; + client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); - char *reply_buf; - size_t reply_length = ipc_handle_command(&reply_buf, buf, received); - sway_log(L_DEBUG, "IPC reply: %s", reply_buf); - - if (send(client_socket, reply_buf, reply_length, 0) == -1) { - char error[256]; - strerror_r(errno, error, sizeof(error)); - sway_log(L_INFO, "Unable to send to IPC client: %s", error); - } - - free(reply_buf); - close(client_socket); return 0; } static const int ipc_header_size = sizeof(ipc_magic)+8; -size_t ipc_handle_command(char **reply_data, char *data, ssize_t length) { - // See https://i3wm.org/docs/ipc.html for protocol details +int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { + struct ipc_client *client = data; + sway_log(L_DEBUG, "Event on IPC client socket %d", client_fd); - if (length < ipc_header_size) { - sway_log(L_DEBUG, "IPC data too short"); - return false; + if (mask & WLC_EVENT_ERROR) { + sway_log(L_INFO, "IPC Client socket error, removing client"); + ipc_client_disconnect(client); + return 0; } - if (memcmp(data, ipc_magic, sizeof(ipc_magic)) != 0) { + if (mask & WLC_EVENT_HANGUP) { + ipc_client_disconnect(client); + return 0; + } + + int read_available; + ioctl(client_fd, FIONREAD, &read_available); + + // Wait for the rest of the command payload in case the header has already been read + if (client->payload_length > 0) { + if (read_available >= client->payload_length) { + ipc_client_handle_command(client); + } + else { + sway_log(L_DEBUG, "Too little data to read payload on IPC Client socket, waiting for more (%d < %d)", read_available, client->payload_length); + } + return 0; + } + + if (read_available < ipc_header_size) { + sway_log(L_DEBUG, "Too little data to read header on IPC Client socket, waiting for more (%d < %d)", read_available, ipc_header_size); + return 0; + } + + char buf[ipc_header_size]; + ssize_t received = recv(client_fd, buf, ipc_header_size, 0); + if (received == -1) { + sway_log_errno(L_INFO, "Unable to receive header from IPC client"); + ipc_client_disconnect(client); + return 0; + } + + if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { sway_log(L_DEBUG, "IPC header check failed"); - return false; + ipc_client_disconnect(client); + return 0; } - uint32_t payload_length = *(uint32_t *)&data[sizeof(ipc_magic)]; - uint32_t command_type = *(uint32_t *)&data[sizeof(ipc_magic)+4]; + client->payload_length = *(uint32_t *)&buf[sizeof(ipc_magic)]; + client->current_command = (enum ipc_command_type) *(uint32_t *)&buf[sizeof(ipc_magic)+4]; - if (length != payload_length + ipc_header_size) { - // TODO: try to read enough data - sway_log(L_DEBUG, "IPC payload size mismatch"); - return false; + if (read_available - received >= client->payload_length) { + ipc_client_handle_command(client); } - switch (command_type) { + return 0; +} + +void ipc_client_disconnect(struct ipc_client *client) +{ + if (!sway_assert(client != NULL, "client != NULL")) { + return; + } + + sway_log(L_INFO, "IPC Client %d disconnected", client->fd); + wlc_event_source_remove(client->event_source); + close(client->fd); + free(client); +} + +void ipc_client_handle_command(struct ipc_client *client) { + if (!sway_assert(client != NULL, "client != NULL")) { + return; + } + + char buf[client->payload_length + 1]; + if (client->payload_length > 0) + { + ssize_t received = recv(client->fd, buf, client->payload_length, 0); + if (received == -1) + { + sway_log_errno(L_INFO, "Unable to receive payload from IPC client"); + ipc_client_disconnect(client); + return; + } + } + + switch (client->current_command) { case IPC_COMMAND: { - char *cmd = &data[ipc_header_size]; - data[ipc_header_size + payload_length] = '\0'; - bool success = handle_command(config, cmd); - char buf[64]; - int length = snprintf(buf, sizeof(buf), "{\"success\":%s}", success ? "true" : "false"); - return ipc_format_reply(reply_data, IPC_COMMAND, buf, (uint32_t) length); + buf[client->payload_length] = '\0'; + bool success = handle_command(config, buf); + char reply[64]; + int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false"); + ipc_send_reply(client, reply, (uint32_t) length); + break; } default: - sway_log(L_INFO, "Unknown IPC command type %i", command_type); - return false; + sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); + ipc_client_disconnect(client); + break; } + + client->payload_length = 0; } -size_t ipc_format_reply(char **data, enum ipc_command_type command_type, const char *payload, uint32_t payload_length) { - assert(data); +bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { assert(payload); - size_t length = ipc_header_size + payload_length; - *data = malloc(length); + char data[ipc_header_size]; - memcpy(*data, ipc_magic, sizeof(ipc_magic)); - *(uint32_t *)&((*data)[sizeof(ipc_magic)]) = payload_length; - *(uint32_t *)&((*data)[sizeof(ipc_magic)+4]) = command_type; - memcpy(&(*data)[ipc_header_size], payload, payload_length); + memcpy(data, ipc_magic, sizeof(ipc_magic)); + *(uint32_t *)&(data[sizeof(ipc_magic)]) = payload_length; + *(uint32_t *)&(data[sizeof(ipc_magic)+4]) = client->current_command; - return length; + if (write(client->fd, data, ipc_header_size) == -1) { + sway_log_errno(L_INFO, "Unable to send header to IPC client"); + ipc_client_disconnect(client); + return false; + } + + if (write(client->fd, payload, payload_length) == -1) { + sway_log_errno(L_INFO, "Unable to send payload to IPC client"); + ipc_client_disconnect(client); + return false; + } + + return true; } diff --git a/sway/log.c b/sway/log.c index 2d633abb2..e8c1b78fb 100644 --- a/sway/log.c +++ b/sway/log.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include int colored = 1; int v = 0; @@ -66,6 +68,34 @@ void sway_log(int verbosity, const char* format, ...) { } } +void sway_log_errno(int verbosity, char* format, ...) { + if (verbosity <= v) { + int c = verbosity; + if (c > sizeof(verbosity_colors) / sizeof(char *)) { + c = sizeof(verbosity_colors) / sizeof(char *) - 1; + } + + if (colored) { + fprintf(stderr, verbosity_colors[c]); + } + + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + fprintf(stderr, ": "); + char error[256]; + strerror_r(errno, error, sizeof(error)); + fprintf(stderr, error); + + if (colored) { + fprintf(stderr, "\x1B[0m"); + } + fprintf(stderr, "\n"); + } +} + bool sway_assert(bool condition, const char* format, ...) { if (condition) { return true; From bfbadadf702c6c7f078cc2e854afa02686b91c22 Mon Sep 17 00:00:00 2001 From: minus Date: Wed, 19 Aug 2015 01:40:49 +0200 Subject: [PATCH 36/42] use env var SWAYSOCK if available or fall back to /tmp/sway-ipc.sock --- sway/ipc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sway/ipc.c b/sway/ipc.c index 292d9593c..ba01a6790 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -40,10 +40,13 @@ void init_ipc() { struct sockaddr_un ipc_sockaddr = { .sun_family = AF_UNIX, - // TODO: use a proper socket path - .sun_path = "/tmp/sway.sock" + .sun_path = "/tmp/sway-ipc.sock" }; + if (getenv("SWAYSOCK") != NULL) { + strncpy(ipc_sockaddr.sun_path, getenv("SWAYSOCK"), sizeof(ipc_sockaddr.sun_path)); + } + unlink(ipc_sockaddr.sun_path); if (bind(ipc_socket, (struct sockaddr *)&ipc_sockaddr, sizeof(ipc_sockaddr)) == -1) { sway_abort("Unable to bind IPC socket"); From 91c08772645e2162015c3acf8a8ae7187502adb4 Mon Sep 17 00:00:00 2001 From: minus Date: Wed, 19 Aug 2015 01:52:46 +0200 Subject: [PATCH 37/42] properly exit sway - wlc_terminate() instead of exit(0) - unlink IPC socket --- include/ipc.h | 3 ++- sway/commands.c | 2 +- sway/ipc.c | 23 ++++++++++++++++------- sway/main.c | 4 +++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index 25d2fc613..606c47bab 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -12,6 +12,7 @@ enum ipc_command_type { IPC_GET_VERSION = 7, }; -void init_ipc(void); +void ipc_init(void); +void ipc_shutdown(void); #endif diff --git a/sway/commands.c b/sway/commands.c index 803d9a214..38557b62d 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -186,7 +186,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) { } // Close all views container_map(&root_container, kill_views, NULL); - exit(0); + wlc_terminate(); return true; } diff --git a/sway/ipc.c b/sway/ipc.c index ba01a6790..a6c4eb1ac 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -16,6 +16,11 @@ #include "commands.h" static int ipc_socket = -1; +static struct wlc_event_source *ipc_event_source = NULL; +static struct sockaddr_un ipc_sockaddr = { + .sun_family = AF_UNIX, + .sun_path = "/tmp/sway-ipc.sock" +}; static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; @@ -32,17 +37,12 @@ void ipc_client_disconnect(struct ipc_client *client); void ipc_client_handle_command(struct ipc_client *client); bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); -void init_ipc() { +void ipc_init(void) { ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); if (ipc_socket == -1) { sway_abort("Unable to create IPC socket"); } - struct sockaddr_un ipc_sockaddr = { - .sun_family = AF_UNIX, - .sun_path = "/tmp/sway-ipc.sock" - }; - if (getenv("SWAYSOCK") != NULL) { strncpy(ipc_sockaddr.sun_path, getenv("SWAYSOCK"), sizeof(ipc_sockaddr.sun_path)); } @@ -56,10 +56,19 @@ void init_ipc() { sway_abort("Unable to listen on IPC socket"); } - wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); + ipc_event_source = wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); +} + +void ipc_shutdown(void) { + if (ipc_event_source) { + wlc_event_source_remove(ipc_event_source); + } + close(ipc_socket); + unlink(ipc_sockaddr.sun_path); } int ipc_handle_connection(int fd, uint32_t mask, void *data) { + (void) fd; (void) data; sway_log(L_DEBUG, "Event on IPC listening socket"); assert(mask == WLC_EVENT_READABLE); diff --git a/sway/main.c b/sway/main.c index 1af1278d2..a42fbcb78 100644 --- a/sway/main.c +++ b/sway/main.c @@ -100,13 +100,15 @@ int main(int argc, char **argv) { free(config_path); } - init_ipc(); + ipc_init(); wlc_run(); if (devnull) { fclose(devnull); } + ipc_shutdown(); + return 0; } From 70f046c87a1fc03c3b3132bf3b05d2e4c4495805 Mon Sep 17 00:00:00 2001 From: minus Date: Thu, 20 Aug 2015 14:49:54 +0200 Subject: [PATCH 38/42] set IPC client sockets to close on exec --- sway/ipc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/ipc.c b/sway/ipc.c index a6c4eb1ac..69f4a4f38 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "ipc.h" #include "log.h" #include "config.h" @@ -78,6 +79,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { return 0; } + int flags; + if ((flags=fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { + sway_log_errno(L_INFO, "Unable to set CLOEXEC on IPC client socket"); + return 0; + } + struct ipc_client* client = malloc(sizeof(struct ipc_client)); client->payload_length = 0; client->fd = client_fd; From f26ed32e460f3007e623c529d28562f4a0b261cd Mon Sep 17 00:00:00 2001 From: minus Date: Thu, 20 Aug 2015 15:12:34 +0200 Subject: [PATCH 39/42] added sway_terminate to exit cleanly --- include/ipc.h | 2 +- sway/commands.c | 3 ++- sway/ipc.c | 2 +- sway/log.c | 3 ++- sway/main.c | 15 +++++++++++++-- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index 606c47bab..0b6441f66 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -13,6 +13,6 @@ enum ipc_command_type { }; void ipc_init(void); -void ipc_shutdown(void); +void ipc_terminate(void); #endif diff --git a/sway/commands.c b/sway/commands.c index 38557b62d..644b80050 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -15,6 +15,7 @@ #include "commands.h" #include "container.h" #include "handlers.h" +#include "sway.h" struct modifier_key { char *name; @@ -186,7 +187,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) { } // Close all views container_map(&root_container, kill_views, NULL); - wlc_terminate(); + sway_terminate(); return true; } diff --git a/sway/ipc.c b/sway/ipc.c index 69f4a4f38..d55469edc 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -60,7 +60,7 @@ void ipc_init(void) { ipc_event_source = wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); } -void ipc_shutdown(void) { +void ipc_terminate(void) { if (ipc_event_source) { wlc_event_source_remove(ipc_event_source); } diff --git a/sway/log.c b/sway/log.c index e8c1b78fb..6e01421bc 100644 --- a/sway/log.c +++ b/sway/log.c @@ -1,4 +1,5 @@ #include "log.h" +#include "sway.h" #include #include #include @@ -42,7 +43,7 @@ void sway_abort(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); - exit(1); + sway_terminate(); } void sway_log(int verbosity, const char* format, ...) { diff --git a/sway/main.c b/sway/main.c index a42fbcb78..f37f086df 100644 --- a/sway/main.c +++ b/sway/main.c @@ -10,6 +10,14 @@ #include "log.h" #include "handlers.h" #include "ipc.h" +#include "sway.h" + +static bool terminate_request = false; + +void sway_terminate(void) { + terminate_request = true; + wlc_terminate(); +} static void sigchld_handle(int signal); @@ -102,12 +110,15 @@ int main(int argc, char **argv) { ipc_init(); - wlc_run(); + if (!terminate_request) { + wlc_run(); + } + if (devnull) { fclose(devnull); } - ipc_shutdown(); + ipc_terminate(); return 0; } From 6ab968e63eb8c59abda6ddf9c5ae6d5a15d4c25e Mon Sep 17 00:00:00 2001 From: minus Date: Thu, 20 Aug 2015 15:15:04 +0200 Subject: [PATCH 40/42] fixed formatting --- sway/ipc.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sway/ipc.c b/sway/ipc.c index d55469edc..074f2a787 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -183,19 +183,19 @@ void ipc_client_handle_command(struct ipc_client *client) { } switch (client->current_command) { - case IPC_COMMAND: - { - buf[client->payload_length] = '\0'; - bool success = handle_command(config, buf); - char reply[64]; - int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false"); - ipc_send_reply(client, reply, (uint32_t) length); - break; - } - default: - sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); - ipc_client_disconnect(client); - break; + case IPC_COMMAND: + { + buf[client->payload_length] = '\0'; + bool success = handle_command(config, buf); + char reply[64]; + int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false"); + ipc_send_reply(client, reply, (uint32_t) length); + break; + } + default: + sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); + ipc_client_disconnect(client); + break; } client->payload_length = 0; From 4c56cd0ed638cc59f4412b7091220d2d32ba130c Mon Sep 17 00:00:00 2001 From: minus Date: Thu, 20 Aug 2015 15:22:38 +0200 Subject: [PATCH 41/42] set I3SOCK for i3-msg compatibility --- sway/ipc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/ipc.c b/sway/ipc.c index 074f2a787..505c17f83 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -57,6 +57,9 @@ void ipc_init(void) { sway_abort("Unable to listen on IPC socket"); } + // Set i3 IPC socket path so that i3-msg works out of the box + setenv("I3SOCK", ipc_sockaddr.sun_path, 1); + ipc_event_source = wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); } From f8787ce69e35be4569aa76a2e35f540b20ed40a4 Mon Sep 17 00:00:00 2001 From: minus Date: Thu, 20 Aug 2015 15:23:52 +0200 Subject: [PATCH 42/42] added missing header file --- include/sway.h | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 include/sway.h diff --git a/include/sway.h b/include/sway.h new file mode 100644 index 000000000..6499c81df --- /dev/null +++ b/include/sway.h @@ -0,0 +1,6 @@ +#ifndef _SWAY_SWAY_H +#define _SWAY_SWAY_H + +void sway_terminate(void); + +#endif