* 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)
- continue;
+ 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);
else workspace->num = parsed_num;
LOG("num = %d\n", workspace->num);
workspace->orientation = HORIZ;
- con_attach(workspace, output, false);
+ 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;
}
*
*/
void workspace_show(const char *num) {
- Con *workspace, *current, *old;
+ Con *workspace, *current, *old = NULL;
+
+ 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. */
+ TAILQ_FOREACH(current, &(workspace->parent->nodes_head), nodes) {
+ if (current->fullscreen_mode == CF_OUTPUT)
+ old = current;
+ current->fullscreen_mode = CF_NONE;
+ }
+ assert(old != NULL);
- old = con_get_workspace(focused);
+ /* Check if the the currently focused con is on the same Output as the
+ * workspace we chose as 'old'. If not, use the workspace of the currently
+ * focused con */
+ Con *ws = con_get_workspace(focused);
+ if (ws && ws->parent != old->parent)
+ old = ws;
- workspace = workspace_get(num);
+ /* 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)
return;
- workspace->fullscreen_mode = CF_OUTPUT;
- /* 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;
}
}
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
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);
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);
+}