]> git.sur5r.net Git - i3/i3/commitdiff
Implement screen-spanning fullscreen-mode (command: 'fg')
authorAxel Wagner <mail@merovius.de>
Mon, 8 Mar 2010 01:02:35 +0000 (02:02 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 8 Mar 2010 10:15:31 +0000 (11:15 +0100)
This closes ticket #188

docs/userguide
include/client.h
src/client.c
src/commands.c
src/workspace.c

index fb537a90a9c6d1c722762750f142c668f74389db..b7c84b2101a496228f56ee2e32cb5560be39a4dc 100644 (file)
@@ -86,6 +86,9 @@ image:modes.png[Container modes]
 To display a window fullscreen or to go out of fullscreen mode again, press
 +Mod1+f+.
 
+There is also a global fullscreen mode in i3 in which the client will use all
+available outputs. To use it, or to get out of it again, press +Mod1+Shift+f+.
+
 === Opening other applications
 
 Aside from opening applicatios from a terminal, you can also use the handy
@@ -515,7 +518,8 @@ focus_follows_mouse no
 
 To change the layout of the current container to stacking, use +s+, for default
 use +d+ and for tabbed, use +T+. To make the current client (!) fullscreen,
-use +f+, to make it floating (or tiling again) use +t+:
+use +f+, to make it spanning all outputs, use +fg+, to make it floating (or
+tiling again) use +t+:
 
 *Examples*:
 --------------
@@ -526,6 +530,9 @@ bindsym Mod1+w T
 # Toggle fullscreen
 bindsym Mod1+f f
 
+# Toggle global fullscreen
+bindsym Mod1+Shift+f fg
+
 # Toggle floating/tiling
 bindsym Mod1+t t
 --------------
index 4eac127e1da5d0ddbf58d525a73b1aefdc2d4eee..8f97eb445d323d8a7d3217ea9ebaf91ff26b9ebf 100644 (file)
@@ -51,7 +51,13 @@ bool client_matches_class_name(Client *client, char *to_class, char *to_title,
  * and when moving a fullscreen client to another screen.
  *
  */
-void client_enter_fullscreen(xcb_connection_t *conn, Client *client);
+void client_enter_fullscreen(xcb_connection_t *conn, Client *client, bool global);
+
+/**
+ * Leaves fullscreen mode for the given client. This is called by toggle_fullscreen.
+ *
+ */
+void client_leave_fullscreen(xcb_connection_t *conn, Client *client);
 
 /**
  * Toggles fullscreen mode for the given client. It updates the data
@@ -62,6 +68,12 @@ void client_enter_fullscreen(xcb_connection_t *conn, Client *client);
  */
 void client_toggle_fullscreen(xcb_connection_t *conn, Client *client);
 
+/**
+ * Like client_toggle_fullscreen(), but putting it in global fullscreen-mode.
+ *
+ */
+void client_toggle_fullscreen_global(xcb_connection_t *conn, Client *client);
+
 /**
  * Sets the position of the given client in the X stack to the highest (tiling
  * layer is always on the same position, so this doesn’t matter) below the
index 1ca35dc7cd35b4e8bd2fb34ac9f5165d998b9b1b..f5e7718ec495fc7af9d9e3cb2e38fa81dcb2a5f2 100644 (file)
@@ -13,6 +13,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <limits.h>
 
 #include <xcb/xcb.h>
 #include <xcb/xcb_icccm.h>
@@ -152,20 +153,62 @@ bool client_matches_class_name(Client *client, char *to_class, char *to_title,
  * and when moving a fullscreen client to another screen.
  *
  */
-void client_enter_fullscreen(xcb_connection_t *conn, Client *client) {
-        Workspace *workspace = client->workspace;
+void client_enter_fullscreen(xcb_connection_t *conn, Client *client, bool global) {
+        Workspace *workspace;
+        Rect r;
 
-        if (workspace->fullscreen_client != NULL) {
-                LOG("Not entering fullscreen mode, there already is a fullscreen client.\n");
-                return;
+        if (global) {
+                TAILQ_FOREACH(workspace, workspaces, workspaces) {
+                        if (workspace->fullscreen_client == NULL && workspace->fullscreen_client != client)
+                                continue;
+
+                        LOG("Not entering global fullscreen mode, there already is a fullscreen client.\n");
+                        return;
+                }
+
+                r = (Rect) { UINT_MAX, UINT_MAX, 0,0 };
+                Output *output;
+
+                /* Set fullscreen_client for each active workspace.
+                 * Expand the rectangle to contain all outputs. */
+                TAILQ_FOREACH(output, &outputs, outputs) {
+                        if(!output->active)
+                                continue;
+
+                        output->current_workspace->fullscreen_client = client;
+
+                        /* Temporarily abuse width/heigth as coordinates of the lower right corner */
+                        if(r.x > output->rect.x)
+                                r.x = output->rect.x;
+                        if(r.y > output->rect.y)
+                                r.y = output->rect.y;
+                        if(r.x + r.width < output->rect.x + output->rect.width)
+                                r.width = output->rect.x + output->rect.width;
+                        if(r.y + r.height < output->rect.y + output->rect.height)
+                                r.height = output->rect.y + output->rect.height;
+                }
+
+                /* Putting them back to their original meaning */
+                r.height -= r.x;
+                r.width -= r.y;
+
+                LOG("Entering global fullscreen mode...\n");
+        } else {
+                workspace = client->workspace;
+                if (workspace->fullscreen_client != NULL && workspace->fullscreen_client != client) {
+                        LOG("Not entering fullscreen mode, there already is a fullscreen client.\n");
+                        return;
+                }
+
+                workspace->fullscreen_client = client;
+                r = workspace->rect;
+
+                LOG("Entering fullscreen mode...\n");
         }
 
         client->fullscreen = true;
-        workspace->fullscreen_client = client;
-        LOG("Entering fullscreen mode...\n");
-        /* We just entered fullscreen mode, let’s configure the window */
-        Rect r = workspace->rect;
 
+        /* We just entered fullscreen mode, let’s configure the window */
         DLOG("child itself will be at %dx%d with size %dx%d\n",
                         r.x, r.y, r.width, r.height);
 
@@ -186,25 +229,17 @@ void client_enter_fullscreen(xcb_connection_t *conn, Client *client) {
 }
 
 /*
- * Toggles fullscreen mode for the given client. It updates the data structures and
- * reconfigures (= resizes/moves) the client and its frame to the full size of the
- * screen. When leaving fullscreen, re-rendering the layout is forced.
+ * Leaves fullscreen mode for the current client. This is called by toggle_fullscreen.
  *
  */
-void client_toggle_fullscreen(xcb_connection_t *conn, Client *client) {
-        /* dock clients cannot enter fullscreen mode */
-        assert(!client->dock);
-
-        Workspace *workspace = client->workspace;
-
-        if (!client->fullscreen) {
-                client_enter_fullscreen(conn, client);
-                return;
-        }
-
+void client_leave_fullscreen(xcb_connection_t *conn, Client *client) {
         LOG("leaving fullscreen mode\n");
         client->fullscreen = false;
-        workspace->fullscreen_client = NULL;
+        Workspace *ws;
+        TAILQ_FOREACH(ws, workspaces, workspaces)
+                if (ws->fullscreen_client == client)
+                        ws->fullscreen_client = NULL;
+
         if (client_is_floating(client)) {
                 /* For floating clients it’s enough if we just reconfigure that window (in fact,
                  * re-rendering the layout will not update the client.) */
@@ -225,6 +260,38 @@ void client_toggle_fullscreen(xcb_connection_t *conn, Client *client) {
         xcb_flush(conn);
 }
 
+/*
+ * Toggles fullscreen mode for the given client. It updates the data structures and
+ * reconfigures (= resizes/moves) the client and its frame to the full size of the
+ * screen. When leaving fullscreen, re-rendering the layout is forced.
+ *
+ */
+void client_toggle_fullscreen(xcb_connection_t *conn, Client *client) {
+        /* dock clients cannot enter fullscreen mode */
+        assert(!client->dock);
+
+        if (!client->fullscreen) {
+                client_enter_fullscreen(conn, client, false);
+        } else {
+                client_leave_fullscreen(conn, client);
+        }
+}
+
+/*
+ * Like client_toggle_fullscreen(), but putting it in global fullscreen-mode.
+ *
+ */
+void client_toggle_fullscreen_global(xcb_connection_t *conn, Client *client) {
+        /* dock clients cannot enter fullscreen mode */
+        assert(!client->dock);
+
+        if (!client->fullscreen) {
+                client_enter_fullscreen(conn, client, true);
+        } else {
+                client_leave_fullscreen(conn, client);
+        }
+}
+
 /*
  * Sets the position of the given client in the X stack to the highest (tiling layer is always
  * on the same position, so this doesn’t matter) below the first floating client, so that
index 184394b40323e747421206df634d4e903e1119f1..fd81e65c5b6bbe529a0109f07d33a1ff0457eb83 100644 (file)
@@ -629,7 +629,7 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa
         } else {
                 if (current_client->fullscreen) {
                         DLOG("Calling client_enter_fullscreen again\n");
-                        client_enter_fullscreen(conn, current_client);
+                        client_enter_fullscreen(conn, current_client, false);
                 }
         }
 
@@ -1021,11 +1021,14 @@ void parse_command(xcb_connection_t *conn, const char *command) {
                 return;
         }
 
-        /* Is it 'f' for fullscreen? */
+        /* Is it 'f' for fullscreen, or 'fg' for fullscreen_global? */
         if (command[0] == 'f') {
                 if (last_focused == NULL)
                         return;
-                client_toggle_fullscreen(conn, last_focused);
+                if (command[1] == 'g')
+                        client_toggle_fullscreen_global(conn, last_focused);
+                else
+                        client_toggle_fullscreen(conn, last_focused);
                 return;
         }
 
index a17560ed6b2ad81a79b8b71b8c127f641ca0c355..f3cc24c8a29114299862f6f77b3897d036bff6ba 100644 (file)
@@ -144,6 +144,12 @@ 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)
+                        client_enter_fullscreen(conn, client, false);
         }
 
         /* Check if we need to change something or if we’re already there */