Skip to content

Commit e59a76e

Browse files
d912e3stapelberg
authored andcommitted
Extend the fullscreen command
Rather than just toggling the fullscreen modes, allow to set them directly with: fullscreen enable|toggle [global] fullscreen disable For compatibility, retain the previous command and its toggling behavior: fullscreen [global] fixes i3#1120
1 parent dc351fb commit e59a76e

File tree

11 files changed

+273
-45
lines changed

11 files changed

+273
-45
lines changed

docs/userguide

+10-6
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ To display a window in fullscreen mode or to go out of fullscreen mode again,
9191
press +$mod+f+.
9292

9393
There is also a global fullscreen mode in i3 in which the client will span all
94-
available outputs (the command is +fullscreen global+).
94+
available outputs (the command is +fullscreen toggle global+).
9595

9696
=== Opening other applications
9797

@@ -367,7 +367,7 @@ bindcode [--release] [Modifiers+]keycode command
367367
*Examples*:
368368
--------------------------------
369369
# Fullscreen
370-
bindsym $mod+f fullscreen
370+
bindsym $mod+f fullscreen toggle
371371

372372
# Restart
373373
bindsym $mod+Shift+r restart
@@ -1502,9 +1502,13 @@ Use +layout toggle split+, +layout stacking+, +layout tabbed+, +layout splitv+
15021502
or +layout splith+ to change the current container layout to splith/splitv,
15031503
stacking, tabbed layout, splitv or splith, respectively.
15041504

1505-
To make the current window (!) fullscreen, use +fullscreen+, to make
1506-
it floating (or tiling again) use +floating enable+ respectively +floating disable+
1507-
(or +floating toggle+):
1505+
To make the current window (!) fullscreen, use +fullscreen enable+ (or
1506+
+fullscreen enable global+ for the global mode), to leave either fullscreen
1507+
mode use +fullscreen disable+, and to toggle between these two states use
1508+
+fullscreen toggle+ (or +fullscreen toggle global+).
1509+
1510+
Likewise, to make the current window floating (or tiling again) use +floating
1511+
enable+ respectively +floating disable+ (or +floating toggle+):
15081512

15091513
*Syntax*:
15101514
--------------
@@ -1525,7 +1529,7 @@ bindsym $mod+x layout toggle
15251529
bindsym $mod+x layout toggle all
15261530

15271531
# Toggle fullscreen
1528-
bindsym $mod+f fullscreen
1532+
bindsym $mod+f fullscreen toggle
15291533

15301534
# Toggle floating/tiling
15311535
bindsym $mod+t floating toggle

i3.config

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ bindsym Mod1+h split h
7575
bindsym Mod1+v split v
7676

7777
# enter fullscreen mode for the focused container
78-
bindsym Mod1+f fullscreen
78+
bindsym Mod1+f fullscreen toggle
7979

8080
# change container layout (stacked, tabbed, toggle split)
8181
bindsym Mod1+s layout stacking

i3.config.keycodes

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ bindcode $mod+43 split h
6969
bindcode $mod+55 split v
7070

7171
# enter fullscreen mode for the focused container
72-
bindcode $mod+41 fullscreen
72+
bindcode $mod+41 fullscreen toggle
7373

7474
# change container layout (stacked, tabbed, toggle split)
7575
bindcode $mod+39 layout stacking

include/commands.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,10 @@ void cmd_focus_level(I3_CMD, char *level);
187187
void cmd_focus(I3_CMD);
188188

189189
/**
190-
* Implementation of 'fullscreen [global]'.
190+
* Implementation of 'fullscreen [enable|disable|toggle] [global]'.
191191
*
192192
*/
193-
void cmd_fullscreen(I3_CMD, char *fullscreen_mode);
193+
void cmd_fullscreen(I3_CMD, char *action, char *fullscreen_mode);
194194

195195
/**
196196
* Implementation of 'move <direction> [<pixels> [px]]'.

include/con.h

+12
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ void con_fix_percent(Con *con);
172172
*/
173173
void con_toggle_fullscreen(Con *con, int fullscreen_mode);
174174

