diff options
-rw-r--r-- | common/loop.c | 179 | ||||
-rw-r--r-- | common/meson.build | 1 | ||||
-rw-r--r-- | include/loop.h | 54 | ||||
-rw-r--r-- | include/swaybar/bar.h | 3 | ||||
-rw-r--r-- | include/swaybar/event_loop.h | 26 | ||||
-rw-r--r-- | include/swaybar/status_line.h | 2 | ||||
-rw-r--r-- | include/swaylock/swaylock.h | 4 | ||||
-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 | ||||
-rw-r--r-- | swaylock/main.c | 14 | ||||
-rw-r--r-- | swaylock/password.c | 62 |
13 files changed, 328 insertions, 195 deletions
diff --git a/common/loop.c b/common/loop.c new file mode 100644 index 00000000..1b174967 --- /dev/null +++ b/common/loop.c | |||
@@ -0,0 +1,179 @@ | |||
1 | #include <limits.h> | ||
2 | #include <string.h> | ||
3 | #include <stdbool.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <stdio.h> | ||
6 | #include <poll.h> | ||
7 | #include <time.h> | ||
8 | #include <unistd.h> | ||
9 | #include "list.h" | ||
10 | #include "log.h" | ||
11 | #include "loop.h" | ||
12 | |||
13 | struct loop_fd_event { | ||
14 | void (*callback)(int fd, short mask, void *data); | ||
15 | void *data; | ||
16 | }; | ||
17 | |||
18 | struct loop_timer { | ||
19 | void (*callback)(void *data); | ||
20 | void *data; | ||
21 | struct timespec expiry; | ||
22 | }; | ||
23 | |||
24 | struct loop { | ||
25 | struct pollfd *fds; | ||
26 | int fd_length; | ||
27 | int fd_capacity; | ||
28 | |||
29 | list_t *fd_events; // struct loop_fd_event | ||
30 | list_t *timers; // struct loop_timer | ||
31 | }; | ||
32 | |||
33 | struct loop *loop_create(void) { | ||
34 | struct loop *loop = calloc(1, sizeof(struct loop)); | ||
35 | if (!loop) { | ||
36 | wlr_log(WLR_ERROR, "Unable to allocate memory for loop"); | ||
37 | return NULL; | ||
38 | } | ||
39 | loop->fd_capacity = 10; | ||
40 | loop->fds = malloc(sizeof(struct pollfd) * loop->fd_capacity); | ||
41 | loop->fd_events = create_list(); | ||
42 | loop->timers = create_list(); | ||
43 | return loop; | ||
44 | } | ||
45 | |||
46 | void loop_destroy(struct loop *loop) { | ||
47 | list_foreach(loop->fd_events, free); | ||
48 | list_foreach(loop->timers, free); | ||
49 | list_free(loop->fd_events); | ||
50 | list_free(loop->timers); | ||
51 | free(loop->fds); | ||
52 | free(loop); | ||
53 | } | ||
54 | |||
55 | void loop_poll(struct loop *loop) { | ||
56 | // Calculate next timer in ms | ||
57 | int ms = INT_MAX; | ||
58 | if (loop->timers->length) { | ||
59 | struct timespec now; | ||
60 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
61 | for (int i = 0; i < loop->timers->length; ++i) { | ||
62 | struct loop_timer *timer = loop->timers->items[i]; | ||
63 | int timer_ms = (timer->expiry.tv_sec - now.tv_sec) * 1000; | ||
64 | timer_ms += (timer->expiry.tv_nsec - now.tv_nsec) / 1000000; | ||
65 | if (timer_ms < ms) { | ||
66 | ms = timer_ms; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | if (ms < 0) { | ||
71 | ms = 0; | ||
72 | } | ||
73 | |||
74 | poll(loop->fds, loop->fd_length, ms); | ||
75 | |||
76 | // Dispatch fds | ||
77 | for (int i = 0; i < loop->fd_length; ++i) { | ||
78 | struct pollfd pfd = loop->fds[i]; | ||
79 | struct loop_fd_event *event = loop->fd_events->items[i]; | ||
80 | |||
81 | // Always send these events | ||
82 | unsigned events = pfd.events | POLLHUP | POLLERR; | ||
83 | |||
84 | if (pfd.revents & events) { | ||
85 | event->callback(pfd.fd, pfd.revents, event->data); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // Dispatch timers | ||
90 | if (loop->timers->length) { | ||
91 | struct timespec now; | ||
92 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
93 | for (int i = 0; i < loop->timers->length; ++i) { | ||
94 | struct loop_timer *timer = loop->timers->items[i]; | ||
95 | bool expired = timer->expiry.tv_sec < now.tv_sec || | ||
96 | (timer->expiry.tv_sec == now.tv_sec && | ||
97 | timer->expiry.tv_nsec < now.tv_nsec); | ||
98 | if (expired) { | ||
99 | timer->callback(timer->data); | ||
100 | loop_remove_timer(loop, timer); | ||
101 | --i; | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | |||
107 | void loop_add_fd(struct loop *loop, int fd, short mask, | ||
108 | void (*callback)(int fd, short mask, void *data), void *data) { | ||
109 | struct loop_fd_event *event = calloc(1, sizeof(struct loop_fd_event)); | ||
110 | if (!event) { | ||
111 | wlr_log(WLR_ERROR, "Unable to allocate memory for event"); | ||
112 | return; | ||
113 | } | ||
114 | event->callback = callback; | ||
115 | event->data = data; | ||
116 | list_add(loop->fd_events, event); | ||
117 | |||
118 | struct pollfd pfd = {fd, mask, 0}; | ||
119 | |||
120 | if (loop->fd_length == loop->fd_capacity) { | ||
121 | loop->fd_capacity += 10; | ||
122 | loop->fds = realloc(loop->fds, | ||
123 | sizeof(struct pollfd) * loop->fd_capacity); | ||
124 | } | ||
125 | |||
126 | loop->fds[loop->fd_length++] = pfd; | ||
127 | } | ||
128 | |||
129 | struct loop_timer *loop_add_timer(struct loop *loop, int ms, | ||
130 | void (*callback)(void *data), void *data) { | ||
131 | struct loop_timer *timer = calloc(1, sizeof(struct loop_timer)); | ||
132 | if (!timer) { | ||
133 | wlr_log(WLR_ERROR, "Unable to allocate memory for timer"); | ||
134 | return NULL; | ||
135 | } | ||
136 | timer->callback = callback; | ||
137 | timer->data = data; | ||
138 | |||
139 | clock_gettime(CLOCK_MONOTONIC, &timer->expiry); | ||
140 | timer->expiry.tv_sec += ms / 1000; | ||
141 | |||
142 | long int nsec = (ms % 1000) * 1000000; | ||
143 | if (timer->expiry.tv_nsec + nsec >= 1000000000) { | ||
144 | timer->expiry.tv_sec++; | ||
145 | nsec -= 1000000000; | ||
146 | } | ||
147 | timer->expiry.tv_nsec += nsec; | ||
148 | |||
149 | list_add(loop->timers, timer); | ||
150 | |||
151 | return timer; | ||
152 | } | ||
153 | |||
154 | bool loop_remove_fd(struct loop *loop, int fd) { | ||
155 | for (int i = 0; i < loop->fd_length; ++i) { | ||
156 | if (loop->fds[i].fd == fd) { | ||
157 | free(loop->fd_events->items[i]); | ||
158 | list_del(loop->fd_events, i); | ||
159 | |||
160 | loop->fd_length--; | ||
161 | memmove(&loop->fds[i], &loop->fds[i + 1], | ||
162 | sizeof(struct pollfd) * (loop->fd_length - i)); | ||
163 | |||
164 | return true; | ||
165 | } | ||
166 | } | ||
167 | return false; | ||
168 | } | ||
169 | |||
170 | bool loop_remove_timer(struct loop *loop, struct loop_timer *timer) { | ||
171 | for (int i = 0; i < loop->timers->length; ++i) { | ||
172 | if (loop->timers->items[i] == timer) { | ||
173 | list_del(loop->timers, i); | ||
174 | free(timer); | ||
175 | return true; | ||
176 | } | ||
177 | } | ||
178 | return false; | ||
179 | } | ||
diff --git a/common/meson.build b/common/meson.build index 44a29508..224a9c3f 100644 --- a/common/meson.build +++ b/common/meson.build | |||
@@ -5,6 +5,7 @@ lib_sway_common = static_library( | |||
5 | 'cairo.c', | 5 | 'cairo.c', |
6 | 'ipc-client.c', | 6 | 'ipc-client.c', |
7 | 'log.c', | 7 | 'log.c', |
8 | 'loop.c', | ||
8 | 'list.c', | 9 | 'list.c', |
9 | 'pango.c', | 10 | 'pango.c', |
10 | 'readline.c', | 11 | 'readline.c', |
diff --git a/include/loop.h b/include/loop.h new file mode 100644 index 00000000..2f608eda --- /dev/null +++ b/include/loop.h | |||
@@ -0,0 +1,54 @@ | |||
1 | #ifndef _SWAY_LOOP_H | ||
2 | #define _SWAY_LOOP_H | ||
3 | #include <stdbool.h> | ||
4 | |||
5 | /** | ||
6 | * This is an event loop system designed for sway clients, not sway itself. | ||
7 | * | ||
8 | * The loop consists of file descriptors and timers. Typically the Wayland | ||
9 | * display's file descriptor will be one of the fds in the loop. | ||
10 | */ | ||
11 | |||
12 | struct loop; | ||
13 | struct loop_timer; | ||
14 | |||
15 | /** | ||
16 | * Create an event loop. | ||
17 | */ | ||
18 | struct loop *loop_create(void); | ||
19 | |||
20 | /** | ||
21 | * Destroy the event loop (eg. on program termination). | ||
22 | */ | ||
23 | void loop_destroy(struct loop *loop); | ||
24 | |||
25 | /** | ||
26 | * Poll the event loop. This will block until one of the fds has data. | ||
27 | */ | ||
28 | void loop_poll(struct loop *loop); | ||
29 | |||
30 | /** | ||
31 | * Add a file descriptor to the loop. | ||
32 | */ | ||
33 | void loop_add_fd(struct loop *loop, int fd, short mask, | ||
34 | void (*func)(int fd, short mask, void *data), void *data); | ||
35 | |||
36 | /** | ||
37 | * Add a timer to the loop. | ||
38 | * | ||
39 | * When the timer expires, the timer will be removed from the loop and freed. | ||
40 | */ | ||
41 | struct loop_timer *loop_add_timer(struct loop *loop, int ms, | ||
42 | void (*callback)(void *data), void *data); | ||
43 | |||
44 | /** | ||
45 | * Remove a file descriptor from the loop. | ||
46 | */ | ||
47 | bool loop_remove_fd(struct loop *loop, int fd); | ||
48 | |||
49 | /** | ||
50 | * Remove a timer from the loop. | ||
51 | */ | ||
52 | bool loop_remove_timer(struct loop *loop, struct loop_timer *timer); | ||
53 | |||
54 | #endif | ||
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 9ff3fe7b..58e2dee6 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -8,6 +8,7 @@ | |||
8 | struct swaybar_config; | 8 | struct swaybar_config; |
9 | struct swaybar_output; | 9 | struct swaybar_output; |
10 | struct swaybar_workspace; | 10 | struct swaybar_workspace; |
11 | struct loop; | ||
11 | 12 | ||
12 | struct swaybar_pointer { | 13 | struct swaybar_pointer { |
13 | struct wl_pointer *pointer; | 14 | struct wl_pointer *pointer; |
@@ -66,6 +67,8 @@ struct swaybar { | |||
66 | struct swaybar_pointer pointer; | 67 | struct swaybar_pointer pointer; |
67 | struct status_line *status; | 68 | struct status_line *status; |
68 | 69 | ||
70 | struct loop *eventloop; | ||
71 | |||
69 | int ipc_event_socketfd; | 72 | int ipc_event_socketfd; |
70 | int ipc_socketfd; | 73 | int ipc_socketfd; |
71 | 74 | ||
diff --git a/include/swaybar/event_loop.h b/include/swaybar/event_loop.h deleted file mode 100644 index 47be5b79..00000000 --- a/include/swaybar/event_loop.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | #ifndef _SWAYBAR_EVENT_LOOP_H | ||
2 | #define _SWAYBAR_EVENT_LOOP_H | ||
3 | #include <stdbool.h> | ||
4 | #include <time.h> | ||
5 | |||
6 | void add_event(int fd, short mask, | ||
7 | void(*cb)(int fd, short mask, void *data), | ||
8 | void *data); | ||
9 | |||
10 | // Not guaranteed to notify cb immediately | ||
11 | void add_timer(timer_t timer, | ||
12 | void(*cb)(timer_t timer, void *data), | ||
13 | void *data); | ||
14 | |||
15 | // Returns false if nothing exists, true otherwise | ||
16 | bool remove_event(int fd); | ||
17 | |||
18 | // Returns false if nothing exists, true otherwise | ||
19 | bool remove_timer(timer_t timer); | ||
20 | |||
21 | // Blocks and returns after sending callbacks | ||
22 | void event_loop_poll(void); | ||
23 | |||
24 | void init_event_loop(void); | ||
25 | |||
26 | #endif | ||
diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 5e7e8771..957a808e 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h | |||
@@ -14,6 +14,8 @@ enum status_protocol { | |||
14 | }; | 14 | }; |
15 | 15 | ||
16 | struct status_line { | 16 | struct status_line { |
17 | struct swaybar *bar; | ||
18 | |||
17 | pid_t pid; | 19 | pid_t pid; |
18 | int read_fd, write_fd; | 20 | int read_fd, write_fd; |
19 | FILE *read, *write; | 21 | FILE *read, *write; |
diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index fbdd42a8..25b41a71 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h | |||
@@ -54,6 +54,10 @@ struct swaylock_password { | |||
54 | }; | 54 | }; |
55 | 55 | ||
56 | struct swaylock_state { | 56 | struct swaylock_state { |
57 | struct loop *eventloop; | ||
58 | struct loop_timer *clear_indicator_timer; // clears the indicator | ||
59 | struct loop_timer *clear_password_timer; // clears the password buffer | ||
60 | struct loop_timer *verify_password_timer; | ||
57 | struct wl_display *display; | 61 | struct wl_display *display; |
58 | struct wl_compositor *compositor; | 62 | struct wl_compositor *compositor; |
59 | struct zwlr_layer_shell_v1 *layer_shell; | 63 | struct zwlr_layer_shell_v1 *layer_shell; |
diff --git a/swaybar/bar.c b/swaybar/bar.c index 9f72c94c..be290c18 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_fd(bar->eventloop, fd); |
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 | loop_add_fd(bar->eventloop, bar->status->read_fd, POLLIN, |
662 | 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..65d6c052 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_fd(status->bar->eventloop, status->read_fd); |
20 | close(status->read_fd); | 20 | close(status->read_fd); |
21 | status->read_fd = -1; | 21 | status->read_fd = -1; |
22 | } | 22 | } |
diff --git a/swaylock/main.c b/swaylock/main.c index d1384c6f..27bcfe32 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "pool-buffer.h" | 21 | #include "pool-buffer.h" |
22 | #include "cairo.h" | 22 | #include "cairo.h" |
23 | #include "log.h" | 23 | #include "log.h" |
24 | #include "loop.h" | ||
24 | #include "readline.h" | 25 | #include "readline.h" |
25 | #include "stringop.h" | 26 | #include "stringop.h" |
26 | #include "util.h" | 27 | #include "util.h" |
@@ -844,6 +845,10 @@ static int load_config(char *path, struct swaylock_state *state, | |||
844 | 845 | ||
845 | static struct swaylock_state state; | 846 | static struct swaylock_state state; |
846 | 847 | ||
848 | static void display_in(int fd, short mask, void *data) { | ||
849 | wl_display_dispatch(state.display); | ||
850 | } | ||
851 | |||
847 | int main(int argc, char **argv) { | 852 | int main(int argc, char **argv) { |
848 | wlr_log_init(WLR_DEBUG, NULL); | 853 | wlr_log_init(WLR_DEBUG, NULL); |
849 | initialize_pw_backend(); | 854 | initialize_pw_backend(); |
@@ -946,9 +951,14 @@ int main(int argc, char **argv) { | |||
946 | daemonize(); | 951 | daemonize(); |
947 | } | 952 | } |
948 | 953 | ||
954 | state.eventloop = loop_create(); | ||
955 | loop_add_fd(state.eventloop, wl_display_get_fd(state.display), POLL_IN, | ||
956 | display_in, NULL); | ||
957 | |||
949 | state.run_display = true; | 958 | state.run_display = true; |
950 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { | 959 | while (state.run_display) { |
951 | // This space intentionally left blank | 960 | wl_display_flush(state.display); |
961 | loop_poll(state.eventloop); | ||
952 | } | 962 | } |
953 | 963 | ||
954 | free(state.args.font); | 964 | free(state.args.font); |
diff --git a/swaylock/password.c b/swaylock/password.c index 50b81f6b..fecaecbf 100644 --- a/swaylock/password.c +++ b/swaylock/password.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <xkbcommon/xkbcommon.h> | 8 | #include <xkbcommon/xkbcommon.h> |
9 | #include "swaylock/swaylock.h" | 9 | #include "swaylock/swaylock.h" |
10 | #include "swaylock/seat.h" | 10 | #include "swaylock/seat.h" |
11 | #include "loop.h" | ||
11 | #include "unicode.h" | 12 | #include "unicode.h" |
12 | 13 | ||
13 | void clear_password_buffer(struct swaylock_password *pw) { | 14 | void clear_password_buffer(struct swaylock_password *pw) { |
@@ -39,6 +40,43 @@ static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { | |||
39 | pw->len += utf8_size; | 40 | pw->len += utf8_size; |
40 | } | 41 | } |
41 | 42 | ||
43 | static void clear_indicator(void *data) { | ||
44 | struct swaylock_state *state = data; | ||
45 | state->clear_indicator_timer = NULL; | ||
46 | state->auth_state = AUTH_STATE_IDLE; | ||
47 | damage_state(state); | ||
48 | } | ||
49 | |||
50 | static void schedule_indicator_clear(struct swaylock_state *state) { | ||
51 | if (state->clear_indicator_timer) { | ||
52 | loop_remove_timer(state->eventloop, state->clear_indicator_timer); | ||
53 | } | ||
54 | state->clear_indicator_timer = loop_add_timer( | ||
55 | state->eventloop, 3000, clear_indicator, state); | ||
56 | } | ||
57 | |||
58 | static void clear_password(void *data) { | ||
59 | struct swaylock_state *state = data; | ||
60 | state->clear_password_timer = NULL; | ||
61 | state->auth_state = AUTH_STATE_CLEAR; | ||
62 | clear_password_buffer(&state->password); | ||
63 | damage_state(state); | ||
64 | schedule_indicator_clear(state); | ||
65 | } | ||
66 | |||
67 | static void schedule_password_clear(struct swaylock_state *state) { | ||
68 | if (state->clear_password_timer) { | ||
69 | loop_remove_timer(state->eventloop, state->clear_password_timer); | ||
70 | } | ||
71 | state->clear_password_timer = loop_add_timer( | ||
72 | state->eventloop, 10000, clear_password, state); | ||
73 | } | ||
74 | |||
75 | static void handle_preverify_timeout(void *data) { | ||
76 | struct swaylock_state *state = data; | ||
77 | state->verify_password_timer = NULL; | ||
78 | } | ||
79 | |||
42 | void swaylock_handle_key(struct swaylock_state *state, | 80 | void swaylock_handle_key(struct swaylock_state *state, |
43 | xkb_keysym_t keysym, uint32_t codepoint) { | 81 | xkb_keysym_t keysym, uint32_t codepoint) { |
44 | switch (keysym) { | 82 | switch (keysym) { |
@@ -50,7 +88,18 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
50 | 88 | ||
51 | state->auth_state = AUTH_STATE_VALIDATING; | 89 | state->auth_state = AUTH_STATE_VALIDATING; |
52 | damage_state(state); | 90 | damage_state(state); |
53 | while (wl_display_dispatch(state->display) != -1 && state->run_display) { | 91 | |
92 | // We generally want to wait until all surfaces are showing the | ||
93 | // "verifying" state before we go and verify the password, because | ||
94 | // verifying it is a blocking operation. However, if the surface is on | ||
95 | // an output with DPMS off then it won't update, so we set a timer. | ||
96 | state->verify_password_timer = loop_add_timer( | ||
97 | state->eventloop, 50, handle_preverify_timeout, state); | ||
98 | |||
99 | while (state->run_display && state->verify_password_timer) { | ||
100 | wl_display_flush(state->display); | ||
101 | loop_poll(state->eventloop); | ||
102 | |||
54 | bool ok = 1; | 103 | bool ok = 1; |
55 | struct swaylock_surface *surface; | 104 | struct swaylock_surface *surface; |
56 | wl_list_for_each(surface, &state->surfaces, link) { | 105 | wl_list_for_each(surface, &state->surfaces, link) { |
@@ -70,6 +119,7 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
70 | } | 119 | } |
71 | state->auth_state = AUTH_STATE_INVALID; | 120 | state->auth_state = AUTH_STATE_INVALID; |
72 | damage_state(state); | 121 | damage_state(state); |
122 | schedule_indicator_clear(state); | ||
73 | break; | 123 | break; |
74 | case XKB_KEY_Delete: | 124 | case XKB_KEY_Delete: |
75 | case XKB_KEY_BackSpace: | 125 | case XKB_KEY_BackSpace: |
@@ -79,11 +129,14 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
79 | state->auth_state = AUTH_STATE_CLEAR; | 129 | state->auth_state = AUTH_STATE_CLEAR; |
80 | } | 130 | } |
81 | damage_state(state); | 131 | damage_state(state); |
132 | schedule_indicator_clear(state); | ||
133 | schedule_password_clear(state); | ||
82 | break; | 134 | break; |
83 | case XKB_KEY_Escape: | 135 | case XKB_KEY_Escape: |
84 | clear_password_buffer(&state->password); | 136 | clear_password_buffer(&state->password); |
85 | state->auth_state = AUTH_STATE_CLEAR; | 137 | state->auth_state = AUTH_STATE_CLEAR; |
86 | damage_state(state); | 138 | damage_state(state); |
139 | schedule_indicator_clear(state); | ||
87 | break; | 140 | break; |
88 | case XKB_KEY_Caps_Lock: | 141 | case XKB_KEY_Caps_Lock: |
89 | /* The state is getting active after this | 142 | /* The state is getting active after this |
@@ -91,6 +144,8 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
91 | state->xkb.caps_lock = !state->xkb.caps_lock; | 144 | state->xkb.caps_lock = !state->xkb.caps_lock; |
92 | state->auth_state = AUTH_STATE_INPUT_NOP; | 145 | state->auth_state = AUTH_STATE_INPUT_NOP; |
93 | damage_state(state); | 146 | damage_state(state); |
147 | schedule_indicator_clear(state); | ||
148 | schedule_password_clear(state); | ||
94 | break; | 149 | break; |
95 | case XKB_KEY_Shift_L: | 150 | case XKB_KEY_Shift_L: |
96 | case XKB_KEY_Shift_R: | 151 | case XKB_KEY_Shift_R: |
@@ -104,12 +159,15 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
104 | case XKB_KEY_Super_R: | 159 | case XKB_KEY_Super_R: |
105 | state->auth_state = AUTH_STATE_INPUT_NOP; | 160 | state->auth_state = AUTH_STATE_INPUT_NOP; |
106 | damage_state(state); | 161 | damage_state(state); |
162 | schedule_indicator_clear(state); | ||
163 | schedule_password_clear(state); | ||
107 | break; | 164 | break; |
108 | case XKB_KEY_u: | 165 | case XKB_KEY_u: |
109 | if (state->xkb.control) { | 166 | if (state->xkb.control) { |
110 | clear_password_buffer(&state->password); | 167 | clear_password_buffer(&state->password); |
111 | state->auth_state = AUTH_STATE_CLEAR; | 168 | state->auth_state = AUTH_STATE_CLEAR; |
112 | damage_state(state); | 169 | damage_state(state); |
170 | schedule_indicator_clear(state); | ||
113 | break; | 171 | break; |
114 | } | 172 | } |
115 | // fallthrough | 173 | // fallthrough |
@@ -118,6 +176,8 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
118 | append_ch(&state->password, codepoint); | 176 | append_ch(&state->password, codepoint); |
119 | state->auth_state = AUTH_STATE_INPUT; | 177 | state->auth_state = AUTH_STATE_INPUT; |
120 | damage_state(state); | 178 | damage_state(state); |
179 | schedule_indicator_clear(state); | ||
180 | schedule_password_clear(state); | ||
121 | } | 181 | } |
122 | break; | 182 | break; |
123 | } | 183 | } |