]> git.lizzy.rs Git - bspwm.git/commitdiff
Implement private windows
authorBastien Dejean <nihilhill@gmail.com>
Sat, 12 Oct 2013 19:16:51 +0000 (21:16 +0200)
committerBastien Dejean <nihilhill@gmail.com>
Sat, 12 Oct 2013 19:16:51 +0000 (21:16 +0200)
16 files changed:
contrib/bash_completion
contrib/zsh_completion
doc/bspwm.1
doc/bspwm.1.txt
messages.c
query.c
restore.c
rule.c
rule.h
settings.c
settings.h
tree.c
tree.h
types.h
window.c
window.h

index e07dff7e6344c3d88d4ce4bfb5f130dd4ae45904..fffa1dc266598fbc6da18b2aba181e80f7d341ff 100644 (file)
@@ -1,7 +1,7 @@
 _bspc() {
     local commands='window desktop monitor query pointer rule restore control config quit'
 
-    local settings='focused_border_color active_border_color normal_border_color presel_border_color focused_locked_border_color active_locked_border_color normal_locked_border_color focused_sticky_border_color normal_sticky_border_color urgent_border_color focused_frame_opacity active_frame_opacity normal_frame_opacity border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio growth_factor borderless_monocle gapless_monocle focus_follows_pointer pointer_follows_monitor apply_floating_atom auto_alternate auto_cancel history_aware_focus honor_ewmh_focus'
+    local settings='focused_border_color active_border_color normal_border_color presel_border_color focused_locked_border_color active_locked_border_color normal_locked_border_color focused_sticky_border_color normal_sticky_border_color focused_private_border_color active_private_border_color normal_private_border_color urgent_border_color focused_frame_opacity active_frame_opacity normal_frame_opacity border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio growth_factor borderless_monocle gapless_monocle focus_follows_pointer pointer_follows_monitor apply_floating_atom auto_alternate auto_cancel history_aware_focus honor_ewmh_focus'
 
     COMPREPLY=()
 
index a668e5a98608b14dda56f7bcc1fa15ae7e9c32f6..97a4ee4d09ac11e8ac7345920c49e67ae7732c4f 100644 (file)
@@ -3,7 +3,7 @@
 _bspc() {
     local -a commands settings
     commands=('window' 'desktop' 'monitor' 'query' 'pointer' 'rule' 'restore' 'control' 'config' 'quit')
-    settings=('focused_border_color' 'active_border_color' 'normal_border_color' 'presel_border_color' 'focused_locked_border_color' 'active_locked_border_color' 'normal_locked_border_color' 'focused_sticky_border_color' 'normal_sticky_border_color' 'urgent_border_color' 'focused_frame_opacity' 'active_frame_opacity' 'normal_frame_opacity' 'border_width' 'window_gap' 'top_padding' 'right_padding' 'bottom_padding' 'left_padding' 'split_ratio' 'growth_factor' 'borderless_monocle' 'gapless_monocle' 'focus_follows_pointer' 'pointer_follows_monitor' 'apply_floating_atom' 'auto_alternate' 'auto_cancel' 'history_aware_focus' 'honor_ewmh_focus')
+    settings=('focused_border_color' 'active_border_color' 'normal_border_color' 'presel_border_color' 'focused_locked_border_color' 'active_locked_border_color' 'normal_locked_border_color' 'focused_sticky_border_color' 'normal_sticky_border_color' 'focused_private_border_color' 'active_private_border_color' 'normal_private_border_color' 'urgent_border_color' 'focused_frame_opacity' 'active_frame_opacity' 'normal_frame_opacity' 'border_width' 'window_gap' 'top_padding' 'right_padding' 'bottom_padding' 'left_padding' 'split_ratio' 'growth_factor' 'borderless_monocle' 'gapless_monocle' 'focus_follows_pointer' 'pointer_follows_monitor' 'apply_floating_atom' 'auto_alternate' 'auto_cancel' 'history_aware_focus' 'honor_ewmh_focus')
     if (( CURRENT == 2 )) ; then
         _values 'command' "$commands[@]"
     elif (( CURRENT == 3 )) ; then
index 5a504c5af7bdb46378a3f65f2112d6cb8e1ca636..a90fa02e408c6bd36efbafb9a6fe5a543d4955b1 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/11/2013
+.\"      Date: 10/12/2013
 .\"    Manual: Bspwm Manual
 .\"    Source: Bspwm 0.8.5
 .\"  Language: English
 .\"
-.TH "BSPWM" "1" "10/11/2013" "Bspwm 0\&.8\&.5" "Bspwm Manual"
+.TH "BSPWM" "1" "10/12/2013" "Bspwm 0\&.8\&.5" "Bspwm Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -518,7 +518,7 @@ Set the splitting ratio (or pull, or push) the edge located in the given directi
 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|locked|sticky|visible[=on|off]
+\fB\-t\fR, \fB\-\-toggle\fR floating|fullscreen|locked|sticky|private|visible[=on|off]
 .RS 4
 Set or toggle the given state for the selected window\&.
 .RE
@@ -914,7 +914,7 @@ rule \fIOPTIONS\fR
 \fBOptions\fR
 .RS 4
 .PP
-\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name> [\-d \fIDESKTOP_SEL\fR [\-\-follow]] [\-\-tags <name>|^<n>[,\&...]][\-\-floating] [\-\-fullscreen] [\-\-locked] [\-\-sticky] [\-\-focus] [\-\-frame] [\-\-unmanage] [\-\-one\-shot]
+\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name> [\-d \fIDESKTOP_SEL\fR [\-\-follow]] [\-\-tags <name>|^<n>[,\&...]][\-\-floating] [\-\-fullscreen] [\-\-locked] [\-\-sticky] [\-\-focus] [\-\-frame] [\-\-private] [\-\-unmanage] [\-\-one\-shot]
 .RS 4
 Create a new rule\&.
 .RE
@@ -1018,6 +1018,21 @@ Color of the border of a focused sticky window of an unfocused monitor\&.
 Color of the border of an unfocused sticky window\&.
 .RE
 .PP
+\fIfocused_private_border_color\fR
+.RS 4
+Color of the border of a focused private window of a focused monitor\&.
+.RE
+.PP
+\fIactive_private_border_color\fR
+.RS 4
+Color of the border of a focused private window of an unfocused monitor\&.
+.RE
+.PP
+\fInormal_private_border_color\fR
+.RS 4
+Color of the border of an unfocused private window\&.
+.RE
+.PP
 \fIurgent_border_color\fR
 .RS 4
 Color of the border of an urgent window\&.
index dc79dc9934c8b46930a86bccd6566e1a42efd2ba..a86a3d8548db63a2e6520aa570defc62b739ddb2 100644 (file)
@@ -334,7 +334,7 @@ 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|locked|sticky|visible[=on|off]::
+*-t*, *--toggle* floating|fullscreen|locked|sticky|private|visible[=on|off]::
     Set or toggle the given state for the selected window.
 
 *-c*, *--close*::
@@ -550,7 +550,7 @@ rule 'OPTIONS'
 Options
 ^^^^^^^
 
-*-a*, *--add* <class_name>|<instance_name> [-d 'DESKTOP_SEL' [--follow]] [--tags <name>|^<n>[,...]][--floating] [--fullscreen] [--locked] [--sticky] [--focus] [--frame] [--unmanage] [--one-shot]::
+*-a*, *--add* <class_name>|<instance_name> [-d 'DESKTOP_SEL' [--follow]] [--tags <name>|^<n>[,...]][--floating] [--fullscreen] [--locked] [--sticky] [--focus] [--frame] [--private] [--unmanage] [--one-shot]::
     Create a new rule.
 
 *-r*, *--remove* <name>|^<n>|tail|head...::
@@ -616,6 +616,15 @@ Global Settings
 'normal_sticky_border_color'::
     Color of the border of an unfocused sticky window.
 
+'focused_private_border_color'::
+    Color of the border of a focused private window of a focused monitor.
+
+'active_private_border_color'::
+    Color of the border of a focused private window of an unfocused monitor.
+
+'normal_private_border_color'::
+    Color of the border of an unfocused private window.
+
 'urgent_border_color'::
     Color of the border of an urgent window.
 
index 81d9ab2cf3237cf949e9b56163e91c2c9bdd8917..1c14b8a4266a8bc6fcfd94fa8d3d27e46f18a7ba 100644 (file)
@@ -214,6 +214,8 @@ bool cmd_window(char **args, int num)
                 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));
