]> git.lizzy.rs Git - bspwm.git/commitdiff
Make a clear distinction between states and flags
authorBastien Dejean <nihilhill@gmail.com>
Thu, 5 Nov 2015 13:00:49 +0000 (14:00 +0100)
committerBastien Dejean <nihilhill@gmail.com>
Thu, 5 Nov 2015 13:00:49 +0000 (14:00 +0100)
22 files changed:
Sourcedeps
desktop.c
doc/bspwm.1
doc/bspwm.1.txt
events.c
examples/bspwmrc
examples/sxhkdrc
helpers.h
messages.c
messages.h
monitor.c
pointer.c
query.c
restore.c
rule.c
stack.c
stack.h
subscribe.h
tree.c
types.h
window.c
window.h

index 5c9320726d8f631acb2474bf97d15b298c5865c6..894f69eb46333b455003ab4622a055ff74b1011a 100644 (file)
@@ -1,18 +1,18 @@
 bspc.o: bspc.c common.h helpers.h
 bspwm.o: bspwm.c bspwm.h common.h desktop.h events.h ewmh.h helpers.h history.h messages.h monitor.h rule.h settings.h stack.h subscribe.h types.h window.h
-desktop.o: desktop.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h tree.h types.h window.h
+desktop.o: desktop.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h subscribe.h tree.h types.h window.h
 events.o: events.c bspwm.h events.h ewmh.h helpers.h monitor.h query.h settings.h tree.h types.h window.h
 ewmh.o: ewmh.c bspwm.h ewmh.h helpers.h settings.h tree.h types.h
 helpers.o: helpers.c bspwm.h helpers.h types.h
 history.o: history.c bspwm.h helpers.h query.h types.h
 messages.o: messages.c bspwm.h common.h desktop.h ewmh.h helpers.h history.h messages.h monitor.h pointer.h query.h restore.h rule.h settings.h subscribe.h tree.h types.h window.h
-monitor.o: monitor.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h tree.h types.h window.h
+monitor.o: monitor.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h subscribe.h tree.h types.h window.h
 pointer.o: pointer.c bspwm.h helpers.h monitor.h pointer.h query.h settings.h stack.h tree.h types.h window.h
-query.o: query.c bspwm.h desktop.h helpers.h history.h messages.h monitor.h query.h tree.h types.h
+query.o: query.c bspwm.h desktop.h helpers.h history.h messages.h monitor.h query.h subscribe.h tree.h types.h
 restore.o: restore.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h restore.h settings.h stack.h tree.h types.h
-rule.o: rule.c bspwm.h ewmh.h helpers.h messages.h rule.h settings.h types.h window.h
+rule.o: rule.c bspwm.h ewmh.h helpers.h messages.h rule.h settings.h subscribe.h types.h window.h
 settings.o: settings.c bspwm.h helpers.h settings.h types.h
 stack.o: stack.c bspwm.h helpers.h stack.h types.h window.h
 subscribe.o: subscribe.c bspwm.h helpers.h settings.h subscribe.h tree.h types.h
-tree.o: tree.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h stack.h tree.h types.h window.h
-window.o: window.c bspwm.h ewmh.h helpers.h messages.h monitor.h query.h rule.h settings.h stack.h tree.h types.h window.h
+tree.o: tree.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h stack.h subscribe.h tree.h types.h window.h
+window.o: window.c bspwm.h ewmh.h helpers.h messages.h monitor.h query.h rule.h settings.h stack.h subscribe.h tree.h types.h window.h
index 1e44bacd9c9705df9dd59a06036d2de49146d616..3e45340a34afe87a6262f4c0ba3fdf1af7f7852a 100644 (file)
--- a/desktop.c
+++ b/desktop.c
@@ -76,8 +76,9 @@ void change_layout(monitor_t *m, desktop_t *d, layout_t l)
        put_status(SBSC_MASK_DESKTOP_LAYOUT, "desktop_layout %s %s %s\n", m->name, d->name, l==LAYOUT_TILED?"tiled":"monocle");
        d->layout = l;
        arrange(m, d);
-       if (d == m->desk)
+       if (d == m->desk) {
                put_status(SBSC_MASK_REPORT);
+       }
 }
 
 void transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d)
@@ -92,19 +93,23 @@ void transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d)
        insert_desktop(md, d);
 
        if (d == dd) {
-               if (ms->desk != NULL)
+               if (ms->desk != NULL) {
                        show_desktop(ms->desk);
-               if (md->desk != d)
+               }
+               if (md->desk != d) {
                        hide_desktop(d);
+               }
        }
 
-       for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
+       for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
                translate_client(ms, md, n->client);
+       }
 
        arrange(md, d);
 
-       if (d != dd && md->desk == d)
+       if (d != dd && md->desk == d) {
                show_desktop(d);
+       }
 
        history_transfer_desktop(md, d);
 
@@ -139,7 +144,6 @@ void initialize_desktop(desktop_t *d)
        d->top_padding = d->right_padding = d->bottom_padding = d->left_padding = 0;
        d->window_gap = window_gap;
        d->border_width = border_width;
-       d->floating = false;
 }
 
 void insert_desktop(monitor_t *m, desktop_t *d)
index 38f9c0d723bc12aee16d05724a352c5750f920bd..5ecfdd2303250745f4cf4a52e3e7580a45c82826 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: bspwm
 .\"    Author: [see the "Author" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 10/27/2015
+.\"      Date: 11/05/2015
 .\"    Manual: Bspwm Manual
 .\"    Source: Bspwm 0.9
 .\"  Language: English
 .\"
-.TH "BSPWM" "1" "10/27/2015" "Bspwm 0\&.9" "Bspwm Manual"
+.TH "BSPWM" "1" "11/05/2015" "Bspwm 0\&.9" "Bspwm Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -167,7 +167,7 @@ Select a window\&.
 .\}
 .nf
 WINDOW_SEL := <window_id>
-            | (DIR|CYCLE_DIR|biggest|last|focused|older|newer)[\&.floating|\&.tiled][\&.like|\&.unlike][\&.manual|\&.automatic][\&.urgent|\&.nonurgent][\&.local|\&.foreign][\&.focused|\&.unfocused][\&.below|\&.normal|\&.above][\&.fullscreen|\&.nonfullscreen][\&.sticky|\&.nonsticky][\&.public|\&.private][\&.locked|\&.unlocked][\&.pseudotiled|\&.nonpseudotiled]
+            | (DIR|CYCLE_DIR|biggest|last|focused|older|newer)[\&.manual|\&.automatic][\&.tiled|nontiled][\&.pseudotiled|\&.nonpseudotiled][\&.floating|\&.nonfloating][\&.fullscreen|\&.nonfullscreen][\&.below|\&.normal|\&.above][\&.local|\&.foreign][\&.like|\&.unlike][\&.focused|\&.unfocused][\&.urgent|\&.nonurgent][\&.sticky|\&.nonsticky][\&.public|\&.private][\&.locked|\&.unlocked]
 .fi
 .if n \{\
 .RE
@@ -225,134 +225,139 @@ Selects the window newer than the focused window in the history\&.
 \fBModifiers\fR
 .RS 4
 .PP
-floating
+tiled
 .RS 4
-Only consider floating windows\&.
+Only consider tiled windows\&.
 .RE
 .PP
-tiled
+nontiled
 .RS 4
 Only consider tiled windows\&.
 .RE
 .PP
-like
+pseudotiled
 .RS 4
-Only consider windows that have the same class as the current window\&.
+Only consider pseudo\-tiled windows\&.
 .RE
 .PP
-unlike
+nonpseudotiled
 .RS 4
-Only consider windows that have a different class than the current window\&.
+Only consider non pseudo\-tiled windows\&.
 .RE
 .PP
-manual
+floating
 .RS 4
-Only consider windows in manual splitting mode\&.
+Only consider floating windows\&.
 .RE
 .PP
-automatic
+nonfloating
 .RS 4
-Only consider windows in automatic splitting mode\&.
+Only consider non floating windows\&.
 .RE
 .PP
-local
+fullscreen
 .RS 4
-Only consider windows of the current desktop\&.
+Only consider fullscreen windows\&.
 .RE
 .PP
-foreign
+nonfullscreen
 .RS 4
-Only consider windows outside of the current desktop\&.
+Only consider non fullscreen windows\&.
 .RE
 .PP
-private
+manual
 .RS 4
-Only consider private windows\&.
+Only consider windows in manual splitting mode\&.
 .RE
 .PP
-public
+automatic
 .RS 4
-Only consider non private windows\&.
+Only consider windows in automatic splitting mode\&.
 .RE
 .PP
-urgent
+focused
 .RS 4
-Only consider urgent windows\&.
+Only consider focused windows\&.
 .RE
 .PP
-nonurgent
+unfocused
 .RS 4
-Only consider non urgent windows\&.
+Only consider unfocused windows\&.
 .RE
 .PP
-pseudotiled
+below
 .RS 4
-Only consider pseudo\-tiled windows\&.
+Only consider windows of the BELOW layer\&.
 .RE
 .PP
-nonpseudotiled
+normal
 .RS 4
-Only consider non pseudo\-tiled windows\&.
+Only consider windows of the NORMAL layer\&.
 .RE
 .PP
-sticky
+above
 .RS 4
-Only consider sticky windows\&.
+Only consider windows of the ABOVE layer\&.
 .RE
 .PP
-nonsticky
+like
 .RS 4
-Only consider non sticky windows\&.
+Only consider windows that have the same class as the current window\&.
 .RE
 .PP
-locked
+unlike
 .RS 4
-Only consider locked windows\&.
+Only consider windows that have a different class than the current window\&.
 .RE
 .PP
-unlocked
+local
 .RS 4
-Only consider non locked windows\&.
+Only consider windows of the current desktop\&.
 .RE
 .PP
-nonfullscreen
+foreign
 .RS 4
-Only consider non fullscreen windows\&.
+Only consider windows outside of the current desktop\&.
 .RE
 .PP
-fullscreen
+private
 .RS 4
-Only consider fullscreen windows\&.
+Only consider private windows\&.
 .RE
 .PP
-nonfullscreen
+public
 .RS 4
-Only consider non fullscreen windows\&.
+Only consider non private windows\&.
 .RE
 .PP
-focused
+urgent
 .RS 4
-Only consider focused windows\&.
+Only consider urgent windows\&.
 .RE
 .PP
-unfocused
+nonurgent
 .RS 4
-Only consider unfocused windows\&.
+Only consider non urgent windows\&.
 .RE
 .PP
-below
+sticky
 .RS 4
-Only consider windows of the BELOW layer\&.
+Only consider sticky windows\&.
 .RE
 .PP
-normal
+nonsticky
 .RS 4
-Only consider windows of the NORMAL layer\&.
+Only consider non sticky windows\&.
 .RE
 .PP
-above
+locked
 .RS 4
-Only consider windows of the ABOVE layer\&.
+Only consider locked windows\&.
+.RE
+.PP
+unlocked
+.RS 4
+Only consider non locked windows\&.
 .RE
 .RE
 .SS "Desktop"
@@ -543,9 +548,9 @@ Only consider monitors where the focused desktop is free\&.
 .RE
 .SH "WINDOW STATES"
 .PP
-floating
+tiled
 .RS 4
-Can be moved/resized freely\&. Although it doesn\(cqt occupy any tiling space, it is still part of the window tree\&.
+Its size and position are determined by the splitting type and ratio of each node of its path in the window tree\&.
 .RE
 .PP
 pseudo_tiled
@@ -553,10 +558,16 @@ pseudo_tiled
 Has an unrestricted size while being centered in its tiling space\&.
 .RE
 .PP
+floating
+.RS 4
+Can be moved/resized freely\&. Although it doesn\(cqt occupy any tiling space, it is still part of the window tree\&.
+.RE
+.PP
 fullscreen
 .RS 4
-Fills its monitor rectangle and has no borders\&.
+Fills its monitor rectangle and has no borders\&. It is send in the ABOVE layer by default\&.
 .RE
+.SH "WINDOW FLAGS"
 .PP
 locked
 .RS 4
@@ -577,13 +588,13 @@ Tries to keep the same tiling position/size\&.
 .PP
 urgent
 .RS 4
-Has its urgency hint set\&.
+Has its urgency hint set\&. This flag is set externally\&.
 .RE
 .SH "STACKING LAYERS"
 .sp
 There\(cqs three stacking layers: BELOW, NORMAL and ABOVE\&.
 .sp
-In each layer, floating windows are stacked above tiled windows\&.
+In each layer, the window are orderered as follow: tiled & pseudo\-tiled < fullscreen < floating\&.
 .SH "COMMANDS"
 .SS "Window"
 .sp
@@ -653,9 +664,14 @@ Set or change the splitting ratio of the edge located in the given direction in
 Rotate the tree holding the edge located in the given direction in relation to the selected window\&.
 .RE
 .PP
-\fB\-t\fR, \fB\-\-toggle\fR floating|fullscreen|pseudo_tiled|locked|sticky|private[=on|off]
+\fB\-t\fR, \fB\-\-state\fR tiled|pseudo_tiled|floating|fullscreen
+.RS 4
+Set the state of the selected window\&.
+.RE
+.PP
+\fB\-g\fR, \fB\-\-flag\fR locked|sticky|private[=on|off]
 .RS 4
-Set or toggle the given state for the selected window\&.
+Set or toggle the given flag for the selected window\&.
 .RE
 .PP
 \fB\-l\fR, \fB\-\-layer\fR below|normal|above
@@ -758,11 +774,6 @@ Adjust the split ratios of the tree of the selected desktop so that all windows
 .RS 4
 Circulate the leaves of the tree of the selected desktop\&.
 .RE
-.PP
-\fB\-t\fR, \fB\-\-toggle\fR floating[=on|off]
-.RS 4
-Set or toggle the given state for the selected desktop\&.
-.RE
 .RE
 .SS "Monitor"
 .sp
@@ -1015,7 +1026,7 @@ rule \fIOPTIONS\fR
 \fBOptions\fR
 .RS 4
 .PP
-\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name>|* [\fB\-o\fR|\fB\-\-one\-shot\fR] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|window=WINDOW_SEL] [(floating|fullscreen|pseudo_tiled|locked|sticky|private|center|follow|manage|focus|border)=(on|off)] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO]
+\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name>|* [\fB\-o\fR|\fB\-\-one\-shot\fR] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|window=WINDOW_SEL] [state=STATE] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO] [(locked|sticky|private|center|follow|manage|focus|border)=(on|off)]
 .RS 4
 Create a new rule\&.
 .RE
