static swayc_t *fetch_view_from_scratchpad() { if (sp_index >= scratchpad->length) { sp_index = 0; } swayc_t *view = scratchpad->items[sp_index++]; if (wlc_view_get_output(view->handle) != swayc_active_output()->handle) { wlc_view_set_output(view->handle, swayc_active_output()->handle); } if (!view->is_floating) { view->width = swayc_active_workspace()->width/2; view->height = swayc_active_workspace()->height/2; view->x = (swayc_active_workspace()->width - view->width)/2; view->y = (swayc_active_workspace()->height - view->height)/2; } if (swayc_active_workspace()->width < view->x + 20 || view->x + view->width < 20) { view->x = (swayc_active_workspace()->width - view->width)/2; } if (swayc_active_workspace()->height < view->y + 20 || view->y + view->height < 20) { view->y = (swayc_active_workspace()->height - view->height)/2; } add_floating(swayc_active_workspace(), view); wlc_view_set_mask(view->handle, VISIBLE); view->visible = true; arrange_windows(swayc_active_workspace(), -1, -1); set_focused_container(view); return view; }
struct cmd_results *cmd_scratchpad(int argc, char **argv) { struct cmd_results *error = NULL; if (config->reading) return cmd_results_new(CMD_FAILURE, "scratchpad", "Can't be used in config file."); if (!config->active) return cmd_results_new(CMD_FAILURE, "scratchpad", "Can only be used when sway is running."); if ((error = checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1))) { return error; } if (strcasecmp(argv[0], "show") == 0 && scratchpad->length > 0) { if (!sp_view) { sp_view = fetch_view_from_scratchpad(); } else { if (swayc_active_workspace() != sp_view->parent) { hide_view_in_scratchpad(sp_view); if (sp_index == 0) { sp_index = scratchpad->length; } sp_index--; sp_view = fetch_view_from_scratchpad(); } else { hide_view_in_scratchpad(sp_view); sp_view = NULL; } } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } return cmd_results_new(CMD_FAILURE, "scratchpad", "Expected 'scratchpad show' when scratchpad is not empty."); }
static bool resize(int dimension, bool use_width, enum resize_dim_types dim_type) { swayc_t *focused = get_focused_view_include_floating(swayc_active_workspace()); // translate "10 ppt" (10%) to appropriate # of pixels in case we need it float ppt_dim = (float)dimension / 100; if (use_width) { ppt_dim = focused->width * ppt_dim; } else { ppt_dim = focused->height * ppt_dim; } if (focused) { if (focused->is_floating) { // floating view resize dimensions should default to px, so only // use ppt if specified if (dim_type == RESIZE_DIM_PPT) { dimension = (int)ppt_dim; } return resize_floating(dimension, use_width); } else { // tiled view resize dimensions should default to ppt, so only use // px if specified if (dim_type != RESIZE_DIM_PX) { dimension = (int)ppt_dim; } return resize_tiled(dimension, use_width); } } return false; }
/* XXX:DEBUG:XXX */ static void container_log(const swayc_t *c) { fprintf(stderr, "focus:%c|", 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); 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:%.f|h:%.f|", c->width, c->height); fprintf(stderr, "x:%.f|y:%.f|", c->x, c->y); fprintf(stderr, "g:%d|",c->gaps); fprintf(stderr, "vis:%c|", c->visible?'t':'f'); fprintf(stderr, "name:%.16s|", c->name); fprintf(stderr, "children:%d\n",c->children?c->children->length:0); }
static bool set_size_floating(int new_dimension, bool use_width) { swayc_t *view = get_focused_float(swayc_active_workspace()); if (view) { if (use_width) { int current_width = view->width; view->desired_width = new_dimension; floating_view_sane_size(view); int new_x = view->x + (int)(((view->desired_width - current_width) / 2) * -1); view->width = view->desired_width; view->x = new_x; update_geometry(view); } else { int current_height = view->height; view->desired_height = new_dimension; floating_view_sane_size(view); int new_y = view->y + (int)(((view->desired_height - current_height) / 2) * -1); view->height = view->desired_height; view->y = new_y; update_geometry(view); } return true; } return false; }
swayc_t *get_focused_float(swayc_t *ws) { if(!sway_assert(ws->type == C_WORKSPACE, "must be of workspace type")) { ws = swayc_active_workspace(); } if (ws->floating->length) { return ws->floating->items[ws->floating->length - 1]; } return NULL; }
swayc_t *get_focused_container(swayc_t *parent) { if (!parent) { return swayc_active_workspace(); } // get focusde container while (!parent->is_focused && parent->focused) { parent = parent->focused; } return parent; }
static bool set_size_tiled(int amount, bool use_width) { int desired; swayc_t *focused = get_focused_view(swayc_active_workspace()); if (use_width) { desired = amount - focused->width; } else { desired = amount - focused->height; } return resize_tiled(desired, use_width); }
static bool set_size(int dimension, bool use_width) { swayc_t *focused = get_focused_view_include_floating(swayc_active_workspace()); if (focused) { if (focused->is_floating) { return set_size_floating(dimension, use_width); } else { return set_size_tiled(dimension, use_width); } } return false; }
static bool resize_floating(int amount, bool use_width) { swayc_t *view = get_focused_float(swayc_active_workspace()); if (view) { if (use_width) { return set_size_floating(view->width + amount, true); } else { return set_size_floating(view->height + amount, false); } } return false; }
bool workspace_switch(swayc_t *workspace) { if (!workspace) { return false; } swayc_t *active_ws = swayc_active_workspace(); if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { swayc_t *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); } if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) && active_ws != workspace)) { free(prev_workspace_name); prev_workspace_name = malloc(strlen(active_ws->name)+1); strcpy(prev_workspace_name, active_ws->name); } // move sticky containers if (swayc_parent_by_type(active_ws, C_OUTPUT) == swayc_parent_by_type(workspace, C_OUTPUT)) { // don't change list while traversing it, use intermediate list instead list_t *stickies = create_list(); for (int i = 0; i < active_ws->floating->length; i++) { swayc_t *cont = active_ws->floating->items[i]; if (cont->sticky) { list_add(stickies, cont); } } for (int i = 0; i < stickies->length; i++) { swayc_t *cont = stickies->items[i]; sway_log(L_DEBUG, "Moving sticky container %p to %p:%s", cont, workspace, workspace->name); swayc_t *parent = remove_child(cont); add_floating(workspace, cont); // Destroy old container if we need to destroy_container(parent); } list_free(stickies); } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); if (!set_focused_container(get_focused_view(workspace))) { return false; } swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); arrange_backgrounds(); arrange_windows(output, -1, -1); return true; }
static bool handle_output_created(wlc_handle output) { swayc_t *op = new_output(output); // Visibility mask to be able to make view invisible wlc_output_set_mask(output, VISIBLE); if (!op) { return false; } // Switch to workspace if we need to if (swayc_active_workspace() == NULL) { swayc_t *ws = op->children->items[0]; workspace_switch(ws); } return true; }
void workspace_switch(swayc_t *workspace) { if (!workspace) { return; } if (strcmp(prev_workspace_name, swayc_active_workspace()->name) != 0 && swayc_active_workspace() != workspace) { prev_workspace_name = malloc(strlen(swayc_active_workspace()->name) + 1); strcpy(prev_workspace_name, swayc_active_workspace()->name); } else if (config->auto_back_and_forth && swayc_active_workspace() == workspace && strlen(prev_workspace_name) != 0) { workspace = workspace_by_name(prev_workspace_name) ? workspace_by_name(prev_workspace_name) : workspace_create(prev_workspace_name); prev_workspace_name = malloc(strlen(swayc_active_workspace()->name) + 1); strcpy(prev_workspace_name, swayc_active_workspace()->name); } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); set_focused_container(get_focused_view(workspace)); arrange_windows(workspace, -1, -1); }
swayc_t *workspace_by_name(const char* name) { if (strcmp(name, "prev") == 0) { return workspace_prev(); } else if (strcmp(name, "prev_on_output") == 0) { return workspace_output_prev(); } else if (strcmp(name, "next") == 0) { return workspace_next(); } else if (strcmp(name, "next_on_output") == 0) { return workspace_output_next(); } else if (strcmp(name, "current") == 0) { return swayc_active_workspace(); } else { return swayc_by_test(&root_container, _workspace_by_name, (void *) name); } }
void workspace_switch(swayc_t *workspace) { if (!workspace) { return; } swayc_t *active_ws = swayc_active_workspace(); if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { swayc_t *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); } if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) && active_ws != workspace)) { free(prev_workspace_name); prev_workspace_name = malloc(strlen(active_ws->name)+1); strcpy(prev_workspace_name, active_ws->name); } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); set_focused_container(get_focused_view(workspace)); arrange_windows(workspace, -1, -1); }
static bool handle_output_created(wlc_handle output) { swayc_t *op = new_output(output); // Visibility mask to be able to make view invisible wlc_output_set_mask(output, VISIBLE); if (!op) { return false; } // Switch to workspace if we need to if (swayc_active_workspace() == NULL) { swayc_t *ws = op->children->items[0]; workspace_switch(ws); } // Fixes issues with backgrounds and wlc wlc_handle prev = wlc_get_focused_output(); wlc_output_focus(output); wlc_output_focus(prev); return true; }
/* XXX:DEBUG:XXX */ static void container_log(const swayc_t *c, int depth) { fprintf(stderr, "focus:%c", 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 for (int i = 6; i > depth; i--) { fprintf(stderr, " "); } fprintf(stderr,"|(%p)",c); fprintf(stderr,"(p:%-8p)",c->parent); fprintf(stderr,"(f:%-8p)",c->focused); fprintf(stderr,"(h:%2" PRIuPTR ")",c->handle); fprintf(stderr,"Type:%-4s|", c->type == C_ROOT ? "root" : c->type == C_OUTPUT ? "op" : c->type == C_WORKSPACE ? "ws" : c->type == C_CONTAINER ? "cont" : c->type == C_VIEW ? "view" : "?"); fprintf(stderr,"layout:%-5s|", c->layout == L_NONE ? "-" : c->layout == L_HORIZ ? "Horiz": c->layout == L_VERT ? "Vert": c->layout == L_STACKED ? "Stack": c->layout == L_TABBED ? "Tab": c->layout == L_FLOATING ? "Float": c->layout == L_AUTO_LEFT ? "A_lft": c->layout == L_AUTO_RIGHT ? "A_rgt": c->layout == L_AUTO_TOP ? "A_top": c->layout == L_AUTO_BOTTOM ? "A_bot": "Unknown"); fprintf(stderr, "w:%4.f|h:%4.f|", c->width, c->height); fprintf(stderr, "x:%4.f|y:%4.f|", c->x, c->y); fprintf(stderr, "g:%3d|",c->gaps); fprintf(stderr, "vis:%c|", c->visible?'t':'f'); fprintf(stderr, "children:%2d|",c->children?c->children->length:0); fprintf(stderr, "name:%.16s\n", c->name); }
swayc_t *workspace_next() { return workspace_prev_next_impl(swayc_active_workspace(), true); }
static 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 && parent->parent->children) { 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->parent == NULL || parent->parent->children == NULL) { 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; }
bool set_focused_container(swayc_t *c) { if (locked_container_focus || !c || !c->parent) { return false; } swayc_t *active_ws = swayc_active_workspace(); int active_ws_child_count = 0; if (active_ws) { active_ws_child_count = active_ws->children->length + active_ws->floating->length; } swayc_log(L_DEBUG, c, "Setting focus to %p:%" PRIuPTR, c, c->handle); // 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 (swayc_is_fullscreen(focused) && focused != c) { // if switching to a workspace with a fullscreen view, // focus on the fullscreen view c = focused; } if (c->type == C_VIEW) { // dispatch a window event ipc_event_window(c, "focus"); } // 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; p->is_focused = false; } // 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)) { // unactivate previous focus if (focused->type == C_VIEW) { wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); update_view_border(focused); } // 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 if (!locked_view_focus) { wlc_view_focus(p->handle); if (p->parent->layout != L_TABBED && p->parent->layout != L_STACKED) { update_view_border(p); } } } // rearrange if parent container is tabbed/stacked swayc_t *parent = swayc_tabbed_stacked_ancestor(p); if (parent != NULL) { arrange_backgrounds(); arrange_windows(parent, -1, -1); } } else if (p->type == C_WORKSPACE) { // remove previous focus if view_focus is unlocked if (!locked_view_focus) { wlc_view_focus(0); } } if (active_ws != workspace) { // active_ws might have been destroyed by now // (focus swap away from empty ws = destroy ws) if (active_ws_child_count == 0) { active_ws = NULL; } ipc_event_workspace(active_ws, workspace, "focus"); } return true; }
struct cmd_results *cmd_floating(int argc, char **argv) { struct cmd_results *error = NULL; if (config->reading) return cmd_results_new(CMD_FAILURE, "floating", "Can't be used in config file."); if ((error = checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1))) { return error; } swayc_t *view = current_container; bool wants_floating; if (strcasecmp(argv[0], "enable") == 0) { wants_floating = true; } else if (strcasecmp(argv[0], "disable") == 0) { wants_floating = false; } else if (strcasecmp(argv[0], "toggle") == 0) { wants_floating = !view->is_floating; } else { return cmd_results_new(CMD_FAILURE, "floating", "Expected 'floating <enable|disable|toggle>"); } // Prevent running floating commands on things like workspaces if (view->type != C_VIEW) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } // Change from nonfloating to floating if (!view->is_floating && wants_floating) { // Remove view from its current location destroy_container(remove_child(view)); // and move it into workspace floating 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(swayc_active_workspace(), -1, -1); } else if (view->is_floating && !wants_floating) { // Delete the view from the floating list and unset its is_floating flag remove_child(view); view->is_floating = false; // 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 if (focused == NULL || focused->is_floating) { focused = swayc_active_workspace(); } set_focused_container(focused); sway_log(L_DEBUG, "Non-floating focused container is %p", focused); // 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 else { add_sibling(focused, view); } // Refocus on the view once its been put back into the layout view->width = view->height = 0; arrange_windows(swayc_active_workspace(), -1, -1); remove_view_from_scratchpad(view); ipc_event_window(view, "floating"); } set_focused_container(view); return cmd_results_new(CMD_SUCCESS, NULL, NULL); }
swayc_t *workspace_prev() { return workspace_prev_next_impl(swayc_active_workspace(), false); }
struct cmd_results *cmd_gaps(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1))) { return error; } const char *expected_syntax = "Expected 'gaps edge_gaps <on|off|toggle>' or " "'gaps <inner|outer> <current|all|workspace> <set|plus|minus n>'"; const char *amount_str = argv[0]; // gaps amount if (argc >= 1 && isdigit(*amount_str)) { int amount = (int)strtol(amount_str, NULL, 10); if (errno == ERANGE) { errno = 0; return cmd_results_new(CMD_INVALID, "gaps", "Number is out out of range."); } config->gaps_inner = config->gaps_outer = amount; arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } // gaps inner|outer n else if (argc >= 2 && isdigit((amount_str = argv[1])[0])) { int amount = (int)strtol(amount_str, NULL, 10); if (errno == ERANGE) { errno = 0; return cmd_results_new(CMD_INVALID, "gaps", "Number is out out of range."); } const char *target_str = argv[0]; if (strcasecmp(target_str, "inner") == 0) { config->gaps_inner = amount; } else if (strcasecmp(target_str, "outer") == 0) { config->gaps_outer = amount; } arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } else if (argc == 2 && strcasecmp(argv[0], "edge_gaps") == 0) { // gaps edge_gaps <on|off|toggle> if (strcasecmp(argv[1], "toggle") == 0) { if (config->reading) { return cmd_results_new(CMD_FAILURE, "gaps edge_gaps toggle", "Can't be used in config file."); } config->edge_gaps = !config->edge_gaps; } else { config->edge_gaps = (strcasecmp(argv[1], "yes") == 0 || strcasecmp(argv[1], "on") == 0); } arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } // gaps inner|outer current|all set|plus|minus n if (argc < 4 || config->reading) { return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); } // gaps inner|outer ... const char *inout_str = argv[0]; enum {INNER, OUTER} inout; if (strcasecmp(inout_str, "inner") == 0) { inout = INNER; } else if (strcasecmp(inout_str, "outer") == 0) { inout = OUTER; } else { return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); } // gaps ... current|all ... const char *target_str = argv[1]; enum {CURRENT, WORKSPACE, ALL} target; if (strcasecmp(target_str, "current") == 0) { target = CURRENT; } else if (strcasecmp(target_str, "all") == 0) { target = ALL; } else if (strcasecmp(target_str, "workspace") == 0) { if (inout == OUTER) { target = CURRENT; } else { // Set gap for views in workspace target = WORKSPACE; } } else { return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); } // gaps ... n amount_str = argv[3]; int amount = (int)strtol(amount_str, NULL, 10); if (errno == ERANGE) { errno = 0; return cmd_results_new(CMD_INVALID, "gaps", "Number is out out of range."); } // gaps ... set|plus|minus ... const char *method_str = argv[2]; enum {SET, ADD} method; if (strcasecmp(method_str, "set") == 0) { method = SET; } else if (strcasecmp(method_str, "plus") == 0) { method = ADD; } else if (strcasecmp(method_str, "minus") == 0) { method = ADD; amount *= -1; } else { return cmd_results_new(CMD_INVALID, "gaps", expected_syntax); } if (target == CURRENT) { swayc_t *cont; if (inout == OUTER) { if ((cont = swayc_active_workspace()) == NULL) { return cmd_results_new(CMD_FAILURE, "gaps", "There's no active workspace."); } } else { if ((cont = get_focused_view(&root_container))->type != C_VIEW) { return cmd_results_new(CMD_FAILURE, "gaps", "Currently focused item is not a view."); } } cont->gaps = swayc_gap(cont); if (method == SET) { cont->gaps = amount; } else if ((cont->gaps += amount) < 0) { cont->gaps = 0; } arrange_windows(cont->parent, -1, -1); } else if (inout == OUTER) { //resize all workspace. int i,j; for (i = 0; i < root_container.children->length; ++i) { swayc_t *op = root_container.children->items[i]; for (j = 0; j < op->children->length; ++j) { swayc_t *ws = op->children->items[j]; if (method == SET) { ws->gaps = amount; } else if ((ws->gaps += amount) < 0) { ws->gaps = 0; } } } arrange_windows(&root_container, -1, -1); } else { // Resize gaps for all views in workspace swayc_t *top; if (target == WORKSPACE) { if ((top = swayc_active_workspace()) == NULL) { return cmd_results_new(CMD_FAILURE, "gaps", "There's currently no active workspace."); } } else { top = &root_container; } int top_gap = top->gaps; container_map(top, method == SET ? set_gaps : add_gaps, &amount); top->gaps = top_gap; arrange_windows(top, -1, -1); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); }