+            } else if (streq("private", key)) {
+                set_private(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->client->private));
             } else if (streq("visible", key)) {
                 set_presence(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !is_visible(trg.desktop, trg.node)));
             }
@@ -770,6 +772,8 @@ bool cmd_rule(char **args, int num, char *rsp)
                     rule->effect.focus = true;
                 } else if (streq("--frame", *args)) {
                     rule->effect.frame = true;
+                } else if (streq("--private", *args)) {
+                    rule->effect.private = true;
                 } else if (streq("--unmanage", *args)) {
                     rule->effect.unmanage = true;
                 } else if (streq("--one-shot", *args)) {
@@ -1029,6 +1033,9 @@ bool set_setting(coordinates_t loc, char *name, char *value)
     SETCOLOR(focused_sticky_border_color)
     SETCOLOR(active_sticky_border_color)
     SETCOLOR(normal_sticky_border_color)
+    SETCOLOR(focused_private_border_color)
+    SETCOLOR(active_private_border_color)
+    SETCOLOR(normal_private_border_color)
     SETCOLOR(urgent_border_color)
 #undef SETCOLOR
     } else if (streq("focus_follows_pointer", name)) {
diff --git a/query.c b/query.c
index e862d42fd0d7a58bd43f6f10890b853118626d78..8bfd154e8d2c0fc9f234e50dff5ce53150135ff4 100644 (file)
--- a/query.c
+++ b/query.c
@@ -90,7 +90,7 @@ void query_tree(desktop_t *d, node_t *n, char *rsp, unsigned int depth)
 
     if (is_leaf(n)) {
         client_t *c = n->client;
-        snprintf(line, sizeof(line), "%c %s 0x%X %u %u %ux%u%+i%+i %c %c%c%c%c%c%c%c%c", (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), c->class_name, c->window, c->tags_field, 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->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (c->frame ? 'e' : '-'), (n->split_mode ? 'p' : '-'));
+        snprintf(line, sizeof(line), "%c %s 0x%X %u %u %ux%u%+i%+i %c %c%c%c%c%c%c%c%c%c", (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), c->class_name, c->window, c->tags_field, 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->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (c->frame ? 'e' : '-'), (c->private ? 'i' : '-'), (n->split_mode ? 'p' : '-'));
     } else {
         snprintf(line, sizeof(line), "%c %c %.2f", (n->split_type == TYPE_HORIZONTAL ? 'H' : 'V'), (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), n->split_ratio);
     }
index 3dad5bd51deaff11540c56f541bd9db8b33e96cf..4a91c9cbb3e31b558c11be70457e465109819027 100644 (file)
--- a/restore.c
+++ b/restore.c
@@ -137,8 +137,8 @@ void restore_tree(char *file_path)
             } else {
                 client_t *c = make_client(XCB_NONE);
                 num_clients++;
-                char floating, transient, fullscreen, urgent, locked, sticky, frame, sd, sm, end = 0;
-                sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c %c%c%c%c%c%c%c%c %c", &br, c->class_name, &c->window, &c->tags_field, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &sd, &floating, &transient, &fullscreen, &urgent, &locked, &sticky, &frame, &sm, &end);
+                char floating, transient, fullscreen, urgent, locked, sticky, frame, private, sd, sm, end = 0;
+                sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c %c%c%c%c%c%c%c%c%c %c", &br, c->class_name, &c->window, &c->tags_field, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &sd, &floating, &transient, &fullscreen, &urgent, &locked, &sticky, &frame, &private, &sm, &end);
                 c->floating = (floating == '-' ? false : true);
                 c->transient = (transient == '-' ? false : true);
                 c->fullscreen = (fullscreen == '-' ? false : true);
@@ -146,6 +146,7 @@ void restore_tree(char *file_path)
                 c->locked = (locked == '-' ? false : true);
                 c->sticky = (sticky == '-' ? false : true);
                 c->frame = (frame == '-' ? false : true);
+                c->private = (private == '-' ? false : true);
                 n->split_mode = (sm == '-' ? MODE_AUTOMATIC : MODE_MANUAL);
                 if (sd == 'U')
                     n->split_dir = DIR_UP;
@@ -182,6 +183,8 @@ void restore_tree(char *file_path)
                     n->vacant = true;
                     update_vacant_state(n->parent);
                 }
