X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcommands.c;h=9830478f7eeaa94ad97d761cce0727b65bd3e95f;hb=4622cde7b785b522b29d66c7d9bdcc9aa1eeb452;hp=cf8187b70542ea9ab588ec7d22b08b2de1ad3a30;hpb=250c260eaadc77ec4b0bd73107e8f863a55f8dbb;p=i3%2Fi3 diff --git a/src/commands.c b/src/commands.c index cf8187b7..9830478f 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1,3 +1,5 @@ +#undef I3__FILE__ +#define I3__FILE__ "commands.c" /* * vim:ts=4:sw=4:expandtab * @@ -23,7 +25,7 @@ } while (0) /** When the command did not include match criteria (!), we use the currently - * focused command. Do not confuse this case with a command which included + * focused container. Do not confuse this case with a command which included * criteria but which did not match any windows. This macro has to be called in * every command. */ @@ -351,7 +353,7 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) { /* * Implementation of 'move [window|container] [to] workspace - * next|prev|next_on_output|prev_on_output'. + * next|prev|next_on_output|prev_on_output|current'. * */ void cmd_move_con_to_workspace(I3_CMD, char *which) { @@ -359,6 +361,15 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) { DLOG("which=%s\n", which); + /* We have nothing to move: + * when criteria was specified but didn't match any window or + * when criteria wasn't specified and we don't have any window focused. */ + if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) || + (match_is_empty(current_match) && focused->type == CT_WORKSPACE)) { + ysuccess(false); + return; + } + HANDLE_EMPTY_MATCH; /* get the workspace */ @@ -371,6 +382,8 @@ void cmd_move_con_to_workspace(I3_CMD, char *which) { ws = workspace_next_on_output(); else if (strcmp(which, "prev_on_output") == 0) ws = workspace_prev_on_output(); + else if (strcmp(which, "current") == 0) + ws = con_get_workspace(focused); else { ELOG("BUG: called with which=%s\n", which); ysuccess(false); @@ -400,9 +413,17 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) { owindow *current; - /* Error out early to not create a non-existing workspace (in - * workspace_get()) if we are not actually able to move anything. */ + /* We have nothing to move: + * when criteria was specified but didn't match any window or + * when criteria wasn't specified and we don't have any window focused. */ + if (!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) { + ELOG("No windows match your criteria, cannot move.\n"); + ysuccess(false); + return; + } + if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) { + ELOG("No window to move, you have focused a workspace.\n"); ysuccess(false); return; } @@ -430,14 +451,16 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) { void cmd_move_con_to_workspace_number(I3_CMD, char *which) { owindow *current; - /* Error out early to not create a non-existing workspace (in - * workspace_get()) if we are not actually able to move anything. */ - if (match_is_empty(current_match) && focused->type == CT_WORKSPACE) { + /* We have nothing to move: + * when criteria was specified but didn't match any window or + * when criteria wasn't specified and we don't have any window focused. */ + if ((!match_is_empty(current_match) && TAILQ_EMPTY(&owindows)) || + (match_is_empty(current_match) && focused->type == CT_WORKSPACE)) { ysuccess(false); return; } - LOG("should move window to workspace with number %d\n", which); + LOG("should move window to workspace %s\n", which); /* get the workspace */ Con *output, *workspace = NULL; @@ -490,7 +513,7 @@ static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floatin if (strcmp(direction, "up") == 0) { floating_con->rect.y -= px; floating_con->rect.height += px; - } else if (strcmp(direction, "down") == 0) { + } else if (strcmp(direction, "down") == 0 || strcmp(direction, "height") == 0) { floating_con->rect.height += px; } else if (strcmp(direction, "left") == 0) { floating_con->rect.x -= px; @@ -500,10 +523,12 @@ static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floatin } } -static void cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int ppt) { +static bool cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int ppt) { LOG("tiling resize\n"); /* get the appropriate current container (skip stacked/tabbed cons) */ Con *current = focused; + Con *other = NULL; + double percentage = 0; while (current->parent->layout == L_STACKED || current->parent->layout == L_TABBED) current = current->parent; @@ -512,40 +537,50 @@ static void cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int orientation_t search_orientation = (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0 ? HORIZ : VERT); - while (current->type != CT_WORKSPACE && - current->type != CT_FLOATING_CON && - current->parent->orientation != search_orientation) - current = current->parent; + do { + if (con_orientation(current->parent) != search_orientation) { + current = current->parent; + continue; + } - /* get the default percentage */ - int children = con_num_children(current->parent); - Con *other; - LOG("ins. %d children\n", children); - double percentage = 1.0 / children; - LOG("default percentage = %f\n", percentage); + /* get the default percentage */ + int children = con_num_children(current->parent); + LOG("ins. %d children\n", children); + percentage = 1.0 / children; + LOG("default percentage = %f\n", percentage); - orientation_t orientation = current->parent->orientation; + orientation_t orientation = con_orientation(current->parent); - if ((orientation == HORIZ && - (strcmp(direction, "up") == 0 || strcmp(direction, "down") == 0)) || - (orientation == VERT && - (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0))) { - LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n", - (orientation == HORIZ ? "horizontal" : "vertical")); - ysuccess(false); - return; - } + if ((orientation == HORIZ && + (strcmp(direction, "up") == 0 || strcmp(direction, "down") == 0)) || + (orientation == VERT && + (strcmp(direction, "left") == 0 || strcmp(direction, "right") == 0))) { + LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n", + (orientation == HORIZ ? "horizontal" : "vertical")); + ysuccess(false); + return false; + } - if (strcmp(direction, "up") == 0 || strcmp(direction, "left") == 0) { - other = TAILQ_PREV(current, nodes_head, nodes); - } else { - other = TAILQ_NEXT(current, nodes); - } - if (other == TAILQ_END(workspaces)) { - LOG("No other container in this direction found, cannot resize.\n"); + if (strcmp(direction, "up") == 0 || strcmp(direction, "left") == 0) { + other = TAILQ_PREV(current, nodes_head, nodes); + } else { + other = TAILQ_NEXT(current, nodes); + } + if (other == TAILQ_END(workspaces)) { + LOG("No other container in this direction found, trying to look further up in the tree...\n"); + current = current->parent; + continue; + } + break; + } while (current->type != CT_WORKSPACE && + current->type != CT_FLOATING_CON); + + if (other == NULL) { + LOG("No other container in this direction found, trying to look further up in the tree...\n"); ysuccess(false); - return; + return false; } + LOG("other->percent = %f\n", other->percent); LOG("current->percent before = %f\n", current->percent); if (current->percent == 0.0) @@ -567,9 +602,11 @@ static void cmd_resize_tiling_direction(I3_CMD, char *way, char *direction, int } else { LOG("Not resizing, already at minimum size\n"); } + + return true; } -static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, int ppt) { +static bool cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, int ppt) { LOG("width/height resize\n"); /* get the appropriate current container (skip stacked/tabbed cons) */ Con *current = focused; @@ -583,7 +620,7 @@ static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, i while (current->type != CT_WORKSPACE && current->type != CT_FLOATING_CON && - current->parent->orientation != search_orientation) + con_orientation(current->parent) != search_orientation) current = current->parent; /* get the default percentage */ @@ -592,7 +629,7 @@ static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, i double percentage = 1.0 / children; LOG("default percentage = %f\n", percentage); - orientation_t orientation = current->parent->orientation; + orientation_t orientation = con_orientation(current->parent); if ((orientation == HORIZ && strcmp(direction, "height") == 0) || @@ -601,13 +638,13 @@ static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, i LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n", (orientation == HORIZ ? "horizontal" : "vertical")); ysuccess(false); - return; + return false; } if (children == 1) { LOG("This is the only container, cannot resize.\n"); ysuccess(false); - return; + return false; } /* Ensure all the other children have a percentage set. */ @@ -630,13 +667,13 @@ static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, i if (!definitelyGreaterThan(child->percent - subtract_percent, 0.05, DBL_EPSILON)) { LOG("Not resizing, already at minimum size (child %p would end up with a size of %.f\n", child, child->percent - subtract_percent); ysuccess(false); - return; + return false; } } if (!definitelyGreaterThan(new_current_percent, 0.05, DBL_EPSILON)) { LOG("Not resizing, already at minimum size\n"); ysuccess(false); - return; + return false; } current->percent += ((double)ppt / 100.0); @@ -648,6 +685,8 @@ static void cmd_resize_tiling_width_height(I3_CMD, char *way, char *direction, i child->percent -= subtract_percent; LOG("child->percent after (%p) = %f\n", child, child->percent); } + + return true; } /* @@ -670,9 +709,13 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz cmd_resize_floating(current_match, cmd_output, way, direction, floating_con, px); } else { if (strcmp(direction, "width") == 0 || - strcmp(direction, "height") == 0) - cmd_resize_tiling_width_height(current_match, cmd_output, way, direction, ppt); - else cmd_resize_tiling_direction(current_match, cmd_output, way, direction, ppt); + strcmp(direction, "height") == 0) { + if (!cmd_resize_tiling_width_height(current_match, cmd_output, way, direction, ppt)) + return; + } else { + if (!cmd_resize_tiling_direction(current_match, cmd_output, way, direction, ppt)) + return; + } } cmd_output->needs_tree_render = true; @@ -800,7 +843,7 @@ void cmd_workspace_number(I3_CMD, char *which) { child->num == parsed_num); if (!workspace) { - LOG("There is no workspace with number %d, creating a new one.\n", parsed_num); + LOG("There is no workspace with number %ld, creating a new one.\n", parsed_num); ysuccess(true); /* terminate the which string after the endposition of the number */ *endptr = '\0'; @@ -993,9 +1036,14 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) { TAILQ_FOREACH(current, &owindows, owindows) { Output *current_output = get_output_containing(current->con->rect.x, current->con->rect.y); + if (!current_output) { + ELOG("Cannot get current output. This is a bug in i3.\n"); + ysuccess(false); + return; + } Output *output = get_output_from_string(current_output, name); if (!output) { - LOG("No such output\n"); + ELOG("Could not get output from string \"%s\"\n", name); ysuccess(false); return; } @@ -1223,7 +1271,7 @@ void cmd_focus_level(I3_CMD, char *level) { if (con_fullscreen_permits_focusing(focused->parent)) success = level_up(); else - LOG("Currently in fullscreen, not going up\n"); + ELOG("'focus parent': Currently in fullscreen, not going up\n"); } } @@ -1362,17 +1410,31 @@ void cmd_move_direction(I3_CMD, char *direction, char *move_px) { } /* - * Implementation of 'layout default|stacked|stacking|tabbed'. + * Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'. * */ void cmd_layout(I3_CMD, char *layout_str) { if (strcmp(layout_str, "stacking") == 0) layout_str = "stacked"; - DLOG("changing layout to %s\n", layout_str); owindow *current; - int layout = (strcmp(layout_str, "default") == 0 ? L_DEFAULT : - (strcmp(layout_str, "stacked") == 0 ? L_STACKED : - L_TABBED)); + int layout; + /* default is a special case which will be handled in con_set_layout(). */ + if (strcmp(layout_str, "default") == 0) + layout = L_DEFAULT; + else if (strcmp(layout_str, "stacked") == 0) + layout = L_STACKED; + else if (strcmp(layout_str, "tabbed") == 0) + layout = L_TABBED; + else if (strcmp(layout_str, "splitv") == 0) + layout = L_SPLITV; + else if (strcmp(layout_str, "splith") == 0) + layout = L_SPLITH; + else { + ELOG("Unknown layout \"%s\", this is a mismatch between code and parser spec.\n", layout_str); + return; + } + + DLOG("changing layout to %s (%d)\n", layout_str, layout); /* check if the match is empty, not if the result is empty */ if (match_is_empty(current_match)) @@ -1389,12 +1451,40 @@ void cmd_layout(I3_CMD, char *layout_str) { ysuccess(true); } +/* + * Implementation of 'layout toggle [all|split]'. + * + */ +void cmd_layout_toggle(I3_CMD, char *toggle_mode) { + owindow *current; + + if (toggle_mode == NULL) + toggle_mode = "default"; + + DLOG("toggling layout (mode = %s)\n", toggle_mode); + + /* check if the match is empty, not if the result is empty */ + if (match_is_empty(current_match)) + con_toggle_layout(focused->parent, toggle_mode); + else { + TAILQ_FOREACH(current, &owindows, owindows) { + DLOG("matching: %p / %s\n", current->con, current->con->name); + con_toggle_layout(current->con, toggle_mode); + } + } + + cmd_output->needs_tree_render = true; + // XXX: default reply for now, make this a better reply + ysuccess(true); +} + /* * Implementaiton of 'exit'. * */ void cmd_exit(I3_CMD) { LOG("Exiting due to user command.\n"); + xcb_disconnect(conn); exit(0); /* unreached */ @@ -1407,6 +1497,7 @@ void cmd_exit(I3_CMD) { void cmd_reload(I3_CMD) { LOG("reloading\n"); kill_configerror_nagbar(false); + kill_commanderror_nagbar(false); load_configuration(conn, NULL, true); x_set_i3_atoms(); /* Send an IPC event just in case the ws names have changed */ @@ -1435,6 +1526,7 @@ void cmd_restart(I3_CMD) { void cmd_open(I3_CMD) { LOG("opening new container\n"); Con *con = tree_open_con(NULL, NULL); + con->layout = L_SPLITH; con_focus(con); y(map_open);