index 21cfccaf45a06c33f124986504b84671d1bf2a98..e20bfa6b18de2f9183a868142217ec5613214d66 100644 (file)
@@ -134,7 +134,7 @@ Select a window.
 
 ----
 WINDOW_SEL := <window_id> 
-            | (DIR|CYCLE_DIR|biggest|last|focused|older|newer)[.floating|.tiled][.like|.unlike][.manual|.automatic][.urgent|.nonurgent][.local|.foreign][.focused|.unfocused][.below|.normal|.above][.fullscreen|.nonfullscreen][.sticky|.nonsticky][.public|.private][.locked|.unlocked][.pseudotiled|.nonpseudotiled]
+            | (DIR|CYCLE_DIR|biggest|last|focused|older|newer)[.manual|.automatic][.tiled|nontiled][.pseudotiled|.nonpseudotiled][.floating|.nonfloating][.fullscreen|.nonfullscreen][.below|.normal|.above][.local|.foreign][.like|.unlike][.focused|.unfocused][.urgent|.nonurgent][.sticky|.nonsticky][.public|.private][.locked|.unlocked]
 ----
 
 Primary Selectors
@@ -164,17 +164,29 @@ newer::
 Modifiers
 ^^^^^^^^^
 
+tiled::
+       Only consider tiled windows.
+
+nontiled::
+       Only consider tiled windows.
+
+pseudotiled::
+       Only consider pseudo-tiled windows.
+
+nonpseudotiled::
+       Only consider non pseudo-tiled windows.
+
 floating::
        Only consider floating windows.
 
-tiled::
-       Only consider tiled windows.
+nonfloating::
+       Only consider non floating windows.
 
-like::
-       Only consider windows that have the same class as the current window.
+fullscreen::
+       Only consider fullscreen windows.
 
-unlike::
-       Only consider windows that have a different class than the current window.
+nonfullscreen::
+       Only consider non fullscreen windows.
 
 manual::
        Only consider windows in manual splitting mode.
@@ -182,6 +194,27 @@ manual::
 automatic::
        Only consider windows in automatic splitting mode.
 
+focused::
+       Only consider focused windows.
+
+unfocused::
+       Only consider unfocused windows.
+
+below::
+       Only consider windows of the BELOW layer.
+
+normal::
+       Only consider windows of the NORMAL layer.
+
+above::
+       Only consider windows of the ABOVE layer.
+
+like::
+       Only consider windows that have the same class as the current window.
+
+unlike::
+       Only consider windows that have a different class than the current window.
+
 local::
        Only consider windows of the current desktop.
 
@@ -200,12 +233,6 @@ urgent::
 nonurgent::
        Only consider non urgent windows.
 
-pseudotiled::
-       Only consider pseudo-tiled windows.
-
-nonpseudotiled::
-       Only consider non pseudo-tiled windows.
-
 sticky::
        Only consider sticky windows.
 
@@ -218,30 +245,6 @@ locked::
 unlocked::
        Only consider non locked windows.
 
-nonfullscreen::
-       Only consider non fullscreen windows.
-
-fullscreen::
-       Only consider fullscreen windows.
-
-nonfullscreen::
-       Only consider non fullscreen windows.
-
-focused::
-       Only consider focused windows.
-
-unfocused::
-       Only consider unfocused windows.
-
-below::
-       Only consider windows of the BELOW layer.
-
-normal::
-       Only consider windows of the NORMAL layer.
-
-above::
-       Only consider windows of the ABOVE layer.
-
 Desktop
 ~~~~~~~
 
@@ -352,14 +355,21 @@ free::
 Window States
 -------------
 
-floating::
-       Can be moved/resized freely. Although it doesn't occupy any tiling space, it is still part of the window tree.
+tiled::
+       Its size and position are determined by the splitting type and ratio of each node of its path in the window tree.
 
 pseudo_tiled::
        Has an unrestricted size while being centered in its tiling space.
 
+floating::
+       Can be moved/resized freely. Although it doesn't occupy any tiling space, it is still part of the window tree.
+
 fullscreen::
-       Fills its monitor rectangle and has no borders.
+       Fills its monitor rectangle and has no borders. It is send in the ABOVE layer by default.
+
+
+Window Flags
+-------------
 
 locked::
        Ignores the *close* message.
@@ -371,7 +381,7 @@ private::
        Tries to keep the same tiling position/size.
 
 urgent::
-       Has its urgency hint set.
+       Has its urgency hint set. This flag is set externally.
 
 
 Stacking Layers
@@ -379,7 +389,7 @@ Stacking Layers
 
 There's three stacking layers: BELOW, NORMAL and ABOVE.
 
-In each layer, floating windows are stacked above tiled windows.
+In each layer, the window are orderered as follow: tiled & pseudo-tiled < fullscreen < floating.
 
 
 Commands
@@ -422,8 +432,11 @@ Options
 *-R*, *--rotate* 'DIR' '90|270|180'::
        Rotate the tree holding the edge located in the given direction in relation to the selected window.
 
-*-t*, *--toggle* floating|fullscreen|pseudo_tiled|locked|sticky|private[=on|off]::
-       Set or toggle the given state for the selected window.
+*-t*, *--state* tiled|pseudo_tiled|floating|fullscreen::
+       Set the state of the selected window.
+
+*-g*, *--flag* locked|sticky|private[=on|off]::
+       Set or toggle the given flag for the selected window.
 
 *-l*, *--layer* below|normal|above::
        Set the stacking layer of the selected window.
@@ -483,9 +496,6 @@ Options
 *-C*, *--circulate* forward|backward::
        Circulate the leaves of the tree of the selected desktop.
 
-*-t*, *--toggle* floating[=on|off]::
-       Set or toggle the given state for the selected desktop.
-
 
 Monitor
 ~~~~~~~
@@ -626,7 +636,7 @@ rule 'OPTIONS'
 Options
 ^^^^^^^
 
-*-a*, *--add* <class_name>|<instance_name>|* [*-o*|*--one-shot*] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|window=WINDOW_SEL] [(floating|fullscreen|pseudo_tiled|locked|sticky|private|center|follow|manage|focus|border)=(on|off)] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO]::
+*-a*, *--add* <class_name>|<instance_name>|* [*-o*|*--one-shot*] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|window=WINDOW_SEL] [state=STATE] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO] [(locked|sticky|private|center|follow|manage|focus|border)=(on|off)]::
        Create a new rule.
 
 *-r*, *--remove* ^<n>|head|tail|<class_name>|<instance_name>|*...::
index 131f0a780bb4da03840724c7a2d176a6b57e5bd5..49dbedbb7d8f7b12f665e1956aa073961c1d4901 100644 (file)
--- a/events.c
+++ b/events.c
@@ -93,7 +93,7 @@ void configure_request(xcb_generic_event_t *evt)
        client_t *c = (is_managed ? loc.node->client : NULL);
        int w = 0, h = 0;
 
-       if (is_managed && !c->floating) {
+       if (is_managed && !IS_FLOATING(c)) {
                if (e->value_mask & XCB_CONFIG_WINDOW_X)
                        c->floating_rectangle.x = e->x;
                if (e->value_mask & XCB_CONFIG_WINDOW_Y)
@@ -114,14 +114,10 @@ void configure_request(xcb_generic_event_t *evt)
                }
 
                xcb_configure_notify_event_t evt;
-               xcb_rectangle_t rect;
                xcb_window_t win = c->window;
                unsigned int bw = c->border_width;
 
-               if (c->fullscreen)
-                       rect = loc.monitor->rectangle;
-               else
-                       rect = c->tiled_rectangle;
+               xcb_rectangle_t rect = get_rectangle(loc.monitor, c);
 
                evt.response_type = XCB_CONFIGURE_NOTIFY;
                evt.event = win;
@@ -136,8 +132,9 @@ void configure_request(xcb_generic_event_t *evt)
 
                xcb_send_event(dpy, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt);
 
-               if (c->pseudo_tiled)
+               if (c->state == STATE_PSEUDO_TILED) {
                        arrange(loc.monitor, loc.desktop);
+               }
        } else {
                uint16_t mask = 0;
                uint32_t values[7];
@@ -195,8 +192,9 @@ void configure_request(xcb_generic_event_t *evt)
                xcb_configure_window(dpy, e->window, mask, values);
        }
 
-       if (is_managed)
+       if (is_managed) {
                translate_client(monitor_from_client(c), loc.monitor, c);
+       }
 }
 
 void destroy_notify(xcb_generic_event_t *evt)
