summaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-10-13 16:04:37 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-10-15 00:26:27 +1000
commit4056c09e13c1aeead6dd4085fc7e263a17a0b195 (patch)
treea3413f2a5717968e370d68521b689580d5adc5a0 /swaybar
parentDocument `border csd` (diff)
downloadsway-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.c17
-rw-r--r--swaybar/event_loop.c156
-rw-r--r--swaybar/meson.build1
-rw-r--r--swaybar/status_line.c4
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
574bool bar_setup(struct swaybar *bar, const char *socket_path) { 574bool 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
655void bar_run(struct swaybar *bar) { 656void 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
11struct event_item {
12 void (*cb)(int fd, short mask, void *data);
13 void *data;
14};
15
16struct timer_item {
17 timer_t timer;
18 void (*cb)(timer_t timer, void *data);
19 void *data;
20};
21
22static 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
35void 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
47void 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
74bool 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
89static 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}
98bool 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
108void 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
149void 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
17static void status_line_close_fds(struct status_line *status) { 17static 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 }