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,
|
||||
};
|
||||
|
||||
struct workspace_scroll {
|
||||
double percent;
|
||||
double avg_velocity;
|
||||
int num_updates;
|
||||
enum swipe_gesture_direction direction;
|
||||
};
|
||||
|
||||
struct render_data {
|
||||
pixman_region32_t *damage;
|
||||
struct wlr_box *clip_box;
|
||||
|
@ -64,10 +71,7 @@ struct sway_output {
|
|||
struct wl_listener frame;
|
||||
struct wl_listener needs_frame;
|
||||
|
||||
struct {
|
||||
float percent;
|
||||
enum swipe_gesture_direction direction;
|
||||
} workspace_scroll;
|
||||
struct workspace_scroll workspace_scroll;
|
||||
|
||||
struct {
|
||||
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 *data);
|
||||
|
||||
void update_workspace_scroll_percent(struct sway_seat *seat, int gesture_percent,
|
||||
int invert, enum swipe_gesture_direction direction);
|
||||
void workspace_scroll_begin(struct sway_seat *seat,
|
||||
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);
|
||||
|
||||
|
|
|
@ -36,6 +36,15 @@
|
|||
#define PREV_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) {
|
||||
for (int i = 0; i < root->outputs->length; ++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);
|
||||
update_output_manager_config(server);
|
||||
|
||||
output->workspace_scroll.percent = 0.0f;
|
||||
output->workspace_scroll.direction = SWIPE_GESTURE_DIRECTION_NONE;
|
||||
output->workspace_scroll = workspace_scroll_get_default();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void update_workspace_scroll_percent(struct sway_seat *seat, int gesture_percent,
|
||||
int invert, enum swipe_gesture_direction direction) {
|
||||
void workspace_scroll_begin(struct sway_seat *seat,
|
||||
enum swipe_gesture_direction direction) {
|
||||
struct sway_workspace *focused_ws = seat_get_focused_workspace(seat);
|
||||
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);
|
||||
if (visible_index == -1) {
|
||||
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...
|
||||
// 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;
|
||||
double min = PREV_WS_LIMIT, max = NEXT_WS_LIMIT;
|
||||
if (!config->workspace_gesture_wrap_around) {
|
||||
// Visualized to the user that this is the last / first workspace by
|
||||
// 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;
|
||||
// Make sure that the limit is always smaller than the threshold to
|
||||
// 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);
|
||||
// Limit the percent depending on if the workspace is the first/last or in
|
||||
// the middle somewhere.
|
||||
|
@ -1152,32 +1170,42 @@ void update_workspace_scroll_percent(struct sway_seat *seat, int gesture_percent
|
|||
min = -spring_limit;
|
||||
}
|
||||
}
|
||||
output->workspace_scroll.percent = MIN(max, MAX(min, percent));
|
||||
output->workspace_scroll.direction = direction;
|
||||
ws_scroll->percent = CLAMP(percent, min, max);
|
||||
ws_scroll->direction = direction;
|
||||
|
||||
output_damage_whole(output);
|
||||
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_output *output = focused_ws->output;
|
||||
struct workspace_scroll *ws_scroll = &output->workspace_scroll;
|
||||
|
||||
if (fabs(output->workspace_scroll.percent) <= config->workspace_gesture_threshold) {
|
||||
goto reset_state;
|
||||
}
|
||||
int visible_index = list_find(output->workspaces, focused_ws);
|
||||
|
||||
int dir = 0;
|
||||
if (output->workspace_scroll.percent < 0) {
|
||||
bool not_edge_ws = config->workspace_gesture_wrap_around;
|
||||
int dir;
|
||||
if (ws_scroll->percent < 0) {
|
||||
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;
|
||||
not_edge_ws |= visible_index + 1 < output->workspaces->length;
|
||||
} else {
|
||||
// Skip setting workspace if the percentage is zero
|
||||
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);
|
||||
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 the state
|
||||
output->workspace_scroll.percent = 0;
|
||||
output->workspace_scroll.direction = SWIPE_GESTURE_DIRECTION_NONE;
|
||||
output->workspace_scroll = workspace_scroll_get_default();
|
||||
|
||||
output_damage_whole(output);
|
||||
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)) {
|
||||
struct seatop_default_event *seatop = seat->seatop_data;
|
||||
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)) {
|
||||
struct seatop_default_event *seatop = seat->seatop_data;
|
||||
gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL, event->fingers);
|
||||
workspace_scroll_begin(seat, SWIPE_GESTURE_DIRECTION_VERTICAL);
|
||||
} else {
|
||||
// ... otherwise forward to client
|
||||
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);
|
||||
} 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 =
|
||||
|
@ -1058,13 +1057,15 @@ static void handle_swipe_update(struct sway_seat *seat,
|
|||
|
||||
if (binding) {
|
||||
int invert = binding->flags & BINDING_INVERTED ? 1 : -1;
|
||||
tracker->dx += event->dx * invert;
|
||||
tracker->dy += event->dy * invert;
|
||||
switch (binding->gesture.type) {
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||
update_workspace_scroll_percent(seat, tracker->dx, invert,
|
||||
workspace_scroll_update(seat, tracker->dx,
|
||||
SWIPE_GESTURE_DIRECTION_HORIZONTAL);
|
||||
break;
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||
update_workspace_scroll_percent(seat, tracker->dy, invert,
|
||||
workspace_scroll_update(seat, tracker->dy,
|
||||
SWIPE_GESTURE_DIRECTION_VERTICAL);
|
||||
break;
|
||||
default:
|
||||
|
@ -1109,7 +1110,7 @@ static void handle_swipe_end(struct sway_seat *seat,
|
|||
switch (binding->gesture.type) {
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_HORIZONTAL:
|
||||
case GESTURE_TYPE_WORKSPACE_SWIPE_VERTICAL:
|
||||
snap_workspace_scroll_percent(seat);
|
||||
workspace_scroll_end(seat);
|
||||
break;
|
||||
default:
|
||||
gesture_binding_execute(seat, binding);
|
||||
|
|
Loading…
Reference in a new issue