+                if (n->client->private)
+                    update_privacy_level(n, true);
             }
     ewmh_update_current_desktop();
 }
diff --git a/rule.c b/rule.c
index eef471d1061d6a79761959ad8f6901e466f9cc3f..1f08710962f976210a2286e79c891d2cac8df03e 100644 (file)
--- a/rule.c
+++ b/rule.c
@@ -42,6 +42,7 @@ rule_t *make_rule(void)
     r->effect.follow = false;
     r->effect.focus = false;
     r->effect.frame = false;
+    r->effect.private = false;
     r->effect.unmanage = false;
     r->one_shot = false;
     r->effect.desc[0] = '\0';
@@ -115,7 +116,7 @@ bool is_match(rule_t *r, xcb_window_t win)
     return false;
 }
 
-void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *frame, bool *manage)
+void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *frame, bool *private, bool *manage)
 {
     xcb_ewmh_get_atoms_reply_t win_type;
 
@@ -183,6 +184,8 @@ void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *
                 *takes_focus = true;
             if (efc.frame)
                 *frame = true;
+            if (efc.private)
+                *private = private;
             if (efc.unmanage)
                 *manage = false;
             if (efc.desc[0] != '\0') {
@@ -243,6 +246,8 @@ void list_rules(char *pattern, char *rsp)
             strncat(rsp, " --focus", REMLEN(rsp));
         if (r->effect.frame)
             strncat(rsp, " --frame", REMLEN(rsp));
+        if (r->effect.private)
+            strncat(rsp, " --private", REMLEN(rsp));
         if (r->effect.unmanage)
             strncat(rsp, " --unmanage", REMLEN(rsp));
         if (r->one_shot)
diff --git a/rule.h b/rule.h
index 7d8c35a7bb91980bb7d096de04f75ab3031b5b9e..fe8e507b9a90c8a1195e4eb3e92e717ab5d3ae97 100644 (file)
--- a/rule.h
+++ b/rule.h
@@ -34,7 +34,7 @@ void remove_rule(rule_t *r);
 void remove_rule_by_name(char *name);
 bool remove_rule_by_index(int idx);
 bool is_match(rule_t *r, xcb_window_t win);
-void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *frame, bool *manage);
+void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *frame, bool *private, bool *manage);
 void list_rules(char *pattern, char *rsp);
 
 #endif