@@ -382,41 +380,46 @@ void motion_notify(xcb_generic_event_t *evt)
 void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action)
 {
        if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {
-               if (action == XCB_EWMH_WM_STATE_ADD)
-                       set_fullscreen(n, true);
-               else if (action == XCB_EWMH_WM_STATE_REMOVE)
-                       set_fullscreen(n, false);
-               else if (action == XCB_EWMH_WM_STATE_TOGGLE)
-                       set_fullscreen(n, !n->client->fullscreen);
+               if (action == XCB_EWMH_WM_STATE_ADD) {
+                       set_state(m, d, n, STATE_FULLSCREEN);
+               } else if (action == XCB_EWMH_WM_STATE_REMOVE) {
+                       set_state(m, d, n, n->client->last_state);
+               } else if (action == XCB_EWMH_WM_STATE_TOGGLE) {
+                       set_state(m, d, n, IS_FULLSCREEN(n->client) ? n->client->last_state : STATE_FULLSCREEN);
+               }
                arrange(m, d);
        } else if (state == ewmh->_NET_WM_STATE_BELOW) {
-               if (action == XCB_EWMH_WM_STATE_ADD)
-                       set_layer(n, LAYER_BELOW);
-               else if (action == XCB_EWMH_WM_STATE_REMOVE)
-                       set_layer(n, LAYER_NORMAL);
-               else if (action == XCB_EWMH_WM_STATE_TOGGLE)
-                       set_layer(n, n->client->layer == LAYER_BELOW ? LAYER_NORMAL : LAYER_BELOW);
+               if (action == XCB_EWMH_WM_STATE_ADD) {
+                       set_layer(m, d, n, LAYER_BELOW);
+               } else if (action == XCB_EWMH_WM_STATE_REMOVE) {
+                       set_layer(m, d, n, LAYER_NORMAL);
+               } else if (action == XCB_EWMH_WM_STATE_TOGGLE) {
+                       set_layer(m, d, n, n->client->layer == LAYER_BELOW ? n->client->last_layer : LAYER_BELOW);
+               }
        } else if (state == ewmh->_NET_WM_STATE_ABOVE) {
-               if (action == XCB_EWMH_WM_STATE_ADD)
-                       set_layer(n, LAYER_ABOVE);
-               else if (action == XCB_EWMH_WM_STATE_REMOVE)
-                       set_layer(n, LAYER_NORMAL);
-               else if (action == XCB_EWMH_WM_STATE_TOGGLE)
-                       set_layer(n, n->client->layer == LAYER_ABOVE ? LAYER_NORMAL : LAYER_ABOVE);
+               if (action == XCB_EWMH_WM_STATE_ADD) {
+                       set_layer(m, d, n, LAYER_ABOVE);
+               } else if (action == XCB_EWMH_WM_STATE_REMOVE) {
+                       set_layer(m, d, n, n->client->last_layer);
+               } else if (action == XCB_EWMH_WM_STATE_TOGGLE) {
+                       set_layer(m, d, n, n->client->layer == LAYER_ABOVE ? n->client->last_layer : LAYER_ABOVE);
+               }
        } else if (state == ewmh->_NET_WM_STATE_STICKY) {
-               if (action == XCB_EWMH_WM_STATE_ADD)
+               if (action == XCB_EWMH_WM_STATE_ADD) {
                        set_sticky(m, d, n, true);
-               else if (action == XCB_EWMH_WM_STATE_REMOVE)
+               } else if (action == XCB_EWMH_WM_STATE_REMOVE) {
                        set_sticky(m, d, n, false);
-               else if (action == XCB_EWMH_WM_STATE_TOGGLE)
+               } else if (action == XCB_EWMH_WM_STATE_TOGGLE) {
                        set_sticky(m, d, n, !n->client->sticky);
+               }
        } else if (state == ewmh->_NET_WM_STATE_DEMANDS_ATTENTION) {
-               if (action == XCB_EWMH_WM_STATE_ADD)
+               if (action == XCB_EWMH_WM_STATE_ADD) {
                        set_urgency(m, d, n, true);
-               else if (action == XCB_EWMH_WM_STATE_REMOVE)
+               } else if (action == XCB_EWMH_WM_STATE_REMOVE) {
                        set_urgency(m, d, n, false);
-               else if (action == XCB_EWMH_WM_STATE_TOGGLE)
+               } else if (action == XCB_EWMH_WM_STATE_TOGGLE) {
                        set_urgency(m, d, n, !n->client->urgent);
+               }
        }
 }
 
index f54e04dca7f3b515c201bace55427f4227572776..55bb9647625589da561a55f340db1bc18aaa1fcf 100755 (executable)
@@ -10,8 +10,8 @@ bspc config focus_by_distance   true
 
 bspc monitor -d I II III IV V VI VII VIII IX X
 
-bspc rule -a Gimp desktop=^8 follow=on floating=on
+bspc rule -a Gimp desktop=^8 state=floating follow=on
 bspc rule -a Chromium desktop=^2
-bspc rule -a mplayer2 floating=on
+bspc rule -a mplayer2 state=floating
 bspc rule -a Kupfer.py focus=on
 bspc rule -a Screenkey manage=off
index b512c84878e3975cbaf817abc29618cdc5f4742b..83dae47119748c80d4ea6f493c89cb263ec077a4 100644 (file)
@@ -8,14 +8,11 @@ super + alt + Escape
 super + w
        bspc window -c
 
-super + t
+super + n
        bspc desktop -l next
 
-super + b
-       bspc desktop -B
-
-super + {s,f}
-       bspc window -t {floating,fullscreen}
+super + {t,p,s,f}
+       bspc window -t {tiled,pseudo_tiled,floating,fullscreen}
 
 super + {grave,Tab}
        bspc {window,desktop} -f last
@@ -61,8 +58,11 @@ super + alt + shift + {h,j,k,l}
 super + ctrl + {1-9}
        bspc window -r 0.{1-9}
 
+super + {Left,Down,Up,Right}
+       xdo move {-x -20,-y +20,-y -20,-x +20}
+
 super + {_,shift + }{1-9,0}
-       bspc {desktop -f,window -d} ^{1-9,10}
+       bspc {desktop -f,window -d} '^{1-9,10}'
 
 ~button1
        bspc pointer -g focus
index aac052791a097c6d553029304d767535c1ccaf6c..f550ec9df47950cc0412a50bbe1e6c936970e692 100644 (file)
--- a/helpers.h
+++ b/helpers.h
 #define BOOLSTR(A)        ((A) ? "true" : "false")
 #define ONOFFSTR(A)       ((A) ? "on" : "off")
 #define LAYERSTR(A)       ((A) == LAYER_BELOW ? "below" : ((A) == LAYER_NORMAL ? "normal" : "above"))
+#define STATESTR(A)       ((A) == STATE_TILED ? "tiled" : ((A) == STATE_FLOATING ? "floating" : ((A) == STATE_FULLSCREEN ? "fullscreen" : "pseudo_tiled")))
+#define IS_TILED(c)       (c->state == STATE_TILED || c->state == STATE_PSEUDO_TILED)
+#define IS_FLOATING(c)    (c->state == STATE_FLOATING)
+#define IS_FULLSCREEN(c)  (c->state == STATE_FULLSCREEN)
 
 #define XCB_CONFIG_WINDOW_X_Y               XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
 #define XCB_CONFIG_WINDOW_WIDTH_HEIGHT      XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT
index db00fa9819d7a976e8638d4f2b15e4891c9ca7a1..476b863220ac5a32a068d25e7c9a0203464eea6e 100644 (file)
@@ -187,7 +187,21 @@ int cmd_window(char **args, int num)
                        } else {
                                return MSG_FAILURE;
                        }
-               } else if (streq("-t", *args) || streq("--toggle", *args)) {
+               } else if (streq("-t", *args) || streq("--state", *args)) {
+                       num--, args++;
+                       if (num < 1)
+                               return MSG_SYNTAX;
+                       client_state_t cst;
+                       if (parse_client_state(*args, &cst)) {
+                               if (trg.node->client->state == cst) {
+                                       cst = trg.node->client->last_state;
+                               }
+                               set_state(trg.monitor, trg.desktop, trg.node, cst);
+                               dirty = true;
+                       } else {
+                               return MSG_FAILURE;
+                       }
+               } else if (streq("-g", *args) || streq("--flag", *args)) {
                        num--, args++;
                        if (num < 1)
                                return MSG_SYNTAX;
@@ -198,21 +212,13 @@ int cmd_window(char **args, int num)
                        if (val == NULL) {
                                a = ALTER_TOGGLE;
                        } else {
-                               if (parse_bool(val, &b))
+                               if (parse_bool(val, &b)) {
                                        a = ALTER_SET;
-                               else
+                               } else {
                                        return MSG_FAILURE;
+                               }
                        }
-                       if (streq("fullscreen", key)) {
-                               set_fullscreen(trg.node, (a == ALTER_SET ? b : !trg.node->client->fullscreen));
-                               dirty = true;
-                       } else if (streq("pseudo_tiled", key)) {
-                               set_pseudo_tiled(trg.node, (a == ALTER_SET ? b : !trg.node->client->pseudo_tiled));
-                               dirty = true;
-                       } else if (streq("floating", key)) {
-                               set_floating(trg.node, (a == ALTER_SET ? b : !trg.node->client->floating));
-                               dirty = true;
-                       } else if (streq("locked", key)) {
+                       if (streq("locked", key)) {
                                set_locked(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->client->locked));
                        } else if (streq("sticky", key)) {
                                set_sticky(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->client->sticky));
@@ -225,7 +231,7 @@ int cmd_window(char **args, int num)
                        num--, args++;
                        if (num < 1)
                                return MSG_SYNTAX;
-                       if (trg.node->client->floating ||
+                       if (IS_FLOATING(trg.node->client) ||
                            trg.desktop->layout != LAYOUT_TILED)
                                return MSG_FAILURE;
                        if (streq("cancel", *args)) {
@@ -257,7 +263,7 @@ int cmd_window(char **args, int num)
                        num--, args++;
                        if (num < 2)
                                return MSG_SYNTAX;
-                       if (trg.node->client->floating)
+                       if (IS_FLOATING(trg.node->client))
                                return MSG_FAILURE;
                        direction_t dir;
                        if (!parse_direction(*args, &dir))
@@ -304,7 +310,7 @@ int cmd_window(char **args, int num)
                        }
                        stack_layer_t lyr;
                        if (parse_stack_layer(*args, &lyr)) {
-                               set_layer(trg.node, lyr);
+                               set_layer(trg.monitor, trg.desktop, trg.node, lyr);
                        } else {
                                return MSG_FAILURE;
                        }
@@ -498,28 +504,6 @@ int cmd_desktop(char **args, int num)
                        } else {
                                return MSG_FAILURE;
                        }
-               } else if (streq("-t", *args) || streq("--toggle", *args)) {
-                       num--, args++;
-                       if (num < 1)
-                               return MSG_SYNTAX;
-                       char *key = strtok(*args, EQL_TOK);
-                       char *val = strtok(NULL, EQL_TOK);
-                       alter_state_t a;
-                       bool b;
-                       if (val == NULL) {
-                               a = ALTER_TOGGLE;
-                       } else {
-                               if (parse_bool(val, &b))
-                                       a = ALTER_SET;
-                               else
-                                       return MSG_FAILURE;
-                       }
-                       if (streq("floating", key))
-                               trg.desktop->floating = (a == ALTER_SET ? b : !trg.desktop->floating);
-                       else
-                               return MSG_FAILURE;
-               } else {
-                       return MSG_SYNTAX;
                }
                num--, args++;
        }
