diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-10-13 16:04:37 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-10-15 00:26:27 +1000 |
commit | 4056c09e13c1aeead6dd4085fc7e263a17a0b195 (patch) | |
tree | a3413f2a5717968e370d68521b689580d5adc5a0 /swaybar | |
parent | Document `border csd` (diff) | |
download | sway-4056c09e13c1aeead6dd4085fc7e263a17a0b195.tar.gz sway-4056c09e13c1aeead6dd4085fc7e263a17a0b195.tar.zst sway-4056c09e13c1aeead6dd4085fc7e263a17a0b195.zip |
Move swaybar's event loop to common directory and refactor
* The loop functions are now prefixed with `loop_`.
* It is now easy to add timers to the loop.
* Timers are implemented using pollfd and timerfd, rather than manually
checking them when any other event happens to arrive.
Diffstat (limited to 'swaybar')
-rw-r--r-- | swaybar/bar.c | 17 | ||||
-rw-r--r-- | swaybar/event_loop.c | 156 | ||||
-rw-r--r-- | swaybar/meson.build | 1 | ||||
-rw-r--r-- | swaybar/status_line.c | 4 |
4 files changed, 12 insertions, 166 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c index 9f72c94c..8e89c9a8 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #endif | 18 | #endif |
19 | #include "swaybar/bar.h" | 19 | #include "swaybar/bar.h" |
20 | #include "swaybar/config.h" | 20 | #include "swaybar/config.h" |
21 | #include "swaybar/event_loop.h" | ||
22 | #include "swaybar/i3bar.h" | 21 | #include "swaybar/i3bar.h" |
23 | #include "swaybar/ipc.h" | 22 | #include "swaybar/ipc.h" |
24 | #include "swaybar/status_line.h" | 23 | #include "swaybar/status_line.h" |
@@ -26,6 +25,7 @@ | |||
26 | #include "ipc-client.h" | 25 | #include "ipc-client.h" |
27 | #include "list.h" | 26 | #include "list.h" |
28 | #include "log.h" | 27 | #include "log.h" |
28 | #include "loop.h" | ||
29 | #include "pool-buffer.h" | 29 | #include "pool-buffer.h" |
30 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | 30 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" |
31 | #include "xdg-output-unstable-v1-client-protocol.h" | 31 | #include "xdg-output-unstable-v1-client-protocol.h" |
@@ -573,7 +573,7 @@ static void set_bar_dirty(struct swaybar *bar) { | |||
573 | 573 | ||
574 | bool bar_setup(struct swaybar *bar, const char *socket_path) { | 574 | bool bar_setup(struct swaybar *bar, const char *socket_path) { |
575 | bar_init(bar); | 575 | bar_init(bar); |
576 | init_event_loop(); | 576 | bar->eventloop = loop_create(); |
577 | 577 | ||
578 | bar->ipc_socketfd = ipc_open_socket(socket_path); | 578 | bar->ipc_socketfd = ipc_open_socket(socket_path); |
579 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); | 579 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); |
@@ -582,6 +582,7 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) { | |||
582 | } | 582 | } |
583 | if (bar->config->status_command) { | 583 | if (bar->config->status_command) { |
584 | bar->status = status_line_init(bar->config->status_command); | 584 | bar->status = status_line_init(bar->config->status_command); |
585 | bar->status->bar = bar; | ||
585 | } | 586 | } |
586 | 587 | ||
587 | bar->display = wl_display_connect(NULL); | 588 | bar->display = wl_display_connect(NULL); |
@@ -646,21 +647,23 @@ static void status_in(int fd, short mask, void *data) { | |||
646 | if (mask & (POLLHUP | POLLERR)) { | 647 | if (mask & (POLLHUP | POLLERR)) { |
647 | status_error(bar->status, "[error reading from status command]"); | 648 | status_error(bar->status, "[error reading from status command]"); |
648 | set_bar_dirty(bar); | 649 | set_bar_dirty(bar); |
649 | remove_event(fd); | 650 | loop_remove_event(bar->eventloop, bar->status_event); |
650 | } else if (status_handle_readable(bar->status)) { | 651 | } else if (status_handle_readable(bar->status)) { |
651 | set_bar_dirty(bar); | 652 | set_bar_dirty(bar); |
652 | } | 653 | } |
653 | } | 654 | } |
654 | 655 | ||
655 | void bar_run(struct swaybar *bar) { | 656 | void bar_run(struct swaybar *bar) { |
656 | add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); | 657 | loop_add_fd(bar->eventloop, wl_display_get_fd(bar->display), POLLIN, |
657 | add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar); | 658 | display_in, bar); |
659 | loop_add_fd(bar->eventloop, bar->ipc_event_socketfd, POLLIN, ipc_in, bar); | ||
658 | if (bar->status) { | 660 | if (bar->status) { |
659 | add_event(bar->status->read_fd, POLLIN, status_in, bar); | 661 | bar->status_event = loop_add_fd( |
662 | bar->eventloop, bar->status->read_fd, POLLIN, status_in, bar); | ||
660 | } | 663 | } |
661 | while (1) { | 664 | while (1) { |
662 | wl_display_flush(bar->display); | 665 | wl_display_flush(bar->display); |
663 | event_loop_poll(); | 666 | loop_poll(bar->eventloop); |
664 | } | 667 | } |
665 | } | 668 | } |
666 | 669 | ||
diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c deleted file mode 100644 index 686b9962..00000000 --- a/swaybar/event_loop.c +++ /dev/null | |||
@@ -1,156 +0,0 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <stdlib.h> | ||
3 | #include <stdbool.h> | ||
4 | #include <string.h> | ||
5 | #include <strings.h> | ||
6 | #include <poll.h> | ||
7 | #include <time.h> | ||
8 | #include "swaybar/event_loop.h" | ||
9 | #include "list.h" | ||
10 | |||
11 | struct event_item { | ||
12 | void (*cb)(int fd, short mask, void *data); | ||
13 | void *data; | ||
14 | }; | ||
15 | |||
16 | struct timer_item { | ||
17 | timer_t timer; | ||
18 | void (*cb)(timer_t timer, void *data); | ||
19 | void *data; | ||
20 | }; | ||
21 | |||
22 | static struct { | ||
23 | // The order of each must be kept consistent | ||
24 | struct { /* pollfd array */ | ||
25 | struct pollfd *items; | ||
26 | int capacity; | ||
27 | int length; | ||
28 | } fds; | ||
29 | list_t *items; /* event_item list */ | ||
30 | |||
31 | // Timer list | ||
32 | list_t *timers; | ||
33 | } event_loop; | ||
34 | |||
35 | void add_timer(timer_t timer, | ||
36 | void(*cb)(timer_t timer, void *data), | ||
37 | void *data) { | ||
38 | |||
39 | struct timer_item *item = malloc(sizeof(struct timer_item)); | ||
40 | item->timer = timer; | ||
41 | item->cb = cb; | ||
42 | item->data = data; | ||
43 | |||
44 | list_add(event_loop.timers, item); | ||
45 | } | ||
46 | |||
47 | void add_event(int fd, short mask, | ||
48 | void(*cb)(int fd, short mask, void *data), void *data) { | ||
49 | |||
50 | struct pollfd pollfd = { | ||
51 | fd, | ||
52 | mask, | ||
53 | 0, | ||
54 | }; | ||
55 | |||
56 | // Resize | ||
57 | if (event_loop.fds.length == event_loop.fds.capacity) { | ||
58 | event_loop.fds.capacity += 10; | ||
59 | event_loop.fds.items = realloc(event_loop.fds.items, | ||
60 | sizeof(struct pollfd) * event_loop.fds.capacity); | ||
61 | } | ||
62 | |||
63 | event_loop.fds.items[event_loop.fds.length++] = pollfd; | ||
64 | |||
65 | struct event_item *item = malloc(sizeof(struct event_item)); | ||
66 | item->cb = cb; | ||
67 | item->data = data; | ||
68 | |||
69 | list_add(event_loop.items, item); | ||
70 | |||
71 | return; | ||
72 | } | ||
73 | |||
74 | bool remove_event(int fd) { | ||
75 | /* | ||
76 | * Instead of removing events immediately, we mark them for deletion | ||
77 | * and clean them up later. This is so we can call remove_event inside | ||
78 | * an event callback safely. | ||
79 | */ | ||
80 | for (int i = 0; i < event_loop.fds.length; ++i) { | ||
81 | if (event_loop.fds.items[i].fd == fd) { | ||
82 | event_loop.fds.items[i].fd = -1; | ||
83 | return true; | ||
84 | } | ||
85 | } | ||
86 | return false; | ||
87 | } | ||
88 | |||
89 | static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { | ||
90 | const struct timer_item *timer_item = _timer_item; | ||
91 | const timer_t *timer = _timer; | ||
92 | if (timer_item->timer == *timer) { | ||
93 | return 0; | ||
94 | } else { | ||
95 | return -1; | ||
96 | } | ||
97 | } | ||
98 | bool remove_timer(timer_t timer) { | ||
99 | int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); | ||
100 | if (index != -1) { | ||
101 | free(event_loop.timers->items[index]); | ||
102 | list_del(event_loop.timers, index); | ||
103 | return true; | ||
104 | } | ||
105 | return false; | ||
106 | } | ||
107 | |||
108 | void event_loop_poll(void) { | ||
109 | poll(event_loop.fds.items, event_loop.fds.length, -1); | ||
110 | |||
111 | for (int i = 0; i < event_loop.fds.length; ++i) { | ||
112 | struct pollfd pfd = event_loop.fds.items[i]; | ||
113 | struct event_item *item = (struct event_item *)event_loop.items->items[i]; | ||
114 | |||
115 | // Always send these events | ||
116 | unsigned events = pfd.events | POLLHUP | POLLERR; | ||
117 | |||
118 | if (pfd.revents & events) { | ||
119 | item->cb(pfd.fd, pfd.revents, item->data); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | // Cleanup removed events | ||
124 | int end = 0; | ||
125 | int length = event_loop.fds.length; | ||
126 | for (int i = 0; i < length; ++i) { | ||
127 | if (event_loop.fds.items[i].fd == -1) { | ||
128 | free(event_loop.items->items[i]); | ||
129 | list_del(event_loop.items, i); | ||
130 | --event_loop.fds.length; | ||
131 | } else if (end != i) { | ||
132 | event_loop.fds.items[end++] = event_loop.fds.items[i]; | ||
133 | } else { | ||
134 | end = i + 1; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | // check timers | ||
139 | // not tested, but seems to work | ||
140 | for (int i = 0; i < event_loop.timers->length; ++i) { | ||
141 | struct timer_item *item = event_loop.timers->items[i]; | ||
142 | int overrun = timer_getoverrun(item->timer); | ||
143 | if (overrun && overrun != -1) { | ||
144 | item->cb(item->timer, item->data); | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | void init_event_loop(void) { | ||
150 | event_loop.fds.length = 0; | ||
151 | event_loop.fds.capacity = 10; | ||
152 | event_loop.fds.items = malloc( | ||
153 | event_loop.fds.capacity * sizeof(struct pollfd)); | ||
154 | event_loop.items = create_list(); | ||
155 | event_loop.timers = create_list(); | ||
156 | } | ||
diff --git a/swaybar/meson.build b/swaybar/meson.build index 7a02a33f..0c116172 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build | |||
@@ -2,7 +2,6 @@ executable( | |||
2 | 'swaybar', [ | 2 | 'swaybar', [ |
3 | 'bar.c', | 3 | 'bar.c', |
4 | 'config.c', | 4 | 'config.c', |
5 | 'event_loop.c', | ||
6 | 'i3bar.c', | 5 | 'i3bar.c', |
7 | 'ipc.c', | 6 | 'ipc.c', |
8 | 'main.c', | 7 | 'main.c', |
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 000609ce..3f7a386f 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -7,16 +7,16 @@ | |||
7 | #include <stdio.h> | 7 | #include <stdio.h> |
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include <wlr/util/log.h> | 9 | #include <wlr/util/log.h> |
10 | #include "loop.h" | ||
10 | #include "swaybar/bar.h" | 11 | #include "swaybar/bar.h" |
11 | #include "swaybar/config.h" | 12 | #include "swaybar/config.h" |
12 | #include "swaybar/i3bar.h" | 13 | #include "swaybar/i3bar.h" |
13 | #include "swaybar/event_loop.h" | ||
14 | #include "swaybar/status_line.h" | 14 | #include "swaybar/status_line.h" |
15 | #include "readline.h" | 15 | #include "readline.h" |
16 | 16 | ||
17 | static void status_line_close_fds(struct status_line *status) { | 17 | static void status_line_close_fds(struct status_line *status) { |
18 | if (status->read_fd != -1) { | 18 | if (status->read_fd != -1) { |
19 | remove_event(status->read_fd); | 19 | loop_remove_event(status->bar->eventloop, status->bar->status_event); |
20 | close(status->read_fd); | 20 | close(status->read_fd); |
21 | status->read_fd = -1; | 21 | status->read_fd = -1; |
22 | } | 22 | } |