]> git.lizzy.rs Git - bspwm.git/commitdiff
Print status informations via control --subscribe
authorBastien Dejean <nihilhill@gmail.com>
Thu, 7 Nov 2013 13:28:39 +0000 (14:28 +0100)
committerBastien Dejean <nihilhill@gmail.com>
Thu, 7 Nov 2013 13:28:39 +0000 (14:28 +0100)
18 files changed:
Makefile
bspc.c
bspwm.c
bspwm.h
contrib/bash_completion
contrib/lightdm/bspwm-session
contrib/zsh_completion
doc/bspwm.1
doc/bspwm.1.txt
examples/panel/panel
examples/panel/xinitrc [deleted file]
messages.c
messages.h
settings.c
settings.h
subscribe.c [new file with mode: 0644]
subscribe.h [new file with mode: 0644]
types.h

index a35524156f9c15f99aba09ad675bcc5a63503fcd..c790d0547ffc2879b1f702a63ec7a0823d333bf5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ BASHCPL = $(PREFIX)/share/bash-completion/completions
 ZSHCPL = $(PREFIX)/share/zsh/site-functions
 
 WM_SRC = bspwm.c helpers.c settings.c monitor.c desktop.c tree.c stack.c history.c \
-        events.c pointer.c window.c messages.c query.c restore.c rule.c ewmh.c
+        events.c pointer.c window.c messages.c query.c restore.c rule.c ewmh.c subscribe.c
 WM_OBJ = $(WM_SRC:.c=.o)
 CL_SRC = bspc.c helpers.c
 CL_OBJ = $(CL_SRC:.c=.o)
diff --git a/bspc.c b/bspc.c
index 8fd753204268eee5aa8d3712f760d746aa0837b1..fd138f211e574aa4e1ad7c3f8d532454c0a17055 100644 (file)
--- a/bspc.c
+++ b/bspc.c
 
 int main(int argc, char *argv[])
 {
-    int sock_fd;
+    int fd;
     struct sockaddr_un sock_address;
-    char msg[BUFSIZ];
-    char rsp[BUFSIZ];
+    char msg[BUFSIZ], rsp[BUFSIZ];
 
     if (argc < 2)
         err("No arguments given.\n");
@@ -55,31 +54,26 @@ int main(int argc, char *argv[])
         msg_len += n;
     }
 
-    if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
         err("Failed to create the socket.\n");
 
-    if (connect(sock_fd, (struct sockaddr *) &sock_address, sizeof(sock_address)) == -1)
+    if (connect(fd, (struct sockaddr *) &sock_address, sizeof(sock_address)) == -1)
         err("Failed to connect to the socket.\n");
 
-    if (send(sock_fd, msg, msg_len, 0) == -1)
+    if (send(fd, msg, msg_len, 0) == -1)
         err("Failed to send the data.\n");
 
