]> git.lizzy.rs Git - bspwm.git/blob - bsps.c
Status: read from fifo
[bspwm.git] / bsps.c
1 #define _BSD_SOURCE
2
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <ctype.h>
12 #include <xcb/xcb.h>
13 #include <xcb/xcb_event.h>
14 #include <xcb/xcb_ewmh.h>
15 #include "bsps.h"
16
17 #define MAX(A, B)         ((A) > (B) ? (A) : (B))
18
19 #define FIFO_PATH  "BSPWM_FIFO"
20 #define NO_VALUE   " "
21 #define NAME_SEP   "\0"
22
23 typedef enum {
24     false,
25     true
26 } bool;
27
28 char *desktop_name = NO_VALUE;
29 char *window_title = NO_VALUE;
30 char external_info[BUFSIZ] = NO_VALUE;
31 xcb_window_t curwin;
32
33 char *fifo_path;
34 int fifo_fd, dpy_fd, sel_fd;
35
36 xcb_connection_t *dpy;
37 xcb_ewmh_connection_t ewmh;
38 xcb_screen_t *screen;
39 int default_screen;
40
41 bool running;
42
43 void setup(void)
44 {
45     dpy = xcb_connect(NULL, &default_screen);
46     xcb_intern_atom_cookie_t *ewmh_cookies;
47     ewmh_cookies = xcb_ewmh_init_atoms(dpy, &ewmh);
48     xcb_ewmh_init_atoms_replies(&ewmh, ewmh_cookies, NULL);
49     fifo_path = getenv(FIFO_PATH);
50     mkfifo(fifo_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
51     /* fifo_fd = open(fifo_path, O_RDONLY); */
52     fifo_fd = open(fifo_path, O_RDWR | O_NONBLOCK);
53     /* fprintf(stderr, "fifo_fd %i\n", fifo_fd); */
54     dpy_fd = xcb_get_file_descriptor(dpy);
55     sel_fd = MAX(fifo_fd, dpy_fd) + 1;
56     curwin = 0;
57     running = true;
58 }
59
60 void register_events(void)
61 {
62     xcb_generic_error_t *err;
63     uint32_t values[] = {XCB_EVENT_MASK_PROPERTY_CHANGE};
64     err = xcb_request_check(dpy, xcb_change_window_attributes_checked(dpy, screen->root, XCB_CW_EVENT_MASK, values));
65     if (err != NULL)
66         running = false;
67 }
68
69 void handle_signal(int sig)
70 {
71     if (sig == SIGTERM || sig == SIGINT || sig == SIGHUP)
72         running = false;
73 }
74
75 void update_window_title(void)
76 {
77     xcb_window_t win;
78     xcb_ewmh_get_utf8_strings_reply_t name;
79     xcb_generic_error_t *err;
80     uint32_t values[] = {XCB_EVENT_MASK_PROPERTY_CHANGE};
81     uint32_t values_reset[] = {XCB_EVENT_MASK_NO_EVENT};
82
83     if (xcb_ewmh_get_active_window_reply(&ewmh, xcb_ewmh_get_active_window(&ewmh, default_screen), &win, NULL) == 1)
84     {
85         if (xcb_ewmh_get_wm_name_reply(&ewmh, xcb_ewmh_get_wm_name(&ewmh, win), &name, NULL) == 1) {
86             window_title = strdup(name.strings);
87             if (win != curwin) {
88                 xcb_change_window_attributes(dpy, curwin, XCB_CW_EVENT_MASK, values_reset);
89                 curwin = win;
90             }
91             err = xcb_request_check(dpy, xcb_change_window_attributes_checked(dpy, win, XCB_CW_EVENT_MASK, values));
92             if (err != NULL)
93                 running = false;
94
95         } else {
96             window_title = strdup(NO_VALUE);
97         }
98     }
99 }
100
101 void update_desktop_name(void)
102 {
103     uint32_t cd;
104     xcb_ewmh_get_utf8_strings_reply_t names;
105     unsigned int pos = 0, cnt = 0;
106
107     if (xcb_ewmh_get_current_desktop_reply(&ewmh, xcb_ewmh_get_current_desktop(&ewmh, default_screen), &cd, NULL) == 1  && xcb_ewmh_get_desktop_names_reply(&ewmh, xcb_ewmh_get_desktop_names(&ewmh, default_screen), &names, NULL) == 1) {
108         while (cnt < cd && pos < names.strings_len) {
109             pos += strlen(names.strings + pos) + 1;
110             cnt++;
111         }
112         desktop_name = strdup(names.strings + pos);
113         for (cnt = 0; cnt < strlen(desktop_name); cnt++)
114             desktop_name[cnt] = toupper(desktop_name[cnt]);
115     } else {
116         desktop_name = strdup(NO_VALUE);
117     }
118 }
119
120 void output_infos(void)
121 {
122     printf("\\l %s\\c%s\\r%s \n", desktop_name, window_title, external_info);
123     fflush(stdout);
124 }
125
126 void handle_event(xcb_generic_event_t *evt)
127 {
128     xcb_property_notify_event_t *pne;
129     switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
130         case XCB_PROPERTY_NOTIFY:
131             pne = (xcb_property_notify_event_t *) evt;
132             if (pne->atom == ewmh._NET_CURRENT_DESKTOP) {
133                 update_desktop_name();
134                 output_infos();
135             } else if (pne->atom == ewmh._NET_ACTIVE_WINDOW) {
136                 update_window_title();
137                 output_infos();
138             } else if (pne->window != screen->root && (pne->atom == ewmh._NET_WM_NAME || pne->atom == XCB_ATOM_WM_NAME)) {
139                 update_window_title();
140                 output_infos();
141             } else {
142             }
143         default:
144             break;
145     }
146 }
147
148 int main(void)
149 {
150     fd_set descriptors;
151     xcb_generic_event_t *evt;
152     signal(SIGTERM, handle_signal);
153     signal(SIGINT, handle_signal);
154     signal(SIGHUP, handle_signal);
155     setup();
156     screen = ewmh.screens[default_screen];
157     register_events();
158     update_desktop_name();
159     update_window_title();
160     output_infos();
161     xcb_flush(dpy);
162
163     while (running) {
164         FD_ZERO(&descriptors);
165         FD_SET(fifo_fd, &descriptors);
166         FD_SET(dpy_fd, &descriptors);
167
168         if (select(sel_fd, &descriptors, NULL, NULL, NULL)) {
169             if (FD_ISSET(dpy_fd, &descriptors)) {
170                 while ((evt = xcb_poll_for_event(dpy)) != NULL) {
171                     handle_event(evt);
172                     free(evt);
173                 }
174             }
175
176             if (FD_ISSET(fifo_fd, &descriptors)) {
177                 read(fifo_fd, external_info, sizeof(external_info));
178                 output_infos();
179             }
180         }
181     }
182
183     xcb_disconnect(dpy);
184     return 0;
185 }