]> git.lizzy.rs Git - bspwm.git/commitdiff
Add wm command: --restart
authorSam Bazley <sambazley@protonmail.com>
Fri, 18 Jan 2019 21:15:20 +0000 (21:15 +0000)
committerBastien Dejean <nihilhill@gmail.com>
Wed, 30 Jan 2019 10:18:51 +0000 (11:18 +0100)
Closes #904.

18 files changed:
contrib/zsh_completion
doc/bspwm.1
doc/bspwm.1.asciidoc
examples/loop/bspwmrc [deleted file]
examples/loop/profile [deleted file]
examples/loop/sxhkdrc [deleted file]
examples/loop/wm [deleted file]
examples/loop/xinitrc [deleted file]
examples/sxhkdrc
src/bspwm.c
src/bspwm.h
src/messages.c
src/query.c
src/query.h
src/restore.c
src/restore.h
src/subscribe.c
src/subscribe.h

index 0638ac641b68d0a22ad65dce3d103e1cd14593dd..417dde59ab76eb3abc47bc196d7ba8c7c527d6c2 100644 (file)
@@ -235,7 +235,8 @@ _bspc() {
                                '*'{-O,--reorder-monitors}'[Reorder the list of monitors to match the given order]:*: :_bspc_query_names -- monitors -M'\
                                '*'{-o,--adopt-orphans}'[Manage all the unmanaged windows remaining from a previous session]'\
                                '*'{-h,--record-history}'[Enable or disable the recording of node focus history]:history:(on off)'\
-                               '*'{-g,--get-status}'[Print the current status information]'
+                               '*'{-g,--get-status}'[Print the current status information]'\
+                               '*'{-r,--restart}'[Restart the window manager]'
                        ;;
                (subscribe)
                        if [[ "$words[CURRENT-1]" != (-c|--count) ]] ;then
index 107d3067353fac5494109fca07a0657815197baa..fee3d96fb1502b13dac7cdd72c0d7cf580212c94 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: bspwm
 .\"    Author: [see the "Author" section]
 .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\"      Date: 01/29/2019
+.\"      Date: 01/30/2019
 .\"    Manual: Bspwm Manual
-.\"    Source: Bspwm 0.9.5-35-g32ff624
+.\"    Source: Bspwm 0.9.5-44-gd36664b
 .\"  Language: English
 .\"
-.TH "BSPWM" "1" "01/29/2019" "Bspwm 0\&.9\&.5\-35\-g32ff624" "Bspwm Manual"
+.TH "BSPWM" "1" "01/30/2019" "Bspwm 0\&.9\&.5\-44\-gd36664b" "Bspwm Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -999,6 +999,11 @@ Enable or disable the recording of node focus history\&.
 .RS 4
 Print the current status information\&.
 .RE
+.PP
+\fB\-r\fR, \fB\-\-restart\fR
+.RS 4
+Restart the window manager
+.RE
 .RE
 .SS "Rule"
 .sp
index e95839984602fdcb342c95de02e1c601bdf405f6..905399caae7b09f1be85cfbacf162d5a3595d09a 100644 (file)
@@ -592,6 +592,9 @@ Commands
 *-g*, *--get-status*::
        Print the current status information.
 
+*-r*, *--restart*::
+       Restart the window manager
+
 Rule
 ~~~~
 
diff --git a/examples/loop/bspwmrc b/examples/loop/bspwmrc
deleted file mode 100755 (executable)
index 797a973..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#! /bin/sh
-
-if [ -e "$BSPWM_STATE" ] ; then
-       bspc wm -l "$BSPWM_STATE"
-       rm "$BSPWM_STATE"
-fi
diff --git a/examples/loop/profile b/examples/loop/profile
deleted file mode 100644 (file)
index 790d657..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export BSPWM_STATE=/tmp/bspwm-state.json
diff --git a/examples/loop/sxhkdrc b/examples/loop/sxhkdrc
deleted file mode 100644 (file)
index 40480cc..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# refresh or quit bspwm
-super + alt + {_,shift + }Escape
-       {bspc wm -d > "$BSPWM_STATE" && bspc quit, \
-        bspc quit 1}
diff --git a/examples/loop/wm b/examples/loop/wm
deleted file mode 100755 (executable)
index 489893e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /bin/sh
-
-while true ; do
-       bspwm || break
-done
diff --git a/examples/loop/xinitrc b/examples/loop/xinitrc
deleted file mode 100644 (file)
index 49f38e8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-exec wm
index 3b8c6249d67a7bebf303ca00433f48848531b445..0e5ea5a2b59204e7db2816718098cf5c6d42eb63 100644 (file)
@@ -18,9 +18,9 @@ super + Escape
 # bspwm hotkeys
 #
 
-# quit bspwm normally
-super + alt + Escape
-       bspc quit
+# quit/restart bspwm
+super + alt + {q,r}
+       bspc {quit,wm -r}
 
 # close and kill
 super + {_,shift + }w
index 91fc0971da614dd7ea93d1ea9bcf42677d92a11c..a7f04b0afbb910e053282f86ed9074b34ffdef99 100644 (file)
@@ -33,6 +33,7 @@
 #include <signal.h>
 #include <unistd.h>
 #include <stdbool.h>
+#include <string.h>
 #include <xcb/xinerama.h>
 #include "types.h"
 #include "desktop.h"
 #include "history.h"
 #include "ewmh.h"
 #include "rule.h"
+#include "restore.h"
+#include "query.h"
 #include "bspwm.h"
 
 int main(int argc, char *argv[])
 {
        fd_set descriptors;
        char socket_path[MAXLEN];
+       char state_path[MAXLEN] = {0};
        config_path[0] = '\0';
-       int sock_fd, cli_fd, dpy_fd, max_fd, n;
+       int sock_fd = -1, cli_fd, dpy_fd, max_fd, n;
        struct sockaddr_un sock_address;
        char msg[BUFSIZ] = {0};
        xcb_generic_event_t *event;
+       char *end;
        int opt;
 
-       while ((opt = getopt(argc, argv, "hvc:")) != -1) {
+       while ((opt = getopt(argc, argv, "hvc:s:o:")) != -1) {
                switch (opt) {
                        case 'h':
                                printf(WM_NAME " [-h|-v|-c CONFIG_PATH]\n");
@@ -72,6 +77,15 @@ int main(int argc, char *argv[])
                        case 'c':
                                snprintf(config_path, sizeof(config_path), "%s", optarg);
                                break;
+                       case 's':
+                               snprintf(state_path, sizeof(state_path), "%s", optarg);
+                               break;
+                       case 'o':
+                               sock_fd = strtol(optarg, &end, 0);
+                               if (*end != '\0') {
+                                       sock_fd = -1;
+                               }
+                               break;
                }
        }
 
@@ -93,36 +107,44 @@ int main(int argc, char *argv[])
        load_settings();
        setup();
 
+       if (state_path[0] != '\0') {
+               restore_state(state_path);
+               unlink(state_path);
+       }
+
        dpy_fd = xcb_get_file_descriptor(dpy);
 
-       char *sp = getenv(SOCKET_ENV_VAR);
-       if (sp != NULL) {
-               snprintf(socket_path, sizeof(socket_path), "%s", sp);
-       } else {
-               char *host = NULL;
-               int dn = 0, sn = 0;
-               if (xcb_parse_display(NULL, &host, &dn, &sn) != 0) {
-                       snprintf(socket_path, sizeof(socket_path), SOCKET_PATH_TPL, host, dn, sn);
+       if (sock_fd == -1) {
+               char *sp = getenv(SOCKET_ENV_VAR);
+               if (sp != NULL) {
+                       snprintf(socket_path, sizeof(socket_path), "%s", sp);
+               } else {
+                       char *host = NULL;
+                       int dn = 0, sn = 0;
+                       if (xcb_parse_display(NULL, &host, &dn, &sn) != 0) {
+                               snprintf(socket_path, sizeof(socket_path), SOCKET_PATH_TPL, host, dn, sn);
+                       }
+                       free(host);
                }
-               free(host);
-       }
 
-       sock_address.sun_family = AF_UNIX;
-       snprintf(sock_address.sun_path, sizeof(sock_address.sun_path), "%s", socket_path);
+               sock_address.sun_family = AF_UNIX;
+               snprintf(sock_address.sun_path, sizeof(sock_address.sun_path), "%s", socket_path);
 
-       sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+               sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
 
-       if (sock_fd == -1) {
-               err("Couldn't create the socket.\n");
-       }
+               if (sock_fd == -1) {
+                       err("Couldn't create the socket.\n");
+               }
 
-       unlink(socket_path);
-       if (bind(sock_fd, (struct sockaddr *) &sock_address, sizeof(sock_address)) == -1) {
-               err("Couldn't bind a name to the socket.\n");
-       }
+               unlink(socket_path);
+
+               if (bind(sock_fd, (struct sockaddr *) &sock_address, sizeof(sock_address)) == -1) {
+                       err("Couldn't bind a name to the socket.\n");
+               }
 
-       if (listen(sock_fd, SOMAXCONN) == -1) {
-               err("Couldn't listen to the socket.\n");
+               if (listen(sock_fd, SOMAXCONN) == -1) {
+                       err("Couldn't listen to the socket.\n");
+               }
        }
 
        signal(SIGINT, sig_handler);
@@ -193,9 +215,19 @@ int main(int argc, char *argv[])
                }
        }
 
+       if (restart) {
+               char *host = NULL;
+               int dn = 0, sn = 0;
+               if (xcb_parse_display(NULL, &host, &dn, &sn) != 0) {
+                       snprintf(state_path, sizeof(state_path), STATE_PATH_TPL, host, dn, sn);
+               }
+               free(host);
+               FILE *f = fopen(state_path, "w");
+               query_state(f);
+               fclose(f);
+       }
+
        cleanup();
-       close(sock_fd);
-       unlink(socket_path);
        ungrab_buttons();
        xcb_ewmh_connection_wipe(ewmh);
        xcb_destroy_window(dpy, meta_window);
@@ -203,6 +235,38 @@ int main(int argc, char *argv[])
        free(ewmh);
        xcb_flush(dpy);
        xcb_disconnect(dpy);
+
+       if (restart) {
+               int rargc;
+               for (rargc = 0; rargc < argc; rargc++) {
+                       if (streq("-s", argv[rargc])) {
+                               break;
+                       }
+               }
+
+               int len = (argc + 1 + (rargc < argc ? 4 : 0));
+               char **rargv = malloc(len * sizeof(char *));
+
+               for (int i = 0; i < rargc; i++) {
+                       rargv[i] = argv[i];
+               }
+
+               char sock_fd_arg[SMALEN];
+               snprintf(sock_fd_arg, sizeof(sock_fd_arg), "%i", sock_fd);
+
+               rargv[rargc] = "-s";
+               rargv[rargc + 1] = state_path;
+               rargv[rargc + 2] = "-o";
+               rargv[rargc + 3] = sock_fd_arg;
+               rargv[rargc + 4] = 0;
+
+               exit_status = execvp(*rargv, rargv);
+               free(rargv);
+       }
+
+       close(sock_fd);
+       unlink(socket_path);
+
        return exit_status;
 }
 
@@ -218,6 +282,7 @@ void init(void)
        auto_raise = sticky_still = hide_sticky = record_history = true;
        randr_base = 0;
        exit_status = 0;
+       restart = false;
 }
 
 void setup(void)
index 834c15596ea1a48688379feacc3a033d4a309409..9ad04756c0b08991f70c94a9bcbc67cad90ba625 100644 (file)
@@ -32,6 +32,8 @@
 #define CONFIG_HOME_ENV          "XDG_CONFIG_HOME"
 #define RUNTIME_DIR_ENV          "XDG_RUNTIME_DIR"
 
+#define STATE_PATH_TPL           "/tmp/bspwm%s_%i_%i-state"
+
 #define ROOT_EVENT_MASK     (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_BUTTON_PRESS)
 #define CLIENT_EVENT_MASK   (XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE)
 #define BSPWM_CLASS_NAME    "Bspwm"
@@ -81,6 +83,7 @@ bool sticky_still;
 bool hide_sticky;
 bool record_history;
 bool running;
+bool restart;
 bool randr;
 
 void init(void);
index 99fd520c839a0c85187a2d0a23b3525c7f6770bf..b08ca045901cade8da1f966924b817afaf6aecd3 100644 (file)
@@ -1195,7 +1195,7 @@ void cmd_wm(char **args, int num, FILE *rsp)
 
        while (num > 0) {
                if (streq("-d", *args) || streq("--dump-state", *args)) {
-                       query_tree(rsp);
+                       query_state(rsp);
                        fprintf(rsp, "\n");
                } else if (streq("-l", *args) || streq("--load-state", *args)) {
                        num--, args++;
@@ -1203,7 +1203,7 @@ void cmd_wm(char **args, int num, FILE *rsp)
                                fail(rsp, "wm %s: Not enough arguments.\n", *(args - 1));
                                break;
                        }
-                       if (!restore_tree(*args)) {
+                       if (!restore_state(*args)) {
                                fail(rsp, "");
                                break;
                        }
@@ -1260,6 +1260,10 @@ void cmd_wm(char **args, int num, FILE *rsp)
                                fail(rsp, "wm %s: Invalid argument: '%s'.\n", *(args - 1), *args);
                                break;
                        }
+               } else if (streq("-r", *args) || streq("--restart", *args)) {
+                       running = false;
+                       restart = true;
+                       break;
                } else {
                        fail(rsp, "wm: Unknown command: '%s'.\n", *args);
                        break;
@@ -1319,7 +1323,8 @@ void cmd_subscribe(char **args, int num, FILE *rsp)
                }
        }
 
