]> git.sur5r.net Git - i3/i3/blobdiff - src/workspace.c
ipc: also send workspace event when initializing a workspace for an output
[i3/i3] / src / workspace.c
index 5a4902ca2034cdb46df350126580ac03e35bd656..8d76272925ff8ff5b3d9eb754ffac2147d252072 100644 (file)
@@ -28,6 +28,7 @@
 #include "client.h"
 #include "log.h"
 #include "ewmh.h"
+#include "ipc.h"
 
 /*
  * Returns a pointer to the workspace with the given number (starting at 0),
@@ -57,6 +58,8 @@ Workspace *workspace_get(int number) {
                 workspace_set_name(ws, NULL);
 
                 TAILQ_INSERT_TAIL(workspaces, ws, workspaces);
+
+                ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
         }
         DLOG("done\n");
 
@@ -84,13 +87,13 @@ void workspace_set_name(Workspace *ws, const char *name) {
                 errx(1, "asprintf() failed");
 
         FREE(ws->name);
+        FREE(ws->utf8_name);
 
         ws->name = convert_utf8_to_ucs2(label, &(ws->name_len));
         if (config.font != NULL)
                 ws->text_width = predict_text_width(global_conn, config.font, ws->name, ws->name_len);
         else ws->text_width = 0;
-
-        free(label);
+        ws->utf8_name = label;
 }
 
 /*
@@ -144,6 +147,15 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
                 if ((old_client != NULL) && !old_client->dock)
                         redecorate_window(conn, old_client);
                 else xcb_flush(conn);
+
+                /* We need to check if a global fullscreen-client is blocking
+                 * the t_ws and if necessary switch that to local fullscreen */
+                Client* client = c_ws->fullscreen_client;
+                if (client != NULL && client->workspace != c_ws) {
+                        if (c_ws->fullscreen_client->workspace != c_ws)
+                                c_ws->fullscreen_client = NULL;
+                        client_enter_fullscreen(conn, client, false);
+                }
         }
 
         /* Check if we need to change something or if we’re already there */
@@ -156,6 +168,8 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
                         xcb_flush(conn);
                 }
 
+                ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"focus\"}");
+
                 return;
         }
 
@@ -169,6 +183,8 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
         current_col = c_ws->current_col;
         DLOG("new current row = %d, current col = %d\n", current_row, current_col);
 
+        ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"focus\"}");
+
         workspace_map_clients(conn, c_ws);
 
         /* POTENTIAL TO IMPROVE HERE: due to the call to _map_clients first and
@@ -195,58 +211,6 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
         }
 }
 
-
-/*
- * Parses the preferred_screen property of a workspace. You can either specify
- * the screen number (it is not given that the screen numbering always stays
- * the same) or the screen coordinates (exact coordinates, e.g. 1280 will match
- * the screen starting at x=1280, but 1281 will not). For coordinates, you can
- * either specify an x coordinate ("1280") or an y coordinate ("x800") or both
- * ("1280x800").
- *
- */
-static Output *get_screen_from_preference(char *preference) {
-        Output *screen;
-        char *rest;
-        int preferred_screen = strtol(preference, &rest, 10);
-
-        DLOG("Getting screen for preference \"%s\" (%d)\n", preference, preferred_screen);
-
-        if ((rest == preference) || (preferred_screen >= num_screens)) {
-                int x = INT_MAX, y = INT_MAX;
-                if (strchr(preference, 'x') != NULL) {
-                        /* Check if only the y coordinate was specified */
-                        if (*preference == 'x')
-                                y = atoi(preference+1);
-                        else {
-                                x = atoi(preference);
-                                y = atoi(strchr(preference, 'x') + 1);
-                        }
-                } else {
-                        x = atoi(preference);
-                }
-
-                DLOG("Looking for screen at %d x %d\n", x, y);
-
-                TAILQ_FOREACH(screen, &outputs, outputs)
-                        if ((x == INT_MAX || screen->rect.x == x) &&
-                            (y == INT_MAX || screen->rect.y == y)) {
-                                DLOG("found %p\n", screen);
-                                return screen;
-                        }
-
-                DLOG("none found\n");
-                return NULL;
-        } else {
-                int c = 0;
-                TAILQ_FOREACH(screen, &outputs, outputs)
-                        if (c++ == preferred_screen)
-                                return screen;
-        }
-
-        return NULL;
-}
-
 /*
  * Assigns the given workspace to the given output by correctly updating its
  * state and reconfiguring all the clients on this workspace.
@@ -256,9 +220,10 @@ static Output *get_screen_from_preference(char *preference) {
  * output 1 and you just plugged in output 1).
  *
  */
