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
* 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.
* 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
* 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
* 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.:
%type <number> direction
%type <number> split_direction
+%type <number> fullscreen_mode
%type <number> level
%type <number> boolean
%type <number> border_style
;
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
{
* 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
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);
* 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) {
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 */
*
*/
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;
(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();
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);
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) {
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);
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();
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");
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);
}
}
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
/* 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;
}
/* 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;
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: */
* 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)) {
/* 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);
* 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
+ };
}
/*
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");
}
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);
}
/* 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 */