-       add_subscriber(stream, fifo_path, field, count);
+       subscriber_list_t *sb = make_subscriber(stream, fifo_path, field, count);
+       add_subscriber(sb);
        return;
 
 failed:
index c10e018e0a63269c5c42e7d531f63cfcf3a3edef..156dbfe86433f54d301697c45061dd6287554ce8 100644 (file)
@@ -35,7 +35,7 @@
 #include "query.h"
 #include "geometry.h"
 
-void query_tree(FILE *rsp)
+void query_state(FILE *rsp)
 {
        fprintf(rsp, "{");
        fprintf(rsp, "\"focusedMonitorId\":%u,", mon->id);
@@ -58,8 +58,12 @@ void query_tree(FILE *rsp)
        fprintf(rsp,",");
        fprintf(rsp, "\"stackingList\":");
        query_stack(rsp);
+       if (restart) {
+               fprintf(rsp,",");
+               fprintf(rsp, "\"eventSubscribers\":");
+               query_subscribers(rsp);
+       }
        fprintf(rsp, "}");
-
 }
 
 void query_monitor(monitor_t *m, FILE *rsp)
@@ -221,6 +225,22 @@ void query_stack(FILE *rsp)
        fprintf(rsp, "]");
 }
 
+void query_subscribers(FILE *rsp)
+{
+       fprintf(rsp, "[");
+       for (subscriber_list_t *s = subscribe_head; s != NULL; s = s->next) {
+               fprintf(rsp, "{\"fileDescriptor\": %i", fileno(s->stream));
+               if (s->fifo_path != NULL) {
+                       fprintf(rsp, ",\"fifoPath\":\"%s\"", s->fifo_path);
+               }
+               fprintf(rsp, ",\"field\":%i,\"count\":%i}", s->field, s->count);
+               if (s->next != NULL) {
+                       fprintf(rsp, ",");
+               }
+       }
+       fprintf(rsp, "]");
+}
+
 int query_node_ids(coordinates_t *ref, coordinates_t *trg, node_select_t *sel, FILE *rsp)
 {
        int count = 0;
index 631336fe86744525a59dc977f56d4e6ca022e530..02e78d541538518187fc347fe230a28d15f8d2e6 100644 (file)
@@ -44,7 +44,7 @@ enum {
 typedef void (*monitor_printer_t)(monitor_t *m, FILE *rsp);
 typedef void (*desktop_printer_t)(desktop_t *m, FILE *rsp);
 
-void query_tree(FILE *rsp);
+void query_state(FILE *rsp);
 void query_monitor(monitor_t *m, FILE *rsp);
 void query_desktop(desktop_t *d, FILE *rsp);
 void query_node(node_t *n, FILE *rsp);
@@ -56,6 +56,7 @@ void query_padding(padding_t p, FILE *rsp);
 void query_history(FILE *rsp);
 void query_coordinates(coordinates_t *loc, FILE *rsp);
 void query_stack(FILE *rsp);
+void query_subscribers(FILE *rsp);
 int query_node_ids(coordinates_t *ref, coordinates_t *trg, node_select_t *sel, FILE *rsp);
 int query_node_ids_in(node_t *n, desktop_t *d, monitor_t *m, coordinates_t *ref, coordinates_t *trg, node_select_t *sel, FILE *rsp);
 int query_desktop_ids(coordinates_t *ref, coordinates_t *trg, desktop_select_t *sel, desktop_printer_t printer, FILE *rsp);
index 4ac0ee4e6e0eedb2eab9bf83346a803fbf093c61..46d2dda32fbcca7a67fc3e062cd601e864d3a02d 100644 (file)
 #include "stack.h"
 #include "tree.h"
 #include "settings.h"
+#include "subscribe.h"
 #include "restore.h"
 #include "window.h"
 #include "parse.h"
 
-bool restore_tree(const char *file_path)
+bool restore_state(const char *file_path)
 {
        size_t jslen;
        char *json = read_string(file_path, &jslen);
@@ -152,6 +153,10 @@ bool restore_tree(const char *file_path)
                        }
                        restore_stack(&t, json);
                        continue;
+               } else if (keyeq("eventSubscribers", t, json)) {
+                       t++;
+                       restore_subscribers(&t, json);
+                       continue;
                }
                t++;
        }
