Implement screen-spanning fullscreen-mode (command: 'fg')
This closes ticket #188
This commit is contained in:
parent
496106cd44
commit
9c77b0f9a1
|
@ -86,6 +86,9 @@ image:modes.png[Container modes]
|
||||||
To display a window fullscreen or to go out of fullscreen mode again, press
|
To display a window fullscreen or to go out of fullscreen mode again, press
|
||||||
+Mod1+f+.
|
+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
|
=== Opening other applications
|
||||||
|
|
||||||
Aside from opening applicatios from a terminal, you can also use the handy
|
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
|
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 +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*:
|
*Examples*:
|
||||||
--------------
|
--------------
|
||||||
|
@ -526,6 +530,9 @@ bindsym Mod1+w T
|
||||||
# Toggle fullscreen
|
# Toggle fullscreen
|
||||||
bindsym Mod1+f f
|
bindsym Mod1+f f
|
||||||
|
|
||||||
|
# Toggle global fullscreen
|
||||||
|
bindsym Mod1+Shift+f fg
|
||||||
|
|
||||||
# Toggle floating/tiling
|
# Toggle floating/tiling
|
||||||
bindsym Mod1+t t
|
bindsym Mod1+t t
|
||||||
--------------
|
--------------
|
||||||
|
|
|
@ -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.
|
* 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
|
* 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);
|
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
|
* 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
|
* layer is always on the same position, so this doesn’t matter) below the
|
||||||
|
|
115
src/client.c
115
src/client.c
|
@ -13,6 +13,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_icccm.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.
|
* 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) {
|
||||||
Workspace *workspace = client->workspace;
|
Workspace *workspace;
|
||||||
|
Rect r;
|
||||||
|
|
||||||
if (workspace->fullscreen_client != NULL) {
|
if (global) {
|
||||||
LOG("Not entering fullscreen mode, there already is a fullscreen client.\n");
|
TAILQ_FOREACH(workspace, workspaces, workspaces) {
|
||||||
return;
|
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;
|
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",
|
DLOG("child itself will be at %dx%d with size %dx%d\n",
|
||||||
r.x, r.y, r.width, r.height);
|
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
|
* Leaves fullscreen mode for the current client. This is called by toggle_fullscreen.
|
||||||
* 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) {
|
void client_leave_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG("leaving fullscreen mode\n");
|
LOG("leaving fullscreen mode\n");
|
||||||
client->fullscreen = false;
|
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)) {
|
if (client_is_floating(client)) {
|
||||||
/* For floating clients it’s enough if we just reconfigure that window (in fact,
|
/* For floating clients it’s enough if we just reconfigure that window (in fact,
|
||||||
* re-rendering the layout will not update the client.) */
|
* 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);
|
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
|
* 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
|
* on the same position, so this doesn’t matter) below the first floating client, so that
|
||||||
|
|
|
@ -629,7 +629,7 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa
|
||||||
} else {
|
} else {
|
||||||
if (current_client->fullscreen) {
|
if (current_client->fullscreen) {
|
||||||
DLOG("Calling client_enter_fullscreen again\n");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is it 'f' for fullscreen? */
|
/* Is it 'f' for fullscreen, or 'fg' for fullscreen_global? */
|
||||||
if (command[0] == 'f') {
|
if (command[0] == 'f') {
|
||||||
if (last_focused == NULL)
|
if (last_focused == NULL)
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,12 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
|
||||||
if ((old_client != NULL) && !old_client->dock)
|
if ((old_client != NULL) && !old_client->dock)
|
||||||
redecorate_window(conn, old_client);
|
redecorate_window(conn, old_client);
|
||||||
else xcb_flush(conn);
|
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 */
|
/* Check if we need to change something or if we’re already there */
|
||||||
|
|
Loading…
Reference in New Issue