-    int ret = EXIT_SUCCESS;
-
-    int n = recv(sock_fd, rsp, sizeof(rsp), 0);
-    if (n == -1) {
-        err("Failed to get the response.\n");
-    } else if (n > 0) {
-        if (n == 1 && rsp[0] == MESSAGE_FAILURE) {
+    int ret = EXIT_SUCCESS, nb;
+    while ((nb = recv(fd, rsp, sizeof(rsp), 0)) > 0) {
+        if (nb == 1 && rsp[0] == MESSAGE_FAILURE) {
             ret = EXIT_FAILURE;
         } else {
-            rsp[n] = '\0';
+            rsp[nb] = '\0';
             printf("%s\n", rsp);
+            fflush(stdout);
         }
     }
 
-    if (sock_fd)
-        close(sock_fd);
-
+    close(fd);
     return ret;
 }
diff --git a/bspwm.c b/bspwm.c
index 606b4fd93102562aaa812fd7323a7ad594f140b4..342a06c6b285f87f582bf78fa278552d4a2e6070 100644 (file)
--- a/bspwm.c
+++ b/bspwm.c
@@ -22,8 +22,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <ctype.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #endif
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <signal.h>
 #include <unistd.h>
 #include "types.h"
 #include "desktop.h"
 #include "monitor.h"
 #include "settings.h"
 #include "messages.h"
+#include "subscribe.h"
 #include "events.h"
 #include "common.h"
-#include "tree.h"
 #include "window.h"
 #include "history.h"
 #include "stack.h"
@@ -52,9 +51,7 @@ int main(int argc, char *argv[])
 {
     fd_set descriptors;
     char socket_path[MAXLEN];
-    char *fifo_path = NULL;
     config_path[0] = '\0';
-    status_prefix = NULL;
     int sock_fd, ret_fd, dpy_fd, sel, n;
     struct sockaddr_un sock_address;
     size_t rsp_len = 0;
@@ -63,10 +60,10 @@ int main(int argc, char *argv[])
     xcb_generic_event_t *event;
     char opt;
 
-    while ((opt = getopt(argc, argv, "hvc:s:p:")) != -1) {
+    while ((opt = getopt(argc, argv, "hvc:")) != -1) {
         switch (opt) {
             case 'h':
-                printf(WM_NAME " [-h|-v|-c CONFIG_PATH|-s PANEL_FIFO|-p PANEL_PREFIX]\n");
+                printf(WM_NAME " [-h|-v|-c CONFIG_PATH]\n");
                 exit(EXIT_SUCCESS);
                 break;
             case 'v':
@@ -76,12 +73,6 @@ int main(int argc, char *argv[])
             case 'c':
                 snprintf(config_path, sizeof(config_path), "%s", optarg);
                 break;
-            case 's':
-                fifo_path = optarg;
-                break;
-            case 'p':
-                status_prefix = optarg;
-                break;
         }
     }
 
@@ -122,14 +113,7 @@ int main(int argc, char *argv[])
 
     sel = MAX(sock_fd, dpy_fd) + 1;
 
-    if (fifo_path != NULL) {
-        int fifo_fd = open(fifo_path, O_RDWR | O_NONBLOCK);
-        if (fifo_fd != -1)
-            status_fifo = fdopen(fifo_fd, "w");
-        else
-            warn("Couldn't open status fifo.\n");
-    }
-
+    signal(SIGPIPE, SIG_IGN);
     load_settings();
     run_config();
     running = true;
@@ -156,8 +140,12 @@ int main(int argc, char *argv[])
                         rsp[0] = MESSAGE_FAILURE;
                         rsp_len = 1;
                     }
-                    send(ret_fd, rsp, rsp_len, 0);
-                    close(ret_fd);
+                    if (rsp_len == 1 && rsp[0] == MESSAGE_SUBSCRIBE) {
+                        add_subscriber(ret_fd);
+                    } else {
+                        send(ret_fd, rsp, rsp_len, 0);
+                        close(ret_fd);
+                    }
                     rsp[0] = '\0';
                 }
             }
@@ -177,8 +165,6 @@ int main(int argc, char *argv[])
 
     cleanup();
     close(sock_fd);
-    if (status_fifo != NULL)
-        fclose(status_fifo);
     xcb_ewmh_connection_wipe(ewmh);
     xcb_destroy_window(dpy, motion_recorder);
     free(ewmh);
@@ -194,7 +180,7 @@ void init(void)
     mon = mon_head = mon_tail = pri_mon = NULL;
     history_head = history_tail = history_needle = NULL;
     stack_head = stack_tail = NULL;
-    status_fifo = NULL;
+    subscribe_head = subscribe_tail = NULL;
     last_motion_time = last_motion_x = last_motion_y = 0;
     visible = auto_raise = sticky_still = record_history = true;
     randr_base = 0;
@@ -296,30 +282,18 @@ void cleanup(void)
         remove_monitor(mon_head);
     while (stack_head != NULL)
         remove_stack(stack_head);
