From a7c045a520811cc6a58c3ee605af16e9c9a96390 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 16:24:01 -0500 Subject: [PATCH 01/77] Patched for wlc updates --- sway/layout.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/layout.c b/sway/layout.c index 105359d2..a6a241f4 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -152,10 +152,10 @@ void arrange_windows(swayc_t *container, int width, int height) { geometry.origin.y = 0; geometry.size.w = parent->width; geometry.size.h = parent->height; - wlc_view_set_geometry(container->handle, &geometry); + wlc_view_set_geometry(container->handle, 0, &geometry); wlc_view_bring_to_front(container->handle); } else { - wlc_view_set_geometry(container->handle, &geometry); + wlc_view_set_geometry(container->handle, 0, &geometry); container->width = width; container->height = height; } @@ -232,10 +232,10 @@ void arrange_windows(swayc_t *container, int width, int height) { geometry.origin.y = 0; geometry.size.w = parent->width; geometry.size.h = parent->height; - wlc_view_set_geometry(view->handle, &geometry); + wlc_view_set_geometry(view->handle, 0, &geometry); wlc_view_bring_to_front(view->handle); } else { - wlc_view_set_geometry(view->handle, &geometry); + wlc_view_set_geometry(view->handle, 0, &geometry); view->width = width; view->height = height; // Bring the views to the front in order of the list, the list From 5b6e48987204c0d2298dda2d9b30b4208abdd8d5 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 16:28:24 -0500 Subject: [PATCH 02/77] More patches for wlc compat --- sway/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/handlers.c b/sway/handlers.c index 534b4e4f..1fe2dc27 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -427,7 +427,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) { + 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 if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { From faccaf6112d923533512e1dd868ec4bf0d30e1b5 Mon Sep 17 00:00:00 2001 From: minus Date: Tue, 18 Aug 2015 23:38:34 +0200 Subject: [PATCH 03/77] added sway_assert function returns false on a failed assertion in release mode and raises SIGABRT in debug mode --- CMakeLists.txt | 1 - include/log.h | 6 ++++-- sway/log.c | 22 ++++++++++++++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba2f8be3..d190cd8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ project(sway C) set(CMAKE_C_FLAGS "-g") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/") add_definitions("-Wall") -set(CMAKE_BUILD_TYPE Debug) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMake) find_package(XKBCommon REQUIRED) diff --git a/include/log.h b/include/log.h index d35b2a54..44f84940 100644 --- a/include/log.h +++ b/include/log.h @@ -1,5 +1,6 @@ #ifndef _SWAY_LOG_H #define _SWAY_LOG_H +#include typedef enum { L_SILENT = 0, @@ -10,7 +11,8 @@ typedef enum { void init_log(int verbosity); void sway_log_colors(int mode); -void sway_log(int verbosity, char* format, ...) __attribute__((format(printf,2,3))); -void sway_abort(char* format, ...)__attribute__((format(printf,1,2))); +void sway_log(int verbosity, const 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))); #endif diff --git a/sway/log.c b/sway/log.c index 8e380ffe..5bd3c8dc 100644 --- a/sway/log.c +++ b/sway/log.c @@ -4,6 +4,7 @@ #include #include #include +#include int colored = 1; int v = 0; @@ -32,7 +33,7 @@ void sway_log_colors(int mode) { colored = (mode == 1) ? 1 : 0; } -void sway_abort(char *format, ...) { +void sway_abort(const char *format, ...) { fprintf(stderr, "ERROR: "); va_list args; va_start(args, format); @@ -42,7 +43,7 @@ void sway_abort(char *format, ...) { exit(1); } -void sway_log(int verbosity, char* format, ...) { +void sway_log(int verbosity, const char* format, ...) { if (verbosity <= v) { int c = verbosity; if (c > sizeof(verbosity_colors) / sizeof(char *)) { @@ -64,3 +65,20 @@ void sway_log(int verbosity, char* format, ...) { fprintf(stderr, "\n"); } } + +bool sway_assert(bool condition, const char* format, ...) { + if (condition) { + return true; + } + +#ifndef NDEBUG + raise(SIGABRT); +#endif + + va_list args; + va_start(args, format); + sway_log(L_ERROR, format, args); + va_end(args); + + return false; +} From 4c688cba4e3528921656d63a09f7015cae13cd0c Mon Sep 17 00:00:00 2001 From: KoffeinFlummi Date: Tue, 18 Aug 2015 23:53:57 +0200 Subject: [PATCH 04/77] Add support for gaps option --- include/config.h | 3 +++ include/container.h | 2 ++ sway/commands.c | 40 ++++++++++++++++++++++++++++++++++++++++ sway/config.c | 2 ++ sway/container.c | 10 ++++++++-- sway/layout.c | 16 ++++++++-------- 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/include/config.h b/include/config.h index 9243bf35..c47eb683 100644 --- a/include/config.h +++ b/include/config.h @@ -41,6 +41,9 @@ struct sway_config { bool active; bool failed; bool reloading; + + int gaps_inner; + int gaps_outer; }; bool load_config(void); diff --git a/include/container.h b/include/container.h index 186ee8b6..6d64b490 100644 --- a/include/container.h +++ b/include/container.h @@ -48,6 +48,8 @@ struct sway_container { char *name; + int gaps; + list_t *children; list_t *floating; diff --git a/sway/commands.c b/sway/commands.c index 51de7a50..f716efa3 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -281,6 +282,44 @@ static bool cmd_focus_follows_mouse(struct sway_config *config, int argc, char * return true; } +static bool cmd_gaps(struct sway_config *config, int argc, char **argv) { + if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { + return false; + } + + if (argc == 1) { + char *end; + int amount = (int)strtol(argv[0], &end, 10); + if (errno == ERANGE || amount == 0) { + errno = 0; + return false; + } + if (config->gaps_inner == 0) { + config->gaps_inner = amount; + } + if (config->gaps_outer == 0) { + config->gaps_outer = amount; + } + } else if (argc == 2) { + char *end; + int amount = (int)strtol(argv[1], &end, 10); + if (errno == ERANGE || amount == 0) { + errno = 0; + return false; + } + if (strcmp(argv[0], "inner") == 0) { + config->gaps_inner = amount; + } else if (strcmp(argv[0], "outer") == 0) { + config->gaps_outer = amount; + } else { + return false; + } + } else { + return false; + } + return true; +} + static bool cmd_kill(struct sway_config *config, int argc, char **argv) { swayc_t *view = get_focused_container(&root_container); wlc_view_close(view->handle); @@ -484,6 +523,7 @@ static struct cmd_handler handlers[] = { { "focus", cmd_focus }, { "focus_follows_mouse", cmd_focus_follows_mouse }, { "fullscreen", cmd_fullscreen }, + { "gaps", cmd_gaps }, { "kill", cmd_kill }, { "layout", cmd_layout }, { "log_colors", cmd_log_colors }, diff --git a/sway/config.c b/sway/config.c index 6d39839d..b0b66315 100644 --- a/sway/config.c +++ b/sway/config.c @@ -170,6 +170,8 @@ void config_defaults(struct sway_config *config) { config->reloading = false; config->active = false; config->failed = false; + config->gaps_inner = 0; + config->gaps_outer = 0; } bool read_config(FILE *file, bool is_active) { diff --git a/sway/container.c b/sway/container.c index e679e823..68511156 100644 --- a/sway/container.c +++ b/sway/container.c @@ -43,8 +43,10 @@ swayc_t *new_output(wlc_handle handle) { sway_log(L_DEBUG, "Added output %lu:%s", handle, name); swayc_t *output = new_swayc(C_OUTPUT); - output->width = size->w; - output->height = size->h; + output->x = (config->gaps_outer + config->gaps_inner) / 2; + output->y = (config->gaps_outer + config->gaps_inner) / 2; + output->width = size->w - (config->gaps_outer + config->gaps_inner); + output->height = size->h - (config->gaps_outer + config->gaps_inner); output->handle = handle; output->name = name ? strdup(name) : NULL; @@ -81,6 +83,8 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { swayc_t *workspace = new_swayc(C_WORKSPACE); workspace->layout = L_HORIZ; // TODO: default layout + workspace->x = output->x; + workspace->y = output->y; workspace->width = output->width; workspace->height = output->height; workspace->name = strdup(name); @@ -143,6 +147,8 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->visible = true; view->is_focused = true; + view->gaps = config->gaps_inner; + view->desired_width = -1; view->desired_height = -1; diff --git a/sway/layout.c b/sway/layout.c index e2ea46a7..737477f7 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -133,12 +133,12 @@ void arrange_windows(swayc_t *container, int width, int height) { { struct wlc_geometry geometry = { .origin = { - .x = container->x, - .y = container->y + .x = container->x + container->gaps / 2, + .y = container->y + container->gaps / 2 }, .size = { - .w = width, - .h = height + .w = width - container->gaps, + .h = height - container->gaps } }; if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { @@ -146,10 +146,10 @@ void arrange_windows(swayc_t *container, int width, int height) { while (parent->type != C_OUTPUT) { parent = parent->parent; } - geometry.origin.x = 0; - geometry.origin.y = 0; - geometry.size.w = parent->width; - geometry.size.h = parent->height; + geometry.origin.x = container->gaps / 2; + geometry.origin.y = container->gaps / 2; + geometry.size.w = parent->width - container->gaps; + geometry.size.h = parent->height - container->gaps; wlc_view_set_geometry(container->handle, &geometry); wlc_view_bring_to_front(container->handle); } else { From 8e201091a52a74d87db18c18a21fc39aedb95eb2 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 18 Aug 2015 18:03:38 -0400 Subject: [PATCH 05/77] Fix indented comments being weird --- sway/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/config.c b/sway/config.c index f1de6080..d4871bab 100644 --- a/sway/config.c +++ b/sway/config.c @@ -188,8 +188,8 @@ bool read_config(FILE *file, bool is_active) { while (!feof(file)) { int _; char *line = read_line(file); - line = strip_comments(line); line = strip_whitespace(line, &_); + line = strip_comments(line); if (!line[0]) { goto _continue; } From cf916bbf6fbdf75abc55d4c1abe26ed6b8153687 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 18 Aug 2015 18:44:50 -0400 Subject: [PATCH 06/77] Improvements to gaps --- sway/commands.c | 4 ++-- sway/container.c | 8 +++----- sway/handlers.c | 6 +++++- sway/layout.c | 27 ++++++++++++++------------- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index 54839322..42d6b173 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -307,9 +307,9 @@ static bool cmd_gaps(struct sway_config *config, int argc, char **argv) { errno = 0; return false; } - if (strcmp(argv[0], "inner") == 0) { + if (strcasecmp(argv[0], "inner") == 0) { config->gaps_inner = amount; - } else if (strcmp(argv[0], "outer") == 0) { + } else if (strcasecmp(argv[0], "outer") == 0) { config->gaps_outer = amount; } else { return false; diff --git a/sway/container.c b/sway/container.c index 06111674..af9bcd73 100644 --- a/sway/container.c +++ b/sway/container.c @@ -63,12 +63,11 @@ swayc_t *new_output(wlc_handle handle) { sway_log(L_DEBUG, "Added output %lu:%s", handle, name); swayc_t *output = new_swayc(C_OUTPUT); - output->x = (config->gaps_outer + config->gaps_inner) / 2; - output->y = (config->gaps_outer + config->gaps_inner) / 2; - output->width = size->w - (config->gaps_outer + config->gaps_inner); - output->height = size->h - (config->gaps_outer + config->gaps_inner); + output->width = size->w; + output->height = size->h; output->handle = handle; output->name = name ? strdup(name) : NULL; + output->gaps = config->gaps_outer; add_child(&root_container, output); @@ -176,7 +175,6 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->desired_width = -1; view->desired_height = -1; - // TODO: properly set this view->is_floating = false; if (sibling->type == C_WORKSPACE) { diff --git a/sway/handlers.c b/sway/handlers.c index 1fe2dc27..9b96a5cf 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -168,7 +168,11 @@ static bool handle_view_created(wlc_handle handle) { } if (newview) { set_focused_container(newview); - arrange_windows(newview->parent, -1, -1); + swayc_t *output = newview->parent; + while (output && output->type != C_OUTPUT) { + output = output->parent; + } + arrange_windows(output, -1, -1); } return true; } diff --git a/sway/layout.c b/sway/layout.c index 02c92026..7cb9186a 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -4,6 +4,7 @@ #include "layout.h" #include "log.h" #include "list.h" +#include "config.h" #include "container.h" #include "workspace.h" #include "focus.h" @@ -123,11 +124,11 @@ void arrange_windows(swayc_t *container, int width, int height) { // y -= container->y; for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, "Arranging workspace #%d", i); - child->x = x; - child->y = y; - child->width = width; - child->height = height; + child->x = x + container->gaps; + child->y = y + container->gaps; + child->width = width - container->gaps * 2; + child->height = height - container->gaps * 2; + sway_log(L_DEBUG, "Arranging workspace #%d at %d, %d", i, child->x, child->y); arrange_windows(child, -1, -1); } return; @@ -135,12 +136,12 @@ void arrange_windows(swayc_t *container, int width, int height) { { struct wlc_geometry geometry = { .origin = { - .x = container->x + container->gaps / 2, - .y = container->y + container->gaps / 2 + .x = container->x + container->gaps, + .y = container->y + container->gaps }, .size = { - .w = width - container->gaps, - .h = height - container->gaps + .w = width - container->gaps * 2, + .h = height - container->gaps * 2 } }; if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { @@ -148,10 +149,10 @@ void arrange_windows(swayc_t *container, int width, int height) { while (parent->type != C_OUTPUT) { parent = parent->parent; } - geometry.origin.x = container->gaps / 2; - geometry.origin.y = container->gaps / 2; - geometry.size.w = parent->width - container->gaps; - geometry.size.h = parent->height - container->gaps; + geometry.origin.x = 0; + geometry.origin.y = 0; + geometry.size.w = parent->width; + geometry.size.h = parent->height; wlc_view_set_geometry(container->handle, 0, &geometry); wlc_view_bring_to_front(container->handle); } else { From e6d83206bdea32481c49c20daadf437e7a46cc60 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 18 Aug 2015 18:51:20 -0400 Subject: [PATCH 07/77] Document new commands in sway(5) --- sway.5.txt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sway.5.txt b/sway.5.txt index 9f92dfe8..b03fb73e 100644 --- a/sway.5.txt +++ b/sway.5.txt @@ -76,13 +76,24 @@ Commands **splitv**:: Equivalent to **split vertical**. -**fullscreen**: +**floating_modifier** :: + When the _modifier_ key is held down, you may use left click to drag floating + windows, and right click to resize them. + +**fullscreen**:: Toggles fullscreen status for the focused view. -**workspace** : +**gaps** **:: + Adds _amount_ pixels between each view, and around each output. + +**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. + +**workspace** :: Switches to the specified workspace. -**workspace** : +**workspace** :: Switches to the next workspace on the current output. **workspace** output :: From 3e950c2b1c77fd3bd6a029eea6d50fbbe124b581 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 17:45:26 -0500 Subject: [PATCH 08/77] Basic fixes to floating movement --- sway/handlers.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 9b96a5cf..d0915fe5 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -337,6 +337,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 = active_workspace->focused; + uint32_t edge = 0; if (m1_held && view) { if (view->is_floating) { while (keys_pressed[i++]) { @@ -348,7 +349,6 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct view->x += dx; view->y += dy; - changed_floating = true; break; } } @@ -366,25 +366,30 @@ 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) { changed_floating = true; if (mouse_origin.x > midway_x) { sway_log(L_INFO, "Downsizing view to the left"); view->width += dx; + edge = WLC_RESIZE_EDGE_RIGHT; } else { sway_log(L_INFO, "Upsizing view to the left"); view->x += dx; view->width -= dx; + edge = WLC_RESIZE_EDGE_LEFT; } } else if (dx > 0){ changed_floating = true; if (mouse_origin.x > midway_x) { sway_log(L_INFO, "Upsizing to the right"); view->width += dx; + edge = WLC_RESIZE_EDGE_RIGHT; } else { sway_log(L_INFO, "Downsizing to the right"); view->x += dx; view->width -= dx; + edge = WLC_RESIZE_EDGE_LEFT; } } @@ -393,20 +398,25 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct if (mouse_origin.y > midway_y) { sway_log(L_INFO, "Downsizing view to the top"); view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; } else { sway_log(L_INFO, "Upsizing the view to the top"); view->y += dy; view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; } } else if (dy > 0) { changed_floating = true; if (mouse_origin.y > midway_y) { sway_log(L_INFO, "Upsizing to the bottom"); view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; } else { + edge = WLC_RESIZE_EDGE_BOTTOM; sway_log(L_INFO, "Downsizing to the bottom"); view->y += dy; view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; } } break; @@ -424,7 +434,17 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct prev_handle = handle; prev_pos = mouse_origin; if (changed_floating) { - arrange_windows(view, -1, -1); + struct wlc_geometry geometry = { + .origin = { + .x = view->x, + .y = view->y + }, + .size = { + .w = view->width, + .h = view->height + } + }; + wlc_view_set_geometry(view->handle, edge, &geometry); return true; } return false; From 7137be9a3fac4780c356d3f7a5d33c4235314a57 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 18:03:11 -0500 Subject: [PATCH 09/77] Fixes to make floating windows work better --- sway/handlers.c | 3 +-- sway/layout.c | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index d0915fe5..99d57529 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -345,10 +345,10 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); - sway_log(L_DEBUG, "Moving: dx: %d, dy: %d", dx, dy); view->x += dx; view->y += dy; + changed_floating = true; break; } } @@ -360,7 +360,6 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); - sway_log(L_INFO, "Moving: dx: %d, dy: %d", dx, dy); // Move and resize the view based on the dx/dy and mouse position int midway_x = view->x + view->width/2; diff --git a/sway/layout.c b/sway/layout.c index 7cb9186a..2f8027a8 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -237,8 +237,6 @@ void arrange_windows(swayc_t *container, int width, int height) { wlc_view_bring_to_front(view->handle); } else { wlc_view_set_geometry(view->handle, 0, &geometry); - view->width = width; - view->height = height; // Bring the views to the front in order of the list, the list // will be kept up to date so that more recently focused views // have higher indexes From ab43927a470f46271ae98faa4e1cfe3a936c6c9d Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 18:04:46 -0500 Subject: [PATCH 10/77] Minor fixes that might be helpful later --- sway/handlers.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 99d57529..c20f3ca0 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -371,24 +371,24 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct if (mouse_origin.x > midway_x) { sway_log(L_INFO, "Downsizing view to the left"); view->width += dx; - edge = WLC_RESIZE_EDGE_RIGHT; + edge += WLC_RESIZE_EDGE_RIGHT; } else { sway_log(L_INFO, "Upsizing view to the left"); view->x += dx; view->width -= dx; - edge = WLC_RESIZE_EDGE_LEFT; + edge += WLC_RESIZE_EDGE_LEFT; } } else if (dx > 0){ changed_floating = true; if (mouse_origin.x > midway_x) { sway_log(L_INFO, "Upsizing to the right"); view->width += dx; - edge = WLC_RESIZE_EDGE_RIGHT; + edge += WLC_RESIZE_EDGE_RIGHT; } else { sway_log(L_INFO, "Downsizing to the right"); view->x += dx; view->width -= dx; - edge = WLC_RESIZE_EDGE_LEFT; + edge += WLC_RESIZE_EDGE_LEFT; } } From f718556a850a5c2bff6a00729c11f630c4b9c00f Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 21:05:58 -0500 Subject: [PATCH 11/77] Removed debugging, added in proper gap resets for config reloads --- sway/config.c | 3 +++ sway/container.c | 9 +++++++++ sway/handlers.c | 23 +++++++++-------------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/sway/config.c b/sway/config.c index 637e2dbc..be9f70c1 100644 --- a/sway/config.c +++ b/sway/config.c @@ -8,6 +8,7 @@ #include "log.h" #include "commands.h" #include "config.h" +#include "layout.h" struct sway_config *config; @@ -227,6 +228,8 @@ _continue: if (is_active) { temp_config->reloading = false; + container_map(&root_container, reset_gaps, NULL); + arrange_windows(&root_container, -1, -1); } config = temp_config; diff --git a/sway/container.c b/sway/container.c index af9bcd73..ec4d48b8 100644 --- a/sway/container.c +++ b/sway/container.c @@ -341,3 +341,12 @@ void set_view_visibility(swayc_t *view, void *data) { } view->visible = (*p == 2); } + +void reset_gaps(swayc_t *view, void *data) { + if (view->type == C_OUTPUT) { + view->gaps = config->gaps_outer; + } + if (view->type == C_VIEW) { + view->gaps = config->gaps_inner; + } +} diff --git a/sway/handlers.c b/sway/handlers.c index c20f3ca0..e785e9c5 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -19,7 +19,9 @@ uint32_t keys_pressed[32]; 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 pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; @@ -338,14 +340,12 @@ 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 = active_workspace->focused; uint32_t edge = 0; - if (m1_held && view) { + if (dragging && view) { if (view->is_floating) { while (keys_pressed[i++]) { if (keys_pressed[i] == config->floating_mod) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; - sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); - view->x += dx; view->y += dy; changed_floating = true; @@ -353,13 +353,12 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } } } - } else if (m2_held && view) { + } else if (resizing && view) { if (view->is_floating) { while (keys_pressed[i++]) { if (keys_pressed[i] == config->floating_mod) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; - sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); // Move and resize the view based on the dx/dy and mouse position int midway_x = view->x + view->width/2; @@ -369,11 +368,9 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct if (dx < 0) { changed_floating = true; if (mouse_origin.x > midway_x) { - sway_log(L_INFO, "Downsizing view to the left"); view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } else { - sway_log(L_INFO, "Upsizing view to the left"); view->x += dx; view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; @@ -381,11 +378,9 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } else if (dx > 0){ changed_floating = true; if (mouse_origin.x > midway_x) { - sway_log(L_INFO, "Upsizing to the right"); view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } else { - sway_log(L_INFO, "Downsizing to the right"); view->x += dx; view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; @@ -395,11 +390,9 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct if (dy < 0) { changed_floating = true; if (mouse_origin.y > midway_y) { - sway_log(L_INFO, "Downsizing view to the top"); view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } else { - sway_log(L_INFO, "Upsizing the view to the top"); view->y += dy; view->height -= dy; edge += WLC_RESIZE_EDGE_TOP; @@ -407,12 +400,10 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } else if (dy > 0) { changed_floating = true; if (mouse_origin.y > midway_y) { - sway_log(L_INFO, "Upsizing to the bottom"); view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } else { edge = WLC_RESIZE_EDGE_BOTTOM; - sway_log(L_INFO, "Downsizing to the bottom"); view->y += dy; view->height -= dy; edge += WLC_RESIZE_EDGE_TOP; @@ -426,7 +417,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 swayc_t *focused = get_focused_view(view); - if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) { + if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) && !(m1_held || m2_held)) { set_focused_container(container_under_pointer()); } } @@ -476,15 +467,19 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w } } arrange_windows(pointer->parent, -1, -1); + dragging = m1_held; + resizing = m2_held; } return (pointer && pointer != focused); } else { sway_log(L_DEBUG, "Mouse button %u released", button); if (button == 272) { m1_held = false; + dragging = false; } if (button == 273) { m2_held = false; + resizing = false; } } return false; From 3c430688a8ffd35dc88ff23c4cb7a066a89fbd3f Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 21:06:41 -0500 Subject: [PATCH 12/77] header update --- include/container.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/container.h b/include/container.h index 6d64b490..76ddec7e 100644 --- a/include/container.h +++ b/include/container.h @@ -79,5 +79,6 @@ void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); // Mappings void set_view_visibility(swayc_t *view, void *data); +void reset_gaps(swayc_t *view, void *data); #endif From 2f40459de49faffa213448677954155cd513d15d Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 18 Aug 2015 19:15:10 -0700 Subject: [PATCH 13/77] fixed focus on fullscreen view destroy --- sway/focus.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sway/focus.c b/sway/focus.c index 628316dd..1f17dfc9 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -142,9 +142,6 @@ void set_focused_container(swayc_t *c) { // Find previous focused view, and the new focused view, if they are the same return swayc_t *focused = get_focused_view(&root_container); swayc_t *workspace = active_workspace; - if (focused == get_focused_view(c)) { - return; - } // update container focus from here to root, making necessary changes along // the way From 774e594714579699a5f73fd110007ebb5a60cec6 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Tue, 18 Aug 2015 21:41:16 -0500 Subject: [PATCH 14/77] Fixed full screen workspace switch focusing --- sway/workspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/workspace.c b/sway/workspace.c index 05a669fe..60108752 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -178,9 +178,9 @@ 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); - active_workspace = workspace; } /* XXX:DEBUG:XXX */ From 6dc1ae802bb8cf1c272dc48c68fb42e3d548e812 Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 18 Aug 2015 22:20:31 -0700 Subject: [PATCH 15/77] focus to only child --- sway/layout.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/layout.c b/sway/layout.c index 2f8027a8..e2e12901 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -33,6 +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; + if (parent->children->length == 1) { + parent->focused = child; + } } swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { From 1bf02144e558630f36b1efca45d6074be456c0b4 Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 18 Aug 2015 23:52:42 -0700 Subject: [PATCH 16/77] fixed floating_modifier related things --- sway/container.c | 5 +++-- sway/focus.c | 5 ++++- sway/handlers.c | 45 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/sway/container.c b/sway/container.c index ec4d48b8..9763f381 100644 --- a/sway/container.c +++ b/sway/container.c @@ -200,8 +200,9 @@ 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); - view->x = geometry->origin.x; - view->y = geometry->origin.y; + //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; view->height = geometry->size.h; diff --git a/sway/focus.c b/sway/focus.c index 1f17dfc9..0ee10694 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -168,8 +168,11 @@ void set_focused_container(swayc_t *c) { } // activate current focus if (p->type == C_VIEW) { - wlc_view_focus(p->handle); wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); + //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 e785e9c5..d5909c8f 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -139,35 +139,54 @@ static void handle_output_focused(wlc_handle output, bool focus) { } static bool handle_view_created(wlc_handle handle) { - swayc_t *focused = get_focused_container(&root_container); + // if view is child of another view, the use that as focused container + wlc_handle parent = wlc_view_get_parent(handle); + swayc_t *focused = NULL; swayc_t *newview = NULL; + + // Get parent container, to add view in + if (parent) { + focused = get_swayc_for_handle(parent, &root_container); + } + 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); + + // TODO properly figure out how each window should be handled. switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: newview = new_view(focused, handle); wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); break; - // takes keyboard focus + + // Dmenu keeps viewfocus, but others with this flag dont, for now simulate + // dmenu case WLC_BIT_OVERRIDE_REDIRECT: - sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle); - 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); break; - // Takes container focus + + // Firefox popups have this flag set. case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: - sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle); wlc_view_bring_to_front(handle); locked_container_focus = true; break; - // set modals as floating containers + + // Modals, get focus, popups do not case WLC_BIT_MODAL: + wlc_view_focus(handle); wlc_view_bring_to_front(handle); newview = new_floating_view(handle); case WLC_BIT_POPUP: + wlc_view_bring_to_front(handle); break; } + if (newview) { set_focused_container(newview); swayc_t *output = newview->parent; @@ -187,19 +206,19 @@ static void handle_view_destroyed(wlc_handle handle) { // regular view created regularly case 0: case WLC_BIT_MODAL: + case WLC_BIT_POPUP: if (view) { swayc_t *parent = destroy_view(view); arrange_windows(parent, -1, -1); } break; - // takes keyboard focus + // 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; - // Takes container focus case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: locked_container_focus = false; - case WLC_BIT_POPUP: break; } set_focused_container(get_focused_view(&root_container)); @@ -279,10 +298,12 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier while (mid < head && keys_pressed[mid] != sym) { ++mid; } + //Add or remove key depending on state if (state == WLC_KEY_STATE_PRESSED && mid == head && head + 1 < QSIZE) { keys_pressed[head++] = sym; } else if (state == WLC_KEY_STATE_RELEASED && mid < head) { memmove(keys_pressed + mid, keys_pressed + mid + 1, sizeof*keys_pressed * (--head - mid)); + keys_pressed[head] = 0; } // TODO: reminder to check conflicts with mod+q+a versus mod+q int i; @@ -314,6 +335,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier uint8_t k; for (k = 0; k < head; ++k) { memmove(keys_pressed + k, keys_pressed + k + 1, sizeof*keys_pressed * (--head - k)); + keys_pressed[head] = 0; break; } } @@ -469,6 +491,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w arrange_windows(pointer->parent, -1, -1); dragging = m1_held; resizing = m2_held; + return true; } return (pointer && pointer != focused); } else { From e16a4015ff216594eeb237ef81534bfaea7533d6 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 00:28:53 -0700 Subject: [PATCH 17/77] fixed focus key handler --- include/layout.h | 1 + sway/commands.c | 39 ++++-------- sway/handlers.c | 163 +++++++++++++++++++++++------------------------ sway/layout.c | 12 ++++ 4 files changed, 103 insertions(+), 112 deletions(-) diff --git a/include/layout.h b/include/layout.h index 282f92ee..98fdb531 100644 --- a/include/layout.h +++ b/include/layout.h @@ -10,6 +10,7 @@ extern swayc_t root_container; void init_layout(void); void add_child(swayc_t *parent, swayc_t *child); +void add_floating(swayc_t *ws, swayc_t *child); // Returns parent container which needs to be rearranged. swayc_t *add_sibling(swayc_t *sibling, swayc_t *child); swayc_t *replace_child(swayc_t *child, swayc_t *new_child); diff --git a/sway/commands.c b/sway/commands.c index 42d6b173..6e1f1848 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -185,40 +185,23 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { int i; // Change from nonfloating to floating if (!view->is_floating) { - view->is_floating = true; - for (i = 0; i < view->parent->children->length; i++) { - if (view->parent->children->items[i] == view) { - // Try to use desired geometry to set w/h - if (view->desired_width != -1) { - view->width = view->desired_width; - } - if (view->desired_height != -1) { - view->height = view->desired_height; - } - - // Swap from the list of whatever container the view was in - // to the workspace->floating list - list_del(view->parent->children, i); - list_add(active_workspace->floating, view); - destroy_container(view->parent); - - // Set the new position of the container and arrange windows - view->x = (active_workspace->width - view->width)/2; - view->y = (active_workspace->height - view->height)/2; - sway_log(L_INFO, "Setting container %p to floating at coordinates X:%d Y:%d, W:%d, H:%d", view, view->x, view->y, view->width, view->height); - // Change parent to active_workspace - view->parent = active_workspace; - arrange_windows(active_workspace, -1, -1); - return true; - } + remove_child(view); + add_floating(active_workspace,view); + view->x = (active_workspace->width - view->width)/2; + view->y = (active_workspace->height - view->height)/2; + arrange_windows(active_workspace, -1, -1); + if (view->desired_width != -1) { + view->width = view->desired_width; + } + if (view->desired_height != -1) { + view->height = view->desired_height; } } else { // Delete the view from the floating list and unset its is_floating flag // Using length-1 as the index is safe because the view must be the currently // focused floating output - list_del(active_workspace->floating, active_workspace->floating->length - 1); + remove_child(view); view->is_floating = false; - active_workspace->focused = NULL; // Get the properly focused container, and add in the view there swayc_t *focused = container_under_pointer(); // If focused is null, it's because the currently focused container is a workspace diff --git a/sway/handlers.c b/sway/handlers.c index d5909c8f..3ae33294 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -15,6 +15,7 @@ #include "focus.h" uint32_t keys_pressed[32]; +int keys_pressed_length = 0; static struct wlc_origin mouse_origin; @@ -23,6 +24,15 @@ static bool dragging = false; static bool m2_held = false; static bool resizing = false; +static bool floating_mod_pressed(void) { + int i = 0; + while (i < keys_pressed_length) { + if (keys_pressed[i++] == config->floating_mod) + return true; + } + return false; +} + static bool pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; // Determine the output that the view is under @@ -286,7 +296,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; } - static uint8_t head = 0; bool cmd_success = false; struct sway_mode *mode = config->current_mode; @@ -295,15 +304,15 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier // Find key, if it has been pressed int mid = 0; - while (mid < head && keys_pressed[mid] != sym) { + while (mid < keys_pressed_length && keys_pressed[mid] != sym) { ++mid; } //Add or remove key depending on state - if (state == WLC_KEY_STATE_PRESSED && mid == head && head + 1 < QSIZE) { - keys_pressed[head++] = sym; - } else if (state == WLC_KEY_STATE_RELEASED && mid < head) { - memmove(keys_pressed + mid, keys_pressed + mid + 1, sizeof*keys_pressed * (--head - mid)); - keys_pressed[head] = 0; + 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; @@ -317,7 +326,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier match = false; xkb_keysym_t *key = binding->keys->items[j]; uint8_t k; - for (k = 0; k < head; ++k) { + for (k = 0; k < keys_pressed_length; ++k) { if (keys_pressed[k] == *key) { match = true; break; @@ -333,9 +342,9 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier int j; for (j = 0; j < binding->keys->length; ++j) { uint8_t k; - for (k = 0; k < head; ++k) { - memmove(keys_pressed + k, keys_pressed + k + 1, sizeof*keys_pressed * (--head - k)); - keys_pressed[head] = 0; + 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; } } @@ -355,84 +364,67 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct static wlc_handle prev_handle = 0; mouse_origin = *origin; bool changed_floating = false; - int i = 0; if (!active_workspace) { return false; } // Do checks to determine if proper keys are being held - swayc_t *view = active_workspace->focused; + swayc_t *view = get_focused_view(active_workspace); uint32_t edge = 0; - if (dragging && view) { - if (view->is_floating) { - while (keys_pressed[i++]) { - if (keys_pressed[i] == config->floating_mod) { - int dx = mouse_origin.x - prev_pos.x; - int dy = mouse_origin.y - prev_pos.y; - view->x += dx; - view->y += dy; - changed_floating = true; - break; - } + if (dragging && view && view->is_floating) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + view->x += dx; + view->y += dy; + changed_floating = true; + } else if (resizing && view && view->is_floating) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + + // Move and resize the view based on the dx/dy and mouse position + int midway_x = view->x + view->width/2; + int midway_y = view->y + view->height/2; + if (dx < 0) { + changed_floating = true; + if (mouse_origin.x > midway_x) { + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } else { + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; + } + } else if (dx > 0){ + changed_floating = true; + if (mouse_origin.x > midway_x) { + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } else { + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; } } - } else if (resizing && view) { - if (view->is_floating) { - while (keys_pressed[i++]) { - if (keys_pressed[i] == config->floating_mod) { - int dx = mouse_origin.x - prev_pos.x; - int dy = mouse_origin.y - prev_pos.y; - // Move and resize the view based on the dx/dy and mouse position - int midway_x = view->x + view->width/2; - int midway_y = view->y + view->height/2; - - - if (dx < 0) { - changed_floating = true; - if (mouse_origin.x > midway_x) { - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else { - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } - } else if (dx > 0){ - changed_floating = true; - if (mouse_origin.x > midway_x) { - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else { - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } - } - - if (dy < 0) { - changed_floating = true; - if (mouse_origin.y > midway_y) { - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else { - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; - } - } else if (dy > 0) { - changed_floating = true; - if (mouse_origin.y > midway_y) { - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else { - edge = WLC_RESIZE_EDGE_BOTTOM; - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; - } - } - break; - } + if (dy < 0) { + changed_floating = true; + if (mouse_origin.y > midway_y) { + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } else { + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; + } + } else if (dy > 0) { + changed_floating = true; + if (mouse_origin.y > midway_y) { + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } else { + edge = WLC_RESIZE_EDGE_BOTTOM; + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; } } } @@ -489,9 +481,12 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w } } arrange_windows(pointer->parent, -1, -1); - dragging = m1_held; - resizing = m2_held; - return true; + if (floating_mod_pressed()) { + dragging = m1_held; + resizing = m2_held; + } + //Dont want pointer sent to window while dragging or resizing + return (dragging || resizing); } return (pointer && pointer != focused); } else { diff --git a/sway/layout.c b/sway/layout.c index e2e12901..7125ffc3 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -38,6 +38,17 @@ void add_child(swayc_t *parent, swayc_t *child) { } } +void add_floating(swayc_t *ws, swayc_t *child) { + sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, + child->width, child->height, ws, ws->type, ws->width, ws->height); + list_add(ws->floating, child); + child->parent = ws; + child->is_floating = true; + if (!ws->focused) { + ws->focused = child; + } +} + swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { swayc_t *parent = sibling->parent; int i = index_child(parent, sibling); @@ -76,6 +87,7 @@ swayc_t *remove_child(swayc_t *child) { break; } } + i = 0; } else { for (i = 0; i < parent->children->length; ++i) { if (parent->children->items[i] == child) { From c5a69828934bf07db9062bd5f24bb2ff94b45b4a Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 01:06:15 -0700 Subject: [PATCH 18/77] fixed some more bugs, moved layout_log into log.ch, restored focus_parent --- include/log.h | 2 ++ include/workspace.h | 1 - sway/commands.c | 10 +++++--- sway/container.c | 1 - sway/focus.c | 3 +++ sway/log.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ sway/workspace.c | 57 ------------------------------------------- 7 files changed, 70 insertions(+), 63 deletions(-) diff --git a/include/log.h b/include/log.h index 44f84940..7aea2ded 100644 --- a/include/log.h +++ b/include/log.h @@ -1,6 +1,7 @@ #ifndef _SWAY_LOG_H #define _SWAY_LOG_H #include +#include "container.h" typedef enum { L_SILENT = 0, @@ -15,4 +16,5 @@ void sway_log(int verbosity, const char* format, ...) __attribute__((format(prin void sway_abort(const char* format, ...) __attribute__((format(printf,1,2))); bool sway_assert(bool condition, const char* format, ...) __attribute__((format(printf,2,3))); +void layout_log(const swayc_t *c, int depth); #endif diff --git a/include/workspace.h b/include/workspace.h index 8ce39bbd..042a15d9 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -15,6 +15,5 @@ void workspace_output_next(); void workspace_next(); void workspace_output_prev(); void workspace_prev(); -void layout_log(const swayc_t *c, int depth); #endif diff --git a/sway/commands.c b/sway/commands.c index 6e1f1848..7dde78bd 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -182,20 +182,22 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { if (view->type != C_VIEW) { return true; } - int i; // Change from nonfloating to floating if (!view->is_floating) { - remove_child(view); + //Remove view from its current location + destroy_container(remove_child(view)); + + //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; - arrange_windows(active_workspace, -1, -1); if (view->desired_width != -1) { view->width = view->desired_width; } if (view->desired_height != -1) { view->height = view->desired_height; } + arrange_windows(active_workspace, -1, -1); } else { // Delete the view from the floating list and unset its is_floating flag // Using length-1 as the index is safe because the view must be the currently @@ -221,10 +223,10 @@ 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 - set_focused_container(view); arrange_windows(active_workspace, -1, -1); return true; } + set_focused_container(view); } return true; diff --git a/sway/container.c b/sway/container.c index 9763f381..0a89f634 100644 --- a/sway/container.c +++ b/sway/container.c @@ -261,7 +261,6 @@ swayc_t *destroy_container(swayc_t *container) { sway_log(L_DEBUG, "Container: Destroying container '%p'", container); swayc_t *parent = container->parent; free_swayc(container); - container = parent; } return container; diff --git a/sway/focus.c b/sway/focus.c index 0ee10694..7023d37d 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -146,6 +146,9 @@ void set_focused_container(swayc_t *c) { // update container focus from here to root, making necessary changes along // the way swayc_t *p = c; + if (p->type != C_OUTPUT && p->type != C_ROOT) { + p->is_focused = true; + } while (p != &root_container) { update_focus(p); p = p->parent; diff --git a/sway/log.c b/sway/log.c index 5bd3c8dc..9b9a9dc0 100644 --- a/sway/log.c +++ b/sway/log.c @@ -82,3 +82,62 @@ bool sway_assert(bool condition, const char* format, ...) { return false; } + +#include "workspace.h" + +/* 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 + fprintf(stderr,"(%p)",c); + fprintf(stderr,"(p:%p)",c->parent); + fprintf(stderr,"(f:%p)",c->focused); + fprintf(stderr,"(h:%ld)",c->handle); + fprintf(stderr,"Type:"); + fprintf(stderr, + c->type == C_ROOT ? "Root|" : + c->type == C_OUTPUT ? "Output|" : + c->type == C_WORKSPACE ? "Workspace|" : + c->type == C_CONTAINER ? "Container|" : + c->type == C_VIEW ? "View|" : "Unknown|"); + fprintf(stderr,"layout:"); + fprintf(stderr, + c->layout == L_NONE ? "NONE|" : + c->layout == L_HORIZ ? "Horiz|": + c->layout == L_VERT ? "Vert|": + c->layout == L_STACKED ? "Stacked|": + c->layout == L_FLOATING ? "Floating|": + "Unknown|"); + 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); +} +void layout_log(const swayc_t *c, int depth) { + int i, d; + int e = c->children ? c->children->length : 0; + container_log(c); + if (e) { + for (i = 0; i < e; ++i) { + fputc('|',stderr); + for (d = 0; d < depth; ++d) fputc('-', stderr); + layout_log(c->children->items[i], depth + 1); + } + } + if (c->type == C_WORKSPACE) { + e = c->floating?c->floating->length:0; + if (e) { + for (i = 0; i < e; ++i) { + fputc('|',stderr); + for (d = 0; d < depth; ++d) fputc('=', stderr); + layout_log(c->floating->items[i], depth + 1); + } + } + } +} +/* XXX:DEBUG:XXX */ diff --git a/sway/workspace.c b/sway/workspace.c index 60108752..9b407c6a 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -182,60 +182,3 @@ void workspace_switch(swayc_t *workspace) { set_focused_container(get_focused_view(workspace)); arrange_windows(workspace, -1, -1); } - -/* 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 - fprintf(stderr,"(%p)",c); - fprintf(stderr,"(p:%p)",c->parent); - fprintf(stderr,"(f:%p)",c->focused); - fprintf(stderr,"(h:%ld)",c->handle); - fprintf(stderr,"Type:"); - fprintf(stderr, - c->type == C_ROOT ? "Root|" : - c->type == C_OUTPUT ? "Output|" : - c->type == C_WORKSPACE ? "Workspace|" : - c->type == C_CONTAINER ? "Container|" : - c->type == C_VIEW ? "View|" : "Unknown|"); - fprintf(stderr,"layout:"); - fprintf(stderr, - c->layout == L_NONE ? "NONE|" : - c->layout == L_HORIZ ? "Horiz|": - c->layout == L_VERT ? "Vert|": - c->layout == L_STACKED ? "Stacked|": - c->layout == L_FLOATING ? "Floating|": - "Unknown|"); - 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); -} -void layout_log(const swayc_t *c, int depth) { - int i, d; - int e = c->children ? c->children->length : 0; - container_log(c); - if (e) { - for (i = 0; i < e; ++i) { - fputc('|',stderr); - for (d = 0; d < depth; ++d) fputc('-', stderr); - layout_log(c->children->items[i], depth + 1); - } - } - if (c->type == C_WORKSPACE) { - e = c->floating?c->floating->length:0; - if (e) { - for (i = 0; i < e; ++i) { - fputc('|',stderr); - for (d = 0; d < depth; ++d) fputc('-', stderr); - layout_log(c->floating->items[i], depth + 1); - } - } - } -} -/* XXX:DEBUG:XXX */ From 95517ac77ebedb6e07011affd9520159acf38376 Mon Sep 17 00:00:00 2001 From: Syed Amer Gilani Date: Wed, 19 Aug 2015 11:27:48 +0200 Subject: [PATCH 19/77] fix a few possible memory leaks --- sway/commands.c | 4 ++++ sway/config.c | 6 ++++++ sway/workspace.c | 15 ++++++++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index 42d6b173..ab24f6ae 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -105,6 +105,10 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) { xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE); if (!sym) { sway_log(L_ERROR, "bindsym - unknown key %s", (char *)split->items[i]); + list_free(binding->keys); + free(binding->command); + free(binding); + list_free(split); return false; } xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); diff --git a/sway/config.c b/sway/config.c index be9f70c1..3a7f3904 100644 --- a/sway/config.c +++ b/sway/config.c @@ -28,6 +28,7 @@ static char *get_config_path() { if (exists(temp)) { return temp; } + free(temp); // Check XDG_CONFIG_HOME with fallback to ~/.config/ sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_HOME/sway/config"); @@ -54,6 +55,7 @@ static char *get_config_path() { if (exists(temp)) { return temp; } + free(temp); // Check XDG_CONFIG_DIRS sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS"); @@ -70,6 +72,7 @@ static char *get_config_path() { free_flat_list(paths); return temp; } + free(temp); } free_flat_list(paths); } @@ -83,6 +86,7 @@ static char *get_config_path() { if (exists(temp)) { return temp; } + free(temp); sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_HOME/i3/config"); if (xdg_config_home == NULL) { @@ -106,6 +110,7 @@ static char *get_config_path() { if (exists(temp)) { return temp; } + free(temp); sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS"); if (xdg_config_dirs != NULL) { @@ -120,6 +125,7 @@ static char *get_config_path() { free_flat_list(paths); return temp; } + free(temp); } free_flat_list(paths); } diff --git a/sway/workspace.c b/sway/workspace.c index 60108752..180c8a66 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -31,7 +31,7 @@ char *workspace_next_name(void) { char* target = malloc(strlen(args->items[1]) + 1); strcpy(target, args->items[1]); while (*target == ' ' || *target == '\t') - target++; + target++; // Make sure that the command references an actual workspace // not a command about workspaces @@ -42,11 +42,15 @@ char *workspace_next_name(void) { strcmp(target, "number") == 0 || strcmp(target, "back_and_forth") == 0 || strcmp(target, "current") == 0) + { + list_free(args); 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)) { - continue; + list_free(args); + continue; } list_free(args); @@ -54,6 +58,7 @@ char *workspace_next_name(void) { sway_log(L_DEBUG, "Workspace: Found free name %s", target); return target; } + list_free(args); } // As a fall back, get the current number of active workspaces // and return that + 1 for the next workspace's name @@ -77,7 +82,7 @@ swayc_t *workspace_create(const char* name) { } bool workspace_by_name(swayc_t *view, void *data) { - return (view->type == C_WORKSPACE) && + return (view->type == C_WORKSPACE) && (strcasecmp(view->name, (char *) data) == 0); } From ba5b451dd0c3f08e92f5960a7dad1deed77317f7 Mon Sep 17 00:00:00 2001 From: Syed Amer Gilani Date: Wed, 19 Aug 2015 12:51:11 +0200 Subject: [PATCH 20/77] fixed string building for XDG_CONFIG_HOME config loading --- sway/config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/config.c b/sway/config.c index be9f70c1..13280f9d 100644 --- a/sway/config.c +++ b/sway/config.c @@ -41,7 +41,7 @@ static char *get_config_path() { } else { name = "/sway/config"; temp = malloc(strlen(xdg_config_home) + strlen(name) + 1); - strcpy(xdg_config_home, home); + strcpy(temp, xdg_config_home); strcat(temp, name); } if (exists(temp)) { @@ -94,7 +94,7 @@ static char *get_config_path() { } else { name = "/i3/config"; temp = malloc(strlen(xdg_config_home) + strlen(name) + 1); - strcpy(xdg_config_home, home); + strcpy(temp, xdg_config_home); strcat(temp, name); } if (exists(temp)) { From 79f9d93ef3581f399173e91db464137d77877c99 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 07:50:27 -0400 Subject: [PATCH 21/77] Refactor config file loading --- sway/config.c | 217 +++++++++++++++++++++++--------------------------- 1 file changed, 99 insertions(+), 118 deletions(-) diff --git a/sway/config.c b/sway/config.c index 0dc53c75..66a3fa21 100644 --- a/sway/config.c +++ b/sway/config.c @@ -16,121 +16,121 @@ static bool exists(const char *path) { return access(path, R_OK) != -1; } +void config_defaults(struct sway_config *config) { + config->symbols = create_list(); + config->modes = create_list(); + config->cmd_queue = create_list(); + config->workspace_outputs = create_list(); + config->current_mode = malloc(sizeof(struct sway_mode)); + config->current_mode->name = NULL; + config->current_mode->bindings = create_list(); + list_add(config->modes, config->current_mode); + // Flags + config->focus_follows_mouse = true; + config->mouse_warping = true; + config->reloading = false; + config->active = false; + config->failed = false; + config->gaps_inner = 0; + config->gaps_outer = 0; +} + +void free_mode(struct sway_mode *mode) { + free(mode->name); + free_flat_list(mode->bindings); +} + +void free_config(struct sway_config *config) { + int i; + for (i = 0; i < config->modes->length; ++i) { + free_mode((struct sway_mode *)config->modes->items[i]); + } + free_flat_list(config->modes); + for (i = 0; i < config->workspace_outputs->length; ++i) { + struct workspace_output *wso = config->workspace_outputs->items[i]; + free(wso->output); + free(wso->workspace); + } + free_flat_list(config->workspace_outputs); + free_flat_list(config->cmd_queue); + for (i = 0; i < config->symbols->length; ++i) { + struct sway_variable *sym = config->symbols->items[i]; + free(sym->name); + free(sym->value); + } + free_flat_list(config->symbols); +} + +static const char *search_paths[] = { + "$home/.sway/config", + "$config/.sway/config", + "/etc/sway/config", + "$home/.i3/config", + "$config/.i3/config", + "/etc/i3/config" +}; + static char *get_config_path() { - char *name = "/.sway/config"; - const char *home = getenv("HOME"); - - // Check home dir - sway_log(L_DEBUG, "Trying to find config in ~/.sway/config"); - char *temp = malloc(strlen(home) + strlen(name) + 1); - strcpy(temp, home); - strcat(temp, name); - if (exists(temp)) { - return temp; - } - free(temp); - - // Check XDG_CONFIG_HOME with fallback to ~/.config/ - sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_HOME/sway/config"); - char *xdg_config_home = getenv("XDG_CONFIG_HOME"); - if (xdg_config_home == NULL) { - sway_log(L_DEBUG, "Falling back to ~/.config/sway/config"); - name = "/.config/sway/config"; - temp = malloc(strlen(home) + strlen(name) + 1); - strcpy(temp, home); - strcat(temp, name); - } else { - name = "/sway/config"; - temp = malloc(strlen(xdg_config_home) + strlen(name) + 1); - strcpy(temp, xdg_config_home); - strcat(temp, name); - } - if (exists(temp)) { - return temp; + char *home = getenv("HOME"); + char *config = getenv("XDG_CONFIG_HOME"); + if (!config) { + const char *def = "/.config/sway"; + config = malloc(strlen(home) + strlen(def) + 1); + strcpy(config, home); + strcat(config, def); } - // Check /etc/ - sway_log(L_DEBUG, "Trying to find config in /etc/sway/config"); - strcpy(temp, "/etc/sway/config"); - if (exists(temp)) { - return temp; - } - free(temp); + // Set up a temporary config for holding set variables + struct sway_config *temp_config = malloc(sizeof(struct sway_config)); + config_defaults(temp_config); + const char *set_home = "set $home "; + char *_home = malloc(strlen(home) + strlen(set_home) + 1); + strcpy(_home, set_home); + strcat(_home, home); + handle_command(temp_config, _home); + free(_home); + const char *set_config = "set $config "; + char *_config = malloc(strlen(config) + strlen(set_config) + 1); + strcpy(_config, set_config); + strcat(_config, config); + handle_command(temp_config, _config); + free(_config); + + char *test = NULL; + int i; + for (i = 0; i < sizeof(search_paths) / sizeof(char *); ++i) { + test = strdup(search_paths[i]); + test = do_var_replacement(temp_config, test); + sway_log(L_DEBUG, "Checking for config at %s", test); + if (exists(test)) { + goto _continue; + } + free(test); + test = NULL; + } - // Check XDG_CONFIG_DIRS sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS"); char *xdg_config_dirs = getenv("XDG_CONFIG_DIRS"); if (xdg_config_dirs != NULL) { list_t *paths = split_string(xdg_config_dirs, ":"); - name = "/sway/config"; + char *name = "/sway/config"; int i; for (i = 0; i < paths->length; i++ ) { - temp = malloc(strlen(paths->items[i]) + strlen(name) + 1); - strcpy(temp, paths->items[i]); - strcat(temp, name); - if (exists(temp)) { + test = malloc(strlen(paths->items[i]) + strlen(name) + 1); + strcpy(test, paths->items[i]); + strcat(test, name); + if (exists(test)) { free_flat_list(paths); - return temp; + return test; } - free(temp); + free(test); } free_flat_list(paths); } - //Now fall back to i3 paths and try the same thing - name = "/.i3/config"; - sway_log(L_DEBUG, "Trying to find config in ~/.i3/config"); - temp = malloc(strlen(home) + strlen(name) + 1); - strcpy(temp, home); - strcat(temp, name); - if (exists(temp)) { - return temp; - } - free(temp); - - sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_HOME/i3/config"); - if (xdg_config_home == NULL) { - sway_log(L_DEBUG, "Falling back to ~/.config/i3/config"); - name = "/.config/i3/config"; - temp = malloc(strlen(home) + strlen(name) + 1); - strcpy(temp, home); - strcat(temp, name); - } else { - name = "/i3/config"; - temp = malloc(strlen(xdg_config_home) + strlen(name) + 1); - strcpy(temp, xdg_config_home); - strcat(temp, name); - } - if (exists(temp)) { - return temp; - } - - sway_log(L_DEBUG, "Trying to find config in /etc/i3/config"); - strcpy(temp, "/etc/i3/config"); - if (exists(temp)) { - return temp; - } - free(temp); - - sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS"); - if (xdg_config_dirs != NULL) { - list_t *paths = split_string(xdg_config_dirs, ":"); - name = "/i3/config"; - int i; - for (i = 0; i < paths->length; i++ ) { - temp = malloc(strlen(paths->items[i]) + strlen(name) + 1); - strcpy(temp, paths->items[i]); - strcat(temp, name); - if (exists(temp)) { - free_flat_list(paths); - return temp; - } - free(temp); - } - free_flat_list(paths); - } - - return NULL; +_continue: + free_config(temp_config); + return test; } bool load_config(void) { @@ -162,25 +162,6 @@ bool load_config(void) { return config_load_success; } -void config_defaults(struct sway_config *config) { - config->symbols = create_list(); - config->modes = create_list(); - config->cmd_queue = create_list(); - config->workspace_outputs = create_list(); - config->current_mode = malloc(sizeof(struct sway_mode)); - config->current_mode->name = NULL; - config->current_mode->bindings = create_list(); - list_add(config->modes, config->current_mode); - // Flags - config->focus_follows_mouse = true; - config->mouse_warping = true; - config->reloading = false; - config->active = false; - config->failed = false; - config->gaps_inner = 0; - config->gaps_outer = 0; -} - bool read_config(FILE *file, bool is_active) { struct sway_config *temp_config = malloc(sizeof(struct sway_config)); config_defaults(temp_config); From 1ec8e082a2693418b79071e052e45a040baab009 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 08:22:18 -0400 Subject: [PATCH 22/77] Free environment vars after loading config Thanks @SyedAmerGilani --- sway/config.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sway/config.c b/sway/config.c index 66a3fa21..e74bfb65 100644 --- a/sway/config.c +++ b/sway/config.c @@ -71,8 +71,8 @@ static const char *search_paths[] = { }; static char *get_config_path() { - char *home = getenv("HOME"); - char *config = getenv("XDG_CONFIG_HOME"); + char *home = strdup(getenv("HOME")); + char *config = strdup(getenv("XDG_CONFIG_HOME")); if (!config) { const char *def = "/.config/sway"; config = malloc(strlen(home) + strlen(def) + 1); @@ -130,6 +130,8 @@ static char *get_config_path() { _continue: free_config(temp_config); + free(home); + free(config); return test; } From 0f29f048167739c6f92d241d2aacbfcf6972c39c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 19 Aug 2015 08:24:39 -0400 Subject: [PATCH 23/77] Set test to NULL when appropriate Thanks @SyedAmerGilani --- sway/config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/config.c b/sway/config.c index e74bfb65..f38e37b6 100644 --- a/sway/config.c +++ b/sway/config.c @@ -124,6 +124,7 @@ static char *get_config_path() { return test; } free(test); + test = NULL; } free_flat_list(paths); } From 0e4df85ba1a931a812c441572f352090a934e6bc Mon Sep 17 00:00:00 2001 From: Luminarys Date: Wed, 19 Aug 2015 09:33:30 -0500 Subject: [PATCH 24/77] Fixed config loading --- sway/config.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sway/config.c b/sway/config.c index f38e37b6..ce05bc68 100644 --- a/sway/config.c +++ b/sway/config.c @@ -71,13 +71,21 @@ static const char *search_paths[] = { }; static char *get_config_path() { - char *home = strdup(getenv("HOME")); - char *config = strdup(getenv("XDG_CONFIG_HOME")); - if (!config) { - const char *def = "/.config/sway"; + char *home = getenv("HOME"); + if (home) { + home = strdup(getenv("HOME")); + } + char *config = getenv("XDG_CONFIG_HOME"); + if (config) { + config = strdup(getenv("XDG_CONFIG_HOME")); + } else if (home) { + const char *def = "/.config"; config = malloc(strlen(home) + strlen(def) + 1); strcpy(config, home); strcat(config, def); + } else { + home = strdup(""); + config = strdup(""); } // Set up a temporary config for holding set variables From dd8ff4a1505e914b6ab9b2de11a4a55f7a4bb61d Mon Sep 17 00:00:00 2001 From: Luminarys Date: Wed, 19 Aug 2015 10:52:01 -0500 Subject: [PATCH 25/77] Added in resize locking --- sway/handlers.c | 134 ++++++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 51 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 3ae33294..306c8abf 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -23,8 +23,10 @@ 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 floating_mod_pressed(void) { + return true; int i = 0; while (i < keys_pressed_length) { if (keys_pressed[i++] == config->floating_mod) @@ -370,61 +372,89 @@ 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 && view->is_floating) { - int dx = mouse_origin.x - prev_pos.x; - int dy = mouse_origin.y - prev_pos.y; - view->x += dx; - view->y += dy; - changed_floating = true; - } else if (resizing && view && view->is_floating) { - int dx = mouse_origin.x - prev_pos.x; - int dy = mouse_origin.y - prev_pos.y; - - // Move and resize the view based on the dx/dy and mouse position - int midway_x = view->x + view->width/2; - int midway_y = view->y + view->height/2; - if (dx < 0) { + if (dragging && view) { + if (view->is_floating) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + view->x += dx; + view->y += dy; changed_floating = true; - if (mouse_origin.x > midway_x) { - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else { - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } - } else if (dx > 0){ - changed_floating = true; - if (mouse_origin.x > midway_x) { - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else { - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } } + } else if (resizing && view) { + if (view->is_floating) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + int min_sane_w = 100; + int min_sane_h = 60; - if (dy < 0) { - changed_floating = true; - if (mouse_origin.y > midway_y) { - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else { - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; + // Move and resize the view based on the dx/dy and mouse position + int midway_x = view->x + view->width/2; + int midway_y = view->y + view->height/2; + if (dx < 0) { + if (mouse_origin.x > midway_x && !lock_right) { + if (view->width > min_sane_w) { + lock_left = true; + changed_floating = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } + } else if (mouse_origin.x < midway_x && !lock_left) { + lock_right = true; + 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) { + lock_left = true; + changed_floating = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + if (view->width > min_sane_w) { + lock_left = false; + } + } else if (mouse_origin.x < midway_x && !lock_left) { + if (view->width > min_sane_w) { + lock_right = true; + changed_floating = true; + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; + } + } } - } else if (dy > 0) { - changed_floating = true; - if (mouse_origin.y > midway_y) { - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else { - edge = WLC_RESIZE_EDGE_BOTTOM; - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; + + if (dy < 0) { + if (mouse_origin.y > midway_y && !lock_bottom) { + if (view->height > min_sane_h) { + lock_top = true; + changed_floating = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } + } else if (mouse_origin.y < midway_y && !lock_top) { + lock_bottom = true; + 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) { + lock_top = true; + changed_floating = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } else if (mouse_origin.y < midway_y && !lock_top) { + if (view->height > min_sane_h) { + lock_bottom = true; + changed_floating = true; + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; + } + } } } } @@ -494,10 +524,12 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w if (button == 272) { m1_held = false; dragging = false; + lock_top = lock_bottom = lock_left = lock_right = false; } if (button == 273) { m2_held = false; resizing = false; + lock_top = lock_bottom = lock_left = lock_right = false; } } return false; From 8205a6fd3bb544b11c9d56abc93da02b03543297 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 09:09:35 -0700 Subject: [PATCH 26/77] floating_modifier uses mod_keys instead of anykey --- sway/commands.c | 19 ++++++++++++++++++- sway/handlers.c | 10 ++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index cc51717b..37bd9b00 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -240,7 +240,24 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) { return false; } - config->floating_mod = xkb_keysym_from_name(argv[0], XKB_KEYSYM_CASE_INSENSITIVE); + int i, j; + list_t *split = split_string(argv[0], "+"); + fprintf(stderr,"%s, %d,%d\n",argv[0], split->length,split->items); + config->floating_mod = 0; + + //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) { + config->floating_mod |= modifiers[j].mod; + } + } + } + list_free(split); + if (!config->floating_mod) { + sway_log(L_ERROR, "bindsym - unknown keys %s", argv[0]); + return false; + } return true; } diff --git a/sway/handlers.c b/sway/handlers.c index 3ae33294..670569cb 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -15,8 +15,10 @@ #include "focus.h" uint32_t keys_pressed[32]; +uint32_t key_modifiers; int keys_pressed_length = 0; + static struct wlc_origin mouse_origin; static bool m1_held = false; @@ -25,12 +27,7 @@ static bool m2_held = false; static bool resizing = false; static bool floating_mod_pressed(void) { - int i = 0; - while (i < keys_pressed_length) { - if (keys_pressed[i++] == config->floating_mod) - return true; - } - return false; + return key_modifiers & config->floating_mod; } static bool pointer_test(swayc_t *view, void *_origin) { @@ -297,6 +294,7 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier return false; } bool cmd_success = false; + key_modifiers = modifiers->mods; struct sway_mode *mode = config->current_mode; // Lowercase if necessary From 289aab9f0adf856e1dc9c8bbe2108171d67c9043 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 09:21:44 -0700 Subject: [PATCH 27/77] removed debug which shouldnt be there --- sway/commands.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/commands.c b/sway/commands.c index 37bd9b00..aafa51f3 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -242,7 +242,6 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv) } int i, j; list_t *split = split_string(argv[0], "+"); - fprintf(stderr,"%s, %d,%d\n",argv[0], split->length,split->items); config->floating_mod = 0; //set modifer keys From 0b23962564a52dff8dd70488f33bc08eeb5aef03 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Wed, 19 Aug 2015 11:23:27 -0500 Subject: [PATCH 28/77] Resolved merge conflicts --- sway/handlers.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 306c8abf..92d9b6af 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -26,13 +26,7 @@ static bool resizing = false; static bool lock_left, lock_right, lock_top, lock_bottom = false; static bool floating_mod_pressed(void) { - return true; - int i = 0; - while (i < keys_pressed_length) { - if (keys_pressed[i++] == config->floating_mod) - return true; - } - return false; + return key_modifiers & config->floating_mod; } static bool pointer_test(swayc_t *view, void *_origin) { From 9542f8746ae691b867ed127a7897dd5e8c7f4305 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Wed, 19 Aug 2015 10:52:01 -0500 Subject: [PATCH 29/77] Added in resize locking --- sway/handlers.c | 133 +++++++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 51 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 670569cb..faade5eb 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -25,6 +25,7 @@ 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 floating_mod_pressed(void) { return key_modifiers & config->floating_mod; @@ -368,61 +369,89 @@ 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 && view->is_floating) { - int dx = mouse_origin.x - prev_pos.x; - int dy = mouse_origin.y - prev_pos.y; - view->x += dx; - view->y += dy; - changed_floating = true; - } else if (resizing && view && view->is_floating) { - int dx = mouse_origin.x - prev_pos.x; - int dy = mouse_origin.y - prev_pos.y; - - // Move and resize the view based on the dx/dy and mouse position - int midway_x = view->x + view->width/2; - int midway_y = view->y + view->height/2; - if (dx < 0) { + if (dragging && view) { + if (view->is_floating) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + view->x += dx; + view->y += dy; changed_floating = true; - if (mouse_origin.x > midway_x) { - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else { - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } - } else if (dx > 0){ - changed_floating = true; - if (mouse_origin.x > midway_x) { - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else { - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } } + } else if (resizing && view) { + if (view->is_floating) { + int dx = mouse_origin.x - prev_pos.x; + int dy = mouse_origin.y - prev_pos.y; + int min_sane_w = 100; + int min_sane_h = 60; - if (dy < 0) { - changed_floating = true; - if (mouse_origin.y > midway_y) { - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else { - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; + // Move and resize the view based on the dx/dy and mouse position + int midway_x = view->x + view->width/2; + int midway_y = view->y + view->height/2; + if (dx < 0) { + if (mouse_origin.x > midway_x && !lock_right) { + if (view->width > min_sane_w) { + lock_left = true; + changed_floating = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } + } else if (mouse_origin.x < midway_x && !lock_left) { + lock_right = true; + 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) { + lock_left = true; + changed_floating = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + if (view->width > min_sane_w) { + lock_left = false; + } + } else if (mouse_origin.x < midway_x && !lock_left) { + if (view->width > min_sane_w) { + lock_right = true; + changed_floating = true; + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; + } + } } - } else if (dy > 0) { - changed_floating = true; - if (mouse_origin.y > midway_y) { - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else { - edge = WLC_RESIZE_EDGE_BOTTOM; - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; + + if (dy < 0) { + if (mouse_origin.y > midway_y && !lock_bottom) { + if (view->height > min_sane_h) { + lock_top = true; + changed_floating = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } + } else if (mouse_origin.y < midway_y && !lock_top) { + lock_bottom = true; + 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) { + lock_top = true; + changed_floating = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } else if (mouse_origin.y < midway_y && !lock_top) { + if (view->height > min_sane_h) { + lock_bottom = true; + changed_floating = true; + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; + } + } } } } @@ -492,10 +521,12 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w if (button == 272) { m1_held = false; dragging = false; + lock_top = lock_bottom = lock_left = lock_right = false; } if (button == 273) { m2_held = false; resizing = false; + lock_top = lock_bottom = lock_left = lock_right = false; } } return false; From 745031e6f97b871de0c37572b085aea4eae855a8 Mon Sep 17 00:00:00 2001 From: Ezra Date: Wed, 19 Aug 2015 11:29:32 -0500 Subject: [PATCH 30/77] More merge resolution. --- sway/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/handlers.c b/sway/handlers.c index 92d9b6af..00f10a0c 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -26,7 +26,7 @@ static bool resizing = false; static bool lock_left, lock_right, lock_top, lock_bottom = false; static bool floating_mod_pressed(void) { - return key_modifiers & config->floating_mod; + return key_modifiers & config->floating_mod; } static bool pointer_test(swayc_t *view, void *_origin) { From daea22bc8920fea1d6fba923169173a2bbdc75f9 Mon Sep 17 00:00:00 2001 From: Luminarys Date: Wed, 19 Aug 2015 12:06:00 -0500 Subject: [PATCH 31/77] Resize lock fixes --- sway/handlers.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index faade5eb..5e8e05b8 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -388,15 +388,13 @@ 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 (mouse_origin.x > midway_x && !lock_right) { + if (!lock_right) { if (view->width > min_sane_w) { - lock_left = true; changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } } else if (mouse_origin.x < midway_x && !lock_left) { - lock_right = true; changed_floating = true; view->x += dx; view->width -= dx; @@ -404,16 +402,11 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } } else if (dx > 0){ if (mouse_origin.x > midway_x && !lock_right) { - lock_left = true; changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; + } else if (!lock_left) { if (view->width > min_sane_w) { - lock_left = false; - } - } else if (mouse_origin.x < midway_x && !lock_left) { - if (view->width > min_sane_w) { - lock_right = true; changed_floating = true; view->x += dx; view->width -= dx; @@ -423,15 +416,13 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } if (dy < 0) { - if (mouse_origin.y > midway_y && !lock_bottom) { + if (!lock_bottom) { if (view->height > min_sane_h) { - lock_top = true; changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } } else if (mouse_origin.y < midway_y && !lock_top) { - lock_bottom = true; changed_floating = true; view->y += dy; view->height -= dy; @@ -439,13 +430,11 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } } else if (dy > 0) { if (mouse_origin.y > midway_y && !lock_bottom) { - lock_top = true; changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; - } else if (mouse_origin.y < midway_y && !lock_top) { + } else if (!lock_top) { if (view->height > min_sane_h) { - lock_bottom = true; changed_floating = true; view->y += dy; view->height -= dy; @@ -511,6 +500,12 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w if (floating_mod_pressed()) { 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; } //Dont want pointer sent to window while dragging or resizing return (dragging || resizing); From 8f529536e3183cb2ebecee71903edd135316b197 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 10:27:53 -0700 Subject: [PATCH 32/77] pointer uses its own modifiers --- sway/handlers.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 5e8e05b8..71691d7d 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -15,7 +15,6 @@ #include "focus.h" uint32_t keys_pressed[32]; -uint32_t key_modifiers; int keys_pressed_length = 0; @@ -27,10 +26,6 @@ static bool m2_held = false; static bool resizing = false; static bool lock_left, lock_right, lock_top, lock_bottom = false; -static bool floating_mod_pressed(void) { - return key_modifiers & config->floating_mod; -} - static bool pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; // Determine the output that the view is under @@ -295,7 +290,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier return false; } bool cmd_success = false; - key_modifiers = modifiers->mods; struct sway_mode *mode = config->current_mode; // Lowercase if necessary @@ -497,7 +491,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w } } arrange_windows(pointer->parent, -1, -1); - if (floating_mod_pressed()) { + if (modifiers->mods & config->floating_mod) { dragging = m1_held; resizing = m2_held; int midway_x = pointer->x + pointer->width/2; @@ -516,7 +510,6 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w if (button == 272) { m1_held = false; dragging = false; - lock_top = lock_bottom = lock_left = lock_right = false; } if (button == 273) { m2_held = false; From acbcf179051fb9f15b0ceb505089d31344cdb755 Mon Sep 17 00:00:00 2001 From: aouelete Date: Wed, 19 Aug 2015 13:41:58 -0400 Subject: [PATCH 33/77] Fixed config path --- sway/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/config.c b/sway/config.c index ce05bc68..94bc2abb 100644 --- a/sway/config.c +++ b/sway/config.c @@ -63,7 +63,7 @@ void free_config(struct sway_config *config) { static const char *search_paths[] = { "$home/.sway/config", - "$config/.sway/config", + "$config/sway/config", "/etc/sway/config", "$home/.i3/config", "$config/.i3/config", From 7bbb102e2d49e90f70fa8a954febb091a4d8bb81 Mon Sep 17 00:00:00 2001 From: taiyu Date: Wed, 19 Aug 2015 10:45:40 -0700 Subject: [PATCH 34/77] 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 71691d7d..46d1fff5 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 35/77] style --- sway/handlers.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 46d1fff5..f7d5386a 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 36/77] 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 f7d5386a..7b82fd03 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 37/77] 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 aafa51f3..f87ab0e5 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 7b82fd03..75adf7dd 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 38/77] man page update --- sway.5.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway.5.txt b/sway.5.txt index b03fb73e..9c40558b 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 39/77] fixed --- sway/handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/handlers.c b/sway/handlers.c index 75adf7dd..344edd07 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 40/77] 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 7023d37d..f76b2d9a 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 344edd07..24189003 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 a690e3ae..ec60c8e0 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 41/77] 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 24189003..a6dbf94c 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 42/77] 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 0a89f634..0a75643d 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 7125ffc3..eb8391ce 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 43/77] 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 0a75643d..9c6b78e9 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 44/77] 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 a6dbf94c..0bb181cc 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 45/77] 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 9b9a9dc0..44f6e366 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 46/77] 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 dfdc3fe8..e75b183f 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 47/77] 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 0bb181cc..6889fb22 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 48/77] 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 6889fb22..c789662e 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 49/77] 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 c789662e..18f1d13c 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 50/77] 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 f87ab0e5..f3553b03 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 51/77] 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 18f1d13c..d45340ad 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 52/77] 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 d45340ad..63db972e 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 53/77] 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 00000000..a8fa8d5e --- /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 f3553b03..66c05a0c 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 63db972e..c9d7c7ac 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 00000000..76561dbc --- /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 54/77] 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 410ed134..383993fa 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 00000000..782b4b19 --- /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 a8fa8d5e..00000000 --- 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 98fdb531..75e72d2f 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 66c05a0c..c4cf96a2 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 f76b2d9a..1dbac003 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 c9d7c7ac..03a32835 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 00000000..0769c30f --- /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 76561dbc..00000000 --- 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 eb8391ce..2a43671b 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 55/77] small fix --- sway/focus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/focus.c b/sway/focus.c index 1dbac003..48017fdf 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 56/77] 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 48017fdf..a6ffe73f 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 57/77] remove debug message --- sway/layout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/layout.c b/sway/layout.c index 2a43671b..f600cf49 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 58/77] 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 9c6b78e9..dee4028d 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 eb8391ce..e628c5ed 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 59/77] 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 9c40558b..5bccbd12 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 0769c30f..51213b19 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 60/77] Fix compiler warning --- sway/handlers.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index 03a32835..6c103b02 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 61/77] 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 76ddec7e..4f1877e3 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 c4cf96a2..babefd02 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 9c6b78e9..c9163784 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 f600cf49..50a25442 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 44f6e366..49a74e02 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 62/77] unnessesary log --- sway/layout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/layout.c b/sway/layout.c index 50a25442..6a4f8b45 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 63/77] 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 c9163784..59dc9e62 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 6a4f8b45..192f09cf 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 64/77] 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 4f1877e3..bd92058d 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 babefd02..a3f74747 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 59dc9e62..7da33b48 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 a6ffe73f..5008dbbf 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 03a32835..2f062911 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 51213b19..a7f88d4a 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 192f09cf..4a9aa907 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 49a74e02..2d633abb 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 ec60c8e0..0f44d3b0 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 65/77] 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 b7b3266c..cf23d168 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 c47eb683..c23c3509 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 a3f74747..803d9a21 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 94bc2abb..9f65e8a2 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 2db4604c..4a7e13c1 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 66/77] 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 00000000..aab9cf0c --- /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 00000000..ac5246d2 --- /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 4a7e13c1..1af1278d 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 67/77] 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 aab9cf0c..25d2fc61 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 ac5246d2..1a074788 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 68/77] 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 7aea2ded..47a83321 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 1a074788..292d9593 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 2d633abb..e8c1b78f 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 69/77] 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 292d9593..ba01a679 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 70/77] 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 25d2fc61..606c47ba 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 803d9a21..38557b62 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 ba01a679..a6c4eb1a 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 1af1278d..a42fbcb7 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 71/77] 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 a6c4eb1a..69f4a4f3 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 72/77] 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 606c47ba..0b6441f6 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 38557b62..644b8005 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 69f4a4f3..d55469ed 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 e8c1b78f..6e01421b 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 a42fbcb7..f37f086d 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 73/77] fixed formatting --- sway/ipc.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sway/ipc.c b/sway/ipc.c index d55469ed..074f2a78 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 74/77] 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 074f2a78..505c17f8 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 75/77] 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 00000000..6499c81d --- /dev/null +++ b/include/sway.h @@ -0,0 +1,6 @@ +#ifndef _SWAY_SWAY_H +#define _SWAY_SWAY_H + +void sway_terminate(void); + +#endif From 36e07e9ebc55b3fc8a8b8cd76ee743202691ad56 Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 09:52:54 -0700 Subject: [PATCH 76/77] find_parent_by_type --- include/container.h | 11 ++++ sway/commands.c | 5 +- sway/container.c | 138 ++++++++++++++++++++++++++++++-------------- sway/handlers.c | 15 +---- sway/layout.c | 10 +--- sway/workspace.c | 4 +- 6 files changed, 112 insertions(+), 71 deletions(-) diff --git a/include/container.h b/include/container.h index bd92058d..fd621490 100644 --- a/include/container.h +++ b/include/container.h @@ -55,6 +55,7 @@ struct sway_container { struct sway_container *focused; }; +// Container Creation swayc_t *new_output(wlc_handle handle); swayc_t *new_workspace(swayc_t *output, const char *name); @@ -65,13 +66,23 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle); // Creates view as a new floating view which is in the active workspace swayc_t *new_floating_view(wlc_handle handle); +// Container Destroying swayc_t *destroy_output(swayc_t *output); // Destroys workspace if empty and returns parent pointer, else returns NULL swayc_t *destroy_workspace(swayc_t *workspace); +// Destroyes container and all parent container if they are empty, returns +// topmost non-empty parent. returns NULL otherwise swayc_t *destroy_container(swayc_t *container); +// Destroys view and all empty parent containers. return topmost non-empty +// parent swayc_t *destroy_view(swayc_t *view); +// Container Lookup + +swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); +swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); + swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); diff --git a/sway/commands.c b/sway/commands.c index 644b8005..3ac7f4dd 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -390,7 +390,6 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) { return false; } swayc_t *parent = get_focused_container(&root_container); - while (parent->type == C_VIEW) { parent = parent->parent; } @@ -512,9 +511,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { // Resize workspace if going from fullscreen -> notfullscreen // otherwise just resize container if (current) { - while (container->type != C_WORKSPACE) { - container = container->parent; - } + container = swayc_parent_by_type(container, C_WORKSPACE); } // Only resize container when going into fullscreen arrange_windows(container, -1, -1); diff --git a/sway/container.c b/sway/container.c index 4559a5f5..7ccc2e09 100644 --- a/sway/container.c +++ b/sway/container.c @@ -8,6 +8,8 @@ #include "layout.h" #include "log.h" +#define ASSERT_NONNULL(PTR) \ + sway_assert (PTR, "%s: " #PTR "must be non-null", __func__) static swayc_t *new_swayc(enum swayc_types type) { swayc_t *c = calloc(1, sizeof(swayc_t)); @@ -20,37 +22,40 @@ static swayc_t *new_swayc(enum swayc_types type) { return c; } -static void free_swayc(swayc_t *c) { +static void free_swayc(swayc_t *cont) { + if (!ASSERT_NONNULL(cont)) { + return; + } // TODO does not properly handle containers with children, // TODO but functions that call this usually check for that - if (c->children) { - if (c->children->length) { + if (cont->children) { + if (cont->children->length) { int i; - for (i = 0; i < c->children->length; ++i) { - free_swayc(c->children->items[i]); + for (i = 0; i < cont->children->length; ++i) { + free_swayc(cont->children->items[i]); } } - list_free(c->children); + list_free(cont->children); } - if (c->floating) { - if (c->floating->length) { + if (cont->floating) { + if (cont->floating->length) { int i; - for (i = 0; i < c->floating->length; ++i) { - free_swayc(c->floating->items[i]); + for (i = 0; i < cont->floating->length; ++i) { + free_swayc(cont->floating->items[i]); } } - list_free(c->floating); + list_free(cont->floating); } - if (c->parent) { - remove_child(c); + if (cont->parent) { + remove_child(cont); } - if (c->name) { - free(c->name); + if (cont->name) { + free(cont->name); } - free(c); + free(cont); } -/* New containers */ +// New containers static bool workspace_test(swayc_t *view, void *name) { return strcasecmp(view->name, (char *)name) == 0; @@ -103,6 +108,9 @@ swayc_t *new_output(wlc_handle handle) { } swayc_t *new_workspace(swayc_t *output, const char *name) { + if (!ASSERT_NONNULL(output)) { + return NULL; + } sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); swayc_t *workspace = new_swayc(C_WORKSPACE); @@ -120,6 +128,9 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { } swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { + if (!ASSERT_NONNULL(child)) { + return NULL; + } swayc_t *cont = new_swayc(C_CONTAINER); sway_log(L_DEBUG, "creating container %p around %p", cont, child); @@ -162,6 +173,9 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { } swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { + if (!ASSERT_NONNULL(sibling)) { + return NULL; + } const char *title = wlc_view_get_title(handle); swayc_t *view = new_swayc(C_VIEW); sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d", @@ -172,14 +186,14 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->visible = true; view->is_focused = true; // Setup geometry + const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); view->width = 0; view->height = 0; + view->desired_width = geometry->size.w; + view->desired_height = geometry->size.h; view->gaps = config->gaps_inner; - view->desired_width = -1; - view->desired_height = -1; - view->is_floating = false; if (sibling->type == C_WORKSPACE) { @@ -225,9 +239,12 @@ swayc_t *new_floating_view(wlc_handle handle) { return view; } -/* Destroy container */ +// Destroy container swayc_t *destroy_output(swayc_t *output) { + if (!ASSERT_NONNULL(output)) { + return NULL; + } if (output->children->length == 0) { // TODO move workspaces to other outputs } @@ -237,23 +254,21 @@ swayc_t *destroy_output(swayc_t *output) { } swayc_t *destroy_workspace(swayc_t *workspace) { + if (!ASSERT_NONNULL(workspace)) { + return NULL; + } // NOTE: This is called from elsewhere without checking children length // TODO move containers to other workspaces? // for now just dont delete // Do not destroy this if it's the last workspace on this output - swayc_t *output = workspace->parent; - while (output && output->type != C_OUTPUT) { - output = output->parent; - } - if (output) { - if (output->children->length == 1) { - return NULL; - } + swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); + if (output && output->children->length == 1) { + return NULL; } if (workspace->children->length == 0) { - sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); + sway_log(L_DEBUG, "%s: '%s'", __func__, workspace->name); swayc_t *parent = workspace->parent; free_swayc(workspace); return parent; @@ -262,6 +277,9 @@ swayc_t *destroy_workspace(swayc_t *workspace) { } swayc_t *destroy_container(swayc_t *container) { + if (!ASSERT_NONNULL(container)) { + return NULL; + } while (container->children->length == 0 && container->type == C_CONTAINER) { sway_log(L_DEBUG, "Container: Destroying container '%p'", container); swayc_t *parent = container->parent; @@ -272,8 +290,7 @@ swayc_t *destroy_container(swayc_t *container) { } swayc_t *destroy_view(swayc_t *view) { - if (view == NULL) { - sway_log(L_DEBUG, "Warning: NULL passed into destroy_view"); + if (!ASSERT_NONNULL(view)) { return NULL; } sway_log(L_DEBUG, "Destroying view '%p'", view); @@ -287,6 +304,34 @@ swayc_t *destroy_view(swayc_t *view) { return parent; } +// Container lookup + +swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { + if (!ASSERT_NONNULL(container)) { + return NULL; + } + if (!sway_assert(type < C_TYPES && type >= C_ROOT, "%s: invalid type", __func__)) { + return NULL; + } + do { + container = container->parent; + } while(container && container->type != type); + return container; +} + +swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) { + if (!ASSERT_NONNULL(container)) { + return NULL; + } + if (!sway_assert(layout < L_LAYOUTS && layout >= L_NONE, "%s: invalid layout", __func__)) { + return NULL; + } + do { + container = container->parent; + } while (container && container->layout != layout); + return container; +} + swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { if (!container->children) { return NULL; @@ -316,25 +361,27 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da } void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { - if (!container || !container->children || !container->children->length) { - return; - } - int i; - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - f(child, data); - container_map(child, f, data); - } - if (container->type == C_WORKSPACE) { - for (i = 0; i < container->floating->length; ++i) { - swayc_t *child = container->floating->items[i]; + if (container && container->children && container->children->length) { + int i; + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; f(child, data); container_map(child, f, data); } + if (container->type == C_WORKSPACE) { + for (i = 0; i < container->floating->length; ++i) { + swayc_t *child = container->floating->items[i]; + f(child, data); + container_map(child, f, data); + } + } } } void set_view_visibility(swayc_t *view, void *data) { + if (!ASSERT_NONNULL(view)) { + return; + } uint32_t *p = data; if (view->type == C_VIEW) { wlc_view_set_mask(view->handle, *p); @@ -348,6 +395,9 @@ void set_view_visibility(swayc_t *view, void *data) { } void reset_gaps(swayc_t *view, void *data) { + if (!ASSERT_NONNULL(view)) { + return; + } if (view->type == C_OUTPUT) { view->gaps = config->gaps_outer; } diff --git a/sway/handlers.c b/sway/handlers.c index 5993223d..79628fe5 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -20,10 +20,7 @@ static struct wlc_origin mouse_origin; static bool pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; // Determine the output that the view is under - swayc_t *parent = view; - while (parent->type != C_OUTPUT) { - parent = parent->parent; - } + swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); if (origin->x >= view->x && origin->y >= view->y && origin->x < view->x + view->width && origin->y < view->y + view->height && view->visible && parent == root_container.focused) { @@ -191,10 +188,7 @@ static bool handle_view_created(wlc_handle handle) { if (newview) { set_focused_container(newview); - swayc_t *output = newview->parent; - while (output && output->type != C_OUTPUT) { - output = output->parent; - } + swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT); arrange_windows(output, -1, -1); } return true; @@ -262,10 +256,7 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s arrange_windows(c->parent, -1, -1); // Set it as focused window for that workspace if its going fullscreen if (toggle) { - swayc_t *ws = c; - while (ws->type != C_WORKSPACE) { - ws = ws->parent; - } + swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE); // Set ws focus to c set_focused_container_for(ws, c); } diff --git a/sway/layout.c b/sway/layout.c index 78b3dd27..8c011fdb 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -161,10 +161,7 @@ void arrange_windows(swayc_t *container, int width, int height) { } }; if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { - swayc_t *parent = container; - while (parent->type != C_OUTPUT) { - parent = parent->parent; - } + swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT); geometry.origin.x = 0; geometry.origin.y = 0; geometry.size.w = parent->width; @@ -263,10 +260,7 @@ void arrange_windows(swayc_t *container, int width, int height) { } }; if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { - swayc_t *parent = view; - while (parent->type != C_OUTPUT) { - parent = parent->parent; - } + swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); geometry.origin.x = 0; geometry.origin.y = 0; geometry.size.w = parent->width; diff --git a/sway/workspace.c b/sway/workspace.c index 0f44d3b0..d436da8e 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -75,9 +75,7 @@ char *workspace_next_name(void) { swayc_t *workspace_create(const char* name) { swayc_t *parent = get_focused_container(&root_container); - while (parent->type != C_OUTPUT) { - parent = parent->parent; - } + parent = swayc_parent_by_type(parent, C_OUTPUT); return new_workspace(parent, name); } From 754793aad4c0f0b93e30804c70807e9984741ae0 Mon Sep 17 00:00:00 2001 From: minus Date: Thu, 20 Aug 2015 21:08:13 +0200 Subject: [PATCH 77/77] added IPC messages get_workspaces and get_outputs No escaping on container names is done yet, as well as some values are hardcoded because they don't exist yet. --- include/stringop.h | 1 + sway/ipc.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++ sway/stringop.c | 39 ++++++++++++++++++++ 3 files changed, 132 insertions(+) diff --git a/include/stringop.h b/include/stringop.h index a5346829..4300f9ed 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -10,5 +10,6 @@ char *code_strchr(const char *string, char delimiter); char *code_strstr(const char *haystack, const char *needle); int unescape_string(char *string); char *join_args(char **argv, int argc); +char *join_list(list_t *list, char *separator); #endif diff --git a/sway/ipc.c b/sway/ipc.c index 505c17f8..39e580cd 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -11,10 +11,13 @@ #include #include #include +#include #include "ipc.h" #include "log.h" #include "config.h" #include "commands.h" +#include "list.h" +#include "stringop.h" static int ipc_socket = -1; static struct wlc_event_source *ipc_event_source = NULL; @@ -37,6 +40,10 @@ 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 ipc_get_workspaces_callback(swayc_t *container, void *data); +void ipc_get_outputs_callback(swayc_t *container, void *data); + +char *json_list(list_t *items); void ipc_init(void) { ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); @@ -195,6 +202,26 @@ void ipc_client_handle_command(struct ipc_client *client) { ipc_send_reply(client, reply, (uint32_t) length); break; } + case IPC_GET_WORKSPACES: + { + list_t *workspaces = create_list(); + container_map(&root_container, ipc_get_workspaces_callback, workspaces); + char *json = json_list(workspaces); + free_flat_list(workspaces); + ipc_send_reply(client, json, strlen(json)); + free(json); + break; + } + case IPC_GET_OUTPUTS: + { + list_t *outputs = create_list(); + container_map(&root_container, ipc_get_outputs_callback, outputs); + char *json = json_list(outputs); + free_flat_list(outputs); + ipc_send_reply(client, json, strlen(json)); + free(json); + break; + } default: sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); ipc_client_disconnect(client); @@ -227,3 +254,68 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay return true; } + +char *json_list(list_t *items) { + char *json_elements = join_list(items, ","); + size_t len = strlen(json_elements); + char *json = malloc(len + 3); + json[0] = '['; + memcpy(json + 1, json_elements, len); + json[len+1] = ']'; + json[len+2] = '\0'; + free(json_elements); + return json; +} + +void ipc_get_workspaces_callback(swayc_t *container, void *data) { + if (container->type == C_WORKSPACE) { + char *json = malloc(512); // Output should usually be around 180 chars + int num = isdigit(container->name[0]) ? atoi(container->name) : -1; + // TODO: escape the name (quotation marks, unicode) + sprintf(json, + "{" + "\"num\":%d," + "\"name\":\"%s\"," + "\"visible\":%s," + "\"focused\":%s," + "\"rect\":{" + "\"x\":%d," + "\"y\":%d," + "\"width\":%d," + "\"height\":%d" + "}," + "\"output\":\"%s\"," + "\"urgent\":%s" + "}", + num, container->name, container->visible ? "true" : "false", container->is_focused ? "true" : "false", + container->x, container->y, container->width, container->height, + container->parent->name, "false" // TODO: urgent hint + ); + list_add((list_t *)data, json); + } +} + +void ipc_get_outputs_callback(swayc_t *container, void *data) { + if (container->type == C_OUTPUT) { + char *json = malloc(512); // Output should usually be around 130 chars + // TODO: escape the name (quotation marks, unicode) + sprintf(json, + "{" + "\"name\":\"%s\"," + "\"active\":%s," + "\"primary\":%s," + "\"rect\":{" + "\"x\":%d," + "\"y\":%d," + "\"width\":%d," + "\"height\":%d" + "}," + "\"current_workspace\":\"%s\"" + "}", + container->name, "true", "false", // TODO: active, primary + container->x, container->y, container->width, container->height, + container->focused ? container->focused->name : "" + ); + list_add((list_t *)data, json); + } +} diff --git a/sway/stringop.c b/sway/stringop.c index 1dff97bf..c39e2c34 100644 --- a/sway/stringop.c +++ b/sway/stringop.c @@ -4,6 +4,7 @@ #include "string.h" #include "list.h" #include +#include /* Note: This returns 8 characters for trimmed_start per tab character. */ char *strip_whitespace(char *_str, int *trimmed_start) { @@ -197,3 +198,41 @@ char *join_args(char **argv, int argc) { res[len - 1] = '\0'; return res; } + +/* + * Join a list of strings, adding separator in between. Separator can be NULL. + */ +char *join_list(list_t *list, char *separator) { + if (!sway_assert(list != NULL, "list != NULL") || list->length == 0) { + return NULL; + } + + size_t len = 1; // NULL terminator + size_t sep_len = 0; + if (separator != NULL) { + sep_len = strlen(separator); + len += (list->length - 1) * sep_len; + } + + for (int i = 0; i < list->length; i++) { + len += strlen(list->items[i]); + } + + char *res = malloc(len); + + char *p = res + strlen(list->items[0]); + strcpy(res, list->items[0]); + + for (int i = 1; i < list->length; i++) { + if (sep_len) { + memcpy(p, separator, sep_len); + p += sep_len; + } + strcpy(p, list->items[i]); + p += strlen(list->items[i]); + } + + *p = '\0'; + + return res; +}