]> git.sur5r.net Git - i3/i3/commitdiff
Implement 'fullscreen global'
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 10 Jun 2011 16:27:20 +0000 (18:27 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 10 Jun 2011 16:27:20 +0000 (18:27 +0200)
13 files changed:
docs/userguide
include/con.h
include/tree.h
src/cmdparse.y
src/con.c
src/handlers.c
src/ipc.c
src/main.c
src/manage.c
src/render.c
src/tree.c
src/workspace.c
src/x.c

index 0cdb2566ff4bee7444bfc870f3284f0a4c5f1887..6c5ba10b352e9c656857a37297d8e746bd486f55 100644 (file)
@@ -99,12 +99,8 @@ image:modes.png[Container modes]
 To display a window fullscreen or to go out of fullscreen mode again, press
 +mod+f+.
 
-/////////////////////////////////////////////////////////////////////////////
-TODO: not yet implemented
-
 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 +mod+Shift+f+.
-/////////////////////////////////////////////////////////////////////////////
 
 === Opening other applications
 
index 37bca3bb07a1056bfde43c4c825b7aac55e3c600..6ce7bf840c975a8e2641c85908609e30e409cf72 100644 (file)
@@ -53,7 +53,7 @@ Con *con_parent_with_orientation(Con *con, orientation_t orientation);
  * Returns the first fullscreen node below this node.
  *
  */
-Con *con_get_fullscreen_con(Con *con);
+Con *con_get_fullscreen_con(Con *con, int fullscreen_mode);
 
 /**
  * Returns true if the node is floating.
@@ -126,7 +126,7 @@ void con_fix_percent(Con *con);
  * entered when there already is a fullscreen container on this workspace.
  *
  */
-void con_toggle_fullscreen(Con *con);
+void con_toggle_fullscreen(Con *con, int fullscreen_mode);
 
 /**
  * Moves the given container to the currently focused container on the given
index b66aa3f7ae7b27366d71cc2ad1f1748abbc8d6c1..b9bf7f54ae0ce9baeee18803a69bd859f0becb36 100644 (file)
@@ -18,7 +18,7 @@ extern struct all_cons_head all_cons;
  * assigning a workspace to each RandR output.
  *
  */
-void tree_init();
+void tree_init(xcb_get_geometry_reply_t *geometry);
 
 /**
  * Opens an empty container in the current container
@@ -77,7 +77,7 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent);
  * Loads tree from ~/.i3/_restart.json (used for in-place restarts).
  *
  */
-bool tree_restore(const char *path);
+bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry);
 
 /**
  * tree_flatten() removes pairs of redundant split containers, e.g.:
index 1c65fbc544bfdb2ed6991a03807770b166d2f1ff..fbc2307f2c7f7953970c4f6a9c9ec7b68e55cded 100644 (file)
@@ -173,6 +173,7 @@ char *parse_cmd(const char *new) {
 
 %type   <number>    direction
 %type   <number>    split_direction
+%type   <number>    fullscreen_mode
 %type   <number>    level
 %type   <number>    boolean
 %type   <number>    border_style
@@ -521,23 +522,27 @@ open:
     ;
 
 fullscreen:
-    TOK_FULLSCREEN
+    TOK_FULLSCREEN fullscreen_mode
     {
-        printf("toggling fullscreen\n");
+        printf("toggling fullscreen, mode = %s\n", ($2 == CF_OUTPUT ? "normal" : "global"));
         owindow *current;
 
-
         HANDLE_EMPTY_MATCH;
 
         TAILQ_FOREACH(current, &owindows, owindows) {
             printf("matching: %p / %s\n", current->con, current->con->name);
-            con_toggle_fullscreen(current->con);
+            con_toggle_fullscreen(current->con, $2);
         }
 
         tree_render();
     }
     ;
 
+fullscreen_mode:
+    /* empty */  { $$ = CF_OUTPUT; }
+    | TOK_GLOBAL { $$ = CF_GLOBAL; }
+    ;
+
 split:
     TOK_SPLIT split_direction
     {
index 1a45076afc84c84f62577870596241ea6454cd70..185cbd3f232fd51a3f500ff8a9e3a2447a4dc10f 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -290,7 +290,7 @@ struct bfs_entry {
  * Returns the first fullscreen node below this node.
  *
  */
-Con *con_get_fullscreen_con(Con *con) {
+Con *con_get_fullscreen_con(Con *con, int fullscreen_mode) {
     Con *current, *child;
 
     /* TODO: is breadth-first-search really appropriate? (check as soon as
@@ -303,7 +303,7 @@ Con *con_get_fullscreen_con(Con *con) {
     while (!TAILQ_EMPTY(&bfs_head)) {
         entry = TAILQ_FIRST(&bfs_head);
         current = entry->con;
-        if (current != con && current->fullscreen_mode != CF_NONE) {
+        if (current != con && current->fullscreen_mode == fullscreen_mode) {
             /* empty the queue */
             while (!TAILQ_EMPTY(&bfs_head)) {
                 entry = TAILQ_FIRST(&bfs_head);
@@ -490,7 +490,7 @@ void con_fix_percent(Con *con) {
  * entered when there already is a fullscreen container on this workspace.
  *
  */
-void con_toggle_fullscreen(Con *con) {
+void con_toggle_fullscreen(Con *con, int fullscreen_mode) {
     Con *workspace, *fullscreen;
 
     if (con->type == CT_WORKSPACE) {
@@ -501,19 +501,27 @@ void con_toggle_fullscreen(Con *con) {
     DLOG("toggling fullscreen for %p / %s\n", con, con->name);
     if (con->fullscreen_mode == CF_NONE) {
         /* 1: check if there already is a fullscreen con */
-        workspace = con_get_workspace(con);
-        if ((fullscreen = con_get_fullscreen_con(workspace)) != NULL) {
+        if (fullscreen_mode == CF_GLOBAL)
+            fullscreen = con_get_fullscreen_con(croot, CF_GLOBAL);
+        else {
+            workspace = con_get_workspace(con);
+            fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT);
+        }
+        if (fullscreen != NULL) {
             LOG("Not entering fullscreen mode, container (%p/%s) "
                 "already is in fullscreen mode\n",
                 fullscreen, fullscreen->name);
-        } else {
-            /* 2: enable fullscreen */
-            con->fullscreen_mode = CF_OUTPUT;
+            goto update_netwm_state;
         }
+
+        /* 2: enable fullscreen */
+        con->fullscreen_mode = fullscreen_mode;
     } else {
         /* 1: disable fullscreen */
         con->fullscreen_mode = CF_NONE;
     }
+
+update_netwm_state:
     DLOG("mode now: %d\n", con->fullscreen_mode);
 
     /* update _NET_WM_STATE if this container has a window */
@@ -797,7 +805,7 @@ Rect con_border_style_rect(Con *con) {
  *
  */
 int con_border_style(Con *con) {
-    Con *fs = con_get_fullscreen_con(con->parent);
+    Con *fs = con_get_fullscreen_con(con->parent, CF_OUTPUT);
     if (fs == con) {
         DLOG("this one is fullscreen! overriding BS_NONE\n");
         return BS_NONE;
index eaf71ddb2301b52d2745fa8b8a62a59ce4849744..b97dd043ad88397338e53625ed263ed90c3575c0 100644 (file)
@@ -648,7 +648,7 @@ static int handle_client_message(xcb_client_message_event_t *event) {
              (event->data.data32[0] == _NET_WM_STATE_ADD ||
               event->data.data32[0] == _NET_WM_STATE_TOGGLE))) {
             DLOG("toggling fullscreen\n");
-            con_toggle_fullscreen(con);
+            con_toggle_fullscreen(con, CF_OUTPUT);
         }
 
         tree_render();
index fa3513bc352ee74dba2879ff644d981c265943f5..1dd9512a55ec79cca14b29a8fc5d5ac0f1a48832 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -437,7 +437,7 @@ IPC_HANDLER(get_outputs) {
 
         ystr("current_workspace");
         Con *ws = NULL;
-        if (output->con && (ws = con_get_fullscreen_con(output->con)))
+        if (output->con && (ws = con_get_fullscreen_con(output->con, CF_OUTPUT)))
             ystr(ws->name);
         else y(null);
 
index c079d8dce8cd1fbbeeadbdb7a5e95a4a84d8ee97..b4ed4a1a061cc18b15cc0b68e5857ed066551063 100644 (file)
@@ -257,6 +257,7 @@ int main(int argc, char *argv[]) {
     xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screens);
     root = root_screen->root;
     root_depth = root_screen->root_depth;
+    xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root);
 
     load_configuration(conn, override_configpath, false);
     if (only_check_config) {
@@ -284,6 +285,13 @@ int main(int argc, char *argv[]) {
     cookie = xcb_change_window_attributes_checked(conn, root, mask, values);
     check_error(conn, cookie, "Another window manager seems to be running");
 
+    xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
+    if (greply == NULL) {
+        ELOG("Could not get geometry of the root window, exiting\n");
+        return 1;
+    }
+    DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
+
     /* Place requests for the atoms we need as soon as possible */
     #define xmacro(atom) \
         xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
@@ -368,13 +376,15 @@ int main(int argc, char *argv[]) {
     bool needs_tree_init = true;
     if (layout_path) {
         LOG("Trying to restore the layout from %s...", layout_path);
-        needs_tree_init = !tree_restore(layout_path);
+        needs_tree_init = !tree_restore(layout_path, greply);
         if (delete_layout_path)
             unlink(layout_path);
         free(layout_path);
     }
     if (needs_tree_init)
-        tree_init();
+        tree_init(greply);
+
+    free(greply);
 
     if (force_xinerama) {
         xinerama_init();
index 85beb4cb8e2c21b7718b26235840254c2a526aff..e609501a46d324dda80eaa105472599754db7f1c 100644 (file)
@@ -251,7 +251,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     free(name);
 
     Con *ws = con_get_workspace(nc);
-    Con *fs = (ws ? con_get_fullscreen_con(ws) : NULL);
+    Con *fs = (ws ? con_get_fullscreen_con(ws, CF_OUTPUT) : NULL);
+    if (fs == NULL)
+        fs = con_get_fullscreen_con(croot, CF_GLOBAL);
 
     if (fs == NULL) {
         DLOG("Not in fullscreen mode, focusing\n");
@@ -293,7 +295,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
         if (config.popup_during_fullscreen == PDF_LEAVE_FULLSCREEN &&
             fs != NULL) {
             LOG("There is a fullscreen window, leaving fullscreen mode\n");
-            con_toggle_fullscreen(fs);
+            con_toggle_fullscreen(fs, CF_OUTPUT);
         }
     }
 
@@ -331,7 +333,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
 
     reply = xcb_get_property_reply(conn, state_cookie, NULL);
     if (xcb_reply_contains_atom(reply, A__NET_WM_STATE_FULLSCREEN))
-        con_toggle_fullscreen(nc);
+        con_toggle_fullscreen(nc, CF_OUTPUT);
 
     /* Put the client inside the save set. Upon termination (whether killed or
      * normal exit does not matter) of the window manager, these clients will
index a59d418b402b8f35e5afee1bc167c35b7c5023e9..b1388b3145fb66638ca37914a4b4122c2f3af592 100644 (file)
@@ -42,8 +42,8 @@ static void render_l_output(Con *con) {
     /* We need to find out if there is a fullscreen con on the current workspace
      * and take the short-cut to render it directly (the user does not want to
      * see the dockareas in that case) */
-    Con *ws = con_get_fullscreen_con(content);
-    Con *fullscreen = con_get_fullscreen_con(ws);
+    Con *ws = con_get_fullscreen_con(content, CF_OUTPUT);
+    Con *fullscreen = con_get_fullscreen_con(ws, CF_OUTPUT);
     if (fullscreen) {
         DLOG("got fs node: %p\n", fullscreen);
         fullscreen->rect = con->rect;
@@ -185,7 +185,10 @@ void render_con(Con *con, bool render_fullscreen) {
     }
 
     /* Check for fullscreen nodes */
-    Con *fullscreen = (con->type == CT_OUTPUT ? NULL : con_get_fullscreen_con(con));
+    Con *fullscreen = NULL;
+    if (con->type != CT_OUTPUT) {
+        fullscreen = con_get_fullscreen_con(con, (con->type == CT_ROOT ? CF_GLOBAL : CF_OUTPUT));
+    }
     if (fullscreen) {
         DLOG("got fs node: %p\n", fullscreen);
         fullscreen->rect = rect;
@@ -222,6 +225,12 @@ void render_con(Con *con, bool render_fullscreen) {
 
     if (con->layout == L_OUTPUT) {
         render_l_output(con);
+    } else if (con->type == CT_ROOT) {
+        DLOG("Root node, rendering outputs\n");
+        Con *child;
+        TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+            render_con(child, false);
+        }
     } else {
 
         /* FIXME: refactor this into separate functions: */
index a32723dfcb576f870bdcc46b3fb0883054b150c5..7e006485093a3928925c29bbf7824bc5683034ee 100644 (file)
@@ -13,7 +13,7 @@ struct all_cons_head all_cons = TAILQ_HEAD_INITIALIZER(all_cons);
  * Loads tree from ~/.i3/_restart.json (used for in-place restarts).
  *
  */
-bool tree_restore(const char *path) {
+bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry) {
     char *globbed = resolve_tilde(path);
 
     if (!path_exists(globbed)) {
@@ -24,6 +24,12 @@ bool tree_restore(const char *path) {
 
     /* TODO: refactor the following */
     croot = con_new(NULL, NULL);
+    croot->rect = (Rect){
+        geometry->x,
+        geometry->y,
+        geometry->width,
+        geometry->height
+    };
     focused = croot;
 
     tree_append_json(globbed);
@@ -44,11 +50,17 @@ bool tree_restore(const char *path) {
  * root node are created in randr.c for each Output.
  *
  */
-void tree_init() {
+void tree_init(xcb_get_geometry_reply_t *geometry) {
     croot = con_new(NULL, NULL);
     FREE(croot->name);
     croot->name = "root";
     croot->type = CT_ROOT;
+    croot->rect = (Rect){
+        geometry->x,
+        geometry->y,
+        geometry->width,
+        geometry->height
+    };
 }
 
 /*
@@ -343,12 +355,8 @@ void tree_render() {
     mark_unmapped(croot);
     croot->mapped = true;
 
-    /* We start rendering at an output */
-    Con *output;
-    TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
-        DLOG("output %p / %s\n", output, output->name);
-        render_con(output, false);
-    }
+    render_con(croot, false);
+
     x_push_changes(croot);
     DLOG("-- END RENDERING --\n");
 }
index ec57df8d43f91b073eec8337fca73b5bc2e46fd8..4021dd14419abbdf01bf6534ff52638171a18454 100644 (file)
@@ -95,7 +95,7 @@ bool workspace_is_visible(Con *ws) {
     Con *output = con_get_output(ws);
     if (output == NULL)
         return false;
-    Con *fs = con_get_fullscreen_con(output);
+    Con *fs = con_get_fullscreen_con(output, CF_OUTPUT);
     LOG("workspace visible? fs = %p, ws = %p\n", fs, ws);
     return (fs == ws);
 }
diff --git a/src/x.c b/src/x.c
index 0228cd23100e802cfc82c9bf5ff660177bb8d018..64f5394b62a17613271aac83dec180220e878dce 100644 (file)
--- a/src/x.c
+++ b/src/x.c
@@ -308,7 +308,7 @@ void x_draw_decoration(Con *con) {
 
     /* If the con is in fullscreen mode, the decoration height we work with is set to 0 */
     Rect deco_rect = con->deco_rect;
-    if (con_get_fullscreen_con(parent) == con)
+    if (con_get_fullscreen_con(parent, CF_OUTPUT) == con)
         deco_rect.height = 0;
 
     /* 2: draw the client.background, but only for the parts around the client_rect */