Updated swipe percentage calculation to also use avg_velocity
This commit is contained in:
parent
42fcd6c86d
commit
54daaa9ed2
|
@ -19,6 +19,13 @@ enum swipe_gesture_direction {
|
||||||
SWIPE_GESTURE_DIRECTION_VERTICAL,
|
SWIPE_GESTURE_DIRECTION_VERTICAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct workspace_scroll {
|
||||||
|
double percent;
|
||||||
|
double avg_velocity;
|
||||||
|
int num_updates;
|
||||||
|
enum swipe_gesture_direction direction;
|
||||||
|
};
|
||||||
|
|
||||||
struct render_data {
|
struct render_data {
|
||||||
pixman_region32_t *damage;
|
pixman_region32_t *damage;
|
||||||
struct wlr_box *clip_box;
|
struct wlr_box *clip_box;
|
||||||
|
@ -64,10 +71,7 @@ struct sway_output {
|
||||||
struct wl_listener frame;
|
struct wl_listener frame;
|
||||||
struct wl_listener needs_frame;
|
struct wl_listener needs_frame;
|
||||||
|
|
||||||
struct {
|
struct workspace_scroll workspace_scroll;
|
||||||
float percent;
|
|
||||||
enum swipe_gesture_direction direction;
|
|
||||||
} workspace_scroll;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal disable;
|
struct wl_signal disable;
|
||||||
|
@ -211,10 +215,13 @@ void handle_output_manager_test(struct wl_listener *listener, void *data);
|
||||||
void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
void update_workspace_scroll_percent(struct sway_seat *seat, int gesture_percent,
|
void workspace_scroll_begin(struct sway_seat *seat,
|
||||||
int invert, enum swipe_gesture_direction direction);
|
enum swipe_gesture_direction direction);
|
||||||
|
|
||||||
void snap_workspace_scroll_percent(struct sway_seat *seat);
|
void workspace_scroll_update(struct sway_seat *seat, double delta_sum,
|
||||||
|
enum swipe_gesture_direction direction);
|
||||||
|
|
||||||
|
void workspace_scroll_end(struct sway_seat *seat);
|
||||||
|
|
||||||
struct sway_output_non_desktop *output_non_desktop_create(struct wlr_output *wlr_output);
|
struct sway_output_non_desktop *output_non_desktop_create(struct wlr_output *wlr_output);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,15 @@
|
||||||
#define PREV_WS_LIMIT -1.0f
|
#define PREV_WS_LIMIT -1.0f
|
||||||
#define NEXT_WS_LIMIT 1.0f
|
#define NEXT_WS_LIMIT 1.0f
|
||||||
|
|
||||||
|
static struct workspace_scroll workspace_scroll_get_default() {
|
||||||
|
return (struct workspace_scroll) {
|
||||||
|
.percent = 0,
|
||||||
|
.avg_velocity = 0,
|
||||||
|
.num_updates = 0,
|
||||||
|
.direction = SWIPE_GESTURE_DIRECTION_NONE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct sway_output *output_by_name_or_id(const char *name_or_id) {
|
struct sway_output *output_by_name_or_id(const char *name_or_id) {
|
||||||
for (int i = 0; i < root->outputs->length; ++i) {
|
for (int i = 0; i < root->outputs->length; ++i) {
|
||||||
struct sway_output *output = root->outputs->items[i];
|
struct sway_output *output = root->outputs->items[i];
|
||||||
|
@ -994,8 +1003,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
||||||
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
|
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
|
||||||
update_output_manager_config(server);
|
update_output_manager_config(server);
|
||||||
|
|
||||||
output->workspace_scroll.percent = 0.0f;
|
output->workspace_scroll = workspace_scroll_get_default();
|
||||||
output->workspace_scroll.direction = SWIPE_GESTURE_DIRECTION_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_output_layout_change(struct wl_listener *listener,
|
void handle_output_layout_change(struct wl_listener *listener,
|
||||||
|
@ -1109,39 +1117,49 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
||||||
apply_output_config(oc, output);
|
apply_output_config(oc, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_workspace_scroll_percent(struct sway_seat *seat, int gesture_percent,
|
void workspace_scroll_begin(struct sway_seat *seat,
|
||||||
int invert, enum swipe_gesture_direction direction) {
|
enum swipe_gesture_direction direction) {
|
||||||
struct sway_workspace *focused_ws = seat_get_focused_workspace(seat);
|
struct sway_workspace *focused_ws = seat_get_focused_workspace(seat);
|
||||||
struct sway_output *output = focused_ws->output;
|
struct sway_output *output = focused_ws->output;
|
||||||
|
|
||||||
|
// Reset the state
|
||||||
|
output->workspace_scroll = workspace_scroll_get_default();
|
||||||
|
output->workspace_scroll.direction = direction;
|
||||||
|
|
||||||
|
output_damage_whole(output);
|
||||||
|
transaction_commit_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_scroll_update(struct sway_seat *seat, double delta_sum,
|
||||||
|
enum swipe_gesture_direction direction) {
|
||||||
|
struct sway_workspace *focused_ws = seat_get_focused_workspace(seat);
|
||||||
|
struct sway_output *output = focused_ws->output;
|
||||||
|
struct workspace_scroll *ws_scroll = &output->workspace_scroll;
|
||||||
|
|
||||||
|
if (direction != ws_scroll->direction) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int visible_index = list_find(output->workspaces, focused_ws);
|
int visible_index = list_find(output->workspaces, focused_ws);
|
||||||
if (visible_index == -1) {
|
if (visible_index == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gesture_percent *= invert;
|
// Get the updated average velocity
|
||||||
|
ws_scroll->avg_velocity = fabs(delta_sum) / (++ws_scroll->num_updates);
|
||||||
|
// TODO: Make configurable
|
||||||
|
const int SPEED_FACTOR = 750;
|
||||||
|
double percent = delta_sum / SPEED_FACTOR;
|
||||||
|
|
||||||
// TODO: Make the speed factor configurable?? Works well on my trackpad...
|
double min = PREV_WS_LIMIT, max = NEXT_WS_LIMIT;
|
||||||
// Maybe also take in account the width of the actual trackpad??
|
|
||||||
const int SPEED_FACTOR = 500;
|
|
||||||
float percent = 0;
|
|
||||||
if (gesture_percent < 0) {
|
|
||||||
percent = (float) gesture_percent / SPEED_FACTOR;
|
|
||||||
} else if (gesture_percent > 0) {
|
|
||||||
percent = (float) gesture_percent / SPEED_FACTOR;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float min = PREV_WS_LIMIT, max = NEXT_WS_LIMIT;
|
|
||||||
if (!config->workspace_gesture_wrap_around) {
|
if (!config->workspace_gesture_wrap_around) {
|
||||||
// Visualized to the user that this is the last / first workspace by
|
// Visualized to the user that this is the last / first workspace by
|
||||||
// allowing a small swipe, a "Spring effect"
|
// allowing a small swipe, a "Spring effect"
|
||||||
float spring_limit = (float) config->workspace_gesture_spring_size /
|
double spring_limit = (double) config->workspace_gesture_spring_size /
|
||||||
output->width * output->wlr_output->scale;
|
output->width * output->wlr_output->scale;
|
||||||
// Make sure that the limit is always smaller than the threshold to
|
// Make sure that the limit is always smaller than the threshold to
|
||||||
// avoid accidental workspace switches
|
// avoid accidental workspace switches
|
||||||
float small_threshold = MAX(config->workspace_gesture_threshold - 0.1, 0);
|
double small_threshold = MAX(config->workspace_gesture_threshold - 0.1, 0);
|
||||||
spring_limit = MIN(small_threshold, spring_limit);
|
spring_limit = MIN(small_threshold, spring_limit);
|
||||||
// Limit the percent depending on if the workspace is the first/last or in
|
// Limit the percent depending on if the workspace is the first/last or in
|
||||||
// the middle somewhere.
|
// the middle somewhere.
|
||||||
|
@ -1152,32 +1170,42 @@ void update_workspace_scroll_percent(struct sway_seat *seat, int gesture_percent
|
||||||
min = -spring_limit;
|
min = -spring_limit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output->workspace_scroll.percent = MIN(max, MAX(min, percent));
|
ws_scroll->percent = CLAMP(percent, min, max);
|
||||||
output->workspace_scroll.direction = direction;
|
ws_scroll->direction = direction;
|
||||||
|
|
||||||
output_damage_whole(output);
|
output_damage_whole(output);
|
||||||
transaction_commit_dirty();
|
transaction_commit_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void snap_workspace_scroll_percent(struct sway_seat *seat) {
|
void workspace_scroll_end(struct sway_seat *seat) {
|
||||||
struct sway_workspace *focused_ws = seat_get_focused_workspace(seat);
|
struct sway_workspace *focused_ws = seat_get_focused_workspace(seat);
|
||||||
struct sway_output *output = focused_ws->output;
|
struct sway_output *output = focused_ws->output;
|
||||||
|
struct workspace_scroll *ws_scroll = &output->workspace_scroll;
|
||||||
|
|
||||||
if (fabs(output->workspace_scroll.percent) <= config->workspace_gesture_threshold) {
|
int visible_index = list_find(output->workspaces, focused_ws);
|
||||||
goto reset_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dir = 0;
|
bool not_edge_ws = config->workspace_gesture_wrap_around;
|
||||||
if (output->workspace_scroll.percent < 0) {
|
int dir;
|
||||||
|
if (ws_scroll->percent < 0) {
|
||||||
dir = PREV_WS_LIMIT;
|
dir = PREV_WS_LIMIT;
|
||||||
} else if (output->workspace_scroll.percent > 0) {
|
not_edge_ws |= visible_index > 0;
|
||||||
|
} else if (ws_scroll->percent > 0) {
|
||||||
dir = NEXT_WS_LIMIT;
|
dir = NEXT_WS_LIMIT;
|
||||||
|
not_edge_ws |= visible_index + 1 < output->workspaces->length;
|
||||||
} else {
|
} else {
|
||||||
// Skip setting workspace if the percentage is zero
|
// Skip setting workspace if the percentage is zero
|
||||||
goto reset_state;
|
goto reset_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int visible_index = list_find(output->workspaces, focused_ws);
|
// TODO: Make configurable
|
||||||
|
const int VELOCITY_NEEDED = 8;
|
||||||
|
// Only switch workspaces when the percent exceeds the threshold or if
|
||||||
|
// the avg_speed exceeds the limit (for fast but short swipes).
|
||||||
|
bool threshold_met = fabs(ws_scroll->percent) >= config->workspace_gesture_threshold;
|
||||||
|
bool enough_velocity = ws_scroll->avg_velocity >= VELOCITY_NEEDED && not_edge_ws;
|
||||||
|
if (!threshold_met && !enough_velocity) {
|
||||||
|
goto reset_state;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ws_index = wrap(visible_index + dir, output->workspaces->length);
|
size_t ws_index = wrap(visible_index + dir, output->workspaces->length);
|
||||||
struct sway_workspace *new_ws = output->workspaces->items[ws_index];
|
struct sway_workspace *new_ws = output->workspaces->items[ws_index];
|
||||||
|
@ -1187,8 +1215,7 @@ void snap_workspace_scroll_percent(struct sway_seat *seat) {
|
||||||
|
|
||||||
reset_state:
|
reset_state:
|
||||||
// Reset the state
|
// Reset the state
|
||||||
output->workspace_scroll.percent = 0;
|
output->workspace_scroll = workspace_scroll_get_default();
|
||||||
output->workspace_scroll.direction = SWIPE_GESTURE_DIRECTION_NONE;
|
|
||||||
|
|
||||||
output_damage_whole(output);
|
output_damage_whole(output);
|
||||||
transaction_commit_dirty();
|
transaction_commit_dirty();
|
||||||
|
|
|
@ -1014,9 +1014,11 @@ static void handle_swipe_begin(struct sway_seat *seat,
|
||||||
} else if (gesture_binding_check(bindings, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL, 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;
|
struct seatop_default_event *seatop = seat->seatop_data;
|
||||||
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL, event->fingers);
|
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL, event->fingers);
|
||||||
|
workspace_scroll_begin(seat, SWIPE_GESTURE_DIRECTION_HORIZONTAL);
|
||||||
} else if (gesture_binding_check(bindings, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL, event->fingers, device)) {
|
} else if (gesture_binding_check(bindings, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL, event->fingers, device)) {
|
||||||
struct seatop_default_event *seatop = seat->seatop_data;
|
struct seatop_default_event *seatop = seat->seatop_data;
|
||||||
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL, event->fingers);
|
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL, event->fingers);
|
||||||
|
workspace_scroll_begin(seat, SWIPE_GESTURE_DIRECTION_VERTICAL);
|
||||||
} else {
|
} else {
|
||||||
// ... otherwise forward to client
|
// ... otherwise forward to client
|
||||||
struct sway_cursor *cursor = seat->cursor;
|
struct sway_cursor *cursor = seat->cursor;
|
||||||
|
@ -1036,9 +1038,6 @@ static void handle_swipe_update(struct sway_seat *seat,
|
||||||
event->dx, event->dy, NAN, NAN);
|
event->dx, event->dy, NAN, NAN);
|
||||||
} else if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL) ||
|
} else if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL) ||
|
||||||
gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL)) {
|
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
|
// Find the gesture and update the swipe percentage
|
||||||
struct gesture_tracker *tracker = &seatop->gestures;
|
struct gesture_tracker *tracker = &seatop->gestures;
|
||||||
struct sway_input_device *device =
|
struct sway_input_device *device =
|
||||||
|
@ -1058,13 +1057,15 @@ static void handle_swipe_update(struct sway_seat *seat,
|
||||||
|
|
||||||
if (binding) {
|
if (binding) {
|
||||||
int invert = binding->flags & BINDING_INVERTED ? 1 : -1;
|
int invert = binding->flags & BINDING_INVERTED ? 1 : -1;
|
||||||
|
tracker->dx += event->dx * invert;
|
||||||
|
tracker->dy += event->dy * invert;
|
||||||
switch (binding->gesture.type) {
|
switch (binding->gesture.type) {
|
||||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||||
update_workspace_scroll_percent(seat, tracker->dx, invert,
|
workspace_scroll_update(seat, tracker->dx,
|
||||||
SWIPE_GESTURE_DIRECTION_HORIZONTAL);
|
SWIPE_GESTURE_DIRECTION_HORIZONTAL);
|
||||||
break;
|
break;
|
||||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||||
update_workspace_scroll_percent(seat, tracker->dy, invert,
|
workspace_scroll_update(seat, tracker->dy,
|
||||||
SWIPE_GESTURE_DIRECTION_VERTICAL);
|
SWIPE_GESTURE_DIRECTION_VERTICAL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1109,7 +1110,7 @@ static void handle_swipe_end(struct sway_seat *seat,
|
||||||
switch (binding->gesture.type) {
|
switch (binding->gesture.type) {
|
||||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||||
snap_workspace_scroll_percent(seat);
|
workspace_scroll_end(seat);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
gesture_binding_execute(seat, binding);
|
gesture_binding_execute(seat, binding);
|
||||||
|
|
Loading…
Reference in a new issue