index 2872146f02e36eb4de8ddb275f155603823f918a..a00ecec2f2d4d4f089a4cd1cf85f1b4ddbfaf562 100644 (file)
@@ -56,6 +56,9 @@ void load_settings(void)
     snprintf(focused_sticky_border_color, sizeof(focused_sticky_border_color), "%s", FOCUSED_STICKY_BORDER_COLOR);
     snprintf(active_sticky_border_color, sizeof(active_sticky_border_color), "%s", ACTIVE_STICKY_BORDER_COLOR);
     snprintf(normal_sticky_border_color, sizeof(normal_sticky_border_color), "%s", NORMAL_STICKY_BORDER_COLOR);
+    snprintf(focused_private_border_color, sizeof(focused_private_border_color), "%s", FOCUSED_PRIVATE_BORDER_COLOR);
+    snprintf(active_private_border_color, sizeof(active_private_border_color), "%s", ACTIVE_PRIVATE_BORDER_COLOR);
+    snprintf(normal_private_border_color, sizeof(normal_private_border_color), "%s", NORMAL_PRIVATE_BORDER_COLOR);
     snprintf(urgent_border_color, sizeof(urgent_border_color), "%s", URGENT_BORDER_COLOR);
 
     focused_frame_opacity = FOCUSED_FRAME_OPACITY;
index 88ae8fb8432f7bd5b7d8cc37f6284bb118aaab32..ba90177b96abf0a0b5f072daaff79446baf8c090 100644 (file)
 #define CONFIG_NAME         WM_NAME "rc"
 #define CONFIG_HOME_ENV     "XDG_CONFIG_HOME"
 
