2 #define I3__FILE__ "workspace.c"
16 #include <yajl/yajl_gen.h>
34 DLOG(
"Auto orientation. Workspace size set to (%d,%d), setting layout to %d.\n",
48 Con *output, *workspace = NULL;
53 if (workspace == NULL) {
54 LOG(
"Creating new workspace \"%s\"\n", num);
60 if (strcmp(assignment->
name, num) != 0)
63 LOG(
"Found workspace assignment to output \"%s\"\n", assignment->
output);
68 LOG(
"got output %p with content %p\n", output, content);
71 workspace =
con_new(NULL, NULL);
73 sasprintf(&name,
"[i3 con] workspace %s", num);
76 workspace->
type = CT_WORKSPACE;
83 long parsed_num = strtol(num, &endptr, 10);
84 if (parsed_num == LONG_MIN ||
85 parsed_num == LONG_MAX ||
89 else workspace->
num = parsed_num;
90 LOG(
"num = %d\n", workspace->
num);
92 workspace->
parent = content;
97 ipc_send_event(
"workspace", I3_IPC_EVENT_WORKSPACE,
"{\"change\":\"init\"}");
101 else if (created != NULL) {
120 ws->
type = CT_WORKSPACE;
126 if (strlen(bind->
command) < strlen(
"workspace ") ||
127 strncasecmp(bind->
command,
"workspace", strlen(
"workspace")) != 0)
130 char *target = bind->
command + strlen(
"workspace ");
136 if (strncasecmp(target,
"next", strlen(
"next")) == 0 ||
137 strncasecmp(target,
"prev", strlen(
"prev")) == 0 ||
138 strncasecmp(target,
"next_on_output", strlen(
"next_on_output")) == 0 ||
139 strncasecmp(target,
"prev_on_output", strlen(
"prev_on_output")) == 0 ||
140 strncasecmp(target,
"number", strlen(
"number")) == 0 ||
141 strncasecmp(target,
"back_and_forth", strlen(
"back_and_forth")) == 0 ||
142 strncasecmp(target,
"current", strlen(
"current")) == 0)
147 ws->
name = strdup(target);
148 if (ws->
name[strlen(ws->
name)-1] ==
'"')
149 ws->
name[strlen(ws->
name)-1] =
'\0';
150 DLOG(
"trying name *%s*\n", ws->
name);
155 bool assigned =
false;
158 if (strcmp(assignment->
name, ws->
name) != 0 ||
159 strcmp(assignment->
output, output->
name) == 0)
173 exists = (current != NULL);
178 long parsed_num = strtol(ws->
name, &endptr, 10);
179 if (parsed_num == LONG_MIN ||
180 parsed_num == LONG_MAX ||
184 else ws->
num = parsed_num;
185 LOG(
"Used number %d for workspace with name %s\n", ws->
num, ws->
name);
193 DLOG(
"Getting next unused workspace by number\n");
204 exists = (current != NULL);
206 DLOG(
"result for ws %s / %d: exists = %d\n", ws->
name, c, exists);
236 LOG(
"workspace visible? fs = %p, ws = %p\n", fs, ws);
248 if (current != exclude &&
250 current->
window != NULL &&
259 TAILQ_FOREACH(current, &(con->floating_head), floating_windows) {
260 if (current != exclude &&
262 current->
window != NULL &&
292 LOG(
"Ah, this one is sticky: %s / %p\n", current->
name, current);
298 LOG(
"No window found for this sticky group\n");
311 LOG(
"re-assigned window from src %p to dest %p\n", src, current);
314 TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
327 DLOG(
"Resetting urgency flag of con %p by timer\n", con);
342 setlocale(LC_NUMERIC,
"C");
361 const unsigned char *payload;
363 y(get_buf, &payload, &length);
365 ipc_send_event(
"workspace", I3_IPC_EVENT_WORKSPACE, (
const char *)payload);
367 setlocale(LC_NUMERIC,
"");
371 Con *current, *old = NULL;
389 if (workspace == current) {
390 DLOG(
"Not switching, already there.\n");
410 DLOG(
"switching to %p / %s\n", workspace, workspace->
name);
429 DLOG(
"Deferring reset of urgency flag of con %p on newly shown workspace %p\n",
438 DLOG(
"Resetting urgency timer of con %p on workspace %p\n",
447 DLOG(
"old = %p / %s\n", old, (old ? old->
name :
"(null)"));
456 LOG(
"Closing old workspace (%p / %s), it is empty\n", old, old->
name);
458 ipc_send_event(
"workspace", I3_IPC_EVENT_WORKSPACE,
"{\"change\":\"empty\"}");
467 if (old_output != new_output) {
502 if (current->
num == -1) {
512 if (child->type != CT_WORKSPACE)
514 if (child->num == -1)
519 if (current->
num < child->num && (!next || child->
num < next->
num))
527 bool found_current =
false;
533 if (child->type != CT_WORKSPACE)
535 if (child == current) {
537 }
else if (child->num == -1 && (current->
num != -1 || found_current)) {
539 goto workspace_next_end;
552 if (child->type != CT_WORKSPACE)
554 if (!next || (child->num != -1 && child->num < next->
num))
572 if (current->
num == -1) {
574 prev =
TAILQ_PREV(current, nodes_head, nodes);
575 if (prev && prev->
num != -1)
584 if (child->type != CT_WORKSPACE || child->num == -1)
589 if (current->
num > child->num && (!prev || child->
num > prev->
num))
597 bool found_current =
false;
603 if (child->type != CT_WORKSPACE)
605 if (child == current) {
606 found_current =
true;
607 }
else if (child->num == -1 && (current->
num != -1 || found_current)) {
609 goto workspace_prev_end;
622 if (child->type != CT_WORKSPACE)
624 if (!prev || child->
num > prev->
num)
644 if (current->
num == -1) {
650 if (child->type != CT_WORKSPACE)
652 if (child->num == -1)
657 if (current->
num < child->num && (!next || child->
num < next->
num))
664 bool found_current =
false;
666 if (child->type != CT_WORKSPACE)
668 if (child == current) {
670 }
else if (child->num == -1 && (current->
num != -1 || found_current)) {
672 goto workspace_next_on_output_end;
680 if (child->type != CT_WORKSPACE)
682 if (!next || (child->num != -1 && child->num < next->
num))
686 workspace_next_on_output_end:
698 DLOG(
"output = %s\n", output->
name);
700 if (current->
num == -1) {
702 prev =
TAILQ_PREV(current, nodes_head, nodes);
703 if (prev && prev->
num != -1)
708 if (child->type != CT_WORKSPACE || child->num == -1)
713 if (current->
num > child->num && (!prev || child->
num > prev->
num))
720 bool found_current =
false;
722 if (child->type != CT_WORKSPACE)
724 if (child == current) {
725 found_current =
true;
726 }
else if (child->num == -1 && (current->
num != -1 || found_current)) {
728 goto workspace_prev_on_output_end;
736 if (child->type != CT_WORKSPACE)
738 if (!prev || child->
num > prev->
num)
743 workspace_prev_on_output_end:
753 DLOG(
"No previous workspace name set. Not switching.");
766 DLOG(
"no previous workspace name set.");
782 TAILQ_FOREACH(child, &(con->floating_head), floating_windows)
795 bool old_flag = ws->
urgent;
797 DLOG(
"Workspace urgency flag changed from %d to %d\n", old_flag, ws->
urgent);
799 if (old_flag != ws->
urgent)
800 ipc_send_event(
"workspace", I3_IPC_EVENT_WORKSPACE,
"{\"change\":\"urgent\"}");
819 DLOG(
"Moving cons\n");
827 ws->
layout = (orientation ==
HORIZ) ? L_SPLITH : L_SPLITV;
831 DLOG(
"Attaching new split (%p) to ws (%p)\n", split, ws);
852 DLOG(
"Attaching a window to workspace %p / %s\n", ws, ws->
name);
855 DLOG(
"Default layout, just attaching it to the workspace itself.\n");
859 DLOG(
"Non-default layout, creating a new split container\n");
868 DLOG(
"Attaching new split %p to workspace %p\n",
new, ws);
882 ELOG(
"Workspace %p / %s has no children to encapsulate\n", ws, ws->
name);
890 DLOG(
"Moving children of workspace %p / %s into container %p\n",