@@ -1189,6 +1173,8 @@ bool parse_subscriber_mask(char *s, subscriber_mask_t *mask)
                *mask = SBSC_MASK_WINDOW_MOVE;
        } else if (streq("window_state", s)) {
                *mask = SBSC_MASK_WINDOW_STATE;
+       } else if (streq("window_flag", s)) {
+               *mask = SBSC_MASK_WINDOW_FLAG;
        } else if (streq("window_layer", s)) {
                *mask = SBSC_MASK_WINDOW_LAYER;
        } else if (streq("desktop_add", s)) {
@@ -1205,8 +1191,6 @@ bool parse_subscriber_mask(char *s, subscriber_mask_t *mask)
                *mask = SBSC_MASK_DESKTOP_FOCUS;
        } else if (streq("desktop_layout", s)) {
                *mask = SBSC_MASK_DESKTOP_LAYOUT;
-       } else if (streq("desktop_state", s)) {
-               *mask = SBSC_MASK_DESKTOP_STATE;
        } else if (streq("monitor_add", s)) {
                *mask = SBSC_MASK_MONITOR_ADD;
        } else if (streq("monitor_rename", s)) {
@@ -1249,6 +1233,24 @@ bool parse_layout(char *s, layout_t *l)
        return false;
 }
 
+bool parse_client_state(char *s, client_state_t *t)
+{
+       if (streq("tiled", s)) {
+               *t = STATE_TILED;
+               return true;
+       } else if (streq("pseudo_tiled", s)) {
+               *t = STATE_PSEUDO_TILED;
+               return true;
+       } else if (streq("floating", s)) {
+               *t = STATE_FLOATING;
+               return true;
+       } else if (streq("fullscreen", s)) {
+               *t = STATE_FULLSCREEN;
+               return true;
+       }
+       return false;
+}
+
 bool parse_stack_layer(char *s, stack_layer_t *l)
 {
        if (streq("below", s)) {
index 20de5a618c6d03f611a00354bb925a7ebedc414f..7c95fefc095250875aeea97646de0708e72228ec 100644 (file)
@@ -49,6 +49,7 @@ int get_setting(coordinates_t loc, char *name, FILE* rsp);
 bool parse_subscriber_mask(char *s, subscriber_mask_t *mask);
 bool parse_bool(char *value, bool *b);
 bool parse_layout(char *s, layout_t *l);
+bool parse_client_state(char *s, client_state_t *t);
 bool parse_stack_layer(char *s, stack_layer_t *l);
 bool parse_direction(char *s, direction_t *d);
 bool parse_cycle_direction(char *s, cycle_dir_t *d);
index 85c01824e1403e53974a695524839ee6ee1a1145..74dc57ccc08a38c89c070e57ff8027cdbdff1dcb 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -168,26 +168,41 @@ void remove_monitor(monitor_t *m)
        PRINTF("remove monitor %s (0x%X)\n", m->name, m->id);
        put_status(SBSC_MASK_MONITOR_REMOVE, "monitor_remove %s\n", m->name);
 
-       while (m->desk_head != NULL)
+       while (m->desk_head != NULL) {
                remove_desktop(m, m->desk_head);
+       }
+
        monitor_t *prev = m->prev;
        monitor_t *next = m->next;
        monitor_t *last_mon = history_get_monitor(m);
-       if (prev != NULL)
+
+       if (prev != NULL) {
                prev->next = next;
-       if (next != NULL)
+       }
+
+       if (next != NULL) {
                next->prev = prev;
-       if (mon_head == m)
+       }
+
+       if (mon_head == m) {
                mon_head = next;
-       if (mon_tail == m)
+       }
+
+       if (mon_tail == m) {
                mon_tail = prev;
-       if (pri_mon == m)
+       }
+
+       if (pri_mon == m) {
                pri_mon = NULL;
+       }
+
        if (mon == m) {
                mon = (last_mon == NULL ? (prev == NULL ? next : prev) : last_mon);
-               if (mon != NULL && mon->desk != NULL)
+               if (mon != NULL && mon->desk != NULL) {
                        update_current();
+               }
        }
+
        xcb_destroy_window(dpy, m->root);
        free(m);
        num_monitors--;
index 4a672e84b567552ce818b8e579e81f59bd4d053e..6e3461592fb3c2b0c030bed0ad2cd95cd19a2ff5 100644 (file)
--- a/pointer.c
+++ b/pointer.c
@@ -69,12 +69,12 @@ void grab_pointer(pointer_action_t pac)
                        case ACTION_MOVE:
                        case ACTION_RESIZE_SIDE:
                        case ACTION_RESIZE_CORNER:
-                               if (c->floating) {
+                               if (IS_FLOATING(c)) {
                                        frozen_pointer->rectangle = c->floating_rectangle;
                                        frozen_pointer->is_tiled = false;
-                               } else if (!c->floating) {
+                               } else if (IS_TILED(c)) {
                                        frozen_pointer->rectangle = c->tiled_rectangle;
-                                       frozen_pointer->is_tiled = (pac == ACTION_MOVE || !c->pseudo_tiled);
+                                       frozen_pointer->is_tiled = (pac == ACTION_MOVE || c->state == STATE_PSEUDO_TILED);
                                } else {
                                        frozen_pointer->action = ACTION_NONE;
                                        return;
@@ -197,7 +197,7 @@ void track_pointer(int root_x, int root_y)
                                        return;
                                coordinates_t loc;
                                bool is_managed = (pwin == XCB_NONE ? false : locate_window(pwin, &loc));
-                               if (is_managed && !loc.node->client->floating && loc.monitor == m) {
+                               if (is_managed && !IS_FLOATING(loc.node->client) && loc.monitor == m) {
                                        swap_nodes(m, d, n, m, d, loc.node);
                                        arrange(m, d);
                                } else {
@@ -314,11 +314,7 @@ void track_pointer(int root_x, int root_y)
                                int oldw = w, oldh = h;
                                restrain_floating_size(c, &w, &h);
 
-                               if (c->pseudo_tiled) {
-                                       c->floating_rectangle.width = w;
-                                       c->floating_rectangle.height = h;
-                                       arrange(m, d);
-                               } else {
+                               if (c->state == STATE_FLOATING) {
                                        if (oldw == w) {
                                                c->floating_rectangle.x = x;
                                                c->floating_rectangle.width = w;
@@ -331,6 +327,10 @@ void track_pointer(int root_x, int root_y)
                                                                c->floating_rectangle.y,
                                                                c->floating_rectangle.width,
                                                                c->floating_rectangle.height);
+                               } else {
+                                       c->floating_rectangle.width = w;
+                                       c->floating_rectangle.height = h;
+                                       arrange(m, d);
                                }
                        }
                        break;
diff --git a/query.c b/query.c
index 64047a4f695dafa78beafd2b9f14f9166bb51762..767d10d55867f0d6def34f753d4d1a3f107e3df8 100644 (file)
--- a/query.c
+++ b/query.c
@@ -65,10 +65,10 @@ void query_desktops(monitor_t *m, domain_t dom, coordinates_t loc, unsigned int
                        fprintf(rsp, "%s\n", d->name);
                        continue;
                } else {
-                       fprintf(rsp, "%s %u %i %i,%i,%i,%i %c %c%s\n", d->name, d->border_width,
+                       fprintf(rsp, "%s %u %i %i,%i,%i,%i %c%s\n", d->name, d->border_width,
                                d->window_gap,
                                d->top_padding, d->right_padding, d->bottom_padding, d->left_padding,
-                               (d->layout == LAYOUT_TILED ? 'T' : 'M'), (d->floating ? 'f' : '-'),
+                               (d->layout == LAYOUT_TILED ? 'T' : 'M'),
                                (d == m->desk ? " *" : ""));
                }
                query_tree(d, d->root, rsp, depth + 1);
@@ -85,16 +85,16 @@ void query_tree(desktop_t *d, node_t *n, FILE *rsp, unsigned int depth)
 
        if (is_leaf(n)) {
                client_t *c = n->client;
-               fprintf(rsp, "%c %s %s 0x%X %u %ux%u%+i%+i %c %c%c%c%c%c%c%c%c%c%s\n",
+               fprintf(rsp, "%c %s %s 0x%X %u %ux%u%+i%+i %c%c %c%c %c%c%c%c%s\n",
                         (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')),
                         c->class_name, c->instance_name, c->window, c->border_width,
                         c->floating_rectangle.width, c->floating_rectangle.height,
                         c->floating_rectangle.x, c->floating_rectangle.y,
                         (n->split_dir == DIR_UP ? 'U' : (n->split_dir == DIR_RIGHT ? 'R' : (n->split_dir == DIR_DOWN ? 'D' : 'L'))),
-                        (c->floating ? 'f' : '-'), (c->pseudo_tiled ? 'd' : '-'), (c->fullscreen ? 'F' : '-'),
-                        (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'),
-                        (c->private ? 'i' : '-'), (n->split_mode ? 'p' : '-'),
-                        (c->layer == LAYER_BELOW ? 'b' : (c->layer == LAYER_ABOVE ? 'a' : '-')),
+                        (n->split_mode == MODE_AUTOMATIC ? '-' : 'p'),
+                        (c->state == STATE_TILED ? '-' : (c->state == STATE_FLOATING ? 'f' : (c->state == STATE_FULLSCREEN ? 'F' : 'p'))),
+                        (c->layer == LAYER_NORMAL ? '-' : (c->layer == LAYER_ABOVE ? 'a' : 'b')),
+                        (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (c->private ? 'i' : '-'),
                         (n == d->focus ? " *" : ""));
        } else {
                fprintf(rsp, "%c %c %lf\n", (n->split_type == TYPE_HORIZONTAL ? 'H' : 'V'),
@@ -155,6 +155,7 @@ client_select_t make_client_select(void)
                OPTION_NONE,
                OPTION_NONE,
                OPTION_NONE,
+               OPTION_NONE,
                NULL
        };
        return sel;
@@ -182,9 +183,17 @@ bool node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
        while ((tok = strrchr(desc, CAT_CHR)) != NULL) {
                tok[0] = '\0';
                tok++;
-               if (streq("floating", tok)) {
+               if (streq("tiled", tok)) {
+                       sel.tiled = OPTION_TRUE;
+               } else if (streq("nontiled", tok)) {
+                       sel.tiled = OPTION_FALSE;
+               } else if (streq("pseudotiled", tok)) {
+                       sel.pseudo_tiled = OPTION_TRUE;
+               } else if (streq("nonpseudotiled", tok)) {
+                       sel.pseudo_tiled = OPTION_FALSE;
+               } else if (streq("floating", tok)) {
                        sel.floating = OPTION_TRUE;
-               } else if (streq("tiled", tok)) {
+               } else if (streq("nonfloating", tok)) {
                        sel.floating = OPTION_FALSE;
                } else if (streq("like", tok)) {
                        sel.same_class = OPTION_TRUE;
@@ -198,10 +207,6 @@ bool node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
                        sel.fullscreen = OPTION_TRUE;
                } else if (streq("nonfullscreen", tok)) {
                        sel.fullscreen = OPTION_FALSE;
-               } else if (streq("pseudotiled", tok)) {
-                       sel.pseudo_tiled = OPTION_TRUE;
-               } else if (streq("nonpseudotiled", tok)) {
-                       sel.pseudo_tiled = OPTION_FALSE;
                } else if (streq("urgent", tok)) {
                        sel.urgent = OPTION_TRUE;
                } else if (streq("nonurgent", tok)) {
@@ -466,15 +471,40 @@ bool node_matches(coordinates_t *loc, coordinates_t *ref, client_select_t sel)
            : sel.prop == OPTION_FALSE) { \
                return false; \
        }
-       WSTATE(floating)
-       WSTATE(fullscreen)
-       WSTATE(pseudo_tiled)
        WSTATE(locked)
        WSTATE(sticky)
        WSTATE(private)
        WSTATE(urgent)
 #undef MATCHSTATE
 
+       if (sel.tiled != OPTION_NONE &&
+           loc->node->client->state != STATE_TILED
+           ? sel.tiled == OPTION_TRUE
+           : sel.tiled == OPTION_FALSE) {
+               return false;
+       }
+
+       if (sel.pseudo_tiled != OPTION_NONE &&
+           loc->node->client->state != STATE_PSEUDO_TILED
+           ? sel.pseudo_tiled == OPTION_TRUE
+           : sel.pseudo_tiled == OPTION_FALSE) {
+               return false;
+       }
+
+       if (sel.floating != OPTION_NONE &&
+           loc->node->client->state != STATE_FLOATING
+           ? sel.floating == OPTION_TRUE
+           : sel.floating == OPTION_FALSE) {
+               return false;
+       }
+
+       if (sel.fullscreen != OPTION_NONE &&
+           loc->node->client->state != STATE_FULLSCREEN
+           ? sel.fullscreen == OPTION_TRUE
+           : sel.fullscreen == OPTION_FALSE) {
+               return false;
+       }
+
        if (sel.same_class != OPTION_NONE && ref->node != NULL &&
            streq(loc->node->client->class_name, ref->node->client->class_name)
            ? sel.same_class == OPTION_FALSE
@@ -489,7 +519,8 @@ bool node_matches(coordinates_t *loc, coordinates_t *ref, client_select_t sel)
                return false;
        }
 
-       if (sel.local != OPTION_NONE && loc->desktop != ref->desktop
+       if (sel.local != OPTION_NONE &&
+           loc->desktop != ref->desktop
            ? sel.local == OPTION_TRUE
            : sel.local == OPTION_FALSE) {
                return false;
index 6ea6fada17f171d6c7a90c083d7cc58e857c96d1..5f6217faa41004a9e6d2021e8366bdf3229b4f55 100644 (file)
--- a/restore.c
+++ b/restore.c
@@ -92,21 +92,23 @@ void restore_tree(char *file_path)
                               &bw, &wg, &top, &right, &bottom, &left, &layout, &floating, &end);
                        locate_desktop(name, &loc);
                        d = loc.desktop;
-                       if (d == NULL)
+                       if (d == NULL) {
                                continue;
+                       }
                        d->border_width = bw;
                        d->window_gap = wg;
                        d->top_padding = top;
                        d->right_padding = right;
                        d->bottom_padding = bottom;
                        d->left_padding = left;
-                       if (layout == 'M')
+                       if (layout == 'M') {
                                d->layout = LAYOUT_MONOCLE;
-                       else if (layout == 'T')
+                       } else if (layout == 'T') {
                                d->layout = LAYOUT_TILED;
-                       d->floating = (floating == '-' ? false : true);
-                       if (end != 0)
+                       }
+                       if (end != 0) {
                                m->desk = d;
+                       }
                } else {
                        if (m == NULL || d == NULL)
                                continue;
@@ -128,76 +130,88 @@ void restore_tree(char *file_path)
                                birth->parent = n;
                        }
                        n = birth;
-                       char br;
+                       char birth_rotation;
                        if (isupper(line[level])) {
-                               char st;
-                               sscanf(line + level, "%c %c %lf", &st, &br, &n->split_ratio);
-                               if (st == 'H')
+                               char split_type;
+                               sscanf(line + level, "%c %c %lf", &split_type, &birth_rotation, &n->split_ratio);
+                               if (split_type == 'H') {
                                        n->split_type = TYPE_HORIZONTAL;
-                               else if (st == 'V')
+                               } else if (split_type == 'V') {
                                        n->split_type = TYPE_VERTICAL;
+                               }
                        } else {
                                client_t *c = make_client(XCB_NONE, d->border_width);
                                num_clients++;
-                               char floating, pseudo_tiled, fullscreen, urgent, locked, sticky, private, sd, sm, sl, end = 0;
-                               sscanf(line + level, "%c %s %s %X %u %hux%hu%hi%hi %c %c%c%c%c%c%c%c%c%c %c", &br,
+                               char urgent, locked, sticky, private, split_dir, split_mode, state, layer, end = 0;
+                               sscanf(line + level, "%c %s %s %X %u %hux%hu%hi%hi %c%c %c%c %c%c%c%c %c", &birth_rotation,
                                       c->class_name, c->instance_name, &c->window, &c->border_width,
                                       &c->floating_rectangle.width, &c->floating_rectangle.height,
                                       &c->floating_rectangle.x, &c->floating_rectangle.y,
-                                      &sd, &floating, &pseudo_tiled, &fullscreen, &urgent,
-                                      &locked, &sticky, &private, &sm, &sl, &end);
-                               c->floating = (floating == '-' ? false : true);
-                               c->pseudo_tiled = (pseudo_tiled == '-' ? false : true);
-                               c->fullscreen = (fullscreen == '-' ? false : true);
-                               c->urgent = (urgent == '-' ? false : true);
-                               c->locked = (locked == '-' ? false : true);
-                               c->sticky = (sticky == '-' ? false : true);
-                               c->private = (private == '-' ? false : true);
-                               n->split_mode = (sm == '-' ? MODE_AUTOMATIC : MODE_MANUAL);
-                               if (sd == 'U') {
+                                      &split_dir, &split_mode, &state, &layer,
+                                      &urgent, &locked, &sticky, &private, &end);
+                               n->split_mode = (split_mode == '-' ? MODE_AUTOMATIC : MODE_MANUAL);
+                               if (split_dir == 'U') {
                                        n->split_dir = DIR_UP;
-                               } else if (sd == 'R') {
+                               } else if (split_dir == 'R') {
                                        n->split_dir = DIR_RIGHT;
-                               } else if (sd == 'D') {
+                               } else if (split_dir == 'D') {
                                        n->split_dir = DIR_DOWN;
-                               } else if (sd == 'L') {
+                               } else if (split_dir == 'L') {
                                        n->split_dir = DIR_LEFT;
                                }
-                               if (sl == 'b') {
+                               if (state == 'f') {
+                                       c->state = STATE_FLOATING;
+                               } else if (state == 'F') {
+                                       c->state = STATE_FULLSCREEN;
+                               } else if (state == 'p') {
+                                       c->state = STATE_PSEUDO_TILED;
+                               }
+                               if (layer == 'b') {
                                        c->layer = LAYER_BELOW;
-                               } else if (sl == 'a') {
+                               } else if (layer == 'a') {
                                        c->layer = LAYER_ABOVE;
                                }
+                               c->urgent = (urgent == '-' ? false : true);
+                               c->locked = (locked == '-' ? false : true);
+                               c->sticky = (sticky == '-' ? false : true);
+                               c->private = (private == '-' ? false : true);
                                n->client = c;
-                               if (end != 0)
+                               if (end != 0) {
                                        d->focus = n;
-                               if (c->sticky)
+                               }
+                               if (c->sticky) {
                                        m->num_sticky++;
+                               }
                        }
-                       if (br == 'a')
+                       if (birth_rotation == 'a') {
                                n->birth_rotation = 90;
-                       else if (br == 'c')
+                       } else if (birth_rotation == 'c') {
                                n->birth_rotation = 270;
-                       else if (br == 'm')
+                       } else if (birth_rotation == 'm') {
                                n->birth_rotation = 0;
+                       }
                }
                last_level = level;
        }
 
        fclose(snapshot);
 
-       for (monitor_t *m = mon_head; m != NULL; m = m->next)
-               for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
+       for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+               for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
                        for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
                                uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
                                xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
-                               if (n->client->floating) {
+                               if (!IS_TILED(n->client)) {
                                        n->vacant = true;
                                        update_vacant_state(n->parent);
                                }
-                               if (n->client->private)
+                               if (n->client->private) {
                                        update_privacy_level(n, true);
+                               }
                        }
+               }
+       }
+
        ewmh_update_current_desktop();
 }
 
diff --git a/rule.c b/rule.c
index 3a76a3fa334072b184637db4673ff9ef4658a196..9120eeb486d14b37725145edc67a363bd9de2cec 100644 (file)
--- a/rule.c
+++ b/rule.c
@@ -95,6 +95,7 @@ rule_consequence_t *make_rule_conquence(void)
        rule_consequence_t *rc = calloc(1, sizeof(rule_consequence_t));
        rc->manage = rc->focus = rc->border = true;
        rc->layer = NULL;
+       rc->state = NULL;
        return rc;
 }
 
@@ -153,14 +154,18 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
                            a == ewmh->_NET_WM_WINDOW_TYPE_UTILITY) {
                                csq->focus = false;
                        } else if (a == ewmh->_NET_WM_WINDOW_TYPE_DIALOG) {
-                               csq->floating = true;
+                               if (csq->state == NULL) {
+                                       csq->state = malloc(sizeof(client_state_t));
+                               }
+                               *(csq->state) = STATE_FLOATING;
                                csq->center = true;
                        } else if (a == ewmh->_NET_WM_WINDOW_TYPE_DOCK ||
                                   a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP ||
                                   a == ewmh->_NET_WM_WINDOW_TYPE_NOTIFICATION) {
                                csq->manage = false;
-                               if (a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP)
+                               if (a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP) {
                                        window_lower(win);
+                               }
                        }
                }
                xcb_ewmh_get_atoms_reply_wipe(&win_type);
@@ -172,7 +177,10 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
                for (unsigned int i = 0; i < win_state.atoms_len; i++) {
                        xcb_atom_t a = win_state.atoms[i];
                        if (a == ewmh->_NET_WM_STATE_FULLSCREEN) {
-                               csq->fullscreen = true;
+                               if (csq->state == NULL) {
+                                       csq->state = malloc(sizeof(client_state_t));
+                               }
+                               *(csq->state) = STATE_FULLSCREEN;
                        } else if (a == ewmh->_NET_WM_STATE_BELOW) {
                                if (csq->layer == NULL) {
                                        csq->layer = malloc(sizeof(stack_layer_t));
@@ -194,8 +202,12 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
        if (xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, win), &size_hints, NULL) == 1) {
                if (size_hints.min_width > 0 && size_hints.min_height > 0 &&
                    size_hints.min_width == size_hints.max_width &&
-                   size_hints.min_height == size_hints.max_height)
-                       csq->floating = true;
+                   size_hints.min_height == size_hints.max_height) {
+                       if (csq->state == NULL) {
+                               csq->state = malloc(sizeof(client_state_t));
+                       }
+                       *(csq->state) = STATE_FLOATING;
+               }
                csq->min_width = size_hints.min_width;
                csq->max_width = size_hints.max_width;
                csq->min_height = size_hints.min_height;
@@ -204,8 +216,12 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
 
        xcb_window_t transient_for = XCB_NONE;
        xcb_icccm_get_wm_transient_for_reply(dpy, xcb_icccm_get_wm_transient_for(dpy, win), &transient_for, NULL);
-       if (transient_for != XCB_NONE)
-               csq->floating = true;
+       if (transient_for != XCB_NONE) {
+               if (csq->state == NULL) {
+                       csq->state = malloc(sizeof(client_state_t));
+               }
+               *(csq->state) = STATE_FLOATING;
+       }
 
        xcb_icccm_get_wm_class_reply_t reply;
        if (xcb_icccm_get_wm_class_reply(dpy, xcb_icccm_get_wm_class(dpy, win), &reply, NULL) == 1) {
@@ -229,8 +245,9 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
                                key = strtok(NULL, CSQ_BLK);
                                value = strtok(NULL, CSQ_BLK);
                        }
-                       if (rule->one_shot)
+                       if (rule->one_shot) {
                                remove_rule(rule);
+                       }
                }
                rule = next;
        }
@@ -238,15 +255,18 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
 
 bool schedule_rules(xcb_window_t win, rule_consequence_t *csq)
 {
-       if (external_rules_command[0] == '\0')
+       if (external_rules_command[0] == '\0') {
                return false;
+       }
        int fds[2];
-       if (pipe(fds) == -1)
+       if (pipe(fds) == -1) {
                return false;
+       }
        pid_t pid = fork();
        if (pid == 0) {
-               if (dpy != NULL)
+               if (dpy != NULL) {
                        close(xcb_get_file_descriptor(dpy));
+               }
                dup2(fds[1], 1);
                close(fds[0]);
                char wid[SMALEN];
@@ -292,6 +312,14 @@ void parse_key_value(char *key, char *value, rule_consequence_t *csq)
                snprintf(csq->node_desc, sizeof(csq->node_desc), "%s", value);
        } else if (streq("split_dir", key)) {
                snprintf(csq->split_dir, sizeof(csq->split_dir), "%s", value);
+       } else if (streq("state", key)) {
+               client_state_t cst;
+               if (parse_client_state(value, &cst)) {
+                       if (csq->state == NULL) {
+                               csq->state = malloc(sizeof(client_state_t));
+                       }
+                       *(csq->state) = cst;
+               }
        } else if (streq("layer", key)) {
                stack_layer_t lyr;
                if (parse_stack_layer(value, &lyr)) {
@@ -306,14 +334,11 @@ void parse_key_value(char *key, char *value, rule_consequence_t *csq)
                        csq->split_ratio = rat;
                }
        } else if (parse_bool(value, &v)) {
-               if (streq("floating", key))
-                       csq->floating = v;
+               if (streq("locked", key))
+                       csq->locked = true;
 #define SETCSQ(name) \
                else if (streq(#name, key)) \
                        csq->name = v;
-               SETCSQ(pseudo_tiled)
-               SETCSQ(fullscreen)
-               SETCSQ(locked)
                SETCSQ(sticky)
                SETCSQ(private)
                SETCSQ(center)
diff --git a/stack.c b/stack.c
index c5db6b12f6896395b8663220786b779f1e7e3cd3..eabcf4689c48f297739b6f53bd7a3622650672ce 100644 (file)
--- a/stack.c
+++ b/stack.c
@@ -102,31 +102,16 @@ void remove_stack_node(node_t *n)
        }
 }
 
+int stack_level(client_t *c)
+{
+       int layer_level = (c->layer == LAYER_NORMAL ? 1 : (c->layer == LAYER_BELOW ? 0 : 2));
+       int state_level = (IS_TILED(c) ? 0 : (IS_FLOATING(c) ? 2 : 1));
+       return 3 * layer_level + state_level;
+}
+
 int stack_cmp(client_t *c1, client_t *c2)
 {
-       if (c1->layer == c2->layer) {
-               if (!c1->floating && c2->floating) {
-                       return -1;
-               } else if (c1->floating && !c2->floating) {
-                       return 1;
-               } else {
-                       return 0;
-               }
-       } else {
-               if (c1->layer == LAYER_BELOW) {
-                       return -1;
-               } else if (c1->layer == LAYER_ABOVE) {
-                       return 1;
-               /* c1->layer == LAYER_NORMAL */
-               } else {
-                       if (c2->layer == LAYER_ABOVE) {
-                               return -1;
-                       /* c2->layer == LAYER_BELOW */
-                       } else {
-                               return 1;
-                       }
-               }
-       }
+       return stack_level(c1) - stack_level(c2);
 }
 
 void stack(node_t *n)
@@ -136,8 +121,9 @@ void stack(node_t *n)
        if (stack_head == NULL) {
                stack_insert_after(NULL, n);
        } else {
-               if (n->client->floating && !auto_raise)
+               if (IS_FLOATING(n->client) && !auto_raise) {
                        return;
+               }
                stacking_list_t *s = stack_head;
                while (s != NULL && stack_cmp(n->client, s->node->client) >= 0) {
                        s = s->next;
diff --git a/stack.h b/stack.h
index a641aef5a4b4004954b930102bc0aa5a4ab8b96c..069fc3827516b8c339a40b6d9247d9a68daae03d 100644 (file)
--- a/stack.h
+++ b/stack.h
@@ -30,6 +30,7 @@ void stack_insert_after(stacking_list_t *a, node_t *n);
 void stack_insert_before(stacking_list_t *a, node_t *n);
 void remove_stack(stacking_list_t *s);
 void remove_stack_node(node_t *n);
+int stack_level(client_t *c);
 int stack_cmp(client_t *c1, client_t *c2);
 void stack(node_t *n);
 
index de07f6db0fe6bf4c43c5507afec592d13441bb00..233e0f50df1c69d8e27777bc168189c80643d697 100644 (file)
@@ -39,19 +39,19 @@ typedef enum {
        SBSC_MASK_DESKTOP_TRANSFER = 1 << 10,
        SBSC_MASK_DESKTOP_FOCUS = 1 << 11,
        SBSC_MASK_DESKTOP_LAYOUT = 1 << 12,
-       SBSC_MASK_DESKTOP_STATE = 1 << 13,
-       SBSC_MASK_WINDOW_MANAGE = 1 << 14,
-       SBSC_MASK_WINDOW_UNMANAGE = 1 << 15,
-       SBSC_MASK_WINDOW_SWAP = 1 << 16,
-       SBSC_MASK_WINDOW_TRANSFER = 1 << 17,
-       SBSC_MASK_WINDOW_FOCUS = 1 << 18,
-       SBSC_MASK_WINDOW_RESIZE = 1 << 19,
-       SBSC_MASK_WINDOW_MOVE = 1 << 20,
-       SBSC_MASK_WINDOW_STATE = 1 << 21,
+       SBSC_MASK_WINDOW_MANAGE = 1 << 13,
+       SBSC_MASK_WINDOW_UNMANAGE = 1 << 14,
+       SBSC_MASK_WINDOW_SWAP = 1 << 15,
+       SBSC_MASK_WINDOW_TRANSFER = 1 << 16,
+       SBSC_MASK_WINDOW_FOCUS = 1 << 17,
+       SBSC_MASK_WINDOW_RESIZE = 1 << 18,
+       SBSC_MASK_WINDOW_MOVE = 1 << 19,
+       SBSC_MASK_WINDOW_STATE = 1 << 20,
+       SBSC_MASK_WINDOW_FLAG = 1 << 21,
        SBSC_MASK_WINDOW_LAYER = 1 << 22,
        SBSC_MASK_MONITOR = (1 << 6) - (1 << 1),
-       SBSC_MASK_DESKTOP = (1 << 14) - (1 << 6),
-       SBSC_MASK_WINDOW = (1 << 23) - (1 << 14),
+       SBSC_MASK_DESKTOP = (1 << 13) - (1 << 6),
+       SBSC_MASK_WINDOW = (1 << 23) - (1 << 13),
        SBSC_MASK_ALL = (1 << 23) - 1
 } subscriber_mask_t;
 
diff --git a/tree.c b/tree.c
index f5d44a4713d643a69341e465b2b082468c4c1693..043122ed84899bdcf16aa7f3785b2de0d20fa692 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -69,42 +69,39 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, x
        if (is_leaf(n)) {
 
                unsigned int bw;
-               if ((borderless_monocle && !n->client->floating &&
-                    !n->client->pseudo_tiled &&
-                    d->layout == LAYOUT_MONOCLE) ||
-                   n->client->fullscreen)
+               if ((borderless_monocle && n->client->state == STATE_TILED && d->layout == LAYOUT_MONOCLE)
+                   || n->client->state == STATE_FULLSCREEN) {
                        bw = 0;
-               else
+               } else {
                        bw = n->client->border_width;
+               }
 
                xcb_rectangle_t r;
-               if (!n->client->fullscreen) {
-                       if (!n->client->floating) {
-                               int wg = (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap);
-                               if (n->client->pseudo_tiled) {
-                               /* pseudo-tiled clients */
-                                       r = n->client->floating_rectangle;
-                                       if (center_pseudo_tiled) {
-                                               r.x = rect.x - bw + (rect.width - wg - r.width) / 2;
-                                               r.y = rect.y - bw + (rect.height - wg - r.height) / 2;
-                                       } else {
-                                               r.x = rect.x;
-                                               r.y = rect.y;
-                                       }
-                               } else {
-                                       /* tiled clients */
-                                       r = rect;
-                                       int bleed = wg + 2 * bw;
-                                       r.width = (bleed < r.width ? r.width - bleed : 1);
-                                       r.height = (bleed < r.height ? r.height - bleed : 1);
-                               }
-                               n->client->tiled_rectangle = r;
+               client_state_t s = n->client->state;
+               if (s == STATE_TILED || s == STATE_PSEUDO_TILED) {
+                       int wg = (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap);
+                       /* tiled clients */
+                       if (s == STATE_TILED) {
+                               r = rect;
+                               int bleed = wg + 2 * bw;
+                               r.width = (bleed < r.width ? r.width - bleed : 1);
+                               r.height = (bleed < r.height ? r.height - bleed : 1);
+                       /* pseudo-tiled clients */
                        } else {
-                               /* floating clients */
                                r = n->client->floating_rectangle;
+                               if (center_pseudo_tiled) {
+                                       r.x = rect.x - bw + (rect.width - wg - r.width) / 2;
+                                       r.y = rect.y - bw + (rect.height - wg - r.height) / 2;
+                               } else {
+                                       r.x = rect.x;
+                                       r.y = rect.y;
+                               }
                        }
+               /* floating clients */
+               } else if (s == STATE_FLOATING) {
+                       r = n->client->floating_rectangle;
+               /* fullscreen clients */
                } else {
-                       /* fullscreen clients */
                        r = m->rectangle;
                }
 
@@ -231,8 +228,9 @@ void insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f)
                                                c->second_child = n;
                                                rot = 270;
                                        }
-                                       if (!n->client->floating)
+                                       if (IS_TILED(n->client)) {
                                                rotate_tree(p, rot);
+                                       }
                                        n->birth_rotation = rot;
                                }
                                break;
@@ -331,20 +329,23 @@ void focus_node(monitor_t *m, desktop_t *d, node_t *n)
                        n->client->urgent = false;
                        put_status(SBSC_MASK_REPORT);
                }
-               if (d->focus != NULL && n != d->focus && d->focus->client->fullscreen && stack_cmp(n->client, d->focus->client) <= 0) {
-                       set_fullscreen(d->focus, false);
-                       arrange(m, d);
+               if (d->focus != NULL && n != d->focus && stack_cmp(n->client, d->focus->client) < 0) {
+                       neutralize_obscuring_windows(m, d, n);
                }
        }
 
        if (mon != m) {
-               for (desktop_t *cd = mon->desk_head; cd != NULL; cd = cd->next)
+               for (desktop_t *cd = mon->desk_head; cd != NULL; cd = cd->next) {
                        window_draw_border(cd->focus, true, false);
-               for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next)
-                       if (cd != d)
+               }
+               for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next) {
+                       if (cd != d) {
                                window_draw_border(cd->focus, true, true);
-               if (d->focus == n)
+                       }
+               }
+               if (d->focus == n) {
                        window_draw_border(n, true, true);
+               }
        }
 
        if (d->focus != n) {
@@ -381,7 +382,7 @@ void focus_node(monitor_t *m, desktop_t *d, node_t *n)
        }
 
        if (pointer_follows_focus) {
-               center_pointer(get_rectangle(n->client));
+               center_pointer(get_rectangle(m, n->client));
        }
 
        ewmh_update_active_window();
@@ -410,11 +411,11 @@ client_t *make_client(xcb_window_t win, unsigned int border_width)
 {
        client_t *c = malloc(sizeof(client_t));
        c->window = win;
+       c->state = c->last_state = STATE_TILED;
        c->layer = c->last_layer = LAYER_NORMAL;
        snprintf(c->class_name, sizeof(c->class_name), "%s", MISSING_VALUE);
        snprintf(c->instance_name, sizeof(c->instance_name), "%s", MISSING_VALUE);
        c->border_width = border_width;
-       c->pseudo_tiled = c->floating = c->fullscreen = false;
        c->locked = c->sticky = c->urgent = c->private = c->icccm_focus = false;
        xcb_icccm_get_wm_protocols_reply_t protocols;
        if (xcb_icccm_get_wm_protocols_reply(dpy, xcb_icccm_get_wm_protocols(dpy, win, ewmh->WM_PROTOCOLS), &protocols, NULL) == 1) {
@@ -479,7 +480,7 @@ void closest_public(desktop_t *d, node_t *n, node_t **closest, node_t **public)
        while (prev != NULL || next != NULL) {
 #define TESTLOOP(n) \
                if (n != NULL) { \
-                       if (!n->client->floating) { \
+                       if (IS_TILED(n->client)) { \
                                if (n->privacy_level == 0) { \
                                        if (n->parent == NULL || n->parent->privacy_level == 0) { \
                                                *public = n; \
@@ -544,7 +545,7 @@ node_t *prev_leaf(node_t *n, node_t *r)
 node_t *next_tiled_leaf(desktop_t *d, node_t *n, node_t *r)
 {
        node_t *next = next_leaf(n, r);
-       if (next == NULL || !next->client->floating)
+       if (next == NULL || IS_TILED(next->client))
                return next;
        else
                return next_tiled_leaf(d, next, r);
@@ -553,25 +554,12 @@ node_t *next_tiled_leaf(desktop_t *d, node_t *n, node_t *r)
 node_t *prev_tiled_leaf(desktop_t *d, node_t *n, node_t *r)
 {
        node_t *prev = prev_leaf(n, r);
-       if (prev == NULL || !prev->client->floating)
+       if (prev == NULL || IS_TILED(prev->client))
                return prev;
        else
                return prev_tiled_leaf(d, prev, r);
 }
 
-/* bool is_adjacent(node_t *a, node_t *r) */
-/* { */
-/*        node_t *f = r->parent; */
-/*        node_t *p = a; */
-/*        bool first_child = is_first_child(r); */
-/*        while (p != r) { */
-/*                if (p->parent->split_type == f->split_type && is_first_child(p) == first_child) */
-/*                        return false; */
-/*                p = p->parent; */
-/*        } */
-/*        return true; */
-/* } */
-
 /* Returns true if *b* is adjacent to *a* in the direction *dir* */
 bool is_adjacent(node_t *a, node_t *b, direction_t dir)
 {
@@ -615,8 +603,8 @@ node_t *find_fence(node_t *n, direction_t dir)
 
 node_t *nearest_neighbor(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, client_select_t sel)
 {
-       if (n == NULL || n->client->fullscreen ||
-           (d->layout == LAYOUT_MONOCLE && !n->client->floating))
+       if (n == NULL || IS_FULLSCREEN(n->client) ||
+           (d->layout == LAYOUT_MONOCLE && IS_TILED(n->client)))
                return NULL;
 
        node_t *nearest = NULL;
@@ -634,8 +622,9 @@ node_t *nearest_neighbor(monitor_t *m, desktop_t *d, node_t *n, direction_t dir,
 
 node_t *nearest_from_tree(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, client_select_t sel)
 {
-    if (n == NULL)
+    if (n == NULL) {
         return NULL;
+    }
 
     node_t *fence = find_fence(n, dir);
 
@@ -644,24 +633,27 @@ node_t *nearest_from_tree(monitor_t *m, desktop_t *d, node_t *n, direction_t dir
 
     node_t *nearest = NULL;
 
-    if (dir == DIR_UP || dir == DIR_LEFT)
+    if (dir == DIR_UP || dir == DIR_LEFT) {
         nearest = second_extrema(fence->first_child);
-    else if (dir == DIR_DOWN || dir == DIR_RIGHT)
+    } else if (dir == DIR_DOWN || dir == DIR_RIGHT) {
         nearest = first_extrema(fence->second_child);
+    }
 
        coordinates_t ref = {m, d, n};
        coordinates_t loc = {m, d, nearest};
 
-       if (node_matches(&loc, &ref, sel))
+       if (node_matches(&loc, &ref, sel)) {
                return nearest;
-       else
+       } else {
                return NULL;
+       }
 }
 
 node_t *nearest_from_history(monitor_t *m, desktop_t *d, node_t *n, direction_t dir, client_select_t sel)
 {
-       if (n == NULL || n->client->floating)
+       if (n == NULL || !IS_TILED(n->client)) {
                return NULL;
+       }
 
        node_t *target = find_fence(n, dir);
        if (target == NULL)
@@ -699,7 +691,7 @@ node_t *nearest_from_distance(monitor_t *m, desktop_t *d, node_t *n, direction_t
 
        node_t *target = NULL;
 
-       if (!n->client->floating) {
+       if (IS_TILED(n->client)) {
                target = find_fence(n, dir);
                if (target == NULL)
                        return NULL;
@@ -724,8 +716,8 @@ node_t *nearest_from_distance(monitor_t *m, desktop_t *d, node_t *n, direction_t
                coordinates_t loc = {m, d, a};
                if (a == n ||
                    !node_matches(&loc, &ref, sel) ||
-                   !a->client->floating != !n->client->floating ||
-                   (!a->client->floating && !is_adjacent(n, a, dir)))
+                   IS_TILED(a->client) != IS_TILED(n->client) ||
+                   (IS_TILED(a->client) && !is_adjacent(n, a, dir)))
                        continue;
 
                get_side_handle(a->client, dir2, &pt2);
@@ -769,7 +761,7 @@ int tiled_count(desktop_t *d)
 {
        int cnt = 0;
        for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root)) {
-               if (!f->client->floating) {
+               if (IS_TILED(f->client)) {
                        cnt++;
                }
        }
@@ -787,7 +779,7 @@ node_t *find_biggest(monitor_t *m, desktop_t *d, node_t *n, client_select_t sel)
 
        for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root)) {
                coordinates_t loc = {m, d, f};
-               if (f->client->floating || !node_matches(&loc, &ref, sel))
+               if (IS_FLOATING(f->client) || !node_matches(&loc, &ref, sel))
                        continue;
                int f_area = tiled_area(f);
                if (r == NULL) {
diff --git a/types.h b/types.h
index 0fbefa5e20675b4800e90ac217cc2ce3857d3a7d..e99f9d18b215933aadf25fe984df1097e35a2c69 100644 (file)
--- a/types.h
+++ b/types.h
@@ -43,6 +43,13 @@ typedef enum {
        MODE_MANUAL
 } split_mode_t;
 
+typedef enum {
+       STATE_TILED,
+       STATE_PSEUDO_TILED,
+       STATE_FLOATING,
+       STATE_FULLSCREEN
+} client_state_t;
+
 typedef enum {
        LAYER_BELOW,
        LAYER_NORMAL,
@@ -120,8 +127,9 @@ typedef enum {
 } child_polarity_t;
 
 typedef struct {
-       option_bool_t floating;
+       option_bool_t tiled;
        option_bool_t pseudo_tiled;
+       option_bool_t floating;
        option_bool_t fullscreen;
        option_bool_t locked;
        option_bool_t sticky;
@@ -145,14 +153,13 @@ typedef struct {
        char class_name[3 * SMALEN / 2];
        char instance_name[3 * SMALEN / 2];
        unsigned int border_width;
-       bool pseudo_tiled;
-       bool floating;
-       bool fullscreen;
        bool locked;                            /* protects window from being closed */
        bool sticky;
        bool urgent;
        bool private;
        bool icccm_focus;
+       client_state_t state;
+       client_state_t last_state;
        stack_layer_t layer;
        stack_layer_t last_layer;
        xcb_rectangle_t floating_rectangle;
@@ -195,7 +202,6 @@ struct desktop_t {
        int left_padding;
        int window_gap;
        unsigned int border_width;
-       bool floating;
 };
 
 typedef struct monitor_t monitor_t;
@@ -264,14 +270,12 @@ typedef struct {
        char node_desc[MAXLEN];
        char split_dir[SMALEN];
        stack_layer_t *layer;
+       client_state_t *state;
        double split_ratio;
        uint16_t min_width;
        uint16_t max_width;
        uint16_t min_height;
        uint16_t max_height;
-       bool pseudo_tiled;
-       bool floating;
-       bool fullscreen;
        bool locked;
        bool sticky;
        bool private;
index 55acbed6d7ad5620c2d7d957ba6e460382099b3d..5d0560d7be0dfe3d271e7a3d4ae00192c4d01702 100644 (file)
--- a/window.c
+++ b/window.c
@@ -72,6 +72,8 @@ void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
        parse_rule_consequence(fd, csq);
 
        if (!csq->manage) {
+               free(csq->layer);
+               free(csq->state);
                disable_floating_atom(win);
                window_show(win);
                return;
@@ -142,41 +144,37 @@ void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
        snprintf(c->class_name, sizeof(c->class_name), "%s", csq->class_name);
        snprintf(c->instance_name, sizeof(c->instance_name), "%s", csq->instance_name);
 
-       csq->floating = csq->floating || d->floating;
-
        node_t *n = make_node();
        n->client = c;
 
        put_status(SBSC_MASK_WINDOW_MANAGE, "window_manage %s %s 0x%X 0x%X\n", m->name, d->name, f!=NULL?f->client->window:0, win);
        insert_node(m, d, n, f);
 
-       if (f != NULL && f->client != NULL && csq->floating) {
+       if (f != NULL && f->client != NULL && csq->state != NULL && *(csq->state) == STATE_FLOATING) {
                c->layer = f->client->layer;
        }
 
        if (csq->layer != NULL) {
                c->layer = *(csq->layer);
-               free(csq->layer);
        }
 
        disable_floating_atom(c->window);
-       set_pseudo_tiled(n, csq->pseudo_tiled);
-       set_floating(n, csq->floating);
+       set_state(m, d, n, csq->state != NULL ? *(csq->state) : c->state);
        set_locked(m, d, n, csq->locked);
        set_sticky(m, d, n, csq->sticky);
        set_private(m, d, n, csq->private);
-       set_fullscreen(n, csq->fullscreen);
 
        arrange(m, d);
 
        bool give_focus = (csq->focus && (d == mon->desk || csq->follow));
 
-       if (give_focus)
+       if (give_focus) {
                focus_node(m, d, n);
-       else if (csq->focus)
+       } else if (csq->focus) {
                pseudo_focus(m, d, n);
-       else
+       } else {
                stack(n);
+       }
 
        uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
        xcb_change_window_attributes(dpy, c->window, XCB_CW_EVENT_MASK, values);
@@ -189,12 +187,15 @@ void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
        }
 
        /* the same function is already called in `focus_node` but has no effects on unmapped windows */
-       if (give_focus)
+       if (give_focus) {
                xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
+       }
 
        num_clients++;
        ewmh_set_wm_desktop(n, d);
        ewmh_update_client_list();
+       free(csq->layer);
+       free(csq->state);
 }
 
 void unmanage_window(xcb_window_t win)
@@ -233,7 +234,7 @@ void window_draw_border(node_t *n, bool focused_window, bool focused_monitor)
                uint32_t presel_border_color_pxl;
                get_color(presel_border_color, win, &presel_border_color_pxl);
 
-               xcb_rectangle_t actual_rectangle = get_rectangle(n->client);
+               xcb_rectangle_t actual_rectangle = get_rectangle(NULL, n->client);
 
                uint16_t width = actual_rectangle.width;
                uint16_t height = actual_rectangle.height;
@@ -312,17 +313,26 @@ bool contains(xcb_rectangle_t a, xcb_rectangle_t b)
                a.y <= b.y && (a.y + a.height) >= (b.y + b.height));
 }
 
-xcb_rectangle_t get_rectangle(client_t *c)
+xcb_rectangle_t get_rectangle(monitor_t *m, client_t *c)
 {
-       if (!c->floating)
-               return c->tiled_rectangle;
-       else
-               return c->floating_rectangle;
+       switch (c->state) {
+               case STATE_TILED:
+                       return c->tiled_rectangle;
+                       break;
+               case STATE_PSEUDO_TILED:
+               case STATE_FLOATING:
+                       return c->floating_rectangle;
+                       break;
+               case STATE_FULLSCREEN:
+                       return m->rectangle;
+                       break;
+        }
 }
 
 void get_side_handle(client_t *c, direction_t dir, xcb_point_t *pt)
 {
-       xcb_rectangle_t rect = get_rectangle(c);
+       xcb_rectangle_t rect = get_rectangle(NULL, c);
+
        switch (dir) {
                case DIR_RIGHT:
                        pt->x = rect.x + rect.width;
@@ -385,81 +395,134 @@ void window_kill(monitor_t *m, desktop_t *d, node_t *n)
        remove_node(m, d, n);
 }
 
-void set_fullscreen(node_t *n, bool value)
+void set_layer(monitor_t *m, desktop_t *d, node_t *n, stack_layer_t l)
 {
-       if (n == NULL || n->client->fullscreen == value)
+       if (n == NULL || n->client->layer == l) {
                return;
+       }
 
        client_t *c = n->client;
 
-       PRINTF("fullscreen %X: %s\n", c->window, BOOLSTR(value));
-       put_status(SBSC_MASK_WINDOW_STATE, "window_state fullscreen %s 0x%X\n", ONOFFSTR(value), c->window);
+       c->layer = l;
 
-       c->fullscreen = value;
-       if (value) {
-               ewmh_wm_state_add(c, ewmh->_NET_WM_STATE_FULLSCREEN);
-               c->last_layer = c->layer;
-               c->layer = LAYER_ABOVE;
-       } else {
-               ewmh_wm_state_remove(c, ewmh->_NET_WM_STATE_FULLSCREEN);
-               c->layer = c->last_layer;
+       put_status(SBSC_MASK_WINDOW_LAYER, "window_layer %s 0x%X\n", LAYERSTR(l), c->window);
+
+       if (d->focus == n) {
+               neutralize_obscuring_windows(m, d, n);
        }
 
        stack(n);
 }
 
-void set_layer(node_t *n, stack_layer_t layer)
+void set_state(monitor_t *m, desktop_t *d, node_t *n, client_state_t s)
 {
-       if (n == NULL || n->client->layer == layer) {
+       if (n == NULL || n->client->state == s) {
                return;
        }
 
        client_t *c = n->client;
-       c->layer = layer;
 
-       put_status(SBSC_MASK_WINDOW_LAYER, "window_layer %s 0x%X\n", LAYERSTR(layer), c->window);
+       c->last_state = c->state;
+       c->state = s;
 
-       stack(n);
+       switch (c->last_state) {
+               case STATE_TILED:
+               case STATE_PSEUDO_TILED:
+                       break;
+               case STATE_FLOATING:
+                       set_floating(m, d, n, false);
+                       break;
+               case STATE_FULLSCREEN:
+                       set_fullscreen(m, d, n, false);
+                       break;
+       }
+
+       put_status(SBSC_MASK_WINDOW_STATE, "window_state %s off 0x%X\n", STATESTR(c->last_state), c->window);
+
+       switch (c->state) {
+               case STATE_TILED:
+               case STATE_PSEUDO_TILED:
+                       break;
+               case STATE_FLOATING:
+                       set_floating(m, d, n, true);
+                       break;
+               case STATE_FULLSCREEN:
+                       set_fullscreen(m, d, n, true);
+                       break;
+       }
+
+       put_status(SBSC_MASK_WINDOW_STATE, "window_state %s on 0x%X\n", STATESTR(c->state), c->window);
 }
 
-void set_pseudo_tiled(node_t *n, bool value)
+void set_floating(monitor_t *m, desktop_t *d, node_t *n, bool value)
 {
-       if (n == NULL || n->client->pseudo_tiled == value)
+       if (n == NULL) {
                return;
+       }
 
        client_t *c = n->client;
 
-       PRINTF("pseudo-tiled %X: %s\n", c->window, BOOLSTR(value));
-       put_status(SBSC_MASK_WINDOW_STATE, "window_state pseudo_tiled %s 0x%X\n", ONOFFSTR(value), c->window);
+       n->split_mode = MODE_AUTOMATIC;
+       n->vacant = value;
+       update_vacant_state(n->parent);
 
-       c->pseudo_tiled = value;
+       if (value) {
+               enable_floating_atom(c->window);
+               unrotate_brother(n);
+       } else {
+               disable_floating_atom(c->window);
+               rotate_brother(n);
+               if (d->focus == n) {
+                       neutralize_obscuring_windows(m, d, n);
+               }
+       }
+
+       stack(n);
 }
 
-void set_floating(node_t *n, bool value)
+void set_fullscreen(monitor_t *m, desktop_t *d, node_t *n, bool value)
 {
-       if (n == NULL || n->client->fullscreen || n->client->floating == value)
+       if (n == NULL) {
                return;
+       }
 
        client_t *c = n->client;
 
-       PRINTF("floating %X: %s\n", c->window, BOOLSTR(value));
-       put_status(SBSC_MASK_WINDOW_STATE, "window_state floating %s 0x%X\n", ONOFFSTR(value), c->window);
-
        n->split_mode = MODE_AUTOMATIC;
-       c->floating = n->vacant = value;
+       n->vacant = value;
        update_vacant_state(n->parent);
 
        if (value) {
-               enable_floating_atom(c->window);
-               unrotate_brother(n);
+               ewmh_wm_state_add(c, ewmh->_NET_WM_STATE_FULLSCREEN);
+               c->last_layer = c->layer;
+               c->layer = LAYER_ABOVE;
        } else {
-               disable_floating_atom(c->window);
-               rotate_brother(n);
+               ewmh_wm_state_remove(c, ewmh->_NET_WM_STATE_FULLSCREEN);
+               c->layer = c->last_layer;
+               if (d->focus == n) {
+                       neutralize_obscuring_windows(m, d, n);
+               }
        }
 
        stack(n);
 }
 
+void neutralize_obscuring_windows(monitor_t *m, desktop_t *d, node_t *n)
+{
+       bool dirty = false;
+       for (node_t *a = first_extrema(d->root); a != NULL; a = next_leaf(a, d->root)) {
+               if (a != n) {
+                       if (IS_FULLSCREEN(a->client) && stack_cmp(n->client, a->client) < 0) {
+                               set_state(m, d, a, a->client->last_state);
+                               dirty = true;
+                       }
+               }
+       }
+       if (dirty) {
+               arrange(m, d);
+       }
+}
+
 void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value)
 {
        if (n == NULL || n->client->locked == value)
@@ -467,8 +530,7 @@ void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value)
 
        client_t *c = n->client;
 
-       PRINTF("set locked %X: %s\n", c->window, BOOLSTR(value));
-       put_status(SBSC_MASK_WINDOW_STATE, "window_state locked %s 0x%X\n", ONOFFSTR(value), c->window);
+       put_status(SBSC_MASK_WINDOW_FLAG, "window_flag locked %s 0x%X\n", ONOFFSTR(value), c->window);
 
        c->locked = value;
        window_draw_border(n, d->focus == n, m == mon);
@@ -481,8 +543,7 @@ void set_sticky(monitor_t *m, desktop_t *d, node_t *n, bool value)
 
        client_t *c = n->client;
 
-       PRINTF("set sticky %X: %s\n", c->window, BOOLSTR(value));
-       put_status(SBSC_MASK_WINDOW_STATE, "window_state sticky %s 0x%X\n", ONOFFSTR(value), c->window);
+       put_status(SBSC_MASK_WINDOW_FLAG, "window_flag sticky %s 0x%X\n", ONOFFSTR(value), c->window);
 
        if (d != m->desk)
                transfer_node(m, d, n, m, m->desk, m->desk->focus);
@@ -506,8 +567,7 @@ void set_private(monitor_t *m, desktop_t *d, node_t *n, bool value)
 
        client_t *c = n->client;
 
-       PRINTF("set private %X: %s\n", c->window, BOOLSTR(value));
-       put_status(SBSC_MASK_WINDOW_STATE, "window_state private %s 0x%X\n", ONOFFSTR(value), c->window);
+       put_status(SBSC_MASK_WINDOW_FLAG, "window_flag private %s 0x%X\n", ONOFFSTR(value), c->window);
 
        c->private = value;
        update_privacy_level(n, value);
@@ -521,7 +581,7 @@ void set_urgency(monitor_t *m, desktop_t *d, node_t *n, bool value)
        n->client->urgent = value;
        window_draw_border(n, d->focus == n, m == mon);
 
-       put_status(SBSC_MASK_WINDOW_STATE, "window_state urgent %s 0x%X\n", ONOFFSTR(value), n->client->window);
+       put_status(SBSC_MASK_WINDOW_FLAG, "window_flag urgent %s 0x%X\n", ONOFFSTR(value), n->client->window);
        put_status(SBSC_MASK_REPORT);
 }
 
index b52fefd121ca9b572eda1d9ed4f6d6a8e6a18ca8..1e55947f338671a0b748a7cff58de04335d27f8c 100644 (file)
--- a/window.h
+++ b/window.h
@@ -37,15 +37,16 @@ void unmanage_window(xcb_window_t win);
 void window_draw_border(node_t *n, bool focused_window, bool focused_monitor);
 pointer_state_t *make_pointer_state(void);
 bool contains(xcb_rectangle_t a, xcb_rectangle_t b);
-xcb_rectangle_t get_rectangle(client_t *c);
+xcb_rectangle_t get_rectangle(monitor_t *m, client_t *c);
 void get_side_handle(client_t *c, direction_t dir, xcb_point_t *pt);
 void adopt_orphans(void);
 void window_close(node_t *n);
 void window_kill(monitor_t *m, desktop_t *d, node_t *n);
-void set_fullscreen(node_t *n, bool value);
-void set_layer(node_t *n, stack_layer_t layer);
-void set_pseudo_tiled(node_t *n, bool value);
-void set_floating(node_t *n, bool value);
+void set_layer(monitor_t *m, desktop_t *d, node_t *n, stack_layer_t l);
+void set_state(monitor_t *m, desktop_t *d, node_t *n, client_state_t s);
+void set_floating(monitor_t *m, desktop_t *d, node_t *n, bool value);
+void set_fullscreen(monitor_t *m, desktop_t *d, node_t *n, bool value);
+void neutralize_obscuring_windows(monitor_t *m, desktop_t *d, node_t *n);
 void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value);
 void set_sticky(monitor_t *m, desktop_t *d, node_t *n, bool value);
 void set_private(monitor_t *m, desktop_t *d, node_t *n, bool value);