-#define FOCUSED_BORDER_COLOR        "#7E7F89"
-#define ACTIVE_BORDER_COLOR         "#545350"
-#define NORMAL_BORDER_COLOR         "#3F3E3B"
-#define PRESEL_BORDER_COLOR         "#E8E8F4"
-#define FOCUSED_LOCKED_BORDER_COLOR "#C7B579"
-#define ACTIVE_LOCKED_BORDER_COLOR  "#545350"
-#define NORMAL_LOCKED_BORDER_COLOR  "#3F3E3B"
-#define FOCUSED_STICKY_BORDER_COLOR "#E3A5DA"
-#define ACTIVE_STICKY_BORDER_COLOR  "#545350"
-#define NORMAL_STICKY_BORDER_COLOR  "#3F3E3B"
-#define URGENT_BORDER_COLOR         "#EFA29A"
+#define FOCUSED_BORDER_COLOR          "#7E7F89"
+#define ACTIVE_BORDER_COLOR           "#545350"
+#define NORMAL_BORDER_COLOR           "#3F3E3B"
+#define PRESEL_BORDER_COLOR           "#E8E8F4"
+#define FOCUSED_LOCKED_BORDER_COLOR   "#C7B579"
+#define ACTIVE_LOCKED_BORDER_COLOR    "#545350"
+#define NORMAL_LOCKED_BORDER_COLOR    "#3F3E3B"
+#define FOCUSED_STICKY_BORDER_COLOR   "#E3A5DA"
+#define ACTIVE_STICKY_BORDER_COLOR    "#545350"
+#define NORMAL_STICKY_BORDER_COLOR    "#3F3E3B"
+#define FOCUSED_PRIVATE_BORDER_COLOR  "#42CAD9"
+#define ACTIVE_PRIVATE_BORDER_COLOR   "#5C5955"
+#define NORMAL_PRIVATE_BORDER_COLOR   "#34322E"
+#define URGENT_BORDER_COLOR           "#EFA29A"
 
 #define FOCUSED_FRAME_OPACITY       0.5
 #define ACTIVE_FRAME_OPACITY        0.25
@@ -70,6 +73,9 @@ char normal_locked_border_color[MAXLEN];
 char focused_sticky_border_color[MAXLEN];
 char active_sticky_border_color[MAXLEN];
 char normal_sticky_border_color[MAXLEN];
+char focused_private_border_color[MAXLEN];
+char active_private_border_color[MAXLEN];
+char normal_private_border_color[MAXLEN];
 char urgent_border_color[MAXLEN];
 
 double focused_frame_opacity;
diff --git a/tree.c b/tree.c
index de65e9c28bf51f6e7db02e92172220a606cd675a..1a3ee5c239cbcc8740d5b236730f8b9f80e1a720 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -147,6 +147,28 @@ void insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f)
             f = p;
             p = f->parent;
         }
+        if (((f->client != NULL && f->client->private) || (p != NULL && p->privacy_level > 0))
+                    && f->split_mode == MODE_AUTOMATIC) {
+            node_t *closest = NULL;
+            node_t *public = NULL;
+            closest_public(d, f, &closest, &public);
+            if (public != NULL) {
+                f = public;
+                p = f->parent;
+            } else {
+                if (closest != NULL) {
+                    f = closest;
+                    p = f->parent;
+                }
+                f->split_mode = MODE_MANUAL;
+                xcb_rectangle_t rect = f->client->tiled_rectangle;
+                f->split_dir = (rect.width >= rect.height ? DIR_LEFT : DIR_UP);
+                if (f->client->private) {
+                    get_opposite(f->split_dir, &f->split_dir);
+                    update_privacy_level(f, false);
+                }
+            }
+        }
         n->parent = c;
         c->birth_rotation = f->birth_rotation;
         switch (f->split_mode) {
@@ -229,7 +251,11 @@ void insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f)
         }
         if (f->vacant)
             update_vacant_state(p);
+        if (f->client != NULL && f->client->private)
+            update_privacy_level(f, true);
     }
+    if (n->client->private)
+        update_privacy_level(n, true);
     if (d->focus == NULL && is_visible(d, n))
         d->focus = n;
     if (n->client->sticky)
@@ -326,6 +352,7 @@ node_t *make_node(void)
     n->split_mode = MODE_AUTOMATIC;
     n->split_type = TYPE_VERTICAL;
     n->birth_rotation = 0;
+    n->privacy_level = 0;
     n->client = NULL;
     n->vacant = false;
     return n;
@@ -338,7 +365,7 @@ client_t *make_client(xcb_window_t win)
     c->border_width = BORDER_WIDTH;
     c->window = win;
     c->floating = c->transient = c->fullscreen = c->locked = c->sticky = c->urgent = false;
-    c->frame = c->icccm_focus = false;
+    c->frame = 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) {
         if (has_proto(WM_TAKE_FOCUS, &protocols))
@@ -441,6 +468,33 @@ node_t *closest_visible(desktop_t *d, node_t *n)
     return NULL;
 }
 