175+
/**
176+
* Enables fullscreen mode for the given container, if necessary.
177+
*
178+
*/
179+
void con_enable_fullscreen(Con *con, fullscreen_mode_t fullscreen_mode);
180+
181+
/**
182+
* Disables fullscreen mode for the given container, if necessary.
183+
*
184+
*/
185+
void con_disable_fullscreen(Con *con);
186+
175187
/**
176188
* Moves the given container to the currently focused container on the given
177189
* workspace.

man/i3.man

+1-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ bindsym Mod1+h split h
230230
bindsym Mod1+v split v
231231

232232
# enter fullscreen mode for the focused container
233-
bindsym Mod1+f fullscreen
233+
bindsym Mod1+f fullscreen toggle
234234

235235
# change container layout (stacked, tabbed, default)
236236
bindsym Mod1+s layout stacking

parser-specs/commands.spec

+19-3
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,28 @@ state KILL:
156156
end
157157
-> call cmd_kill($kill_mode)
158158

159+
# fullscreen enable|toggle [global]
160+
# fullscreen disable
159161
# fullscreen [global]
160162
state FULLSCREEN:
161-
fullscreen_mode = 'global'
162-
-> call cmd_fullscreen($fullscreen_mode)
163+
action = 'disable'
164+
-> call cmd_fullscreen($action, "output")
165+
action = 'enable', 'toggle'
166+
-> FULLSCREEN_MODE
167+
action = ''
168+
-> FULLSCREEN_COMPAT
169+
170+
state FULLSCREEN_MODE:
171+
mode = 'global'
172+
-> call cmd_fullscreen($action, $mode)
163173
end
164-
-> call cmd_fullscreen($fullscreen_mode)
174+
-> call cmd_fullscreen($action, "output")
175+
176+
state FULLSCREEN_COMPAT:
177+
mode = 'global'
178+
-> call cmd_fullscreen("toggle", $mode)
179+
end
180+
-> call cmd_fullscreen("toggle", "output")
165181

166182
# split v|h|vertical|horizontal
167183
state SPLIT:

src/commands.c

+12-6
Original file line numberDiff line numberDiff line change
@@ -1598,20 +1598,26 @@ void cmd_focus(I3_CMD) {
15981598
}
15991599

16001600
/*
1601-
* Implementation of 'fullscreen [global]'.
1601+
* Implementation of 'fullscreen enable|toggle [global]' and
1602+
* 'fullscreen disable'
16021603
*
16031604
*/
1604-
void cmd_fullscreen(I3_CMD, char *fullscreen_mode) {
1605-
if (fullscreen_mode == NULL)
1606-
fullscreen_mode = "output";
1607-
DLOG("toggling fullscreen, mode = %s\n", fullscreen_mode);
1605+
void cmd_fullscreen(I3_CMD, char *action, char *fullscreen_mode) {
1606+
fullscreen_mode_t mode = strcmp(fullscreen_mode, "global") == 0 ? CF_GLOBAL : CF_OUTPUT;
1607+
DLOG("%s fullscreen, mode = %s\n", action, fullscreen_mode);
16081608
owindow *current;
16091609

16101610
HANDLE_EMPTY_MATCH;
16111611

16121612
TAILQ_FOREACH(current, &owindows, owindows) {
16131613
DLOG("matching: %p / %s\n", current->con, current->con->name);
1614-
con_toggle_fullscreen(current->con, (strcmp(fullscreen_mode, "global") == 0 ? CF_GLOBAL : CF_OUTPUT));
1614+
if (strcmp(action, "toggle") == 0) {
1615+
con_toggle_fullscreen(current->con, mode);
1616+
} else if (strcmp(action, "enable") == 0) {
1617+
con_enable_fullscreen(current->con, mode);
1618+
} else if (strcmp(action, "disable") == 0) {
1619+
con_disable_fullscreen(current->con);
1620+
}
16151621
}
16161622

16171623
cmd_output->needs_tree_render = true;

src/con.c

+87-24
Original file line numberDiff line numberDiff line change
@@ -565,37 +565,27 @@ void con_fix_percent(Con *con) {
565565
*
566566
*/
567567
void con_toggle_fullscreen(Con *con, int fullscreen_mode) {
568-
Con *workspace, *fullscreen;
569-
570568
if (con->type == CT_WORKSPACE) {
571569
DLOG("You cannot make a workspace fullscreen.\n");
572570
return;
573571
}
574572

575573
DLOG("toggling fullscreen for %p / %s\n", con, con->name);
576-
if (con->fullscreen_mode == CF_NONE) {
577-
/* 1: check if there already is a fullscreen con */
578-
if (fullscreen_mode == CF_GLOBAL)
579-
fullscreen = con_get_fullscreen_con(croot, CF_GLOBAL);
580-
else {
581-
workspace = con_get_workspace(con);
582-
fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT);
583-
}
584-
if (fullscreen != NULL) {
585-
/* Disable fullscreen for the currently fullscreened
586-
* container and enable it for the one the user wants
587-
* to have in fullscreen mode. */
588-
LOG("Disabling fullscreen for (%p/%s) upon user request\n",
589-
fullscreen, fullscreen->name);
590-
fullscreen->fullscreen_mode = CF_NONE;
591-
}
592574

593-
/* 2: enable fullscreen */
594-
con->fullscreen_mode = fullscreen_mode;
595-
} else {
596-
/* 1: disable fullscreen */
597-
con->fullscreen_mode = CF_NONE;
598-
}
575+
if (con->fullscreen_mode == CF_NONE)
576+
con_enable_fullscreen(con, fullscreen_mode);
577+
else
578+
con_disable_fullscreen(con);
579+
}
580+
581+
/*
582+
* Sets the specified fullscreen mode for the given container, sends the
583+
* “fullscreen_mode” event and changes the XCB fullscreen property of the
584+
* container’s window, if any.
585+
*
586+
*/
587+
static void con_set_fullscreen_mode(Con *con, fullscreen_mode_t fullscreen_mode) {
588+
con->fullscreen_mode = fullscreen_mode;
599589

600590
DLOG("mode now: %d\n", con->fullscreen_mode);
601591

@@ -618,6 +608,79 @@ void con_toggle_fullscreen(Con *con, int fullscreen_mode) {
618608
A__NET_WM_STATE, XCB_ATOM_ATOM, 32, num, values);
619609
}
620610

611+
/*
612+
* Enables fullscreen mode for the given container, if necessary.
613+
*
614+
* If the container’s mode is already CF_OUTPUT or CF_GLOBAL, the container is
615+
* kept fullscreen but its mode is set to CF_GLOBAL and CF_OUTPUT,
616+
* respectively.
617+
*
618+
* Other fullscreen containers will be disabled first, if they hide the new
619+
* one.
620+
*
621+
*/
622+
void con_enable_fullscreen(Con *con, fullscreen_mode_t fullscreen_mode) {
623+
if (con->type == CT_WORKSPACE) {
624+
DLOG("You cannot make a workspace fullscreen.\n");
625+
return;
626+
}
627+
628+
assert(fullscreen_mode == CF_GLOBAL || fullscreen_mode == CF_OUTPUT);
629+
630+
if (fullscreen_mode == CF_GLOBAL)
631+
DLOG("enabling global fullscreen for %p / %s\n", con, con->name);
632+
else
633+
DLOG("enabling fullscreen for %p / %s\n", con, con->name);
634+
635+
if (con->fullscreen_mode == fullscreen_mode) {
636+
DLOG("fullscreen already enabled for %p / %s\n", con, con->name);
637+
return;
638+
}
639+
640+
Con *con_ws = con_get_workspace(con);
641+
642+
/* Disable any fullscreen container that would conflict the new one. */
643+
Con *fullscreen = con_get_fullscreen_con(croot, CF_GLOBAL);
644+
if (fullscreen == NULL)
645+
fullscreen = con_get_fullscreen_con(con_ws, CF_OUTPUT);
646+
if (fullscreen != NULL)
647+
con_disable_fullscreen(fullscreen);
648+
649+
/* Set focus to new fullscreen container. Unless in global fullscreen mode
650+
* and on another workspace restore focus afterwards.
651+
* Switch to the container’s workspace if mode is global. */
652+
Con *cur_ws = con_get_workspace(focused);
653+
Con *old_focused = focused;
654+
if (fullscreen_mode == CF_GLOBAL && cur_ws != con_ws)
655+
workspace_show(con_ws);
656+
con_focus(con);
657+
if (fullscreen_mode != CF_GLOBAL && cur_ws != con_ws)
658+
con_focus(old_focused);
659+
660+
con_set_fullscreen_mode(con, fullscreen_mode);
661+
}
662+
663+
/*
664+
* Disables fullscreen mode for the given container regardless of the mode, if
665+
* necessary.
666+
*
667+
*/
668+
void con_disable_fullscreen(Con *con) {
669+
if (con->type == CT_WORKSPACE) {
670+
DLOG("You cannot make a workspace fullscreen.\n");
671+
return;
672+
}
673+
674+
DLOG("disabling fullscreen for %p / %s\n", con, con->name);
675+
676+
if (con->fullscreen_mode == CF_NONE) {
677+
DLOG("fullscreen already disabled for %p / %s\n", con, con->name);
678+
return;
679+
}
680+
681+
con_set_fullscreen_mode(con, CF_NONE);
682+
}
683+
621684
/*
622685
* Moves the given container to the currently focused container on the given
623686
* workspace.

testcases/i3-test.config

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ bindsym Mod1+h split h
2020
bindsym Mod1+v split v
2121

2222
# Fullscreen (Mod1+f)
23-
bindsym Mod1+f fullscreen
23+
bindsym Mod1+f fullscreen toggle
2424

2525
# Stacking (Mod1+s)
2626
bindsym Mod1+s layout stacking

0 commit comments

Comments
 (0)