]> git.sur5r.net Git - i3/i3/blob - i3bar/src/main.c
Display statusline (without formats)
[i3/i3] / i3bar / src / main.c
1 #include <stdio.h>
2 #include <i3/ipc.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <ev.h>
9 #include <xcb/xcb.h>
10
11 #include "ipc.h"
12 #include "outputs.h"
13 #include "workspaces.h"
14 #include "common.h"
15 #include "xcb.h"
16
17 #define STDIN_CHUNK_SIZE 1024
18
19 void ev_prepare_cb(struct ev_loop *loop, ev_prepare *w, int revents) {
20     xcb_flush(xcb_connection);
21 }
22
23 void ev_check_cb(struct ev_loop *loop, ev_check *w, int revents) {
24     xcb_generic_event_t *event;
25     if ((event = xcb_poll_for_event(xcb_connection)) != NULL) {
26         handle_xcb_event(event);
27     }
28     free(event);
29 }
30
31 void xcb_io_cb(struct ev_loop *loop, ev_io *w, int revents) {
32 }
33
34 void start_child(char *command) {
35     int fd[2];
36     pipe(fd);
37     child_pid = fork();
38     switch (child_pid) {
39         case -1:
40             printf("ERROR: Couldn't fork()");
41             exit(EXIT_FAILURE);
42         case 0:
43             close(fd[0]);
44
45             dup2(fd[1], STDOUT_FILENO);
46
47             static const char *shell = NULL;
48
49             if ((shell = getenv("SHELL")) == NULL)
50                 shell = "/bin/sh";
51
52             execl(shell, shell, "-c", command, (char*) NULL);
53             break;
54         default:
55             close(fd[1]);
56
57             dup2(fd[0], STDIN_FILENO);
58
59             break;
60     }
61 }
62
63 void strip_dzen_formats(char *buffer) {
64     char *src = buffer;
65     char *dest = buffer;
66     while (*src != '\0') {
67         if (*src == '^') {
68             if (!strncmp(src, "^ro", strlen("^ro"))) {
69                 *(dest++) = ' ';
70                 *(dest++) = '|';
71                 *(dest++) = ' ';
72             }
73             while (*src != ')') {
74                 src++;
75             }
76             src++;
77         } else {
78             *dest = *src;
79             src++;
80             dest++;
81         }
82     }
83     *(--dest) = '\0';
84 }
85
86 void child_io_cb(struct ev_loop *loop, ev_io *w, int revents) {
87     int fd = w->fd;
88     int n = 0;
89     int rec = 0;
90     int buffer_len = STDIN_CHUNK_SIZE;
91     char *buffer = malloc(buffer_len);
92     memset(buffer, '\0', buffer_len);
93     while(1) {
94         n = read(fd, buffer + rec, buffer_len - rec);
95         if (n == -1) {
96             if (errno == EAGAIN) {
97                 break;
98             }
99             printf("ERROR: read() failed!");
100             exit(EXIT_FAILURE);
101         }
102         if (n == 0) {
103             if (rec == buffer_len) {
104                 char *tmp = buffer;
105                 buffer = malloc(buffer_len + STDIN_CHUNK_SIZE);
106                 memset(buffer, '\0', buffer_len);
107                 strncpy(buffer, tmp, buffer_len);
108                 buffer_len += STDIN_CHUNK_SIZE;
109                 FREE(tmp);
110             } else {
111                 break;
112             }
113         }
114         rec += n;
115     }
116     if (strlen(buffer) == 0) {
117         FREE(buffer);
118         return;
119     }
120     strip_dzen_formats(buffer);
121     FREE(statusline);
122     statusline = buffer;
123     printf("%s", buffer);
124     draw_bars();
125 }
126
127 int main(int argc, char **argv) {
128     main_loop = ev_default_loop(0);
129
130     init_xcb();
131     init_connection("/home/mero/.i3/ipc.sock");
132
133     subscribe_events();
134
135     ev_io *xcb_io = malloc(sizeof(ev_io));
136     ev_prepare *ev_prep = malloc(sizeof(ev_prepare));
137     ev_check *ev_chk = malloc(sizeof(ev_check));
138
139     ev_io_init(xcb_io, &xcb_io_cb, xcb_get_file_descriptor(xcb_connection), EV_READ);
140     ev_prepare_init(ev_prep, &ev_prepare_cb);
141     ev_check_init(ev_chk, &ev_check_cb);
142
143     ev_io_start(main_loop, xcb_io);
144     ev_prepare_start(main_loop, ev_prep);
145     ev_check_start(main_loop, ev_chk);
146
147     i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL);
148     i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
149
150     start_child("i3status");
151
152     fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
153     ev_io *child_io = malloc(sizeof(ev_io));
154     ev_io_init(child_io, &child_io_cb, STDIN_FILENO, EV_READ);
155     ev_io_start(main_loop, child_io);
156
157     ev_loop(main_loop, 0);
158
159     ev_prepare_stop(main_loop, ev_prep);
160     ev_check_stop(main_loop, ev_chk);
161     FREE(ev_prep);
162     FREE(ev_chk);
163
164     ev_default_destroy();
165     clean_xcb();
166
167     free_workspaces();
168     FREE_SLIST(outputs, i3_output);
169
170     return 0;
171 }