diff --git a/include/config.h b/include/config.h index c23c3509..c896b423 100644 --- a/include/config.h +++ b/include/config.h @@ -22,6 +22,12 @@ struct sway_mode { list_t *bindings; }; +struct output_config { + char *name; + int width, height; + int x, y; +}; + struct workspace_output { char *output; char *workspace; @@ -32,6 +38,7 @@ struct sway_config { list_t *modes; list_t *cmd_queue; list_t *workspace_outputs; + list_t *output_configs; struct sway_mode *current_mode; uint32_t floating_mod; diff --git a/include/container.h b/include/container.h index 4e21461c..2ced248b 100644 --- a/include/container.h +++ b/include/container.h @@ -81,13 +81,22 @@ swayc_t *destroy_view(swayc_t *view); // Container Lookup +swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); 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 *swayc_by_handle(wlc_handle handle); +swayc_t *swayc_active_output(void); +swayc_t *swayc_active_workspace(void); +swayc_t *swayc_active_workspace_for(swayc_t *view); + +// Container information + +bool swayc_is_fullscreen(swayc_t *view); + +// Mapping functions -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 *); - // Mappings void set_view_visibility(swayc_t *view, void *data); void reset_gaps(swayc_t *view, void *data); diff --git a/include/handlers.h b/include/handlers.h index c25c3309..4c71f953 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -5,6 +5,7 @@ #include extern struct wlc_interface interface; +extern struct wlc_origin mouse_origin; extern uint32_t keys_pressed[32]; // set focus to current pointer location and return focused container diff --git a/include/input_state.h b/include/input_state.h index 000996e0..04fde42d 100644 --- a/include/input_state.h +++ b/include/input_state.h @@ -37,13 +37,19 @@ extern struct pointer_state { struct pointer_tiling { bool resize; swayc_t *init_view; - struct wlc_origin *lock_pos; + struct wlc_origin lock_pos; } tiling; struct pointer_lock { + // Lock movement for certain edges bool left; bool right; bool top; bool bottom; + // Lock movement in certain directions + bool temp_left; + bool temp_right; + bool temp_up; + bool temp_down; } lock; } pointer_state; diff --git a/include/layout.h b/include/layout.h index 55bb6709..f8aebe0a 100644 --- a/include/layout.h +++ b/include/layout.h @@ -8,6 +8,9 @@ extern swayc_t root_container; +extern int min_sane_w; +extern int min_sane_h; + void init_layout(void); void add_child(swayc_t *parent, swayc_t *child); @@ -19,17 +22,10 @@ swayc_t *remove_child(swayc_t *child); void move_container(swayc_t* container,swayc_t* root,enum movement_direction direction); - // Layout void arrange_windows(swayc_t *container, double width, double height); -// Focus -void unfocus_all(swayc_t *container); -void focus_view(swayc_t *view); -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); void recursive_resize(swayc_t *container, double amount, enum wlc_resize_edge edge); diff --git a/include/resize.h b/include/resize.h new file mode 100644 index 00000000..4ace1815 --- /dev/null +++ b/include/resize.h @@ -0,0 +1,8 @@ +#ifndef _SWAY_RESIZE_H +#define _SWAY_RESIZE_H + +bool mouse_resize_tiled(struct wlc_origin prev_pos); +bool resize_floating(struct wlc_origin prev_pos); +bool resize_tiled(int amount, bool use_width); + +#endif diff --git a/include/workspace.h b/include/workspace.h index 042a15d9..d447ac2d 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -5,11 +5,9 @@ #include "list.h" #include "layout.h" -extern swayc_t *active_workspace; - char *workspace_next_name(void); swayc_t *workspace_create(const char*); -swayc_t *workspace_find_by_name(const char*); +swayc_t *workspace_by_name(const char*); void workspace_switch(swayc_t*); void workspace_output_next(); void workspace_next(); diff --git a/sway.5.txt b/sway.5.txt index 5bccbd12..e0052ee1 100644 --- a/sway.5.txt +++ b/sway.5.txt @@ -41,6 +41,11 @@ Commands **floating** toggle:: Toggles the "floating" status of the focused view. +**floating_modifier** :: + When the _modifier_ key is held down, you may use left click to drag floating + windows, and right click to resize them. Unlike i3, this modifier may also be + used to resize and move windows that are tiled. + **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 @@ -55,34 +60,6 @@ Commands 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. -**kill**:: - Closes the currently focused view. - -**layout** :: - Sets the layout mode of the focused container. _mode_ can be one of _splith_, - _splitv_, or _toggle split_. - -**reload**:: - Reloads the sway config file without restarting sway. - -**set** :: - Creates a substitution for _value_ that can be used with $_name_ in other - commands. - -**split** :: - Splits the current container, vertically or horiziontally. The letters "h" and - "v" can be used instead of the full words "vertical" or "horizontal". - -**splith**:: - Equivalent to **split horizontal**. - -**splitv**:: - Equivalent to **split vertical**. - -**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. @@ -93,6 +70,41 @@ Commands 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. +**kill**:: + Closes the currently focused view. + +**layout** :: + Sets the layout mode of the focused container. _mode_ can be one of _splith_, + _splitv_, or _toggle split_. + +**move** :: + Moves the focused container _left_, _right_, _up_, or _down_. + +**output** :: + Configures the specified output. It will use the given resolution and be + arranged at the given position in the layout tree. You may omit either of + these parameters if you only want to set one of them. + +**reload**:: + Reloads the sway config file without restarting sway. + +**resize** :: + Resizes the currently focused container or view by _amount_. _amount_ can be + specified as "n px" or "n ppt" or "n px or n ppt". + +**set** :: + Creates a substitution for _value_ that can be used with $_name_ in other + commands. + +**split** :: + Splits the current container, vertically or horiziontally. + +**splith**:: + Equivalent to **split horizontal**. + +**splitv**:: + Equivalent to **split vertical**. + **workspace** :: Switches to the specified workspace. diff --git a/sway/commands.c b/sway/commands.c index e90a40a3..5de1fb0c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -16,6 +16,7 @@ #include "container.h" #include "handlers.h" #include "sway.h" +#include "resize.h" struct modifier_key { char *name; @@ -208,16 +209,16 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { 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; + add_floating(swayc_active_workspace(),view); + view->x = (swayc_active_workspace()->width - view->width)/2; + view->y = (swayc_active_workspace()->height - view->height)/2; 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); + arrange_windows(swayc_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 @@ -228,7 +229,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { swayc_t *focused = container_under_pointer(); // If focused is null, it's because the currently focused container is a workspace if (focused == NULL) { - focused = active_workspace; + focused = swayc_active_workspace(); } set_focused_container(focused); @@ -244,7 +245,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { } // Refocus on the view once its been put back into the layout view->width = view->height = 0; - arrange_windows(active_workspace, -1, -1); + arrange_windows(swayc_active_workspace(), -1, -1); } set_focused_container(view); } @@ -293,37 +294,38 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) { return move_focus(MOVE_PARENT); } else if (strcasecmp(argv[0], "mode_toggle") == 0) { int i; - swayc_t *focused = get_focused_view(active_workspace); + swayc_t *workspace = swayc_active_workspace(); + swayc_t *focused = get_focused_view(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) { + if (workspace->children->length > 0) { + for (i = 0;i < workspace->floating->length; i++) { + if (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])); + if (workspace->children->length > tiled_toggled_index) { + set_focused_container(get_focused_view(workspace->children->items[tiled_toggled_index])); } else { - set_focused_container(get_focused_view(active_workspace->children->items[0])); + set_focused_container(get_focused_view(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) { + if (workspace->floating->length > 0) { + for (i = 0;i < workspace->children->length; i++) { + if (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]; + if (workspace->floating->length > floating_toggled_index) { + swayc_t *floating = 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]; + swayc_t *floating = workspace->floating->items[workspace->floating->length - 1]; set_focused_container(get_focused_view(floating)); - tiled_toggled_index = active_workspace->floating->length - 1; + tiled_toggled_index = workspace->floating->length - 1; } } } @@ -362,6 +364,66 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) { return true; } +static bool cmd_output(struct sway_config *config, int argc, char **argv) { + if (!checkarg(argc, "output", EXPECTED_AT_LEAST, 1)) { + return false; + } + + struct output_config *output = calloc(1, sizeof(struct output_config)); + output->x = output->y = output->width = output->height = -1; + output->name = strdup(argv[0]); + + // TODO: atoi doesn't handle invalid numbers + + int i; + for (i = 1; i < argc; ++i) { + if (strcasecmp(argv[i], "resolution") == 0 || strcasecmp(argv[i], "res") == 0) { + char *res = argv[++i]; + char *x = strchr(res, 'x'); + int width = -1, height = -1; + if (x != NULL) { + // Format is 1234x4321 + *x = '\0'; + width = atoi(res); + height = atoi(x + 1); + *x = 'x'; + } else { + // Format is 1234 4321 + width = atoi(res); + res = argv[++i]; + height = atoi(res); + } + output->width = width; + output->height = height; + } else if (strcasecmp(argv[i], "position") == 0 || strcasecmp(argv[i], "pos") == 0) { + char *res = argv[++i]; + char *c = strchr(res, ','); + int x = -1, y = -1; + if (c != NULL) { + // Format is 1234,4321 + *c = '\0'; + x = atoi(res); + y = atoi(c + 1); + *c = ','; + } else { + // Format is 1234 4321 + x = atoi(res); + res = argv[++i]; + y = atoi(res); + } + output->x = x; + output->y = y; + } + } + + list_add(config->output_configs, output); + + sway_log(L_DEBUG, "Configured output %s to %d x %d @ %d, %d", + output->name, output->width, output->height, output->x, output->y); + + return true; +} + static bool cmd_gaps(struct sway_config *config, int argc, char **argv) { if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) { return false; @@ -452,147 +514,21 @@ static bool cmd_resize(struct sway_config *config, int argc, char **argv) { errno = 0; return false; } + if (strcmp(argv[0], "shrink") != 0 && strcmp(argv[0], "grow") != 0) { return false; } + if (strcmp(argv[0], "shrink") == 0) { amount *= -1; } - swayc_t *parent = get_focused_view(active_workspace); - swayc_t *focused = parent; - swayc_t *sibling; - if (!parent) { - return true; - } - // Find the closest parent container which has siblings of the proper layout. - // Then apply the resize to all of them. - int i; if (strcmp(argv[1], "width") == 0) { - int lnumber = 0; - int rnumber = 0; - while (parent->parent) { - if (parent->parent->layout == L_HORIZ) { - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->x != focused->x) { - if (sibling->x < parent->x) { - lnumber++; - } else if (sibling->x > parent->x) { - rnumber++; - } - } - } - if (rnumber || lnumber) { - break; - } - } - parent = parent->parent; - } - if (parent == &root_container) { - return true; - } - sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); - //TODO: Ensure rounding is done in such a way that there are NO pixel leaks - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->x != focused->x) { - if (sibling->x < parent->x) { - double pixels = -1 * amount; - pixels /= lnumber; - if (rnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT); - } - } else if (sibling->x > parent->x) { - double pixels = -1 * amount; - pixels /= rnumber; - if (lnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT); - } - } - } else { - if (rnumber != 0 && lnumber != 0) { - double pixels = amount; - pixels /= 2; - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT); - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT); - } else if (rnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT); - } else if (lnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT); - } - } - } - // Recursive resize does not handle positions, let arrange_windows - // take care of that. - arrange_windows(active_workspace, -1, -1); - return true; + return resize_tiled(amount, true); } else if (strcmp(argv[1], "height") == 0) { - int tnumber = 0; - int bnumber = 0; - while (parent->parent) { - if (parent->parent->layout == L_VERT) { - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->y != focused->y) { - if (sibling->y < parent->y) { - bnumber++; - } else if (sibling->y > parent->y) { - tnumber++; - } - } - } - if (bnumber || tnumber) { - break; - } - } - parent = parent->parent; - } - if (parent == &root_container) { - return true; - } - sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); - //TODO: Ensure rounding is done in such a way that there are NO pixel leaks - for (i = 0; i < parent->parent->children->length; i++) { - sibling = parent->parent->children->items[i]; - if (sibling->y != focused->y) { - if (sibling->y < parent->y) { - double pixels = -1 * amount; - pixels /= bnumber; - if (tnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM); - } - } else if (sibling->x > parent->x) { - double pixels = -1 * amount; - pixels /= tnumber; - if (bnumber) { - recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP); - } else { - recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP); - } - } - } else { - if (bnumber != 0 && tnumber != 0) { - double pixels = amount/2; - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP); - recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM); - } else if (tnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP); - } else if (bnumber) { - recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM); - } - } - } - arrange_windows(active_workspace, -1, -1); - return true; + return resize_tiled(amount, false); } - return true; + return false; } static bool cmd_set(struct sway_config *config, int argc, char **argv) { @@ -616,8 +552,12 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay } swayc_t *focused = get_focused_container(&root_container); + // Case of floating window, dont split + if (focused->is_floating) { + return true; + } + /* Case that focus is on an workspace with 0/1 children.change its layout */ if (focused->type == C_WORKSPACE && focused->children->length <= 1) { - /* Case that focus is on an workspace with 0/1 children.change its layout */ sway_log(L_DEBUG, "changing workspace layout"); focused->layout = layout; } else if (focused->type != C_WORKSPACE && focused->parent->children->length == 1) { @@ -632,7 +572,6 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay set_focused_container(focused); arrange_windows(parent, -1, -1); } - return true; } @@ -680,7 +619,7 @@ 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; + bool current = swayc_is_fullscreen(container); wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); // Resize workspace if going from fullscreen -> notfullscreen // otherwise just resize container @@ -721,7 +660,7 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) { return true; } - swayc_t *workspace = workspace_find_by_name(argv[0]); + swayc_t *workspace = workspace_by_name(argv[0]); if (!workspace) { workspace = workspace_create(argv[0]); } @@ -758,6 +697,7 @@ static struct cmd_handler handlers[] = { { "layout", cmd_layout }, { "log_colors", cmd_log_colors }, { "move", cmd_move}, + { "output", cmd_output}, { "reload", cmd_reload }, { "resize", cmd_resize }, { "set", cmd_set }, diff --git a/sway/config.c b/sway/config.c index 1ebd95ff..fcd60de7 100644 --- a/sway/config.c +++ b/sway/config.c @@ -22,6 +22,7 @@ void config_defaults(struct sway_config *config) { config->modes = create_list(); config->cmd_queue = create_list(); config->workspace_outputs = create_list(); + config->output_configs = create_list(); config->current_mode = malloc(sizeof(struct sway_mode)); config->current_mode->name = NULL; config->current_mode->bindings = create_list(); @@ -60,6 +61,7 @@ void free_config(struct sway_config *config) { free(sym->value); } free_flat_list(config->symbols); + free_flat_list(config->output_configs); } static const char *search_paths[] = { diff --git a/sway/container.c b/sway/container.c index 7ccc2e09..127e1ecd 100644 --- a/sway/container.c +++ b/sway/container.c @@ -26,14 +26,11 @@ 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 (cont->children) { - if (cont->children->length) { - int i; - for (i = 0; i < cont->children->length; ++i) { - free_swayc(cont->children->items[i]); - } + // remove children until there are no more, free_swayc calls + // remove_child, which removes child from this container + while (cont->children->length) { + free_swayc(cont->children->items[0]); } list_free(cont->children); } @@ -57,34 +54,65 @@ static void free_swayc(swayc_t *cont) { // New containers -static bool workspace_test(swayc_t *view, void *name) { - return strcasecmp(view->name, (char *)name) == 0; -} - swayc_t *new_output(wlc_handle handle) { - const struct wlc_size* size = wlc_output_get_resolution(handle); + const struct wlc_size *size = wlc_output_get_resolution(handle); const char *name = wlc_output_get_name(handle); sway_log(L_DEBUG, "Added output %lu:%s", handle, name); + struct output_config *oc = NULL; + int i; + for (i = 0; i < config->output_configs->length; ++i) { + oc = config->output_configs->items[i]; + if (strcasecmp(name, oc->name) == 0) { + sway_log(L_DEBUG, "Matched output config for %s", name); + break; + } + oc = NULL; + } + swayc_t *output = new_swayc(C_OUTPUT); - output->width = size->w; - output->height = size->h; + if (oc && oc->width != -1 && oc->height != -1) { + output->width = oc->width; + output->height = oc->height; + struct wlc_size new_size = { .w = oc->width, .h = oc->height }; + wlc_output_set_resolution(handle, &new_size); + } else { + output->width = size->w; + output->height = size->h; + } output->handle = handle; output->name = name ? strdup(name) : NULL; output->gaps = config->gaps_outer + config->gaps_inner / 2; + + // Find position for it + if (oc && oc->x != -1 && oc->y != -1) { + sway_log(L_DEBUG, "Set %s position to %d, %d", name, oc->x, oc->y); + output->x = oc->x; + output->y = oc->y; + } else { + int x = 0; + for (i = 0; i < root_container.children->length; ++i) { + swayc_t *c = root_container.children->items[i]; + if (c->type == C_OUTPUT) { + if (c->width + c->x > x) { + x = c->width + c->x; + } + } + } + output->x = x; + } add_child(&root_container, output); // Create workspace char *ws_name = NULL; if (name) { - int i; for (i = 0; i < config->workspace_outputs->length; ++i) { struct workspace_output *wso = config->workspace_outputs->items[i]; if (strcasecmp(wso->output, name) == 0) { 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)) { + if (workspace_by_name(wso->workspace)) { sway_log(L_DEBUG, "But it's already taken"); break; } @@ -128,7 +156,8 @@ 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)) { + if (!ASSERT_NONNULL(child) + && !sway_assert(!child->is_floating, "cannot create container around floating window")) { return NULL; } swayc_t *cont = new_swayc(C_CONTAINER); @@ -207,6 +236,9 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { } swayc_t *new_floating_view(wlc_handle handle) { + if (swayc_active_workspace() == NULL) { + 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:%x:%s as a floating view", @@ -220,8 +252,8 @@ swayc_t *new_floating_view(wlc_handle handle) { const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); // 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->x = (swayc_active_workspace()->width - geometry->size.w) / 2; + view->y = (swayc_active_workspace()->height- geometry->size.h) / 2; view->width = geometry->size.w; view->height = geometry->size.h; @@ -231,10 +263,10 @@ swayc_t *new_floating_view(wlc_handle handle) { view->is_floating = true; // Case of focused workspace, just create as child of it - list_add(active_workspace->floating, view); - view->parent = active_workspace; - if (active_workspace->focused == NULL) { - set_focused_container_for(active_workspace, view); + list_add(swayc_active_workspace()->floating, view); + view->parent = swayc_active_workspace(); + if (swayc_active_workspace()->focused == NULL) { + set_focused_container_for(swayc_active_workspace(), view); } return view; } @@ -267,7 +299,8 @@ swayc_t *destroy_workspace(swayc_t *workspace) { return NULL; } - if (workspace->children->length == 0) { + // Do not destroy if there are children + if (workspace->children->length == 0 && workspace->floating->length == 0) { sway_log(L_DEBUG, "%s: '%s'", __func__, workspace->name); swayc_t *parent = workspace->parent; free_swayc(workspace); @@ -306,33 +339,8 @@ swayc_t *destroy_view(swayc_t *view) { // 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) { +swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { if (!container->children) { return NULL; } @@ -351,7 +359,7 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da if (test(child, data)) { return child; } else { - swayc_t *res = find_container(child, test, data); + swayc_t *res = swayc_by_test(child, test, data); if (res) { return res; } @@ -360,15 +368,115 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da return NULL; } -void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { - 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); +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; +} + +static swayc_t *_swayc_by_handle_helper(wlc_handle handle, swayc_t *parent) { + if (!parent || !parent->children) { + return NULL; + } + int i, len; + swayc_t **child; + if (parent->type == C_WORKSPACE) { + len = parent->floating->length; + child = (swayc_t **)parent->floating->items; + for (i = 0; i < len; ++i, ++child) { + if ((*child)->handle == handle) { + return *child; + } } - if (container->type == C_WORKSPACE) { + } + + len = parent->children->length; + child = (swayc_t**)parent->children->items; + for (i = 0; i < len; ++i, ++child) { + if ((*child)->handle == handle) { + return *child; + } else { + swayc_t *res; + if ((res = _swayc_by_handle_helper(handle, *child))) { + return res; + } + } + } + return NULL; +} + +swayc_t *swayc_by_handle(wlc_handle handle) { + return _swayc_by_handle_helper(handle, &root_container); +} + +swayc_t *swayc_active_output(void) { + return root_container.focused; +} + +swayc_t *swayc_active_workspace(void) { + return root_container.focused ? root_container.focused->focused : NULL; +} + +swayc_t *swayc_active_workspace_for(swayc_t *cont) { + if (!cont) { + return NULL; + } + switch (cont->type) { + case C_ROOT: + cont = cont->focused; + /* Fallthrough */ + + case C_OUTPUT: + cont = cont->focused; + /* Fallthrough */ + + case C_WORKSPACE: + return cont; + + default: + return swayc_parent_by_type(cont, C_WORKSPACE); + } +} + +// Container information + +bool swayc_is_fullscreen(swayc_t *view) { + return view && view->type == C_VIEW && (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN); +} + +// Mapping + +void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { + if (container) { + int i; + if (container->children) { + 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->floating) { for (i = 0; i < container->floating->length; ++i) { swayc_t *child = container->floating->items[i]; f(child, data); diff --git a/sway/focus.c b/sway/focus.c index 5008dbbf..e369de30 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -21,8 +21,6 @@ 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 @@ -36,10 +34,8 @@ static void update_focus(swayc_t *c) { mask = 2; container_map(c, set_view_visibility, &mask); wlc_output_set_mask(parent->handle, 2); - c->parent->focused = c; destroy_workspace(ws); } - active_workspace = c; break; default: @@ -54,8 +50,8 @@ static void update_focus(swayc_t *c) { } bool move_focus(enum movement_direction direction) { - swayc_t *view = get_swayc_in_direction( - get_focused_container(&root_container), direction); + swayc_t *view = get_focused_container(&root_container); + view = get_swayc_in_direction(view, direction); if (view) { if (direction == MOVE_PARENT) { set_focused_container(view); @@ -68,13 +64,12 @@ bool move_focus(enum movement_direction direction) { } swayc_t *get_focused_container(swayc_t *parent) { - while (parent && !parent->is_focused) { - parent = parent->focused; + if (!parent) { + return swayc_active_workspace(); } - // just incase - if (parent == NULL) { - sway_log(L_DEBUG, "get_focused_container unable to find container"); - return active_workspace; + // get focusde container + while (!parent->is_focused && parent->focused) { + parent = parent->focused; } return parent; } @@ -85,9 +80,13 @@ void set_focused_container(swayc_t *c) { } sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); - // 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; + // Get workspace for c, get that workspaces current focused container. + swayc_t *workspace = swayc_active_workspace_for(c); + swayc_t *focused = get_focused_view(workspace); + // if the workspace we are changing focus to has a fullscreen view return + if (swayc_is_fullscreen(focused) && focused != c) { + return; + } // update container focus from here to root, making necessary changes along // the way @@ -101,13 +100,6 @@ void set_focused_container(swayc_t *c) { p->is_focused = false; } - // if the workspace is the same, and previous focus is fullscreen, dont - // change focus - if (workspace == active_workspace - && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { - return; - } - // get new focused view and set focus to it. p = get_focused_view(c); if (p->type == C_VIEW && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { @@ -137,6 +129,15 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { return; } } + + // Get workspace for c, get that workspaces current focused container. + swayc_t *workspace = swayc_active_workspace_for(c); + swayc_t *focused = get_focused_view(workspace); + // if the workspace we are changing focus to has a fullscreen view return + if (swayc_is_fullscreen(focused) && c != focused) { + return; + } + // Check if we changing a parent container that will see chnage bool effective = true; while (find != &root_container) { @@ -171,7 +172,7 @@ swayc_t *get_focused_view(swayc_t *parent) { parent = parent->focused; } if (parent == NULL) { - return active_workspace; + return swayc_active_workspace_for(parent); } return parent; } diff --git a/sway/handlers.c b/sway/handlers.c index 78f8927d..cb42196f 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -15,8 +15,9 @@ #include "container.h" #include "focus.h" #include "input_state.h" +#include "resize.h" -static struct wlc_origin mouse_origin; +struct wlc_origin mouse_origin; static bool pointer_test(swayc_t *view, void *_origin) { const struct wlc_origin *origin = _origin; @@ -86,7 +87,7 @@ static bool handle_output_created(wlc_handle output) { swayc_t *op = new_output(output); // Switch to workspace if we need to - if (active_workspace == NULL) { + if (swayc_active_workspace() == NULL) { swayc_t *ws = op->children->items[0]; workspace_switch(ws); } @@ -104,9 +105,7 @@ static void handle_output_destroyed(wlc_handle output) { if (i < list->length) { destroy_output(list->items[i]); } - if (list->length == 0) { - active_workspace = NULL; - } else { + if (list->length > 0) { // switch to other outputs active workspace workspace_switch(((swayc_t *)root_container.children->items[0])->focused); } @@ -114,7 +113,7 @@ static void handle_output_destroyed(wlc_handle output) { static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); - swayc_t *c = get_swayc_for_handle(output, &root_container); + swayc_t *c = swayc_by_handle(output); if (!c) return; c->width = to->w; c->height = to->h; @@ -122,7 +121,7 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_ } static void handle_output_focused(wlc_handle output, bool focus) { - swayc_t *c = get_swayc_for_handle(output, &root_container); + swayc_t *c = swayc_by_handle(output); // if for some reason this output doesnt exist, create it. if (!c) { handle_output_created(output); @@ -140,7 +139,7 @@ static bool handle_view_created(wlc_handle handle) { // Get parent container, to add view in if (parent) { - focused = get_swayc_for_handle(parent, &root_container); + focused = swayc_by_handle(parent); } if (!focused || focused->type == C_OUTPUT) { focused = get_focused_container(&root_container); @@ -197,7 +196,7 @@ static bool handle_view_created(wlc_handle handle) { static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %lu", handle); - swayc_t *view = get_swayc_for_handle(handle, &root_container); + swayc_t *view = swayc_by_handle(handle); switch (wlc_view_get_type(handle)) { // regular view created regularly @@ -231,7 +230,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo // 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 - swayc_t *view = get_swayc_for_handle(handle, &root_container); + swayc_t *view = swayc_by_handle(handle); if (view) { view->desired_width = geometry->size.w; view->desired_height = geometry->size.h; @@ -247,7 +246,7 @@ 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 = get_swayc_for_handle(view, &root_container); + swayc_t *c = swayc_by_handle(view); switch (state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen @@ -340,212 +339,77 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct mouse_origin = *origin; bool changed_floating = false; bool changed_tiling = false; - int min_sane_w = 100; - int min_sane_h = 60; - if (!active_workspace) { + if (!swayc_active_workspace()) { return false; } // Do checks to determine if proper keys are being held swayc_t *view = container_under_pointer(); - uint32_t edge = 0; 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; view->x += dx; view->y += dy; + struct wlc_geometry geometry = { + .origin = { + .x = view->x, + .y = view->y + }, + .size = { + .w = view->width, + .h = view->height + } + }; + wlc_view_set_geometry(view->handle, 0, &geometry); changed_floating = true; + } else { + swayc_t *init_view = pointer_state.tiling.init_view; + if (view != init_view && view->type == C_VIEW) { + changed_tiling = true; + int i, j; + for (i = 0; i < view->parent->children->length; i++) { + if (view->parent->children->items[i] == view) { + for (j = 0; j < init_view->parent->children->length; j++) { + if (init_view->parent->children->items[j] == init_view) { + double temp_w = view->width; + double temp_h = view->height; + view->width = init_view->width; + view->height = init_view->height; + init_view->width = temp_w; + init_view->height = temp_h; + + init_view->parent->children->items[j] = view; + view->parent->children->items[i] = init_view; + + swayc_t *temp = view->parent; + view->parent = init_view->parent; + init_view->parent = temp; + + arrange_windows(&root_container, -1, -1); + break; + } + } + break; + } + } + } } } 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; - - // 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 (!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 && !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 && !pointer_state.lock.right) { - changed_floating = true; - view->width += dx; - edge += WLC_RESIZE_EDGE_RIGHT; - } else if (!pointer_state.lock.left) { - if (view->width > min_sane_w) { - changed_floating = true; - view->x += dx; - view->width -= dx; - edge += WLC_RESIZE_EDGE_LEFT; - } - } - } - - if (dy < 0) { - 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 && !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 && !pointer_state.lock.bottom) { - changed_floating = true; - view->height += dy; - edge += WLC_RESIZE_EDGE_BOTTOM; - } else if (!pointer_state.lock.top) { - if (view->height > min_sane_h) { - changed_floating = true; - view->y += dy; - view->height -= dy; - edge += WLC_RESIZE_EDGE_TOP; - } - } - } - } + changed_floating = resize_floating(prev_pos); } else if (pointer_state.tiling.resize && view) { - if (view != pointer_state.tiling.init_view) { - // Quit out of the resize - //pointer_state.tiling.init_view = NULL; - } - if (!view->is_floating && view == pointer_state.tiling.init_view) { - // Handle layout resizes -- Find the biggest parent container then apply resizes to that - // and its bordering siblings - swayc_t *parent = view; - double dx = mouse_origin.x - prev_pos.x; - double dy = mouse_origin.y - prev_pos.y; - if (!pointer_state.lock.bottom) { - while (parent->type != C_WORKSPACE) { - // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better - // way of doing this. - if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) { - parent = parent->parent; - } else { - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { - sway_log(L_DEBUG, "Top is locked, found biggest valid parent at: %p", parent); - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN); - if (sibling) { - sway_log(L_DEBUG, "Found sibling at: %p", sibling); - if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) { - recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM); - recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP); - changed_tiling = true; - } - } - } - } else if (!pointer_state.lock.top) { - while (parent->type != C_WORKSPACE) { - if (fabs(parent->parent->y - view->y) <= 1) { - parent = parent->parent; - } else { - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { - sway_log(L_DEBUG, "Bot is locked, found biggest valid parent at: %p", parent); - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP); - if (sibling) { - sway_log(L_DEBUG, "Found sibling at: %p", sibling); - if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) { - recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP); - recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM); - changed_tiling = true; - } - } - } - } - - parent = view; - if (!pointer_state.lock.right) { - while (parent->type != C_WORKSPACE) { - if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) { - parent = parent->parent; - } else { - sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width); - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { - sway_log(L_DEBUG, "Left is locked, found biggest valid parent at: %p", parent); - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT); - if (sibling) { - sway_log(L_DEBUG, "Found sibling at: %p", sibling); - if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) { - recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT); - recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT); - changed_tiling = true; - } - } - } - } else if (!pointer_state.lock.left) { - while (parent->type != C_WORKSPACE) { - if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) { - parent = parent->parent; - } else { - break; - } - } - if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { - sway_log(L_DEBUG, "Right is locked, found biggest valid parent at: %p", parent); - swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT); - if (sibling) { - sway_log(L_DEBUG, "Found sibling at: %p", sibling); - if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) { - recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT); - recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT); - changed_tiling = true; - } - } - } - } - arrange_windows(active_workspace, -1, -1); - } + changed_tiling = mouse_resize_tiled(prev_pos); } 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 (!swayc_is_fullscreen(focused) && !(pointer_state.l_held || pointer_state.r_held)) { set_focused_container(container_under_pointer()); } } prev_handle = handle; prev_pos = mouse_origin; - if (changed_floating) { - 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; - } - if (changed_tiling) { + if (changed_tiling || changed_floating) { return true; } return false; @@ -556,7 +420,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w 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) { + if (swayc_is_fullscreen(focused)) { return false; } if (state == WLC_BUTTON_STATE_PRESSED) { @@ -596,8 +460,13 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w // Dont want pointer sent to window while dragging or resizing return (pointer_state.floating.drag || pointer_state.floating.resize); } else { - pointer_state.tiling.resize = pointer_state.r_held; - pointer_state.tiling.init_view = pointer; + if (modifiers->mods & config->floating_mod) { + pointer_state.floating.drag = pointer_state.l_held; + pointer_state.tiling.resize = pointer_state.r_held; + pointer_state.tiling.init_view = pointer; + // Dont want pointer sent when resizing + return (pointer_state.tiling.resize); + } } return (pointer && pointer != focused); } else { @@ -605,13 +474,14 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w if (button == M_LEFT_CLICK) { pointer_state.l_held = false; pointer_state.floating.drag = false; + pointer_state.tiling.init_view = NULL; } if (button == M_RIGHT_CLICK) { pointer_state.r_held = false; pointer_state.floating.resize = false; pointer_state.tiling.resize = false; pointer_state.tiling.init_view = NULL; - pointer_state.lock = (struct pointer_lock){false ,false ,false ,false}; + pointer_state.lock = (struct pointer_lock){false ,false ,false ,false, false, false, false, false}; } } return false; diff --git a/sway/input_state.c b/sway/input_state.c index 5119930a..e2f3c754 100644 --- a/sway/input_state.c +++ b/sway/input_state.c @@ -48,7 +48,7 @@ void release_key(keycode key) { } } -struct pointer_state pointer_state = {0, 0, {0, 0}, {0, 0, 0}, {0, 0, 0, 0}}; +struct pointer_state pointer_state; static struct wlc_geometry saved_floating; @@ -69,6 +69,6 @@ void reset_floating(swayc_t *view) { 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}; + pointer_state.floating = (struct pointer_floating){0, 0}; + pointer_state.lock = (struct pointer_lock){0, 0, 0, 0, 0, 0, 0, 0}; } diff --git a/sway/layout.c b/sway/layout.c index 573c6f70..035fea34 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -10,6 +10,8 @@ #include "focus.h" swayc_t root_container; +int min_sane_h = 60; +int min_sane_w = 100; void init_layout(void) { root_container.type = C_ROOT; @@ -35,7 +37,7 @@ void add_child(swayc_t *parent, swayc_t *child) { child->parent = parent; // set focus for this container if (parent->children->length == 1) { - set_focused_container_for(parent, child); + parent->focused = child; } } @@ -46,7 +48,7 @@ void add_floating(swayc_t *ws, swayc_t *child) { child->parent = ws; child->is_floating = true; if (!ws->focused) { - set_focused_container_for(ws, child); + ws->focused = child; } } @@ -71,7 +73,7 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { new_child->parent = child->parent; if (child->parent->focused == child) { - set_focused_container_for(child->parent, new_child); + child->parent->focused = new_child; } child->parent = NULL; return parent; @@ -100,7 +102,7 @@ swayc_t *remove_child(swayc_t *child) { // 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]); + parent->focused = parent->children->items[i?i-1:0]; } else { parent->focused = NULL; } @@ -167,21 +169,14 @@ void arrange_windows(swayc_t *container, double width, double height) { for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; sway_log(L_DEBUG, "Arranging output at %d", x); - child->x = x; - child->y = y; arrange_windows(child, -1, -1); - // Removed for now because wlc works with relative positions - // Addition can be reconsidered once wlc positions are changed - // x += child->width; + x += child->width; } return; case C_OUTPUT: container->width = width; container->height = height; - // These lines make x/y negative and result in stuff glitching out - // Their addition can be reconsidered once wlc positions are changed - // x -= container->x; - // y -= container->y; + x = 0, y = 0; for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; child->x = x + container->gaps; @@ -204,7 +199,7 @@ void arrange_windows(swayc_t *container, double width, double height) { .h = height - container->gaps } }; - if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { + if (swayc_is_fullscreen(container)) { swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT); geometry.origin.x = 0; geometry.origin.y = 0; @@ -303,7 +298,7 @@ void arrange_windows(swayc_t *container, double width, double height) { .h = view->height } }; - if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { + if (swayc_is_fullscreen(view)) { swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); geometry.origin.x = 0; geometry.origin.y = 0; @@ -318,7 +313,7 @@ void arrange_windows(swayc_t *container, double width, double height) { // have higher indexes // This is conditional on there not being a fullscreen view in the workspace if (!container->focused - || !(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) { + || !swayc_is_fullscreen(container->focused)) { wlc_view_bring_to_front(view->handle); } } @@ -328,35 +323,6 @@ void arrange_windows(swayc_t *container, double width, double height) { layout_log(&root_container, 0); } -swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { - if (parent->children == NULL) { - return NULL; - } - - // Search for floating workspaces - int i; - if (parent->type == C_WORKSPACE) { - for (i = 0; i < parent->floating->length; ++i) { - swayc_t *child = parent->floating->items[i]; - if (child->handle == handle) { - return child; - } - } - } - - for (i = 0; i < parent->children->length; ++i) { - swayc_t *child = parent->children->items[i]; - if (child->handle == handle) { - return child; - } else { - swayc_t *res; - if ((res = get_swayc_for_handle(handle, child))) { - return res; - } - } - } - return NULL; -} swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) { swayc_t *parent = container->parent; @@ -372,19 +338,75 @@ swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) // 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) { + int i; + if (parent->type == C_ROOT) { + // Find the next output + int target = -1, max_x = 0, max_y = 0, self = -1; + sway_log(L_DEBUG, "Moving between outputs"); + + for (i = 0; i < parent->children->length; ++i) { + swayc_t *next = parent->children->items[i]; + if (next == container) { + self = i; + sway_log(L_DEBUG, "self is %p %d", next, self); + continue; + } + if (next->type == C_OUTPUT) { + sway_log(L_DEBUG, "Testing with %p %d (dir %d)", next, i, dir); + // Check if it's more extreme + if (dir == MOVE_RIGHT) { + if (container->x + container->width <= next->x) { + if (target == -1 || next->x < max_x) { + target = i; + max_x = next->x; + } + } + } else if (dir == MOVE_LEFT) { + if (container->x >= next->x + next->width) { + if (target == -1 || max_x < next->x) { + target = i; + max_x = next->x; + } + } + } else if (dir == MOVE_DOWN) { + if (container->y + container->height <= next->y) { + if (target == -1 || next->y < max_y) { + target = i; + max_y = next->y; + } + } + } else if (dir == MOVE_UP) { + if (container->y >= next->y + next->height) { + if (target == -1 || max_y < next->y) { + target = i; + max_y = next->y; + } + } + } + } + } + + if (target == -1) { + can_move = false; + } else { can_move = true; - diff = dir == MOVE_LEFT ? -1 : 1; + diff = target - self; } } else { - if (parent->layout == L_VERT) { - can_move = true; - diff = dir == MOVE_UP ? -1 : 1; + if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { + if (parent->layout == L_HORIZ) { + 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) { diff --git a/sway/log.c b/sway/log.c index a1e89bad..4a047eef 100644 --- a/sway/log.c +++ b/sway/log.c @@ -119,8 +119,9 @@ 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 == get_focused_view(&root_container) ? 'K': + c == get_focused_container(&root_container) ? 'F' : // Focused + c == swayc_active_workspace() ? 'W' : // active workspace c == &root_container ? 'R' : // root 'X');// not any others fprintf(stderr,"(%p)",c); diff --git a/sway/main.c b/sway/main.c index f37f086d..ffbcdbdf 100644 --- a/sway/main.c +++ b/sway/main.c @@ -38,12 +38,6 @@ int main(int argc, char **argv) { 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; @@ -85,9 +79,6 @@ int main(int argc, char **argv) { if (debug) { init_log(L_DEBUG); - wlc_set_log_file(stderr); - fclose(devnull); - devnull = NULL; } else if (verbose || validate) { init_log(L_INFO); } else { @@ -114,10 +105,6 @@ int main(int argc, char **argv) { wlc_run(); } - if (devnull) { - fclose(devnull); - } - ipc_terminate(); return 0; diff --git a/sway/resize.c b/sway/resize.c new file mode 100644 index 00000000..a08ef4a1 --- /dev/null +++ b/sway/resize.c @@ -0,0 +1,491 @@ +#include +#include +#include "layout.h" +#include "focus.h" +#include "log.h" +#include "input_state.h" +#include "handlers.h" + +bool mouse_resize_tiled(struct wlc_origin prev_pos) { + swayc_t *view = container_under_pointer(); + bool valid = true; + bool changed_tiling = false; + double dx = mouse_origin.x - prev_pos.x; + double dy = mouse_origin.y - prev_pos.y; + if (view != pointer_state.tiling.init_view) { + changed_tiling = true; + valid = false; + if (view->type != C_WORKSPACE) { + if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_LEFT) == view) { + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; + pointer_state.lock.temp_left = true; + } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_RIGHT) == view) { + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; + pointer_state.lock.temp_right = true; + } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_UP) == view) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.lock.temp_up = true; + } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_DOWN) == view) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.lock.temp_down = true; + } + } + } + + if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) { + changed_tiling = true; + valid = false; + } else if (dx > 0 && pointer_state.lock.temp_left) { + pointer_state.lock.temp_left = false; + pointer_state.tiling.lock_pos.x = 0; + } + + if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) { + changed_tiling = true; + valid = false; + } else if (dx < 0 && pointer_state.lock.temp_right) { + pointer_state.lock.temp_right = false; + pointer_state.tiling.lock_pos.x = 0; + } + + if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) { + changed_tiling = true; + valid = false; + } else if (dy > 0 && pointer_state.lock.temp_up) { + pointer_state.lock.temp_up = false; + pointer_state.tiling.lock_pos.y = 0; + } + + if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) { + changed_tiling = true; + valid = false; + } else if (dy < 0 && pointer_state.lock.temp_down) { + pointer_state.lock.temp_down = false; + pointer_state.tiling.lock_pos.y = 0; + } + + if (!view->is_floating && valid) { + // Handle layout resizes -- Find the biggest parent container then apply resizes to that + // and its bordering siblings + swayc_t *parent = view; + if (!pointer_state.lock.bottom) { + while (parent->type != C_WORKSPACE) { + // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better + // way of doing this. + if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) { + parent = parent->parent; + } else { + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN); + if (sibling) { + if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) { + recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM); + recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP); + changed_tiling = true; + } else { + if (parent->height < min_sane_h) { + //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.lock.temp_up = true; + } else if (sibling->height < min_sane_h) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.lock.temp_down = true; + } + } + } + } + } else if (!pointer_state.lock.top) { + while (parent->type != C_WORKSPACE) { + if (fabs(parent->parent->y - view->y) <= 1) { + parent = parent->parent; + } else { + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP); + if (sibling) { + if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) { + recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP); + recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM); + changed_tiling = true; + } else { + if (parent->height < min_sane_h) { + //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20; + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.lock.temp_down = true; + } else if (sibling->height < min_sane_h) { + pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20; + pointer_state.lock.temp_up = true; + } + } + } + } + } + + parent = view; + if (!pointer_state.lock.right) { + while (parent->type != C_WORKSPACE) { + if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) { + parent = parent->parent; + } else { + sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width); + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT); + if (sibling) { + if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) { + recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT); + recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT); + changed_tiling = true; + } else { + if (parent->width < min_sane_w) { + pointer_state.lock.temp_left = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; + } else if (sibling->width < min_sane_w) { + pointer_state.lock.temp_right = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20; + } + } + } + } + } else if (!pointer_state.lock.left) { + while (parent->type != C_WORKSPACE) { + if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) { + parent = parent->parent; + } else { + break; + } + } + if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { + swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT); + if (sibling) { + if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) { + recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT); + recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT); + changed_tiling = true; + } else { + if (parent->width < min_sane_w) { + pointer_state.lock.temp_right = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; + } else if (sibling->width < min_sane_w) { + pointer_state.lock.temp_left = true; + pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20; + } + } + } + } + } + arrange_windows(swayc_active_workspace(), -1, -1); + } + return changed_tiling; +} + +bool resize_floating(struct wlc_origin prev_pos) { + bool changed = false; + swayc_t *view = container_under_pointer(); + uint32_t edge = 0; + 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 (!pointer_state.lock.right) { + if (view->width > min_sane_w) { + changed = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } + } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) { + changed = true; + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; + } + } else if (dx > 0) { + if (mouse_origin.x > midway_x && !pointer_state.lock.right) { + changed = true; + view->width += dx; + edge += WLC_RESIZE_EDGE_RIGHT; + } else if (!pointer_state.lock.left) { + if (view->width > min_sane_w) { + changed = true; + view->x += dx; + view->width -= dx; + edge += WLC_RESIZE_EDGE_LEFT; + } + } + } + + if (dy < 0) { + if (!pointer_state.lock.bottom) { + if (view->height > min_sane_h) { + changed = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } + } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) { + changed = true; + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; + } + } else if (dy > 0) { + if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) { + changed = true; + view->height += dy; + edge += WLC_RESIZE_EDGE_BOTTOM; + } else if (!pointer_state.lock.top) { + if (view->height > min_sane_h) { + changed = true; + view->y += dy; + view->height -= dy; + edge += WLC_RESIZE_EDGE_TOP; + } + } + } + if (changed) { + 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 changed; +} + +bool resize_tiled(int amount, bool use_width) { + swayc_t *parent = get_focused_view(swayc_active_workspace()); + swayc_t *focused = parent; + swayc_t *sibling; + if (!parent) { + return true; + } + // Find the closest parent container which has siblings of the proper layout. + // Then apply the resize to all of them. + int i; + if (use_width) { + int lnumber = 0; + int rnumber = 0; + while (parent->parent) { + if (parent->parent->layout == L_HORIZ) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + lnumber++; + } else if (sibling->x > parent->x) { + rnumber++; + } + } + } + if (rnumber || lnumber) { + break; + } + } + parent = parent->parent; + } + if (parent == &root_container) { + return true; + } + sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); + //TODO: Ensure rounding is done in such a way that there are NO pixel leaks + bool valid = true; + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + double pixels = -1 * amount; + pixels /= lnumber; + if (rnumber) { + if ((sibling->width + pixels/2) < min_sane_w) { + valid = false; + break; + } + } else { + if ((sibling->width + pixels) < min_sane_w) { + valid = false; + break; + } + } + } else if (sibling->x > parent->x) { + double pixels = -1 * amount; + pixels /= rnumber; + if (lnumber) { + if ((sibling->width + pixels/2) < min_sane_w) { + valid = false; + break; + } + } else { + if ((sibling->width + pixels) < min_sane_w) { + valid = false; + break; + } + } + } + } else { + double pixels = amount; + if (parent->width + pixels < min_sane_w) { + valid = false; + break; + } + } + } + if (valid) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->x != focused->x) { + if (sibling->x < parent->x) { + double pixels = -1 * amount; + pixels /= lnumber; + if (rnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT); + } + } else if (sibling->x > parent->x) { + double pixels = -1 * amount; + pixels /= rnumber; + if (lnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT); + } + } + } else { + if (rnumber != 0 && lnumber != 0) { + double pixels = amount; + pixels /= 2; + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT); + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT); + } else if (rnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT); + } else if (lnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT); + } + } + } + // Recursive resize does not handle positions, let arrange_windows + // take care of that. + arrange_windows(swayc_active_workspace(), -1, -1); + } + return true; + } else { + int tnumber = 0; + int bnumber = 0; + while (parent->parent) { + if (parent->parent->layout == L_VERT) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + bnumber++; + } else if (sibling->y > parent->y) { + tnumber++; + } + } + } + if (bnumber || tnumber) { + break; + } + } + parent = parent->parent; + } + if (parent == &root_container) { + return true; + } + sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); + //TODO: Ensure rounding is done in such a way that there are NO pixel leaks + bool valid = true; + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + double pixels = -1 * amount; + pixels /= bnumber; + if (tnumber) { + if ((sibling->height + pixels/2) < min_sane_h) { + valid = false; + break; + } + } else { + if ((sibling->height + pixels) < min_sane_h) { + valid = false; + break; + } + } + } else if (sibling->y > parent->y) { + double pixels = -1 * amount; + pixels /= tnumber; + if (bnumber) { + if ((sibling->height + pixels/2) < min_sane_h) { + valid = false; + break; + } + } else { + if ((sibling->height + pixels) < min_sane_h) { + valid = false; + break; + } + } + } + } else { + double pixels = amount; + if (parent->height + pixels < min_sane_h) { + valid = false; + break; + } + } + } + if (valid) { + for (i = 0; i < parent->parent->children->length; i++) { + sibling = parent->parent->children->items[i]; + if (sibling->y != focused->y) { + if (sibling->y < parent->y) { + double pixels = -1 * amount; + pixels /= bnumber; + if (tnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM); + } + } else if (sibling->x > parent->x) { + double pixels = -1 * amount; + pixels /= tnumber; + if (bnumber) { + recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP); + } else { + recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP); + } + } + } else { + if (bnumber != 0 && tnumber != 0) { + double pixels = amount/2; + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP); + recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM); + } else if (tnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP); + } else if (bnumber) { + recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM); + } + } + } + arrange_windows(swayc_active_workspace(), -1, -1); + } + return true; + } + return true; +} diff --git a/sway/workspace.c b/sway/workspace.c index d436da8e..80b67128 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "workspace.h" #include "layout.h" #include "list.h" @@ -11,8 +12,6 @@ #include "stringop.h" #include "focus.h" -swayc_t *active_workspace = NULL; - char *workspace_next_name(void) { sway_log(L_DEBUG, "Workspace: Generating new name"); int i; @@ -48,7 +47,7 @@ char *workspace_next_name(void) { } // Make sure that the workspace doesn't already exist - if (workspace_find_by_name(target)) { + if (workspace_by_name(target)) { list_free(args); continue; } @@ -79,22 +78,22 @@ swayc_t *workspace_create(const char* name) { return new_workspace(parent, name); } -bool workspace_by_name(swayc_t *view, void *data) { +static bool _workspace_by_name(swayc_t *view, void *data) { return (view->type == C_WORKSPACE) && (strcasecmp(view->name, (char *) data) == 0); } -swayc_t *workspace_find_by_name(const char* name) { - return find_container(&root_container, workspace_by_name, (void *) name); +swayc_t *workspace_by_name(const char* name) { + return swayc_by_test(&root_container, _workspace_by_name, (void *) name); } void workspace_output_next() { // Get the index of the workspace in the current output, and change the view to index+1 workspace. // if we're currently focused on the last workspace in the output, switch to the first - swayc_t *current_output = active_workspace->parent; + swayc_t *current_output = swayc_active_workspace()->parent; int i; for (i = 0; i < current_output->children->length - 1; i++) { - if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) { + if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) { workspace_switch(current_output->children->items[i + 1]); return; } @@ -106,10 +105,10 @@ void workspace_next() { // Get the index of the workspace in the current output, and change the view to index+1 workspace. // if we're currently focused on the last workspace in the output, change focus to there // and call workspace_output_next(), as long as another output actually exists - swayc_t *current_output = active_workspace->parent; + swayc_t *current_output = swayc_active_workspace()->parent; int i; for (i = 0; i < current_output->children->length - 1; i++) { - if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) { + if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) { workspace_switch(current_output->children->items[i + 1]); return; } @@ -134,10 +133,10 @@ void workspace_next() { void workspace_output_prev() { // Get the index of the workspace in the current output, and change the view to index+1 workspace // if we're currently focused on the first workspace in the output, do nothing and return false - swayc_t *current_output = active_workspace->parent; + swayc_t *current_output = swayc_active_workspace()->parent; int i; for (i = 1; i < current_output->children->length; i++) { - if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) { + if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) { workspace_switch(current_output->children->items[i - 1]); return; } @@ -150,10 +149,10 @@ void workspace_prev() { // if we're currently focused on the last workspace in the output, change focus to there // and call workspace_output_next(), as long as another output actually exists - swayc_t *current_output = active_workspace->parent; + swayc_t *current_output = swayc_active_workspace()->parent; int i; for (i = 1; i < current_output->children->length; i++) { - if (strcmp((((swayc_t *)current_output->children->items[i])->name), active_workspace->name) == 0) { + if (strcmp((((swayc_t *)current_output->children->items[i])->name), swayc_active_workspace()->name) == 0) { workspace_switch(current_output->children->items[i - 1]); return; }