mirror of
https://github.com/swaywm/sway.git
synced 2024-11-28 10:51:28 +00:00
swaybar: add bindgesture support
Co-authored-by: Michael Weiser <michael.weiser@gmx.de>
This commit is contained in:
parent
b896841824
commit
2e64eeda42
|
@ -6,6 +6,7 @@
|
|||
#include "pool-buffer.h"
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
|
||||
struct swaybar_config;
|
||||
struct swaybar_output;
|
||||
|
@ -31,6 +32,7 @@ struct swaybar {
|
|||
struct zwlr_layer_shell_v1 *layer_shell;
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||
struct wl_shm *shm;
|
||||
struct zwp_pointer_gestures_v1 *pointer_gestures;
|
||||
|
||||
struct swaybar_config *config;
|
||||
struct status_line *status;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdint.h>
|
||||
#include <wayland-client.h>
|
||||
#include "../include/config.h"
|
||||
#include "gesture.h"
|
||||
#include "list.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -24,6 +25,11 @@ struct swaybar_binding {
|
|||
bool release;
|
||||
};
|
||||
|
||||
struct swaybar_gesture {
|
||||
struct gesture gesture;
|
||||
char *command;
|
||||
};
|
||||
|
||||
struct swaybar_config {
|
||||
char *status_command;
|
||||
bool pango_markup;
|
||||
|
@ -40,6 +46,7 @@ struct swaybar_config {
|
|||
bool workspace_buttons;
|
||||
uint32_t workspace_min_width;
|
||||
list_t *bindings;
|
||||
list_t *gestures;
|
||||
struct wl_list outputs; // config_output::link
|
||||
int height;
|
||||
int status_padding;
|
||||
|
@ -90,5 +97,6 @@ struct swaybar_config *init_config(void);
|
|||
void free_config(struct swaybar_config *config);
|
||||
uint32_t parse_position(const char *position);
|
||||
void free_binding(struct swaybar_binding *binding);
|
||||
void free_gesture(struct swaybar_gesture *gesture);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <wayland-client.h>
|
||||
#include <stdbool.h>
|
||||
#include "gesture.h"
|
||||
#include "list.h"
|
||||
|
||||
#define SWAY_SCROLL_UP KEY_MAX + 1
|
||||
|
@ -66,6 +67,10 @@ struct swaybar_seat {
|
|||
struct wl_seat *wl_seat;
|
||||
struct swaybar_pointer pointer;
|
||||
struct swaybar_touch touch;
|
||||
struct zwp_pointer_gesture_hold_v1 *hold;
|
||||
struct zwp_pointer_gesture_pinch_v1 *pinch;
|
||||
struct zwp_pointer_gesture_swipe_v1 *swipe;
|
||||
struct gesture_tracker gestures;
|
||||
struct wl_list link; // swaybar_seat:link
|
||||
struct swaybar_scroll_axis axis[2];
|
||||
};
|
||||
|
|
|
@ -8,5 +8,6 @@ bool handle_ipc_readable(struct swaybar *bar);
|
|||
bool ipc_get_workspaces(struct swaybar *bar);
|
||||
void ipc_send_workspace_command(struct swaybar *bar, const char *ws);
|
||||
void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind);
|
||||
void ipc_execute_gesture(struct swaybar *bar, struct swaybar_gesture *gest);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,7 @@ protocols = [
|
|||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml'],
|
||||
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
|
@ -25,6 +26,7 @@ protocols = [
|
|||
client_protocols = [
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['wlr-input-inhibitor-unstable-v1.xml'],
|
||||
]
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "pool-buffer.h"
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
|
||||
void free_workspaces(struct wl_list *list) {
|
||||
struct swaybar_workspace *ws, *tmp;
|
||||
|
@ -362,6 +363,9 @@ static void handle_global(void *data, struct wl_registry *registry,
|
|||
} else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
|
||||
bar->xdg_output_manager = wl_registry_bind(registry, name,
|
||||
&zxdg_output_manager_v1_interface, 2);
|
||||
} else if (strcmp(interface, zwp_pointer_gestures_v1_interface.name) == 0) {
|
||||
bar->pointer_gestures = wl_registry_bind(registry, name,
|
||||
&zwp_pointer_gestures_v1_interface, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ struct swaybar_config *init_config(void) {
|
|||
config->workspace_buttons = true;
|
||||
config->workspace_min_width = 0;
|
||||
config->bindings = create_list();
|
||||
config->gestures = create_list();
|
||||
wl_list_init(&config->outputs);
|
||||
config->status_padding = 1;
|
||||
config->status_edge_padding = 3;
|
||||
|
@ -93,6 +94,14 @@ void free_binding(struct swaybar_binding *binding) {
|
|||
free(binding);
|
||||
}
|
||||
|
||||
void free_gesture(struct swaybar_gesture *gesture) {
|
||||
if (!gesture) {
|
||||
return;
|
||||
}
|
||||
free(gesture->command);
|
||||
free(gesture);
|
||||
}
|
||||
|
||||
#if HAVE_TRAY
|
||||
void free_tray_binding(struct tray_binding *binding) {
|
||||
if (!binding) {
|
||||
|
@ -114,6 +123,11 @@ void free_config(struct swaybar_config *config) {
|
|||
free_binding(binding);
|
||||
}
|
||||
list_free(config->bindings);
|
||||
for (int i = 0; i < config->gestures->length; i++) {
|
||||
struct swaybar_gesture *gesture = config->gestures->items[i];
|
||||
free_gesture(gesture);
|
||||
}
|
||||
list_free(config->gestures);
|
||||
struct config_output *coutput, *tmp;
|
||||
wl_list_for_each_safe(coutput, tmp, &config->outputs, link) {
|
||||
wl_list_remove(&coutput->link);
|
||||
|
|
198
swaybar/input.c
198
swaybar/input.c
|
@ -9,6 +9,7 @@
|
|||
#include "swaybar/config.h"
|
||||
#include "swaybar/input.h"
|
||||
#include "swaybar/ipc.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
|
||||
void free_hotspots(struct wl_list *list) {
|
||||
struct swaybar_hotspot *hotspot, *tmp;
|
||||
|
@ -118,6 +119,11 @@ static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
|
|||
uint32_t serial, struct wl_surface *surface) {
|
||||
struct swaybar_seat *seat = data;
|
||||
seat->pointer.current = NULL;
|
||||
|
||||
// Cancel any ongoing gesture if pointer leaves bar
|
||||
if(!gesture_tracker_check(&seat->gestures, GESTURE_TYPE_NONE)) {
|
||||
gesture_tracker_cancel(&seat->gestures);
|
||||
}
|
||||
}
|
||||
|
||||
static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
|
||||
|
@ -461,6 +467,174 @@ static const struct wl_touch_listener touch_listener = {
|
|||
.orientation = wl_touch_orientation,
|
||||
};
|
||||
|
||||
|
||||
static bool gesture_on_bar(struct swaybar_seat *seat,
|
||||
struct wl_surface *surface) {
|
||||
struct swaybar_output *output;
|
||||
|
||||
wl_list_for_each(output, &seat->bar->outputs, link) {
|
||||
if (output->surface == surface) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if bar has any binding for gesture
|
||||
static bool bar_gestures_check(struct swaybar *bar,
|
||||
enum gesture_type type, uint8_t fingers) {
|
||||
for (int i = 0; i < bar->config->gestures->length; i++) {
|
||||
struct swaybar_gesture *binding = bar->config->gestures->items[i];
|
||||
if (gesture_check(&binding->gesture, type, fingers)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check bar gesture binding for match
|
||||
static struct swaybar_gesture *bar_gestures_match(struct swaybar *bar,
|
||||
struct gesture *gesture) {
|
||||
struct swaybar_gesture *current = NULL;
|
||||
|
||||
for (int i = 0; i < bar->config->gestures->length; i++) {
|
||||
struct swaybar_gesture *binding = bar->config->gestures->items[i];
|
||||
if (gesture_match(&binding->gesture, gesture, false)) {
|
||||
if (current &&
|
||||
gesture_compare(¤t->gesture, &binding->gesture) < 0) {
|
||||
continue;
|
||||
}
|
||||
current = binding;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
static void gesture_begin(struct swaybar_seat* seat, struct wl_surface *surface,
|
||||
enum gesture_type type, uint8_t fingers) {
|
||||
// We only want to respond to holds on a bar surface
|
||||
if (!gesture_on_bar(seat, surface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure there is a binding for this gesture
|
||||
if (!bar_gestures_check(seat->bar, type, fingers)) {
|
||||
sway_log(SWAY_DEBUG, "Ignore tracking gesture without binding: %s:%u:any",
|
||||
gesture_type_string(type), fingers);
|
||||
return;
|
||||
}
|
||||
|
||||
gesture_tracker_begin(&seat->gestures, type, fingers);
|
||||
}
|
||||
|
||||
static void gesture_end(struct swaybar_seat* seat, enum gesture_type type,
|
||||
bool cancelled) {
|
||||
|
||||
if (!gesture_tracker_check(&seat->gestures, type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cancelled) {
|
||||
gesture_tracker_cancel(&seat->gestures);
|
||||
return;
|
||||
}
|
||||
|
||||
struct gesture *gesture = gesture_tracker_end(&seat->gestures);
|
||||
struct swaybar_gesture* binding = bar_gestures_match(seat->bar, gesture);
|
||||
|
||||
if (binding) {
|
||||
ipc_execute_gesture(seat->bar, binding);
|
||||
}
|
||||
}
|
||||
|
||||
static void hold_begin(void *data, struct zwp_pointer_gesture_hold_v1 *wl_hold,
|
||||
uint32_t serial, uint32_t time,struct wl_surface *surface,
|
||||
uint32_t fingers) {
|
||||
struct swaybar_seat *seat = data;
|
||||
gesture_begin(seat, surface, GESTURE_TYPE_HOLD, fingers);
|
||||
}
|
||||
|
||||
static void hold_end(void *data,
|
||||
struct zwp_pointer_gesture_hold_v1 *wl_hold,
|
||||
uint32_t serial, uint32_t time, int32_t cancelled) {
|
||||
struct swaybar_seat *seat = data;
|
||||
gesture_end(seat, GESTURE_TYPE_HOLD, cancelled);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_hold_v1_listener hold_listener = {
|
||||
.begin = hold_begin,
|
||||
.end = hold_end,
|
||||
};
|
||||
|
||||
static void pinch_begin(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *wl_pinch, uint32_t serial,
|
||||
uint32_t time, struct wl_surface *surface, uint32_t fingers) {
|
||||
struct swaybar_seat *seat = data;
|
||||
gesture_begin(seat, surface, GESTURE_TYPE_PINCH, fingers);
|
||||
}
|
||||
|
||||
static void pinch_update(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *wl_pinch,
|
||||
uint32_t time, wl_fixed_t dx, wl_fixed_t dy,
|
||||
wl_fixed_t scale, wl_fixed_t rotation) {
|
||||
struct swaybar_seat *seat = data;
|
||||
if (gesture_tracker_check(&seat->gestures, GESTURE_TYPE_PINCH)) {
|
||||
gesture_tracker_update(&seat->gestures,
|
||||
wl_fixed_to_double(dx), wl_fixed_to_double(dy),
|
||||
wl_fixed_to_double(scale),
|
||||
wl_fixed_to_double(rotation));
|
||||
}
|
||||
}
|
||||
|
||||
static void pinch_end(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *wl_pinch,
|
||||
uint32_t serial, uint32_t time, int32_t cancelled) {
|
||||
struct swaybar_seat *seat = data;
|
||||
gesture_end(seat, GESTURE_TYPE_PINCH, cancelled);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_pinch_v1_listener pinch_listener = {
|
||||
.begin = pinch_begin,
|
||||
.update = pinch_update,
|
||||
.end = pinch_end,
|
||||
};
|
||||
|
||||
static void swipe_begin(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *wl_swipe,
|
||||
uint32_t serial, uint32_t time,
|
||||
struct wl_surface *surface, uint32_t fingers) {
|
||||
struct swaybar_seat *seat = data;
|
||||
gesture_begin(seat, surface, GESTURE_TYPE_SWIPE, fingers);
|
||||
}
|
||||
|
||||
static void swipe_update(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *wl_swipe,
|
||||
uint32_t time, wl_fixed_t dx, wl_fixed_t dy) {
|
||||
struct swaybar_seat *seat = data;
|
||||
if (gesture_tracker_check(&seat->gestures, GESTURE_TYPE_SWIPE)) {
|
||||
gesture_tracker_update(&seat->gestures,
|
||||
wl_fixed_to_double(dx), wl_fixed_to_double(dy),
|
||||
NAN, NAN);
|
||||
}
|
||||
}
|
||||
|
||||
static void swipe_end(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1,
|
||||
uint32_t serial, uint32_t time, int32_t cancelled) {
|
||||
struct swaybar_seat *seat = data;
|
||||
gesture_end(seat, GESTURE_TYPE_SWIPE, cancelled);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_swipe_v1_listener swipe_listener = {
|
||||
.begin = swipe_begin,
|
||||
.update = swipe_update,
|
||||
.end = swipe_end,
|
||||
};
|
||||
|
||||
|
||||
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
||||
enum wl_seat_capability caps) {
|
||||
struct swaybar_seat *seat = data;
|
||||
|
@ -479,6 +653,21 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
|||
assert(seat->pointer.cursor_surface);
|
||||
}
|
||||
wl_pointer_add_listener(seat->pointer.pointer, &pointer_listener, seat);
|
||||
|
||||
seat->hold = zwp_pointer_gestures_v1_get_hold_gesture(
|
||||
seat->bar->pointer_gestures, seat->pointer.pointer);
|
||||
zwp_pointer_gesture_hold_v1_add_listener(seat->hold,
|
||||
&hold_listener, seat);
|
||||
|
||||
seat->pinch = zwp_pointer_gestures_v1_get_pinch_gesture(
|
||||
seat->bar->pointer_gestures, seat->pointer.pointer);
|
||||
zwp_pointer_gesture_pinch_v1_add_listener(seat->pinch,
|
||||
&pinch_listener, seat);
|
||||
|
||||
seat->swipe = zwp_pointer_gestures_v1_get_swipe_gesture(
|
||||
seat->bar->pointer_gestures, seat->pointer.pointer);
|
||||
zwp_pointer_gesture_swipe_v1_add_listener(seat->swipe,
|
||||
&swipe_listener, seat);
|
||||
}
|
||||
if (!have_touch && seat->touch.touch != NULL) {
|
||||
wl_touch_release(seat->touch.touch);
|
||||
|
@ -515,6 +704,15 @@ void swaybar_seat_free(struct swaybar_seat *seat) {
|
|||
if (seat->touch.touch != NULL) {
|
||||
wl_touch_release(seat->touch.touch);
|
||||
}
|
||||
if (seat->hold != NULL) {
|
||||
zwp_pointer_gesture_hold_v1_destroy(seat->hold);
|
||||
}
|
||||
if (seat->pinch != NULL) {
|
||||
zwp_pointer_gesture_pinch_v1_destroy(seat->pinch);
|
||||
}
|
||||
if (seat->swipe != NULL) {
|
||||
zwp_pointer_gesture_swipe_v1_destroy(seat->swipe);
|
||||
}
|
||||
wl_seat_destroy(seat->wl_seat);
|
||||
wl_list_remove(&seat->link);
|
||||
free(seat);
|
||||
|
|
|
@ -140,6 +140,30 @@ static bool ipc_parse_config(
|
|||
}
|
||||
}
|
||||
|
||||
json_object *gestures = json_object_object_get(bar_config, "gestures");
|
||||
while (config->gestures->length) {
|
||||
struct swaybar_gesture *binding = config->gestures->items[0];
|
||||
list_del(config->gestures, 0);
|
||||
free_gesture(binding);
|
||||
}
|
||||
if (gestures) {
|
||||
int length = json_object_array_length(gestures);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
json_object *bindobj = json_object_array_get_idx(gestures, i);
|
||||
struct swaybar_gesture *binding =
|
||||
calloc(1, sizeof(struct swaybar_gesture));
|
||||
binding->gesture.type = json_object_get_int(
|
||||
json_object_object_get(bindobj, "type"));
|
||||
binding->gesture.fingers = json_object_get_int(
|
||||
json_object_object_get(bindobj, "fingers"));
|
||||
binding->gesture.directions = json_object_get_int(
|
||||
json_object_object_get(bindobj, "directions"));
|
||||
binding->command = strdup(json_object_get_string(
|
||||
json_object_object_get(bindobj, "command")));
|
||||
list_add(config->gestures, binding);
|
||||
}
|
||||
}
|
||||
|
||||
json_object *colors = json_object_object_get(bar_config, "colors");
|
||||
if (colors) {
|
||||
ipc_parse_colors(config, colors);
|
||||
|
@ -414,6 +438,16 @@ void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) {
|
|||
IPC_COMMAND, bind->command, &len));
|
||||
}
|
||||
|
||||
void ipc_execute_gesture(struct swaybar *bar, struct swaybar_gesture *bind) {
|
||||
char *description = gesture_to_string(&bind->gesture);
|
||||
sway_log(SWAY_DEBUG, "Executing binding for gesture %s: `%s`",
|
||||
description, bind->command);
|
||||
free(description);
|
||||
uint32_t len = strlen(bind->command);
|
||||
free(ipc_single_command(bar->ipc_socketfd,
|
||||
IPC_COMMAND, bind->command, &len));
|
||||
}
|
||||
|
||||
bool ipc_initialize(struct swaybar *bar) {
|
||||
uint32_t len = strlen(bar->id);
|
||||
char *res = ipc_single_command(bar->ipc_socketfd,
|
||||
|
|
Loading…
Reference in a new issue