#include "shmlog.h"
// Macros to make the YAJL API a bit easier to use.
-#define y(x, ...) yajl_gen_ ## x (cmd_output->json_gen, ##__VA_ARGS__)
-#define ystr(str) yajl_gen_string(cmd_output->json_gen, (unsigned char*)str, strlen(str))
+#define y(x, ...) (cmd_output->json_gen != NULL ? yajl_gen_ ## x (cmd_output->json_gen, ##__VA_ARGS__) : 0)
+#define ystr(str) (cmd_output->json_gen != NULL ? yajl_gen_string(cmd_output->json_gen, (unsigned char*)str, strlen(str)) : 0)
#define ysuccess(success) do { \
- y(map_open); \
- ystr("success"); \
- y(bool, success); \
- y(map_close); \
+ if (cmd_output->json_gen != NULL) { \
+ y(map_open); \
+ ystr("success"); \
+ y(bool, success); \
+ y(map_close); \
+ } \
} while (0)
#define yerror(message) do { \
- y(map_open); \
- ystr("success"); \
- y(bool, false); \
- ystr("error"); \
- ystr(message); \
- y(map_close); \
+ if (cmd_output->json_gen != NULL) { \
+ y(map_open); \
+ ystr("success"); \
+ y(bool, false); \
+ ystr("error"); \
+ ystr(message); \
+ y(map_close); \
+ } \
} while (0)
/** When the command did not include match criteria (!), we use the currently
* and return true, signaling that no further workspace switching should occur in the calling function.
*
*/
-static bool maybe_back_and_forth(struct CommandResult *cmd_output, char *name) {
+static bool maybe_back_and_forth(struct CommandResultIR *cmd_output, char *name) {
Con *ws = con_get_workspace(focused);
/* If we switched to a different workspace, do nothing */
owindow *ow;
DLOG("Initializing criteria, current_match = %p\n", current_match);
+ match_free(current_match);
match_init(current_match);
while (!TAILQ_EMPTY(&owindows)) {
ow = TAILQ_FIRST(&owindows);
if (current_match->con_id == current->con) {
DLOG("matches container!\n");
TAILQ_INSERT_TAIL(&owindows, current, owindows);
+ } else {
+ DLOG("doesnt match\n");
+ free(current);
}
} else if (current_match->mark != NULL && current->con->mark != NULL &&
regex_matches(current_match->mark, current->con->mark)) {
DLOG("match by mark\n");
TAILQ_INSERT_TAIL(&owindows, current, owindows);
} else {
- if (current->con->window == NULL)
- continue;
- if (match_matches_window(current_match, current->con->window)) {
+ if (current->con->window && match_matches_window(current_match, current->con->window)) {
DLOG("matches window!\n");
TAILQ_INSERT_TAIL(&owindows, current, owindows);
} else {
ELOG("Could not parse con id \"%s\"\n", cvalue);
} else {
current_match->con_id = (Con*)parsed;
- printf("id as int = %p\n", current_match->con_id);
+ DLOG("id as int = %p\n", current_match->con_id);
}
return;
}
ELOG("Could not parse window id \"%s\"\n", cvalue);
} else {
current_match->id = parsed;
- printf("window id as int = %d\n", current_match->id);
+ DLOG("window id as int = %d\n", current_match->id);
}
return;
}
*
*/
void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
- if (strncasecmp(name, "__i3_", strlen("__i3_")) == 0) {
- LOG("You cannot switch to the i3 internal workspaces.\n");
+ if (strncasecmp(name, "__", strlen("__")) == 0) {
+ LOG("You cannot move containers to i3-internal workspaces (\"%s\").\n", name);
ysuccess(false);
return;
}
owindow *current;
TAILQ_FOREACH(current, &owindows, owindows) {
+ /* Don't handle dock windows (issue #1201) */
+ if (current->con->window && current->con->window->dock) {
+ DLOG("This is a dock window. Not resizing (con = %p)\n)", current->con);
+ continue;
+ }
+
Con *floating_con;
if ((floating_con = con_inside_floating(current->con))) {
cmd_resize_floating(current_match, cmd_output, way, direction, floating_con, px);
void cmd_append_layout(I3_CMD, char *path) {
LOG("Appending layout \"%s\"\n", path);
Con *parent = focused;
- tree_append_json(path);
+ /* We need to append the layout to a split container, since a leaf
+ * container must not have any children (by definition).
+ * Note that we explicitly check for workspaces, since they are okay for
+ * this purpose, but con_accepts_window() returns false for workspaces. */
+ while (parent->type != CT_WORKSPACE && !con_accepts_window(parent))
+ parent = parent->parent;
+ DLOG("Appending to parent=%p instead of focused=%p\n",
+ parent, focused);
+ char *errormsg = NULL;
+ tree_append_json(parent, path, &errormsg);
+ if (errormsg != NULL) {
+ yerror(errormsg);
+ free(errormsg);
+ /* Note that we continue executing since tree_append_json() has
+ * side-effects — user-provided layouts can be partly valid, partly
+ * invalid, leading to half of the placeholder containers being
+ * created. */
+ } else {
+ ysuccess(true);
+ }
// XXX: This is a bit of a kludge. Theoretically, render_con(parent,
// false); should be enough, but when sending 'workspace 4; append_layout
restore_open_placeholder_windows(parent);
cmd_output->needs_tree_render = true;
- // XXX: default reply for now, make this a better reply
- ysuccess(true);
}
/*
*
*/
void cmd_workspace_name(I3_CMD, char *name) {
- if (strncasecmp(name, "__i3_", strlen("__i3_")) == 0) {
- LOG("You cannot switch to the i3 internal workspaces.\n");
+ if (strncasecmp(name, "__", strlen("__")) == 0) {
+ LOG("You cannot switch to the i3-internal workspaces (\"%s\").\n", name);
ysuccess(false);
return;
}
*/
void cmd_exit(I3_CMD) {
LOG("Exiting due to user command.\n");
+ ipc_shutdown();
+ unlink(config.ipc_socket_path);
xcb_disconnect(conn);
exit(0);
*/
void cmd_restart(I3_CMD) {
LOG("restarting i3\n");
+ ipc_shutdown();
+ /* We need to call this manually since atexit handlers don’t get called
+ * when exec()ing */
+ purge_zerobyte_logfile();
+ /* The unlink call is intentionally after the purge_zerobyte_logfile() so
+ * that the latter does not remove the directory yet. We need to store the
+ * restart layout state in there. */
+ unlink(config.ipc_socket_path);
i3_restart(false);
// XXX: default reply for now, make this a better reply
*
*/
void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
+ if (strncasecmp(new_name, "__", strlen("__")) == 0) {
+ LOG("Cannot rename workspace to \"%s\": names starting with __ are i3-internal.", new_name);
+ ysuccess(false);
+ return;
+ }
if (old_name) {
LOG("Renaming workspace \"%s\" to \"%s\"\n", old_name, new_name);
} else {