+void closest_public(desktop_t *d, node_t *n, node_t **closest, node_t **public)
+{
+    if (n == NULL)
+        return;
+    node_t *prev = prev_leaf(n, d->root);
+    node_t *next = next_leaf(n, d->root);
+    while (prev != NULL || next != NULL) {
+#define TESTLOOP(n) \
+        if (n != NULL) { \
+            if (is_visible(d, n) && is_tiled(n->client)) { \
+                if (n->privacy_level == 0) { \
+                    if (n->parent == NULL || n->parent->privacy_level == 0) { \
+                        *public = n; \
+                        return; \
+                    } else if (*closest == NULL) { \
+                        *closest = n; \
+                    } \
+                } \
+            } \
+            n = n##_leaf(n, d->root); \
+        }
+        TESTLOOP(prev)
+        TESTLOOP(next)
+#undef TESTLOOP
+    }
+}
+
 node_t *first_extrema(node_t *n)
 {
     if (n == NULL)
@@ -816,6 +870,9 @@ void unlink_node(monitor_t *m, desktop_t *d, node_t *n)
                 d->focus = closest_visible(d, n);
         }
 
+        if (n->client->private)
+            update_privacy_level(n, false);
+
         node_t *b;
         node_t *g = p->parent;
 
@@ -897,6 +954,8 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop
     bool n2_first_child = is_first_child(n2);
     int br1 = n1->birth_rotation;
     int br2 = n2->birth_rotation;
+    int pl1 = n1->privacy_level;
+    int pl2 = n2->privacy_level;
 
     if (pn1 != NULL) {
         if (n1_first_child)
@@ -916,12 +975,19 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop
     n2->parent = pn1;
     n1->birth_rotation = br2;
     n2->birth_rotation = br1;
+    n1->privacy_level = pl2;
+    n2->privacy_level = pl1;
 
     if (n1->vacant != n2->vacant) {
         update_vacant_state(n1->parent);
         update_vacant_state(n2->parent);
     }
 
+    if (n1->client->private != n2->client->private) {
+        n1->client->private = !n1->client->private;
+        n2->client->private = !n2->client->private;
+    }
+
     if (d1 != d2) {
         if (d1->root == n1)
             d1->root = n2;
@@ -1071,3 +1137,10 @@ void update_vacant_state(node_t *n)
         p = p->parent;
     }
 }
+
+void update_privacy_level(node_t *n, bool value)
+{
+    int v = (value ? 1 : -1);
+    for (node_t *p = n; p != NULL; p = p->parent)
+        p->privacy_level += v;
+}
diff --git a/tree.h b/tree.h
index dbaadade011fc67d92bae47299b50ce95d5d36dc..2e7596b9052b9901df4a48e09cc250212cbd4d7a 100644 (file)
--- a/tree.h
+++ b/tree.h
@@ -43,6 +43,7 @@ void change_split_ratio(node_t *n, value_change_t chg);
 void reset_mode(coordinates_t *loc);
 node_t *brother_tree(node_t *n);
 node_t *closest_visible(desktop_t *d, node_t *n);
+void closest_public(desktop_t *d, node_t *n, node_t **closest, node_t **public);
 node_t *first_extrema(node_t *n);
 node_t *second_extrema(node_t *n);
 node_t *next_leaf(node_t *n, node_t *r);
@@ -72,5 +73,6 @@ bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desk
 node_t *closest_node(monitor_t *m, desktop_t *d, node_t *n, cycle_dir_t dir, client_select_t sel);
 void circulate_leaves(monitor_t *m, desktop_t *d, circulate_dir_t dir);
 void update_vacant_state(node_t *n);
+void update_privacy_level(node_t *n, bool value);
 
 #endif