-void workspace_assign_to(Workspace *ws, Output *output) {
+void workspace_assign_to(Workspace *ws, Output *output, bool hide_it) {
         Client *client;
         bool empty = true;
+        bool visible = workspace_is_visible(ws);
 
         ws->output = output;
 
@@ -280,14 +245,14 @@ void workspace_assign_to(Workspace *ws, Output *output) {
         render_workspace(global_conn, output, ws);
 
         /* …unless we want to see them at the moment, we should hide that workspace */
-        if (workspace_is_visible(ws))
+        if (visible && !hide_it)
                 return;
 
         workspace_unmap_clients(global_conn, ws);
 
         if (c_ws == ws) {
-                DLOG("Need to adjust c_ws...\n");
-                c_ws = output->current_workspace;
+                DLOG("Need to adjust output->current_workspace...\n");
+                output->current_workspace = c_ws;
         }
 }
 
@@ -311,8 +276,8 @@ void workspace_initialize(Workspace *ws, Output *output, bool recheck) {
         /* If this workspace has no preferred output or if the output it wants
          * to be on is not available at the moment, we initialize it with
          * the output which was given */
-        if (ws->preferred_screen == NULL ||
-            (ws->output = get_screen_from_preference(ws->preferred_screen)) == NULL)
+        if (ws->preferred_output == NULL ||
+            (ws->output = get_output_by_name(ws->preferred_output)) == NULL)
                 ws->output = output;
 
         DLOG("old_output = %p, ws->output = %p\n", old_output, ws->output);
@@ -320,21 +285,21 @@ void workspace_initialize(Workspace *ws, Output *output, bool recheck) {
         if (old_output != NULL && ws->output == old_output)
                 return;
 
-        workspace_assign_to(ws, ws->output);
+        workspace_assign_to(ws, ws->output, false);
 }
 
 /*
  * Gets the first unused workspace for the given screen, taking into account
- * the preferred_screen setting of every workspace (workspace assignments).
+ * the preferred_output setting of every workspace (workspace assignments).
  *
  */
-Workspace *get_first_workspace_for_screen(Output *output) {
+Workspace *get_first_workspace_for_output(Output *output) {
         Workspace *result = NULL;
 
         Workspace *ws;
         TAILQ_FOREACH(ws, workspaces, workspaces) {
-                if (ws->preferred_screen == NULL ||
-                    !screens_are_equal(get_screen_from_preference(ws->preferred_screen), output))
+                if (ws->preferred_output == NULL ||
+                    get_output_by_name(ws->preferred_output) != output)
                         continue;
 
                 result = ws;
@@ -343,7 +308,6 @@ Workspace *get_first_workspace_for_screen(Output *output) {
 
         if (result == NULL) {
                 /* No assignment found, returning first unused workspace */
-                Workspace *ws;
                 TAILQ_FOREACH(ws, workspaces, workspaces) {
                         if (ws->output != NULL)
                                 continue;
@@ -356,7 +320,6 @@ Workspace *get_first_workspace_for_screen(Output *output) {
         if (result == NULL) {
                 DLOG("No existing free workspace found to assign, creating a new one\n");
 
-                Workspace *ws;
                 int last_ws = 0;
                 TAILQ_FOREACH(ws, workspaces, workspaces)
                         last_ws = ws->num;
@@ -389,7 +352,7 @@ void workspace_map_clients(xcb_connection_t *conn, Workspace *ws) {
         /* Map all stack windows, if any */
         struct Stack_Window *stack_win;
         SLIST_FOREACH(stack_win, &stack_wins, stack_windows)
-                if (stack_win->container->workspace == ws)
+                if (stack_win->container->workspace == ws && stack_win->rect.height > 0)
                         xcb_map_window(conn, stack_win->window);
 
         ignore_enter_notify_forall(conn, ws, false);
@@ -497,7 +460,8 @@ int workspace_height(Workspace *ws) {
                 height -= client->desired_height;
 
         /* Space for the internal bar */
-        height -= (font->height + 6);
+        if (!config.disable_workspace_bar)
+                height -= (font->height + 6);
 
         return height;
 }