+    while (subscribe_head != NULL)
+        remove_subscriber(subscribe_head);
     empty_history();
     free(frozen_pointer);
 }
 
 void put_status(void)
 {
-    if (status_fifo == NULL)
-        return;
-    if (status_prefix != NULL)
-        fprintf(status_fifo, "%s", status_prefix);
-    bool urgent = false;
-    for (monitor_t *m = mon_head; m != NULL; m = m->next) {
-        fprintf(status_fifo, "%c%s:", (mon == m ? 'M' : 'm'), m->name);
-        for (desktop_t *d = m->desk_head; d != NULL; d = d->next, urgent = false) {
-            for (node_t *n = first_extrema(d->root); n != NULL && !urgent; n = next_leaf(n, d->root))
-                urgent |= n->client->urgent;
-            char c = (urgent ? 'u' : (d->root == NULL ? 'f' : 'o'));
-            if (m->desk == d)
-                c = toupper(c);
-            fprintf(status_fifo, "%c%s:", c, d->name);
-        }
+    subscriber_list_t *sb = subscribe_head;
+    while (sb != NULL) {
+        subscriber_list_t *next = sb->next;
+        feed_subscriber(sb);
+        sb = next;
     }
-    if (mon != NULL && mon->desk != NULL)
-        fprintf(status_fifo, "L%s", (mon->desk->layout == LAYOUT_TILED ? "tiled" : "monocle"));
-    fprintf(status_fifo, "\n");
-    fflush(status_fifo);
 }
diff --git a/bspwm.h b/bspwm.h
index deae2eda2dd49cf21dd368e123551d773def9676..2e43c5177ae76eddaf2d80af99eaa24b2a3056ea 100644 (file)
--- a/bspwm.h
+++ b/bspwm.h
@@ -40,8 +40,6 @@ unsigned int desktop_uid;
 xcb_screen_t *screen;
 xcb_window_t root;
 uint8_t root_depth;
-FILE *status_fifo;
-char *status_prefix;
 char config_path[MAXLEN];
 
 monitor_t *mon;
@@ -53,6 +51,8 @@ history_t *history_tail;
 history_t *history_needle;
 stacking_list_t *stack_head;
 stacking_list_t *stack_tail;
+subscriber_list_t *subscribe_head;
+subscriber_list_t *subscribe_tail;
 
 pointer_state_t *frozen_pointer;
 xcb_window_t motion_recorder;
index 2ffe109006d0a2a46bc2dcf00ad4e926a7a4a33a..17c3999327d9ead1138dd0f6b2e5382a8ef1a593 100644 (file)
@@ -1,7 +1,7 @@
 _bspc() {
     local commands='window desktop monitor query pointer restore control config quit'
 
-    local settings='rule_command 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 ignore_ewmh_focus'
+    local settings='rule_command status_prefix 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 ignore_ewmh_focus'
 
     COMPREPLY=()
 
index b89359abd8e4c7deeb3235e5811018603845d237..2df350132aa50c9b788d521a51e17d85448483b5 100755 (executable)
@@ -34,9 +34,6 @@ if [ $? -ne 0 ]; then
 fi
 
 export BSPWM_SOCKET=${state_path}/bspwm-socket
-export PANEL_FIFO=${state_path}/panel-fifo
-
-mkfifo "${PANEL_FIFO}"
 
 # Trap: make sure everything started in ~/.config/bspwm/autostart is
 # signalled when this script exits or dies. Also clean up $state_path.
@@ -66,4 +63,4 @@ sxhkdrc_path=${XDG_CONFIG_HOME:-"$HOME/.config"}/bspwm/sxhkdrc
 [ -r "${sxhkdrc_path}" ] && sxhkd -c "${sxhkdrc_path}" &
 
 # Launch bspwm:
-bspwm -s "${PANEL_FIFO}" -p W
+bspwm
index 03161767ad00ee172f750892c5173344ac49b4c3..3e0ae422d057fa11b6d434a324c183cedb358ef1 100644 (file)
@@ -3,7 +3,7 @@
 _bspc() {
     local -a commands settings
     commands=('window' 'desktop' 'monitor' 'query' 'pointer' 'restore' 'control' 'config' 'quit')
-    settings=('rule_command' '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' 'ignore_ewmh_focus')
+    settings=('rule_command' 'status_prefix' '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' 'ignore_ewmh_focus')
     if (( CURRENT == 2 )) ; then
         _values 'command' "$commands[@]"
     elif (( CURRENT == 3 )) ; then
index 71b4d2b1ffd65e3b5db68836ddf0da932261bb48..5f6226c7c1589639fb8a2e40e603ba195f30691d 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: 11/05/2013
+.\"      Date: 11/07/2013
 .\"    Manual: Bspwm Manual
 .\"    Source: Bspwm 0.8.6
 .\"  Language: English
 .\"
-.TH "BSPWM" "1" "11/05/2013" "Bspwm 0\&.8\&.6" "Bspwm Manual"
+.TH "BSPWM" "1" "11/07/2013" "Bspwm 0\&.8\&.6" "Bspwm Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -31,7 +31,7 @@
 bspwm \- Binary space partitioning window manager
 .SH "SYNOPSIS"
 .sp
-\fBbspwm\fR [\fB\-h\fR|\fB\-v\fR|\fB\-c\fR \fICONFIG_PATH\fR|\fB\-s\fR \fIPANEL_FIFO\fR|\fB\-p\fR \fIPANEL_PREFIX\fR]
+\fBbspwm\fR [\fB\-h\fR|\fB\-v\fR|\fB\-c\fR \fICONFIG_PATH\fR]
 .sp
 \fBbspc\fR \fICOMMAND\fR [\fIARGUMENTS\fR]
 .SH "DESCRIPTION"
@@ -55,18 +55,6 @@ Print the version and exit\&.
 .RS 4
 Use the given configuration file\&.
 .RE
-.PP
-\fB\-s\fR \fIPANEL_FIFO\fR
-.RS 4
-Write the internal state to the given FIFO\&.
-.RE
-.PP
-\fB\-p\fR \fIPANEL_PREFIX\fR
-.RS 4
-Start every line written to the
-\fIPANEL_FIFO\fR
-with the given prefix\&.
-.RE
 .SH "CONFIGURATION"
 .sp
 \fBbspwm\fR has only two sources of informations: the X events it receives and the messages it reads on a dedicated socket\&.
@@ -783,11 +771,6 @@ control \fIOPTIONS\fR
 Manage all the unmanaged windows remaining from a previous session\&.
 .RE
 .PP
-\fB\-\-put\-status\fR
-.RS 4
-Write the current internal state to the panel FIFO\&.
-.RE
-.PP
 \fB\-\-toggle\-visibility\fR
 .RS 4
 Toggle the visibility of all the windows\&.
@@ -797,6 +780,11 @@ Toggle the visibility of all the windows\&.
 .RS 4
 Enable or disable the recording of window focus history\&.
 .RE
+.PP
+\fB\-\-subscribe\fR
+.RS 4
+Continuously print status informations on standard output\&.
+.RE
 .RE
 .SS "Pointer"
 .sp
@@ -893,6 +881,11 @@ or
 \fImonitor\fR\&.
 .RE
 .PP
+\fIstatus_prefix\fR
+.RS 4
+Prefix prepended to each of the status lines\&.
+.RE
+.PP
 \fIfocused_border_color\fR
 .RS 4
 Color of the border of a focused window of a focused monitor\&.
@@ -1061,11 +1054,9 @@ Size of the gap that separates windows\&.
 .RS 4
 Window border width\&.
 .RE
-.SH "INTERNAL STATE FORMAT"
-.sp
-If a \fIPANEL_FIFO\fR is specified, \fBbspwm\fR will write informations regarding its current state to it\&.
+.SH "STATUS FORMAT"
 .sp
-Those informations are composed of items separated by colons\&.
+Status informations are composed of items separated by colons\&.
 .sp
 Each item as the form \fI<type><value>\fR where \fI<type>\fR is the first character of the item\&.
 .PP
index b630b9c9cab1468813e361bd11e43105674c7cb3..aa379b465e1d2ca58f9bd1e6b92f6c8bbdb19dd5 100644 (file)
@@ -13,7 +13,7 @@ bspwm - Binary space partitioning window manager
 Synopsis
 --------
 
-*bspwm* [*-h*|*-v*|*-c* 'CONFIG_PATH'|*-s* 'PANEL_FIFO'|*-p* 'PANEL_PREFIX']
+*bspwm* [*-h*|*-v*|*-c* 'CONFIG_PATH']
 
 *bspc* 'COMMAND' ['ARGUMENTS']
 
@@ -37,13 +37,6 @@ Options
 *-c* 'CONFIG_PATH'::
     Use the given configuration file.
 
-*-s* 'PANEL_FIFO'::
-    Write the internal state to the given FIFO.
-
-*-p* 'PANEL_PREFIX'::
-    Start every line written to the 'PANEL_FIFO' with the given prefix.
-
-
 Configuration
 -------------
 
@@ -483,15 +476,15 @@ Options
 *--adopt-orphans*::
     Manage all the unmanaged windows remaining from a previous session.
 
-*--put-status*::
-    Write the current internal state to the panel FIFO.
-
 *--toggle-visibility*::
     Toggle the visibility of all the windows.
 
 *--record-history* on|off::
     Enable or disable the recording of window focus history.
 
+*--subscribe*::
+    Continuously print status informations on standard output.
+
 Pointer
 ~~~~~~~
 
@@ -542,6 +535,9 @@ Global Settings
 'rule_command'::
     External command used to retrieve rule consequences. It must contain at least one integer format directive which will be replaced by the ID of the window being processed. The output of that command must have the following format: *key1=value1 key2=value2 ...*, where *keyN* is one of 'floating', 'fullscreen', 'locked', 'sticky', 'private', 'frame', 'center', 'lower', 'follow', 'manage', 'focus', 'desktop' or 'monitor'.
 
+'status_prefix'::
+    Prefix prepended to each of the status lines.
+
 'focused_border_color'::
     Color of the border of a focused window of a focused monitor.
 
@@ -645,12 +641,10 @@ Desktop Settings
     Window border width.
 
 
-Internal State Format
----------------------
-
-If a 'PANEL_FIFO' is specified, *bspwm* will write informations regarding its current state to it.
+Status Format
+-------------
 
-Those informations are composed of items separated by colons.
+Status informations are composed of items separated by colons.
 
 Each item as the form '<type><value>' where '<type>' is the first character of the item.
 
index 44de653e5ca979a47fbce732c9d6a555aea0dcd2..ce1ccb418d5e94d7ad7678ef9d409ad873d29f24 100755 (executable)
@@ -7,10 +7,16 @@ fi
 
 trap 'trap - TERM; kill 0' INT TERM QUIT EXIT
 
+sleep 0.1
+
 flavor=${1:-bar}
 
+[ -e "$PANEL_FIFO" ] && rm "$PANEL_FIFO"
+mkfifo "$PANEL_FIFO"
+
 bspc config top_padding $PANEL_HEIGHT
-bspc control --put-status
+
+bspc control --subscribe > "$PANEL_FIFO" &
 xtitle -sf 'T%s' > "$PANEL_FIFO" &
 clock -sf 'S%a %H:%M' > "$PANEL_FIFO" &
 
diff --git a/examples/panel/xinitrc b/examples/panel/xinitrc
deleted file mode 100644 (file)
index 821d08d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[ -e "$PANEL_FIFO" ] && rm "$PANEL_FIFO"
-mkfifo "$PANEL_FIFO"
-exec bspwm -s "$PANEL_FIFO" -p W
index 46e7415cd0f26ba8bc44e554a45dede74ad6d455..9add04b74f30c8868cc37ed9961c686a54121563 100644 (file)
@@ -88,7 +88,7 @@ bool process_message(char **args, int num, char *rsp)
     } else if (streq("restore", *args)) {
         return cmd_restore(++args, --num);
     } else if (streq("control", *args)) {
-        return cmd_control(++args, --num);
+        return cmd_control(++args, --num, rsp);
     } else if (streq("pointer", *args)) {
         return cmd_pointer(++args, --num);
     } else if (streq("config", *args)) {
@@ -690,7 +690,7 @@ bool cmd_restore(char **args, int num)
     return true;
 }
 
-bool cmd_control(char **args, int num)
+bool cmd_control(char **args, int num, char *rsp)
 {
     if (num < 1)
         return false;
@@ -701,6 +701,8 @@ bool cmd_control(char **args, int num)
             put_status();
         } else if (streq("--toggle-visibility", *args)) {
             toggle_visibility();
+        } else if (streq("--subscribe", *args)) {
+            snprintf(rsp, BUFSIZ, "%c", MESSAGE_SUBSCRIBE);
         } else if (streq("--record-history", *args)) {
             num--, args++;
             if (num < 1)
@@ -797,8 +799,12 @@ bool set_setting(coordinates_t loc, char *name, char *value)
     MONSET(bottom_padding)
     MONSET(left_padding)
 #undef MONSET
-    } else if (streq("rule_command", name)) {
-        return snprintf(rule_command, sizeof(rule_command), "%s", value) >= 0;
+#define SETSTR(s) \
+    } else if (streq(#s, name)) { \
+        return snprintf(s, sizeof(s), "%s", value) >= 0;
+    SETSTR(rule_command)
+    SETSTR(status_prefix)
+#undef SETSTR
     } else if (streq("split_ratio", name)) {
         double r;
         if (sscanf(value, "%lf", &r) == 1 && r > 0 && r < 1)
@@ -907,6 +913,8 @@ bool get_setting(coordinates_t loc, char *name, char* rsp)
             snprintf(rsp, BUFSIZ, "%u", loc.desktop->border_width);
     else if (streq("rule_command", name))
         snprintf(rsp, BUFSIZ, "%s", rule_command);
+    else if (streq("status_prefix", name))
+        snprintf(rsp, BUFSIZ, "%s", status_prefix);
 #define MONGET(k) \
     else if (streq(#k, name)) \
         if (loc.monitor == NULL) \
index 099bae3aeffa724c9d26a2891dba364944a8946d..7da3ed50a444126b58f99fa59030b965f163c717 100644 (file)
@@ -31,6 +31,8 @@
 #define CAT_CHR  '.'
 #define EQL_TOK  "="
 
+#define MESSAGE_SUBSCRIBE  '\x01'
+
 bool handle_message(char *msg, int msg_len, char *rsp);
 bool process_message(char **args, int num, char *rsp);
 bool cmd_window(char **args, int num);
@@ -39,7 +41,7 @@ bool cmd_monitor(char **args, int num);
 bool cmd_query(char **args, int num, char *rsp);
 bool cmd_pointer(char **args, int num);
 bool cmd_restore(char **args, int num);
-bool cmd_control(char **args, int num);
+bool cmd_control(char **args, int num, char *rsp);
 bool cmd_config(char **args, int num, char *rsp);
 bool cmd_quit(char **args, int num);
 bool set_setting(coordinates_t loc, char *name, char *value);
index 72bff633af75a6099971d743a93c6227e54b68cc..4a8e8c4508f7f2beeacba909de4a5c7c4753e3c5 100644 (file)
@@ -47,6 +47,7 @@ void run_config(void)
 void load_settings(void)
 {
     snprintf(rule_command, sizeof(rule_command), "%s", RULE_COMMAND);
+    snprintf(status_prefix, sizeof(status_prefix), "%s", STATUS_PREFIX);
 
     snprintf(normal_border_color, sizeof(normal_border_color), "%s", NORMAL_BORDER_COLOR);
     snprintf(focused_border_color, sizeof(focused_border_color), "%s", FOCUSED_BORDER_COLOR);
index 73a22ac3ffc6250da7287c572f2e62d2c5a69e63..302a122531adec28fba506f24056a483bfa75818 100644 (file)
@@ -31,6 +31,7 @@
 #define CONFIG_NAME         WM_NAME "rc"
 #define CONFIG_HOME_ENV     "XDG_CONFIG_HOME"
 #define RULE_COMMAND        "true"
+#define STATUS_PREFIX       "W"
 
 #define FOCUSED_BORDER_COLOR          "#7E7F89"
 #define ACTIVE_BORDER_COLOR           "#545350"
@@ -65,6 +66,7 @@
 #define IGNORE_EWMH_FOCUS        false
 
 char rule_command[MAXLEN];
+char status_prefix[MAXLEN];
 
 char focused_border_color[MAXLEN];
 char active_border_color[MAXLEN];
diff --git a/subscribe.c b/subscribe.c
new file mode 100644 (file)
index 0000000..76c1544
--- /dev/null
@@ -0,0 +1,77 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "bspwm.h"
+#include "tree.h"
+#include "settings.h"
+#include "subscribe.h"
+
+subscriber_list_t *make_subscriber_list(int fd)
+{
+    subscriber_list_t *sb = malloc(sizeof(subscriber_list_t));
+    sb->prev = sb->next = NULL;
+    sb->fd = fd;
+    sb->stream = fdopen(fd, "w");
+    if (sb->stream == NULL) {
+        warn("Can't open subscriber %i\n", fd);
+        close(fd);
+        free(sb);
+        return NULL;
+    }
+    return sb;
+}
+
+void remove_subscriber(subscriber_list_t *sb)
+{
+    if (sb == NULL)
+        return;
+    subscriber_list_t *a = sb->prev;
+    subscriber_list_t *b = sb->next;
+    if (a != NULL)
+        a->next = b;
+    if (b != NULL)
+        b->prev = a;
+    if (sb == subscribe_head)
+        subscribe_head = b;
+    if (sb == subscribe_tail)
+        subscribe_tail = a;
+    fclose(sb->stream);
+    free(sb);
+}
+
+void add_subscriber(int fd)
+{
+    subscriber_list_t *sb = make_subscriber_list(fd);
+    if (sb == NULL)
+        return;
+    if (subscribe_head == NULL) {
+        subscribe_head = subscribe_tail = sb;
+    } else {
+        subscribe_tail->next = sb;
+        sb->prev = subscribe_tail;
+        subscribe_tail = sb;
+    }
+    feed_subscriber(sb);
+}
+
+void feed_subscriber(subscriber_list_t *sb)
+{
+    fprintf(sb->stream, "%s", status_prefix);
+    bool urgent = false;
+    for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+        fprintf(sb->stream, "%c%s:", (mon == m ? 'M' : 'm'), m->name);
+        for (desktop_t *d = m->desk_head; d != NULL; d = d->next, urgent = false) {
+            for (node_t *n = first_extrema(d->root); n != NULL && !urgent; n = next_leaf(n, d->root))
+                urgent |= n->client->urgent;
+            char c = (urgent ? 'u' : (d->root == NULL ? 'f' : 'o'));
+            if (m->desk == d)
+                c = toupper(c);
+            fprintf(sb->stream, "%c%s:", c, d->name);
+        }
+    }
+    if (mon != NULL && mon->desk != NULL)
+        fprintf(sb->stream, "L%s", (mon->desk->layout == LAYOUT_TILED ? "tiled" : "monocle"));
+    int ret = fflush(sb->stream);
+    if (ret != 0)
+        remove_subscriber(sb);
+}
diff --git a/subscribe.h b/subscribe.h
new file mode 100644 (file)
index 0000000..e5ce7de
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef BSPWM_SUBSCRIBE_H
+#define BSPWM_SUBSCRIBE_H
+
+subscriber_list_t *make_subscriber_list(int fd);
+void remove_subscriber(subscriber_list_t *sb);
+void add_subscriber(int fd);
+void feed_subscriber(subscriber_list_t *sb);
+
+#endif
diff --git a/types.h b/types.h
index 67b78c77606fee464d8e3a2c1a05dfb3ced358a1..408b338e16bed9f6a5f3650fcda01906ec3189ba 100644 (file)
--- a/types.h
+++ b/types.h
@@ -239,6 +239,14 @@ struct stacking_list_t {
     stacking_list_t *next;
 };
 
+typedef struct subscriber_list_t subscriber_list_t;
+struct subscriber_list_t {
+    int fd;
+    FILE *stream;
+    subscriber_list_t *prev;
+    subscriber_list_t *next;
+};
+
 typedef struct {
     char desktop_desc[MAXLEN];
     char monitor_desc[MAXLEN];