diff options
-rw-r--r-- | include/swaybar/bar.h | 38 | ||||
-rw-r--r-- | include/swaybar/i3bar.h | 4 | ||||
-rw-r--r-- | include/swaybar/input.h | 49 | ||||
-rw-r--r-- | swaybar/bar.c | 248 | ||||
-rw-r--r-- | swaybar/i3bar.c | 30 | ||||
-rw-r--r-- | swaybar/input.c | 286 | ||||
-rw-r--r-- | swaybar/meson.build | 1 |
7 files changed, 340 insertions, 316 deletions
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 58e2dee6..95b20510 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _SWAYBAR_BAR_H | 1 | #ifndef _SWAYBAR_BAR_H |
2 | #define _SWAYBAR_BAR_H | 2 | #define _SWAYBAR_BAR_H |
3 | #include <wayland-client.h> | 3 | #include <wayland-client.h> |
4 | #include "input.h" | ||
4 | #include "pool-buffer.h" | 5 | #include "pool-buffer.h" |
5 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | 6 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" |
6 | #include "xdg-output-unstable-v1-client-protocol.h" | 7 | #include "xdg-output-unstable-v1-client-protocol.h" |
@@ -10,42 +11,6 @@ struct swaybar_output; | |||
10 | struct swaybar_workspace; | 11 | struct swaybar_workspace; |
11 | struct loop; | 12 | struct loop; |
12 | 13 | ||
13 | struct swaybar_pointer { | ||
14 | struct wl_pointer *pointer; | ||
15 | struct wl_cursor_theme *cursor_theme; | ||
16 | struct wl_cursor_image *cursor_image; | ||
17 | struct wl_surface *cursor_surface; | ||
18 | struct swaybar_output *current; | ||
19 | int x, y; | ||
20 | }; | ||
21 | |||
22 | enum x11_button { | ||
23 | NONE, | ||
24 | LEFT, | ||
25 | MIDDLE, | ||
26 | RIGHT, | ||
27 | SCROLL_UP, | ||
28 | SCROLL_DOWN, | ||
29 | SCROLL_LEFT, | ||
30 | SCROLL_RIGHT, | ||
31 | BACK, | ||
32 | FORWARD, | ||
33 | }; | ||
34 | |||
35 | enum hotspot_event_handling { | ||
36 | HOTSPOT_IGNORE, | ||
37 | HOTSPOT_PROCESS, | ||
38 | }; | ||
39 | |||
40 | struct swaybar_hotspot { | ||
41 | struct wl_list link; // swaybar_output::hotspots | ||
42 | int x, y, width, height; | ||
43 | enum hotspot_event_handling (*callback)(struct swaybar_output *output, | ||
44 | int x, int y, enum x11_button button, void *data); | ||
45 | void (*destroy)(void *data); | ||
46 | void *data; | ||
47 | }; | ||
48 | |||
49 | struct swaybar { | 14 | struct swaybar { |
50 | char *id; | 15 | char *id; |
51 | char *mode; | 16 | char *mode; |
@@ -125,7 +90,6 @@ void bar_teardown(struct swaybar *bar); | |||
125 | * Returns true if the bar is now visible, otherwise false. | 90 | * Returns true if the bar is now visible, otherwise false. |
126 | */ | 91 | */ |
127 | bool determine_bar_visibility(struct swaybar *bar, bool moving_layer); | 92 | bool determine_bar_visibility(struct swaybar *bar, bool moving_layer); |
128 | void free_hotspots(struct wl_list *list); | ||
129 | void free_workspaces(struct wl_list *list); | 93 | void free_workspaces(struct wl_list *list); |
130 | 94 | ||
131 | #endif | 95 | #endif |
diff --git a/include/swaybar/i3bar.h b/include/swaybar/i3bar.h index d4a48e07..3f1ecc25 100644 --- a/include/swaybar/i3bar.h +++ b/include/swaybar/i3bar.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef _SWAYBAR_I3BAR_H | 1 | #ifndef _SWAYBAR_I3BAR_H |
2 | #define _SWAYBAR_I3BAR_H | 2 | #define _SWAYBAR_I3BAR_H |
3 | 3 | ||
4 | #include "bar.h" | 4 | #include "input.h" |
5 | #include "status_line.h" | 5 | #include "status_line.h" |
6 | 6 | ||
7 | struct i3bar_block { | 7 | struct i3bar_block { |
@@ -28,7 +28,5 @@ void i3bar_block_unref(struct i3bar_block *block); | |||
28 | bool i3bar_handle_readable(struct status_line *status); | 28 | bool i3bar_handle_readable(struct status_line *status); |
29 | enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, | 29 | enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, |
30 | struct i3bar_block *block, int x, int y, enum x11_button button); | 30 | struct i3bar_block *block, int x, int y, enum x11_button button); |
31 | enum x11_button wl_button_to_x11_button(uint32_t button); | ||
32 | enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value); | ||
33 | 31 | ||
34 | #endif | 32 | #endif |
diff --git a/include/swaybar/input.h b/include/swaybar/input.h new file mode 100644 index 00000000..a552e7ac --- /dev/null +++ b/include/swaybar/input.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef _SWAYBAR_INPUT_H | ||
2 | #define _SWAYBAR_INPUT_H | ||
3 | |||
4 | #include <wayland-client.h> | ||
5 | #include "list.h" | ||
6 | |||
7 | struct swaybar_output; | ||
8 | |||
9 | struct swaybar_pointer { | ||
10 | struct wl_pointer *pointer; | ||
11 | struct wl_cursor_theme *cursor_theme; | ||
12 | struct wl_cursor_image *cursor_image; | ||
13 | struct wl_surface *cursor_surface; | ||
14 | struct swaybar_output *current; | ||
15 | int x, y; | ||
16 | }; | ||
17 | |||
18 | enum x11_button { | ||
19 | NONE, | ||
20 | LEFT, | ||
21 | MIDDLE, | ||
22 | RIGHT, | ||
23 | SCROLL_UP, | ||
24 | SCROLL_DOWN, | ||
25 | SCROLL_LEFT, | ||
26 | SCROLL_RIGHT, | ||
27 | BACK, | ||
28 | FORWARD, | ||
29 | }; | ||
30 | |||
31 | enum hotspot_event_handling { | ||
32 | HOTSPOT_IGNORE, | ||
33 | HOTSPOT_PROCESS, | ||
34 | }; | ||
35 | |||
36 | struct swaybar_hotspot { | ||
37 | struct wl_list link; // swaybar_output::hotspots | ||
38 | int x, y, width, height; | ||
39 | enum hotspot_event_handling (*callback)(struct swaybar_output *output, | ||
40 | int x, int y, enum x11_button button, void *data); | ||
41 | void (*destroy)(void *data); | ||
42 | void *data; | ||
43 | }; | ||
44 | |||
45 | extern const struct wl_seat_listener seat_listener; | ||
46 | |||
47 | void free_hotspots(struct wl_list *list); | ||
48 | |||
49 | #endif | ||
diff --git a/swaybar/bar.c b/swaybar/bar.c index 0deba72d..5e9767b2 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -11,14 +11,10 @@ | |||
11 | #include <wayland-client.h> | 11 | #include <wayland-client.h> |
12 | #include <wayland-cursor.h> | 12 | #include <wayland-cursor.h> |
13 | #include <wlr/util/log.h> | 13 | #include <wlr/util/log.h> |
14 | #ifdef __FreeBSD__ | ||
15 | #include <dev/evdev/input-event-codes.h> | ||
16 | #else | ||
17 | #include <linux/input-event-codes.h> | ||
18 | #endif | ||
19 | #include "swaybar/bar.h" | 14 | #include "swaybar/bar.h" |
20 | #include "swaybar/config.h" | 15 | #include "swaybar/config.h" |
21 | #include "swaybar/i3bar.h" | 16 | #include "swaybar/i3bar.h" |
17 | #include "swaybar/input.h" | ||
22 | #include "swaybar/ipc.h" | 18 | #include "swaybar/ipc.h" |
23 | #include "swaybar/status_line.h" | 19 | #include "swaybar/status_line.h" |
24 | #include "swaybar/render.h" | 20 | #include "swaybar/render.h" |
@@ -36,17 +32,6 @@ static void bar_init(struct swaybar *bar) { | |||
36 | wl_list_init(&bar->outputs); | 32 | wl_list_init(&bar->outputs); |
37 | } | 33 | } |
38 | 34 | ||
39 | void free_hotspots(struct wl_list *list) { | ||
40 | struct swaybar_hotspot *hotspot, *tmp; | ||
41 | wl_list_for_each_safe(hotspot, tmp, list, link) { | ||
42 | wl_list_remove(&hotspot->link); | ||
43 | if (hotspot->destroy) { | ||
44 | hotspot->destroy(hotspot->data); | ||
45 | } | ||
46 | free(hotspot); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | void free_workspaces(struct wl_list *list) { | 35 | void free_workspaces(struct wl_list *list) { |
51 | struct swaybar_workspace *ws, *tmp; | 36 | struct swaybar_workspace *ws, *tmp; |
52 | wl_list_for_each_safe(ws, tmp, list, link) { | 37 | wl_list_for_each_safe(ws, tmp, list, link) { |
@@ -107,237 +92,6 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { | |||
107 | .closed = layer_surface_closed, | 92 | .closed = layer_surface_closed, |
108 | }; | 93 | }; |
109 | 94 | ||
110 | static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, | ||
111 | uint32_t serial, struct wl_surface *surface, | ||
112 | wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||
113 | struct swaybar *bar = data; | ||
114 | struct swaybar_pointer *pointer = &bar->pointer; | ||
115 | struct swaybar_output *output; | ||
116 | wl_list_for_each(output, &bar->outputs, link) { | ||
117 | if (output->surface == surface) { | ||
118 | pointer->current = output; | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | int max_scale = 1; | ||
123 | struct swaybar_output *_output; | ||
124 | wl_list_for_each(_output, &bar->outputs, link) { | ||
125 | if (_output->scale > max_scale) { | ||
126 | max_scale = _output->scale; | ||
127 | } | ||
128 | } | ||
129 | wl_surface_set_buffer_scale(pointer->cursor_surface, max_scale); | ||
130 | wl_surface_attach(pointer->cursor_surface, | ||
131 | wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); | ||
132 | wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, | ||
133 | pointer->cursor_image->hotspot_x / max_scale, | ||
134 | pointer->cursor_image->hotspot_y / max_scale); | ||
135 | wl_surface_commit(pointer->cursor_surface); | ||
136 | } | ||
137 | |||
138 | static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, | ||
139 | uint32_t serial, struct wl_surface *surface) { | ||
140 | struct swaybar *bar = data; | ||
141 | bar->pointer.current = NULL; | ||
142 | } | ||
143 | |||
144 | static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | ||
145 | uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||
146 | struct swaybar *bar = data; | ||
147 | bar->pointer.x = wl_fixed_to_int(surface_x); | ||
148 | bar->pointer.y = wl_fixed_to_int(surface_y); | ||
149 | } | ||
150 | |||
151 | static bool check_bindings(struct swaybar *bar, uint32_t x11_button, | ||
152 | uint32_t state) { | ||
153 | bool released = state == WL_POINTER_BUTTON_STATE_RELEASED; | ||
154 | for (int i = 0; i < bar->config->bindings->length; i++) { | ||
155 | struct swaybar_binding *binding = bar->config->bindings->items[i]; | ||
156 | if (binding->button == x11_button && binding->release == released) { | ||
157 | ipc_execute_binding(bar, binding); | ||
158 | return true; | ||
159 | } | ||
160 | } | ||
161 | return false; | ||
162 | } | ||
163 | |||
164 | static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | ||
165 | uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { | ||
166 | struct swaybar *bar = data; | ||
167 | struct swaybar_pointer *pointer = &bar->pointer; | ||
168 | struct swaybar_output *output = pointer->current; | ||
169 | if (!sway_assert(output, "button with no active output")) { | ||
170 | return; | ||
171 | } | ||
172 | |||
173 | if (check_bindings(bar, wl_button_to_x11_button(button), state)) { | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | if (state != WL_POINTER_BUTTON_STATE_PRESSED) { | ||
178 | return; | ||
179 | } | ||
180 | struct swaybar_hotspot *hotspot; | ||
181 | wl_list_for_each(hotspot, &output->hotspots, link) { | ||
182 | double x = pointer->x * output->scale; | ||
183 | double y = pointer->y * output->scale; | ||
184 | if (x >= hotspot->x | ||
185 | && y >= hotspot->y | ||
186 | && x < hotspot->x + hotspot->width | ||
187 | && y < hotspot->y + hotspot->height) { | ||
188 | if (HOTSPOT_IGNORE == hotspot->callback(output, pointer->x, pointer->y, | ||
189 | wl_button_to_x11_button(button), hotspot->data)) { | ||
190 | return; | ||
191 | } | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | ||
197 | uint32_t time, uint32_t axis, wl_fixed_t value) { | ||
198 | struct swaybar *bar = data; | ||
199 | struct swaybar_pointer *pointer = &bar->pointer; | ||
200 | struct swaybar_output *output = bar->pointer.current; | ||
201 | if (!sway_assert(output, "axis with no active output")) { | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | // If there is a button press binding, execute it, skip default behavior, | ||
206 | // and check button release bindings | ||
207 | if (check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
208 | WL_POINTER_BUTTON_STATE_PRESSED)) { | ||
209 | check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
210 | WL_POINTER_BUTTON_STATE_RELEASED); | ||
211 | return; | ||
212 | } | ||
213 | |||
214 | struct swaybar_hotspot *hotspot; | ||
215 | wl_list_for_each(hotspot, &output->hotspots, link) { | ||
216 | double x = pointer->x * output->scale; | ||
217 | double y = pointer->y * output->scale; | ||
218 | if (x >= hotspot->x | ||
219 | && y >= hotspot->y | ||
220 | && x < hotspot->x + hotspot->width | ||
221 | && y < hotspot->y + hotspot->height) { | ||
222 | if (HOTSPOT_IGNORE == hotspot->callback( | ||
223 | output, pointer->x, pointer->y, | ||
224 | wl_axis_to_x11_button(axis, value), hotspot->data)) { | ||
225 | return; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | double amt = wl_fixed_to_double(value); | ||
231 | if (amt == 0.0) { | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | // last doesn't actually need initialization, | ||
236 | // but gcc (7.3.1) is too dumb to figure it out | ||
237 | struct swaybar_workspace *first = NULL; | ||
238 | struct swaybar_workspace *active = NULL; | ||
239 | struct swaybar_workspace *last = NULL; | ||
240 | |||
241 | struct swaybar_workspace *iter; | ||
242 | wl_list_for_each(iter, &output->workspaces, link) { | ||
243 | if (!first) { | ||
244 | first = iter; | ||
245 | } | ||
246 | |||
247 | if (iter->visible) { | ||
248 | active = iter; | ||
249 | } | ||
250 | |||
251 | last = iter; | ||
252 | } | ||
253 | |||
254 | if (!sway_assert(active, "axis with null workspace")) { | ||
255 | return; | ||
256 | } | ||
257 | |||
258 | struct swaybar_workspace *new; | ||
259 | |||
260 | if (amt > 0.0) { | ||
261 | if (active == first) { | ||
262 | if (!bar->config->wrap_scroll) { | ||
263 | return; | ||
264 | } | ||
265 | new = last; | ||
266 | } | ||
267 | |||
268 | new = wl_container_of(active->link.prev, new, link); | ||
269 | } else { | ||
270 | if (active == last) { | ||
271 | if (!bar->config->wrap_scroll) { | ||
272 | return; | ||
273 | } | ||
274 | new = first; | ||
275 | } | ||
276 | |||
277 | new = wl_container_of(active->link.next, new, link); | ||
278 | } | ||
279 | |||
280 | ipc_send_workspace_command(bar, new->name); | ||
281 | |||
282 | // Check button release bindings | ||
283 | check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
284 | WL_POINTER_BUTTON_STATE_RELEASED); | ||
285 | } | ||
286 | |||
287 | static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { | ||
288 | // Who cares | ||
289 | } | ||
290 | |||
291 | static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, | ||
292 | uint32_t axis_source) { | ||
293 | // Who cares | ||
294 | } | ||
295 | |||
296 | static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, | ||
297 | uint32_t time, uint32_t axis) { | ||
298 | // Who cares | ||
299 | } | ||
300 | |||
301 | static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, | ||
302 | uint32_t axis, int32_t discrete) { | ||
303 | // Who cares | ||
304 | } | ||
305 | |||
306 | struct wl_pointer_listener pointer_listener = { | ||
307 | .enter = wl_pointer_enter, | ||
308 | .leave = wl_pointer_leave, | ||
309 | .motion = wl_pointer_motion, | ||
310 | .button = wl_pointer_button, | ||
311 | .axis = wl_pointer_axis, | ||
312 | .frame = wl_pointer_frame, | ||
313 | .axis_source = wl_pointer_axis_source, | ||
314 | .axis_stop = wl_pointer_axis_stop, | ||
315 | .axis_discrete = wl_pointer_axis_discrete, | ||
316 | }; | ||
317 | |||
318 | static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, | ||
319 | enum wl_seat_capability caps) { | ||
320 | struct swaybar *bar = data; | ||
321 | if (bar->pointer.pointer != NULL) { | ||
322 | wl_pointer_release(bar->pointer.pointer); | ||
323 | bar->pointer.pointer = NULL; | ||
324 | } | ||
325 | if ((caps & WL_SEAT_CAPABILITY_POINTER)) { | ||
326 | bar->pointer.pointer = wl_seat_get_pointer(wl_seat); | ||
327 | wl_pointer_add_listener(bar->pointer.pointer, &pointer_listener, bar); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | static void seat_handle_name(void *data, struct wl_seat *wl_seat, | ||
332 | const char *name) { | ||
333 | // Who cares | ||
334 | } | ||
335 | |||
336 | const struct wl_seat_listener seat_listener = { | ||
337 | .capabilities = seat_handle_capabilities, | ||
338 | .name = seat_handle_name, | ||
339 | }; | ||
340 | |||
341 | static void add_layer_surface(struct swaybar_output *output) { | 95 | static void add_layer_surface(struct swaybar_output *output) { |
342 | if (output->layer_surface) { | 96 | if (output->layer_surface) { |
343 | return; | 97 | return; |
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 1d754808..3ea74e13 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "swaybar/bar.h" | 9 | #include "swaybar/bar.h" |
10 | #include "swaybar/config.h" | 10 | #include "swaybar/config.h" |
11 | #include "swaybar/i3bar.h" | 11 | #include "swaybar/i3bar.h" |
12 | #include "swaybar/input.h" | ||
12 | #include "swaybar/status_line.h" | 13 | #include "swaybar/status_line.h" |
13 | 14 | ||
14 | void i3bar_block_unref(struct i3bar_block *block) { | 15 | void i3bar_block_unref(struct i3bar_block *block) { |
@@ -284,32 +285,3 @@ enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, | |||
284 | json_object_put(event_json); | 285 | json_object_put(event_json); |
285 | return HOTSPOT_IGNORE; | 286 | return HOTSPOT_IGNORE; |
286 | } | 287 | } |
287 | |||
288 | enum x11_button wl_button_to_x11_button(uint32_t button) { | ||
289 | switch (button) { | ||
290 | case BTN_LEFT: | ||
291 | return LEFT; | ||
292 | case BTN_MIDDLE: | ||
293 | return MIDDLE; | ||
294 | case BTN_RIGHT: | ||
295 | return RIGHT; | ||
296 | case BTN_SIDE: | ||
297 | return BACK; | ||
298 | case BTN_EXTRA: | ||
299 | return FORWARD; | ||
300 | default: | ||
301 | return NONE; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value) { | ||
306 | switch (axis) { | ||
307 | case WL_POINTER_AXIS_VERTICAL_SCROLL: | ||
308 | return wl_fixed_to_double(value) < 0 ? SCROLL_UP : SCROLL_DOWN; | ||
309 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: | ||
310 | return wl_fixed_to_double(value) < 0 ? SCROLL_LEFT : SCROLL_RIGHT; | ||
311 | default: | ||
312 | wlr_log(WLR_DEBUG, "Unexpected axis value on mouse scroll"); | ||
313 | return NONE; | ||
314 | } | ||
315 | } | ||
diff --git a/swaybar/input.c b/swaybar/input.c new file mode 100644 index 00000000..31137f44 --- /dev/null +++ b/swaybar/input.c | |||
@@ -0,0 +1,286 @@ | |||
1 | #include <assert.h> | ||
2 | #ifdef __FreeBSD__ | ||
3 | #include <dev/evdev/input-event-codes.h> | ||
4 | #else | ||
5 | #include <linux/input-event-codes.h> | ||
6 | #endif | ||
7 | #include <wayland-client.h> | ||
8 | #include <wayland-cursor.h> | ||
9 | #include <wlr/util/log.h> | ||
10 | #include "list.h" | ||
11 | #include "log.h" | ||
12 | #include "swaybar/bar.h" | ||
13 | #include "swaybar/config.h" | ||
14 | #include "swaybar/input.h" | ||
15 | #include "swaybar/ipc.h" | ||
16 | |||
17 | void free_hotspots(struct wl_list *list) { | ||
18 | struct swaybar_hotspot *hotspot, *tmp; | ||
19 | wl_list_for_each_safe(hotspot, tmp, list, link) { | ||
20 | wl_list_remove(&hotspot->link); | ||
21 | if (hotspot->destroy) { | ||
22 | hotspot->destroy(hotspot->data); | ||
23 | } | ||
24 | free(hotspot); | ||
25 | } | ||
26 | } | ||
27 | |||
28 | static enum x11_button wl_button_to_x11_button(uint32_t button) { | ||
29 | switch (button) { | ||
30 | case BTN_LEFT: | ||
31 | return LEFT; | ||
32 | case BTN_MIDDLE: | ||
33 | return MIDDLE; | ||
34 | case BTN_RIGHT: | ||
35 | return RIGHT; | ||
36 | case BTN_SIDE: | ||
37 | return BACK; | ||
38 | case BTN_EXTRA: | ||
39 | return FORWARD; | ||
40 | default: | ||
41 | return NONE; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | static enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value) { | ||
46 | switch (axis) { | ||
47 | case WL_POINTER_AXIS_VERTICAL_SCROLL: | ||
48 | return wl_fixed_to_double(value) < 0 ? SCROLL_UP : SCROLL_DOWN; | ||
49 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: | ||
50 | return wl_fixed_to_double(value) < 0 ? SCROLL_LEFT : SCROLL_RIGHT; | ||
51 | default: | ||
52 | wlr_log(WLR_DEBUG, "Unexpected axis value on mouse scroll"); | ||
53 | return NONE; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, | ||
58 | uint32_t serial, struct wl_surface *surface, | ||
59 | wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||
60 | struct swaybar *bar = data; | ||
61 | struct swaybar_pointer *pointer = &bar->pointer; | ||
62 | struct swaybar_output *output; | ||
63 | wl_list_for_each(output, &bar->outputs, link) { | ||
64 | if (output->surface == surface) { | ||
65 | pointer->current = output; | ||
66 | break; | ||
67 | } | ||
68 | } | ||
69 | int max_scale = 1; | ||
70 | struct swaybar_output *_output; | ||
71 | wl_list_for_each(_output, &bar->outputs, link) { | ||
72 | if (_output->scale > max_scale) { | ||
73 | max_scale = _output->scale; | ||
74 | } | ||
75 | } | ||
76 | wl_surface_set_buffer_scale(pointer->cursor_surface, max_scale); | ||
77 | wl_surface_attach(pointer->cursor_surface, | ||
78 | wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); | ||
79 | wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, | ||
80 | pointer->cursor_image->hotspot_x / max_scale, | ||
81 | pointer->cursor_image->hotspot_y / max_scale); | ||
82 | wl_surface_commit(pointer->cursor_surface); | ||
83 | } | ||
84 | |||
85 | static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, | ||
86 | uint32_t serial, struct wl_surface *surface) { | ||
87 | struct swaybar *bar = data; | ||
88 | bar->pointer.current = NULL; | ||
89 | } | ||
90 | |||
91 | static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | ||
92 | uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||
93 | struct swaybar *bar = data; | ||
94 | bar->pointer.x = wl_fixed_to_int(surface_x); | ||
95 | bar->pointer.y = wl_fixed_to_int(surface_y); | ||
96 | } | ||
97 | |||
98 | static bool check_bindings(struct swaybar *bar, uint32_t x11_button, | ||
99 | uint32_t state) { | ||
100 | bool released = state == WL_POINTER_BUTTON_STATE_RELEASED; | ||
101 | for (int i = 0; i < bar->config->bindings->length; i++) { | ||
102 | struct swaybar_binding *binding = bar->config->bindings->items[i]; | ||
103 | if (binding->button == x11_button && binding->release == released) { | ||
104 | ipc_execute_binding(bar, binding); | ||
105 | return true; | ||
106 | } | ||
107 | } | ||
108 | return false; | ||
109 | } | ||
110 | |||
111 | static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | ||
112 | uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { | ||
113 | struct swaybar *bar = data; | ||
114 | struct swaybar_pointer *pointer = &bar->pointer; | ||
115 | struct swaybar_output *output = pointer->current; | ||
116 | if (!sway_assert(output, "button with no active output")) { | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | if (check_bindings(bar, wl_button_to_x11_button(button), state)) { | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | if (state != WL_POINTER_BUTTON_STATE_PRESSED) { | ||
125 | return; | ||
126 | } | ||
127 | struct swaybar_hotspot *hotspot; | ||
128 | wl_list_for_each(hotspot, &output->hotspots, link) { | ||
129 | double x = pointer->x * output->scale; | ||
130 | double y = pointer->y * output->scale; | ||
131 | if (x >= hotspot->x | ||
132 | && y >= hotspot->y | ||
133 | && x < hotspot->x + hotspot->width | ||
134 | && y < hotspot->y + hotspot->height) { | ||
135 | if (HOTSPOT_IGNORE == hotspot->callback(output, pointer->x, pointer->y, | ||
136 | wl_button_to_x11_button(button), hotspot->data)) { | ||
137 | return; | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | ||
144 | uint32_t time, uint32_t axis, wl_fixed_t value) { | ||
145 | struct swaybar *bar = data; | ||
146 | struct swaybar_pointer *pointer = &bar->pointer; | ||
147 | struct swaybar_output *output = pointer->current; | ||
148 | if (!sway_assert(output, "axis with no active output")) { | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | // If there is a button press binding, execute it, skip default behavior, | ||
153 | // and check button release bindings | ||
154 | if (check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
155 | WL_POINTER_BUTTON_STATE_PRESSED)) { | ||
156 | check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
157 | WL_POINTER_BUTTON_STATE_RELEASED); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | struct swaybar_hotspot *hotspot; | ||
162 | wl_list_for_each(hotspot, &output->hotspots, link) { | ||
163 | double x = pointer->x * output->scale; | ||
164 | double y = pointer->y * output->scale; | ||
165 | if (x >= hotspot->x | ||
166 | && y >= hotspot->y | ||
167 | && x < hotspot->x + hotspot->width | ||
168 | && y < hotspot->y + hotspot->height) { | ||
169 | if (HOTSPOT_IGNORE == hotspot->callback( | ||
170 | output, pointer->x, pointer->y, | ||
171 | wl_axis_to_x11_button(axis, value), hotspot->data)) { | ||
172 | return; | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | double amt = wl_fixed_to_double(value); | ||
178 | if (amt == 0.0) { | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | // last doesn't actually need initialization, | ||
183 | // but gcc (7.3.1) is too dumb to figure it out | ||
184 | struct swaybar_workspace *first = NULL; | ||
185 | struct swaybar_workspace *active = NULL; | ||
186 | struct swaybar_workspace *last = NULL; | ||
187 | |||
188 | struct swaybar_workspace *iter; | ||
189 | wl_list_for_each(iter, &output->workspaces, link) { | ||
190 | if (!first) { | ||
191 | first = iter; | ||
192 | } | ||
193 | |||
194 | if (iter->visible) { | ||
195 | active = iter; | ||
196 | } | ||
197 | |||
198 | last = iter; | ||
199 | } | ||
200 | |||
201 | if (!sway_assert(active, "axis with null workspace")) { | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | struct swaybar_workspace *new; | ||
206 | |||
207 | if (amt > 0.0) { | ||
208 | if (active == first) { | ||
209 | if (!bar->config->wrap_scroll) { | ||
210 | return; | ||
211 | } | ||
212 | new = last; | ||
213 | } | ||
214 | |||
215 | new = wl_container_of(active->link.prev, new, link); | ||
216 | } else { | ||
217 | if (active == last) { | ||
218 | if (!bar->config->wrap_scroll) { | ||
219 | return; | ||
220 | } | ||
221 | new = first; | ||
222 | } | ||
223 | |||
224 | new = wl_container_of(active->link.next, new, link); | ||
225 | } | ||
226 | |||
227 | ipc_send_workspace_command(bar, new->name); | ||
228 | |||
229 | // Check button release bindings | ||
230 | check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
231 | WL_POINTER_BUTTON_STATE_RELEASED); | ||
232 | } | ||
233 | |||
234 | static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { | ||
235 | // Who cares | ||
236 | } | ||
237 | |||
238 | static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, | ||
239 | uint32_t axis_source) { | ||
240 | // Who cares | ||
241 | } | ||
242 | |||
243 | static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, | ||
244 | uint32_t time, uint32_t axis) { | ||
245 | // Who cares | ||
246 | } | ||
247 | |||
248 | static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, | ||
249 | uint32_t axis, int32_t discrete) { | ||
250 | // Who cares | ||
251 | } | ||
252 | |||
253 | struct wl_pointer_listener pointer_listener = { | ||
254 | .enter = wl_pointer_enter, | ||
255 | .leave = wl_pointer_leave, | ||
256 | .motion = wl_pointer_motion, | ||
257 | .button = wl_pointer_button, | ||
258 | .axis = wl_pointer_axis, | ||
259 | .frame = wl_pointer_frame, | ||
260 | .axis_source = wl_pointer_axis_source, | ||
261 | .axis_stop = wl_pointer_axis_stop, | ||
262 | .axis_discrete = wl_pointer_axis_discrete, | ||
263 | }; | ||
264 | |||
265 | static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, | ||
266 | enum wl_seat_capability caps) { | ||
267 | struct swaybar *bar = data; | ||
268 | if (bar->pointer.pointer != NULL) { | ||
269 | wl_pointer_release(bar->pointer.pointer); | ||
270 | bar->pointer.pointer = NULL; | ||
271 | } | ||
272 | if ((caps & WL_SEAT_CAPABILITY_POINTER)) { | ||
273 | bar->pointer.pointer = wl_seat_get_pointer(wl_seat); | ||
274 | wl_pointer_add_listener(bar->pointer.pointer, &pointer_listener, bar); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | static void seat_handle_name(void *data, struct wl_seat *wl_seat, | ||
279 | const char *name) { | ||
280 | // Who cares | ||
281 | } | ||
282 | |||
283 | const struct wl_seat_listener seat_listener = { | ||
284 | .capabilities = seat_handle_capabilities, | ||
285 | .name = seat_handle_name, | ||
286 | }; | ||
diff --git a/swaybar/meson.build b/swaybar/meson.build index 0c116172..c27cf2c2 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build | |||
@@ -3,6 +3,7 @@ executable( | |||
3 | 'bar.c', | 3 | 'bar.c', |
4 | 'config.c', | 4 | 'config.c', |
5 | 'i3bar.c', | 5 | 'i3bar.c', |
6 | 'input.c', | ||
6 | 'ipc.c', | 7 | 'ipc.c', |
7 | 'main.c', | 8 | 'main.c', |
8 | 'render.c', | 9 | 'render.c', |