diff --git a/types.h b/types.h
index e432908b8cac563da9d4e8d6bd8cab204bb7b709..fffb27909aff65c4784838317248b082c5c012e1 100644 (file)
--- a/types.h
+++ b/types.h
@@ -162,6 +162,7 @@ typedef struct {
     bool sticky;
     bool urgent;
     bool frame;
+    bool private;
     bool icccm_focus;
     xcb_rectangle_t floating_rectangle;
     xcb_rectangle_t tiled_rectangle;
@@ -179,6 +180,7 @@ struct node_t {
     int birth_rotation;
     xcb_rectangle_t rectangle;
     bool vacant;          /* vacant nodes only hold floating clients */
+    int privacy_level;
     node_t *first_child;
     node_t *second_child;
     node_t *parent;
@@ -251,6 +253,7 @@ typedef struct {
     bool focus;
     bool unmanage;
     bool frame;
+    bool private;
     char desc[MAXLEN];
     char tags[MAXLEN];
 } rule_effect_t;
index c9ef7e20ca73fb310298b7e1dacf799a18c457fa..b0693becf82d820799a6487e73dbf9a55712f53a 100644 (file)
--- a/window.c
+++ b/window.c
@@ -49,9 +49,9 @@ void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win)
     if (override_redirect || locate_window(win, &loc))
         return;
 
-    bool floating = false, fullscreen = false, locked = false, sticky = false, follow = false, transient = false, takes_focus = true, frame = false, manage = true;
+    bool floating = false, fullscreen = false, locked = false, sticky = false, follow = false, transient = false, takes_focus = true, frame = false, private = false, manage = true;
     unsigned int tags_field = 0;
-    handle_rules(win, &m, &d, &tags_field, &floating, &fullscreen, &locked, &sticky, &follow, &transient, &takes_focus, &frame, &manage);
+    handle_rules(win, &m, &d, &tags_field, &floating, &fullscreen, &locked, &sticky, &follow, &transient, &takes_focus, &frame, &private, &manage);
 
     if (!manage) {
         disable_floating_atom(win);
@@ -84,6 +84,7 @@ void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win)
     set_floating(n, floating);
     set_locked(m, d, n, locked);
     set_sticky(m, d, n, sticky);
+    set_private(m, d, n, private);
 
     if (d->focus != NULL && d->focus->client->fullscreen)
         set_fullscreen(d->focus, false);
@@ -465,6 +466,20 @@ void set_sticky(monitor_t *m, desktop_t *d, node_t *n, bool value)
     window_draw_border(n, d->focus == n, m == mon);
 }
 
+void set_private(monitor_t *m, desktop_t *d, node_t *n, bool value)
+{
+    if (n == NULL || n->client->private == value)
+        return;
+
+    client_t *c = n->client;
+
+    PRINTF("set private %X: %s\n", c->window, BOOLSTR(value));
+
+    c->private = value;
+    update_privacy_level(n, value);
+    window_draw_border(n, d->focus == n, m == mon);
+}
+
 void set_urgency(monitor_t *m, desktop_t *d, node_t *n, bool value)
 {
     if (value && mon->desk->focus == n)
@@ -503,6 +518,8 @@ uint32_t get_border_color(client_t *c, bool focused_window, bool focused_monitor
             get_color(focused_locked_border_color, c->window, &pxl);
         else if (c->sticky)
             get_color(focused_sticky_border_color, c->window, &pxl);
+        else if (c->private)
+            get_color(focused_private_border_color, c->window, &pxl);
         else
             get_color(focused_border_color, c->window, &pxl);
     } else if (focused_window) {
@@ -512,6 +529,8 @@ uint32_t get_border_color(client_t *c, bool focused_window, bool focused_monitor
             get_color(active_locked_border_color, c->window, &pxl);
         else if (c->sticky)
             get_color(active_sticky_border_color, c->window, &pxl);
+        else if (c->private)
+            get_color(active_private_border_color, c->window, &pxl);
         else
             get_color(active_border_color, c->window, &pxl);
     } else {
@@ -521,6 +540,8 @@ uint32_t get_border_color(client_t *c, bool focused_window, bool focused_monitor
             get_color(normal_locked_border_color, c->window, &pxl);
         else if (c->sticky)
             get_color(normal_sticky_border_color, c->window, &pxl);
+        else if (c->private)
+            get_color(normal_private_border_color, c->window, &pxl);
         else
             get_color(normal_border_color, c->window, &pxl);
     }
index e05095379bd40128baa6468a7e98ea7b68aa0ce1..a348c32655a1209c92e020df5d55af809193a7af 100644 (file)
--- a/window.h
+++ b/window.h
@@ -49,6 +49,7 @@ void set_fullscreen(node_t *n, bool value);
 void set_floating(node_t *n, bool value);
 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);
 void set_urgency(monitor_t *m, desktop_t *d, node_t *n, bool value);
 void set_floating_atom(xcb_window_t win, uint32_t value);
 void enable_floating_atom(xcb_window_t win);