@@ -548,6 +553,40 @@ void restore_history(jsmntok_t **t, char *json)
        }
 }
 
+void restore_subscribers(jsmntok_t **t, char *json)
+{
+       int s = (*t)->size;
+       (*t)++;
+
+       for (int i = 0; i < s; i++) {
+               subscriber_list_t *s = make_subscriber(NULL, NULL, 0, 0);
+               restore_subscriber(s, t, json);
+               add_subscriber(s);
+       }
+}
+
+void restore_subscriber(subscriber_list_t *s, jsmntok_t **t, char *json)
+{
+       int n = (*t)->size;
+       (*t)++;
+
+       for (int i = 0; i < n; i++) {
+               if (keyeq("fileDescriptor", *t, json)) {
+                       (*t)++;
+                       int fd;
+                       sscanf(json + (*t)->start, "%i", &fd);
+                       s->stream = fdopen(fd, "w");
+               } else if (keyeq("fifoPath", *t, json)) {
+                       (*t)++;
+                       free(s->fifo_path);
+                       s->fifo_path = copy_string(json + (*t)->start, (*t)->end - (*t)->start);
+               RESTORE_INT(field, &s->field)
+               RESTORE_INT(count, &s->count)
+               }
+               (*t)++;
+       }
+}
+
 void restore_coordinates(coordinates_t *loc, jsmntok_t **t, char *json)
 {
        int s = (*t)->size;
index fd4cb6299c741f33aafc25594e0aa34bec14f1f7..a7d1fca990fa29899def8dd1b42065c9ef273f52 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "jsmn.h"
 
-bool restore_tree(const char *file_path);
+bool restore_state(const char *file_path);
 monitor_t *restore_monitor(jsmntok_t **t, char *json);
 desktop_t *restore_desktop(jsmntok_t **t, char *json);
 node_t *restore_node(jsmntok_t **t, char *json);
@@ -37,6 +37,8 @@ void restore_rectangle(xcb_rectangle_t *r, jsmntok_t **t, char *json);
 void restore_constraints(constraints_t *c, jsmntok_t **t, char *json);
 void restore_padding(padding_t *p, jsmntok_t **t, char *json);
 void restore_history(jsmntok_t **t, char *json);
+void restore_subscribers(jsmntok_t **t, char *json);
+void restore_subscriber(subscriber_list_t *s, jsmntok_t **t, char *json);
 void restore_coordinates(coordinates_t *loc, jsmntok_t **t, char *json);
 void restore_stack(jsmntok_t **t, char *json);
 bool keyeq(char *s, jsmntok_t *key, char *json);
index 8fa50f71d49cb132bf07a885daa377a68e038ceb..54dd0d2aebb968d4a3b51758d2470eb425af2af7 100644 (file)
@@ -33,7 +33,7 @@
 #include "subscribe.h"
 #include "tree.h"
 
-subscriber_list_t *make_subscriber_list(FILE *stream, char *fifo_path, int field, int count)
+subscriber_list_t *make_subscriber(FILE *stream, char *fifo_path, int field, int count)
 {
        subscriber_list_t *sb = calloc(1, sizeof(subscriber_list_t));
        sb->prev = sb->next = NULL;
@@ -63,15 +63,16 @@ void remove_subscriber(subscriber_list_t *sb)
        if (sb == subscribe_tail) {
                subscribe_tail = a;
        }
-       fclose(sb->stream);
-       unlink(sb->fifo_path);
+       if (!restart) {
+               fclose(sb->stream);
+               unlink(sb->fifo_path);
+       }
        free(sb->fifo_path);
        free(sb);
 }
 
-void add_subscriber(FILE *stream, char* fifo_path, int field, int count)
+void add_subscriber(subscriber_list_t *sb)
 {
-       subscriber_list_t *sb = make_subscriber_list(stream, fifo_path, field, count);
        if (subscribe_head == NULL) {
                subscribe_head = subscribe_tail = sb;
        } else {
index 305f3f336ab2be7ae0585a3cb6f5e467ab2d0f3b..cb90a862f0ef43ef490b39b8b49106e32298664b 100644 (file)
@@ -62,9 +62,9 @@ typedef enum {
        SBSC_MASK_ALL = (1 << 28) - 1
 } subscriber_mask_t;
 
-subscriber_list_t *make_subscriber_list(FILE *stream, char *fifo_path, int field, int count);
+subscriber_list_t *make_subscriber(FILE *stream, char *fifo_path, int field, int count);
 void remove_subscriber(subscriber_list_t *sb);
-void add_subscriber(FILE *stream, char* fifo_path, int field, int count);
+void add_subscriber(subscriber_list_t *sb);
 int print_report(FILE *stream);
 void put_status(subscriber_mask_t mask, ...);