X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fworkspace.c;h=8104aa89fc35d6da21765408718255e5d06a0473;hb=36583ec6ee7ada36764a492fdaae158a5cdd04c3;hp=0694b977a442d72e2e525ca826515ecff89995c2;hpb=0ea15ed9620e9cc57305c5d66b0b115f3aec8552;p=i3%2Fi3 diff --git a/src/workspace.c b/src/workspace.c index 0694b977..8104aa89 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -17,27 +17,27 @@ * memory and initializing the data structures correctly). * */ -Con *workspace_get(const char *num) { - Con *output, *workspace = NULL, *current; +Con *workspace_get(const char *num, bool *created) { + Con *output, *workspace = NULL, *child; /* TODO: could that look like this in the future? GET_MATCHING_NODE(workspace, croot, strcasecmp(current->name, num) != 0); */ - TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { - TAILQ_FOREACH(current, &(output->nodes_head), nodes) { - if (strcasecmp(current->name, num) != 0) + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) + TAILQ_FOREACH(child, &(output_get_content(output)->nodes_head), nodes) { + if (strcasecmp(child->name, num) != 0) continue; - workspace = current; + workspace = child; break; } - } LOG("getting ws %s\n", num); if (workspace == NULL) { LOG("need to create this one\n"); output = con_get_output(focused); - LOG("got output %p\n", output); + Con *content = output_get_content(output); + LOG("got output %p with content %p\n", output, content); /* We need to attach this container after setting its type. con_attach * will handle CT_WORKSPACEs differently */ workspace = con_new(NULL); @@ -59,13 +59,27 @@ Con *workspace_get(const char *num) { workspace->num = -1; else workspace->num = parsed_num; LOG("num = %d\n", workspace->num); - workspace->orientation = HORIZ; - con_attach(workspace, output, false); + + /* If default_orientation is set to NO_ORIENTATION we + * determine workspace orientation from workspace size. + * Otherwise we just set the orientation to default_orientation. */ + if (config.default_orientation == NO_ORIENTATION) { + workspace->orientation = (output->rect.height > output->rect.width) ? VERT : HORIZ; + DLOG("Auto orientation. Output resolution set to (%d,%d), setting orientation to %d.\n", + workspace->rect.width, workspace->rect.height, workspace->orientation); + } else { + workspace->orientation = config.default_orientation; + } + + con_attach(workspace, content, false); ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}"); + if (created != NULL) + *created = true; + } + else if (created != NULL) { + *created = false; } - - //ewmh_update_workarea(); return workspace; } @@ -199,9 +213,10 @@ static void workspace_reassign_sticky(Con *con) { * */ void workspace_show(const char *num) { - Con *workspace, *current, *old; + Con *workspace, *current, *old = NULL; - workspace = workspace_get(num); + bool changed_num_workspaces; + workspace = workspace_get(num, &changed_num_workspaces); /* disable fullscreen for the other workspaces and get the workspace we are * currently on. */ @@ -210,31 +225,28 @@ void workspace_show(const char *num) { old = current; current->fullscreen_mode = CF_NONE; } + assert(old != NULL); /* enable fullscreen for the target workspace. If it happens to be the * same one we are currently on anyways, we can stop here. */ workspace->fullscreen_mode = CF_OUTPUT; - if (workspace == old) + if (workspace == con_get_workspace(focused)) { + DLOG("Not switching, already there.\n"); return; - /* disable fullscreen */ - TAILQ_FOREACH(current, &(workspace->parent->nodes_head), nodes) - current->fullscreen_mode = CF_NONE; + } workspace_reassign_sticky(workspace); LOG("switching to %p\n", workspace); - Con *next = workspace; - - while (!TAILQ_EMPTY(&(next->focus_head))) - next = TAILQ_FIRST(&(next->focus_head)); + Con *next = con_descend_focused(workspace); - - if (TAILQ_EMPTY(&(old->nodes_head)) && TAILQ_EMPTY(&(old->floating_head))) { + if (old && TAILQ_EMPTY(&(old->nodes_head)) && TAILQ_EMPTY(&(old->floating_head))) { /* check if this workspace is currently visible */ if (!workspace_is_visible(old)) { LOG("Closing old workspace (%p / %s), it is empty\n", old, old->name); tree_close(old, false, false); ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}"); + changed_num_workspaces = true; } } @@ -242,6 +254,11 @@ void workspace_show(const char *num) { workspace->fullscreen_mode = CF_OUTPUT; LOG("focused now = %p / %s\n", focused, focused->name); + /* Update the EWMH hints */ + if (changed_num_workspaces) + ewmh_update_workarea(); + ewmh_update_current_desktop(); + ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"focus\"}"); #if 0 @@ -453,7 +470,7 @@ Workspace *get_first_workspace_for_output(Output *output) { int last_ws = 0; TAILQ_FOREACH(ws, workspaces, workspaces) last_ws = ws->num; - result = workspace_get(last_ws + 1); + result = workspace_get(last_ws + 1, NULL); } workspace_initialize(result, output, false); @@ -488,3 +505,42 @@ void workspace_update_urgent_flag(Con *ws) { if (old_flag != ws->urgent) ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"urgent\"}"); } + +/* + * 'Forces' workspace orientation by moving all cons into a new split-con with + * the same orientation as the workspace and then changing the workspace + * orientation. + * + */ +void ws_force_orientation(Con *ws, orientation_t orientation) { + /* 1: create a new split container */ + Con *split = con_new(NULL); + split->parent = ws; + + /* 2: copy layout and orientation from workspace */ + split->layout = ws->layout; + split->orientation = ws->orientation; + + Con *old_focused = TAILQ_FIRST(&(ws->focus_head)); + + /* 3: move the existing cons of this workspace below the new con */ + DLOG("Moving cons\n"); + while (!TAILQ_EMPTY(&(ws->nodes_head))) { + Con *child = TAILQ_FIRST(&(ws->nodes_head)); + con_detach(child); + con_attach(child, split, true); + } + + /* 4: switch workspace orientation */ + ws->orientation = orientation; + + /* 5: attach the new split container to the workspace */ + DLOG("Attaching new split to ws\n"); + con_attach(split, ws, false); + + /* 6: fix the percentages */ + con_fix_percent(ws); + + if (old_focused) + con_focus(old_focused); +}