Moved to bindworkspacegesture instead of bindgesture
This commit is contained in:
parent
067613854b
commit
3480479f17
|
@ -50,8 +50,6 @@ char *gesture_parse(const char *input, struct gesture *output) {
|
|||
output->type = GESTURE_TYPE_PINCH;
|
||||
} else if (strcmp(split->items[0], "swipe") == 0) {
|
||||
output->type = GESTURE_TYPE_SWIPE;
|
||||
} else if (strcmp(split->items[0], "workspace_swipe") == 0) {
|
||||
output->type = GESTURE_TYPE_WORKSPACE_SWIPE;
|
||||
} else {
|
||||
return strformat("expected hold|pinch|swipe, got %s",
|
||||
split->items[0]);
|
||||
|
@ -96,10 +94,58 @@ char *gesture_parse(const char *input, struct gesture *output) {
|
|||
output->directions |= GESTURE_DIRECTION_CLOCKWISE;
|
||||
} else if (strcmp(item, "counterclockwise") == 0) {
|
||||
output->directions |= GESTURE_DIRECTION_COUNTERCLOCKWISE;
|
||||
} else if (strcmp(item, "horizontal") == 0) {
|
||||
output->directions |= GESTURE_DIRECTION_HORIZONTAL;
|
||||
} else {
|
||||
return strformat("expected direction, got %s", item);
|
||||
}
|
||||
}
|
||||
list_free_items_and_destroy(directions);
|
||||
}
|
||||
} // if optional args
|
||||
|
||||
list_free_items_and_destroy(split);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *workspace_gesture_parse(const char *input, struct gesture *output) {
|
||||
// Clear output in case of failure
|
||||
output->type = GESTURE_TYPE_NONE;
|
||||
output->fingers = GESTURE_FINGERS_ANY;
|
||||
output->directions = GESTURE_DIRECTION_NONE;
|
||||
|
||||
// Split input type, fingers and directions
|
||||
list_t *split = split_string(input, ":");
|
||||
if (split->length < 1 || split->length > 3) {
|
||||
return strformat(
|
||||
"expected [:<fingers>][:direction], got %s",
|
||||
input);
|
||||
}
|
||||
|
||||
// Parse optional arguments
|
||||
if (split->length > 1) {
|
||||
char *next = split->items[1];
|
||||
|
||||
// Try to parse as finger count (1-9)
|
||||
if (strlen(next) == 1 && '1' <= next[0] && next[0] <= '9') {
|
||||
output->fingers = atoi(next);
|
||||
|
||||
// Move to next if available
|
||||
next = split->length == 3 ? split->items[2] : NULL;
|
||||
} else if (split->length == 3) {
|
||||
// Fail here if argument can only be finger count
|
||||
return strformat("expected 1-9, got %s", next);
|
||||
}
|
||||
|
||||
// If there is an argument left, try to parse as direction
|
||||
if (next) {
|
||||
list_t *directions = split_string(next, "+");
|
||||
|
||||
for (int i = 0; i < directions->length; ++i) {
|
||||
const char *item = directions->items[i];
|
||||
if (strcmp(item, "horizontal") == 0) {
|
||||
output->type = GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL;
|
||||
} else if (strcmp(item, "vertical") == 0) {
|
||||
output->directions |= GESTURE_DIRECTION_VERTICAL;
|
||||
output->type = GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL;
|
||||
} else {
|
||||
return strformat("expected direction, got %s", item);
|
||||
}
|
||||
|
@ -123,22 +169,15 @@ const char *gesture_type_string(enum gesture_type type) {
|
|||
return "pinch";
|
||||
case GESTURE_TYPE_SWIPE:
|
||||
return "swipe";
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE:
|
||||
return "workspace_swipe";
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||
return "workspace_swipe_horizontal";
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||
return "workspace_swipe_vertical";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int gesture_workspace_swipe_command_parse(char *cmd) {
|
||||
if (strcmp(cmd, "normal") == 0) {
|
||||
return -1;
|
||||
} else if (strcmp(cmd, "inverted") == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *gesture_direction_string(enum gesture_direction direction) {
|
||||
switch (direction) {
|
||||
case GESTURE_DIRECTION_NONE:
|
||||
|
@ -159,10 +198,6 @@ const char *gesture_direction_string(enum gesture_direction direction) {
|
|||
return "clockwise";
|
||||
case GESTURE_DIRECTION_COUNTERCLOCKWISE:
|
||||
return "counterclockwise";
|
||||
case GESTURE_DIRECTION_HORIZONTAL:
|
||||
return "horizontal";
|
||||
case GESTURE_DIRECTION_VERTICAL:
|
||||
return "vertical";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -335,13 +370,6 @@ struct gesture *gesture_tracker_end(struct gesture_tracker *tracker) {
|
|||
}
|
||||
__attribute__ ((fallthrough));
|
||||
// Gestures with dx and dy
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE:
|
||||
if (fabs(tracker->dx) > fabs(tracker->dy)) {
|
||||
result->directions |= GESTURE_DIRECTION_HORIZONTAL;
|
||||
} else {
|
||||
result->directions |= GESTURE_DIRECTION_VERTICAL;
|
||||
}
|
||||
__attribute__ ((fallthrough));
|
||||
case GESTURE_TYPE_SWIPE:
|
||||
if (fabs(tracker->dx) > fabs(tracker->dy)) {
|
||||
if (tracker->dx > 0) {
|
||||
|
@ -358,6 +386,8 @@ struct gesture *gesture_tracker_end(struct gesture_tracker *tracker) {
|
|||
}
|
||||
// Gesture without any direction
|
||||
case GESTURE_TYPE_HOLD:
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||
break;
|
||||
// Not tracking any gesture
|
||||
case GESTURE_TYPE_NONE:
|
||||
|
|
|
@ -12,14 +12,13 @@ enum gesture_type {
|
|||
GESTURE_TYPE_HOLD,
|
||||
GESTURE_TYPE_PINCH,
|
||||
GESTURE_TYPE_SWIPE,
|
||||
GESTURE_TYPE_WORKSPACE_SWIPE,
|
||||
GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL,
|
||||
GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL,
|
||||
};
|
||||
|
||||
// Turns single type enum value to constant string representation.
|
||||
const char *gesture_type_string(enum gesture_type direction);
|
||||
|
||||
int gesture_workspace_swipe_command_parse(char *cmd);
|
||||
|
||||
// Value to use to accept any finger count
|
||||
extern const uint8_t GESTURE_FINGERS_ANY;
|
||||
|
||||
|
@ -39,9 +38,6 @@ enum gesture_direction {
|
|||
// Directions based on rotation
|
||||
GESTURE_DIRECTION_CLOCKWISE = 1 << 6,
|
||||
GESTURE_DIRECTION_COUNTERCLOCKWISE = 1 << 7,
|
||||
// Directions for workspace swipe
|
||||
GESTURE_DIRECTION_HORIZONTAL = 1 << 8,
|
||||
GESTURE_DIRECTION_VERTICAL = 1 << 9,
|
||||
};
|
||||
|
||||
// Turns single direction enum value to constant string representation.
|
||||
|
@ -63,6 +59,13 @@ struct gesture {
|
|||
*/
|
||||
char *gesture_parse(const char *input, struct gesture *output);
|
||||
|
||||
/**
|
||||
* Parses workspace gesture from [:<fingers>][:<directions>] string.
|
||||
*
|
||||
* Return NULL on success, otherwise error message string
|
||||
*/
|
||||
char *workspace_gesture_parse(const char *input, struct gesture *output);
|
||||
|
||||
// Turns gesture into string representation
|
||||
char *gesture_to_string(struct gesture *gesture);
|
||||
|
||||
|
|
|
@ -114,6 +114,7 @@ sway_cmd cmd_bindcode;
|
|||
sway_cmd cmd_bindgesture;
|
||||
sway_cmd cmd_bindswitch;
|
||||
sway_cmd cmd_bindsym;
|
||||
sway_cmd cmd_bindworkspacegesture;
|
||||
sway_cmd cmd_blur;
|
||||
sway_cmd cmd_blur_brightness;
|
||||
sway_cmd cmd_blur_contrast;
|
||||
|
@ -223,6 +224,7 @@ sway_cmd cmd_unbindcode;
|
|||
sway_cmd cmd_unbindswitch;
|
||||
sway_cmd cmd_unbindgesture;
|
||||
sway_cmd cmd_unbindsym;
|
||||
sway_cmd cmd_unbindworkspacegesture;
|
||||
sway_cmd cmd_unmark;
|
||||
sway_cmd cmd_urgent;
|
||||
sway_cmd cmd_workspace;
|
||||
|
|
|
@ -49,6 +49,7 @@ enum binding_flags {
|
|||
BINDING_INHIBITED = 1 << 7, // keyboard only: ignore shortcut inhibitor
|
||||
BINDING_NOREPEAT = 1 << 8, // keyboard only; do not trigger when repeating a held key
|
||||
BINDING_EXACT = 1 << 9, // gesture only; only trigger on exact match
|
||||
BINDING_INVERTED = 1 << 10, // workspace gesture only; gesture is inverted
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,7 @@ static const struct cmd_handler handlers[] = {
|
|||
{ "bindgesture", cmd_bindgesture },
|
||||
{ "bindswitch", cmd_bindswitch },
|
||||
{ "bindsym", cmd_bindsym },
|
||||
{ "bindworkspacegesture", cmd_bindworkspacegesture },
|
||||
{ "blur", cmd_blur },
|
||||
{ "blur_brightness", cmd_blur_brightness },
|
||||
{ "blur_contrast", cmd_blur_contrast },
|
||||
|
@ -118,6 +119,7 @@ static const struct cmd_handler handlers[] = {
|
|||
{ "unbindgesture", cmd_unbindgesture },
|
||||
{ "unbindswitch", cmd_unbindswitch },
|
||||
{ "unbindsym", cmd_unbindsym },
|
||||
{ "unbindworkspacegesture", cmd_unbindworkspacegesture },
|
||||
{ "workspace", cmd_workspace },
|
||||
{ "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth },
|
||||
};
|
||||
|
|
|
@ -154,19 +154,6 @@ static struct cmd_results *cmd_bind_or_unbind_gesture(int argc, char **argv, boo
|
|||
return gesture_binding_remove(binding, argv[0]);
|
||||
}
|
||||
binding->command = join_args(argv + 1, argc - 1);
|
||||
// Make sure that the gesture command is valid
|
||||
switch (binding->gesture.type) {
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE:
|
||||
if (gesture_workspace_swipe_command_parse(binding->command) == 0) {
|
||||
free(binding);
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Invalid %s command (%s). Either normal or inverted",
|
||||
bindtype, errmsg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return gesture_binding_add(binding, argv[0], warn);
|
||||
}
|
||||
|
||||
|
@ -177,3 +164,76 @@ struct cmd_results *cmd_bindgesture(int argc, char **argv) {
|
|||
struct cmd_results *cmd_unbindgesture(int argc, char **argv) {
|
||||
return cmd_bind_or_unbind_gesture(argc, argv, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and execute bindgesture or unbindgesture command.
|
||||
*/
|
||||
static struct cmd_results *cmd_bind_or_unbind_workspacegesture(int argc,
|
||||
char **argv, bool unbind) {
|
||||
int minargs = 1;
|
||||
char *bindtype = "bindgesture";
|
||||
if (unbind) {
|
||||
bindtype = "unbindgesture";
|
||||
}
|
||||
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, bindtype, EXPECTED_AT_LEAST, minargs))) {
|
||||
return error;
|
||||
}
|
||||
struct sway_gesture_binding *binding = calloc(1, sizeof(struct sway_gesture_binding));
|
||||
if (!binding) {
|
||||
return cmd_results_new(CMD_FAILURE, "Unable to allocate binding");
|
||||
}
|
||||
binding->input = strdup("*");
|
||||
|
||||
bool warn = true;
|
||||
|
||||
// Handle flags
|
||||
binding->flags |= BINDING_EXACT;
|
||||
while (argc > 0) {
|
||||
if (strcmp("--inverted", argv[0]) == 0) {
|
||||
binding->flags |= BINDING_INVERTED;
|
||||
} else if (strcmp("--no-warn", argv[0]) == 0) {
|
||||
warn = false;
|
||||
} else if (strncmp("--input-device=", argv[0],
|
||||
strlen("--input-device=")) == 0) {
|
||||
free(binding->input);
|
||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (argc < minargs) {
|
||||
free(binding);
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Invalid %s command (expected at least %d "
|
||||
"non-option arguments, got %d)", bindtype, minargs, argc);
|
||||
}
|
||||
|
||||
char* errmsg = NULL;
|
||||
if ((errmsg = workspace_gesture_parse(argv[0], &binding->gesture))) {
|
||||
free(binding);
|
||||
struct cmd_results *final = cmd_results_new(CMD_FAILURE,
|
||||
"Invalid %s command (%s)",
|
||||
bindtype, errmsg);
|
||||
free(errmsg);
|
||||
return final;
|
||||
}
|
||||
|
||||
if (unbind) {
|
||||
return gesture_binding_remove(binding, argv[0]);
|
||||
}
|
||||
binding->command = NULL;
|
||||
return gesture_binding_add(binding, argv[0], warn);
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_bindworkspacegesture(int argc, char **argv) {
|
||||
return cmd_bind_or_unbind_workspacegesture(argc, argv, false);
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_unbindworkspacegesture(int argc, char **argv) {
|
||||
return cmd_bind_or_unbind_workspacegesture(argc, argv, true);
|
||||
}
|
||||
|
|
|
@ -1011,9 +1011,12 @@ static void handle_swipe_begin(struct sway_seat *seat,
|
|||
if (gesture_binding_check(bindings, GESTURE_TYPE_SWIPE, event->fingers, device)) {
|
||||
struct seatop_default_event *seatop = seat->seatop_data;
|
||||
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_SWIPE, event->fingers);
|
||||
} else if (gesture_binding_check(bindings, GESTURE_TYPE_WORKSPACE_SWIPE, event->fingers, device)) {
|
||||
} else if (gesture_binding_check(bindings, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL, event->fingers, device)) {
|
||||
struct seatop_default_event *seatop = seat->seatop_data;
|
||||
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE, event->fingers);
|
||||
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL, event->fingers);
|
||||
} else if (gesture_binding_check(bindings, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL, event->fingers, device)) {
|
||||
struct seatop_default_event *seatop = seat->seatop_data;
|
||||
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL, event->fingers);
|
||||
} else {
|
||||
// ... otherwise forward to client
|
||||
struct sway_cursor *cursor = seat->cursor;
|
||||
|
@ -1031,10 +1034,12 @@ static void handle_swipe_update(struct sway_seat *seat,
|
|||
if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) {
|
||||
gesture_tracker_update(&seatop->gestures,
|
||||
event->dx, event->dy, NAN, NAN);
|
||||
} else if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE)) {
|
||||
} else if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL) ||
|
||||
gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL)) {
|
||||
gesture_tracker_update(&seatop->gestures,
|
||||
event->dx, event->dy, NAN, NAN);
|
||||
|
||||
// Find the gesture and update the swipe percentage
|
||||
struct gesture_tracker *tracker = &seatop->gestures;
|
||||
struct sway_input_device *device =
|
||||
event->pointer ? event->pointer->base.data : NULL;
|
||||
|
@ -1046,22 +1051,24 @@ static void handle_swipe_update(struct sway_seat *seat,
|
|||
struct gesture gesture = {
|
||||
.fingers = tracker->fingers,
|
||||
.type = tracker->type,
|
||||
.directions = fabs(tracker->dx) > fabs(tracker->dy)
|
||||
? GESTURE_DIRECTION_HORIZONTAL : GESTURE_DIRECTION_VERTICAL,
|
||||
.directions = GESTURE_DIRECTION_NONE,
|
||||
};
|
||||
|
||||
struct sway_gesture_binding *binding = gesture_binding_match(
|
||||
config->current_mode->gesture_bindings, &gesture, input);
|
||||
|
||||
if (binding) {
|
||||
int invert = gesture_workspace_swipe_command_parse(binding->command);
|
||||
if ((binding->gesture.directions & GESTURE_DIRECTION_VERTICAL) ==
|
||||
GESTURE_DIRECTION_VERTICAL) {
|
||||
update_workspace_scroll_percent(seat, tracker->dy, invert,
|
||||
SWIPE_GESTURE_DIRECTION_VERTICAL);
|
||||
} else if ((binding->gesture.directions & GESTURE_DIRECTION_HORIZONTAL) ==
|
||||
GESTURE_DIRECTION_HORIZONTAL) {
|
||||
int invert = binding->flags & BINDING_INVERTED ? 1 : -1;
|
||||
switch (binding->gesture.type) {
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||
update_workspace_scroll_percent(seat, tracker->dx, invert,
|
||||
SWIPE_GESTURE_DIRECTION_HORIZONTAL);
|
||||
break;
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||
update_workspace_scroll_percent(seat, tracker->dy, invert,
|
||||
SWIPE_GESTURE_DIRECTION_VERTICAL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1078,13 +1085,16 @@ static void handle_swipe_end(struct sway_seat *seat,
|
|||
// Ensure gesture is being tracked and was not cancelled
|
||||
struct seatop_default_event *seatop = seat->seatop_data;
|
||||
if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE) &&
|
||||
!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE)) {
|
||||
!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL) &&
|
||||
!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL)) {
|
||||
struct sway_cursor *cursor = seat->cursor;
|
||||
wlr_pointer_gestures_v1_send_swipe_end(cursor->pointer_gestures,
|
||||
cursor->seat->wlr_seat, event->time_msec, event->cancelled);
|
||||
return;
|
||||
}
|
||||
if (event->cancelled && seatop->gestures.type != GESTURE_TYPE_WORKSPACE_SWIPE) {
|
||||
if (event->cancelled &&
|
||||
seatop->gestures.type != GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL
|
||||
&& seatop->gestures.type != GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL) {
|
||||
gesture_tracker_cancel(&seatop->gestures);
|
||||
return;
|
||||
}
|
||||
|
@ -1097,7 +1107,8 @@ static void handle_swipe_end(struct sway_seat *seat,
|
|||
|
||||
if (binding) {
|
||||
switch (binding->gesture.type) {
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE:;
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||
snap_workspace_scroll_percent(seat);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -547,6 +547,47 @@ runtime.
|
|||
|
||||
```
|
||||
|
||||
*bindworkspacegesture* [--input-device=<device>] [--no-warn] \
|
||||
[--inverted] [<fingers>][:direction]
|
||||
Binds the swipe to switch workspaces in a 1:1 fashion, but only when
|
||||
detected. Optionally can be limited to bind to a certain number of
|
||||
_fingers_ or to certain _directions_.
|
||||
|
||||
[[ *type*
|
||||
:[ *fingers*
|
||||
:< *direction*
|
||||
| swipe
|
||||
: 3 - 5
|
||||
: horizontal, vertical
|
||||
|
||||
The _fingers_ can be limited to any sensible number or left empty to accept
|
||||
any finger counts.
|
||||
Valid directions are _horizontal_ and _vertical_.
|
||||
|
||||
If a _input-device_ is given, the binding will only be executed for
|
||||
that input device and will be executed instead of any binding that is
|
||||
generic to all devices. By default, if you overwrite a binding,
|
||||
swaynag will give you a warning. To silence this, use the _--no-warn_ flag.
|
||||
|
||||
If _inverted_ is given, the swipe direction will be reversed.
|
||||
|
||||
The priority for matching bindings is as follows: input device, then
|
||||
exact matches.
|
||||
|
||||
Gestures executed while the pointer is above a bar are not handled by sway.
|
||||
See the respective documentation, e.g. *bindgesture* in *sway-bar*(5).
|
||||
|
||||
Example:
|
||||
```
|
||||
# Allow switching between workspaces with left and right swipes
|
||||
bindworkspacegesture 4:horizontal
|
||||
# Allow switching between workspaces with up and down swipes
|
||||
bindworkspacegesture 3:vertical
|
||||
# Allow switching between workspaces with up and down swipes but inverted
|
||||
bindworkspacegesture --inverted 3:vertical
|
||||
|
||||
```
|
||||
|
||||
*client.background* <color>
|
||||
This command is ignored and is only present for i3 compatibility.
|
||||
|
||||
|
|
Loading…
Reference in a new issue