Revert to using a fixed timer interval
Sadly, we cant rely on the Wayland compositor to send us reliably timed scroll events.
This commit is contained in:
25
glfw/momentum-scroll.c
vendored
25
glfw/momentum-scroll.c
vendored
@@ -24,13 +24,13 @@ typedef struct MomentumScroller {
|
||||
min_velocity, // Minimum velocity before stopping
|
||||
max_velocity, // Maximum velocity to prevent runaway scrolling
|
||||
velocity_scale; // Scale factor for initial velocity
|
||||
monotonic_t timer_interval; // animation speed
|
||||
|
||||
GLFWid timer_id, window_id;
|
||||
ScrollSamples samples;
|
||||
ScrollerState state;
|
||||
struct { double x, y; } velocity;
|
||||
int keyboard_modifiers;
|
||||
monotonic_t timer_interval;
|
||||
struct {
|
||||
monotonic_t start, duration;
|
||||
struct { double x, y; } displacement;
|
||||
@@ -42,11 +42,13 @@ static const MomentumScroller defaults = {
|
||||
.min_velocity = 0.5,
|
||||
.max_velocity = 100,
|
||||
.velocity_scale = 0.9,
|
||||
.timer_interval = 10,
|
||||
};
|
||||
static MomentumScroller s = defaults;
|
||||
|
||||
GLFWAPI void
|
||||
glfwConfigureMomentumScroller(double friction, double min_velocity, double max_velocity, double velocity_scale) {
|
||||
glfwConfigureMomentumScroller(double friction, double min_velocity, double max_velocity, double velocity_scale, unsigned timer_interval_ms) {
|
||||
s.timer_interval = ms_to_monotonic_t(timer_interval_ms);
|
||||
#define S(w) s.w = w >= 0 ? w : defaults.w
|
||||
S(friction); S(min_velocity); S(max_velocity); S(velocity_scale);
|
||||
#undef S
|
||||
@@ -118,29 +120,17 @@ set_velocity_from_samples(monotonic_t now) {
|
||||
monotonic_t first_time = deque_peek_front(&s.samples)->timestamp;
|
||||
monotonic_t last_time = deque_peek_back(&s.samples)->timestamp;
|
||||
double time_span = MAX(1, last_time - first_time);
|
||||
double total_time_between_events = 0;
|
||||
monotonic_t prev_timestamp = 0;
|
||||
double ts_weight = 0;
|
||||
for (size_t i = 0; i < deque_size(&s.samples); i++) {
|
||||
const ScrollSample *ss = deque_at(&s.samples, i);
|
||||
double weight = 1.0 + (ss->timestamp - first_time) / time_span;
|
||||
total_dx += ss->dx * weight; total_dy += ss->dy * weight;
|
||||
total_weight += weight;
|
||||
if (prev_timestamp) {
|
||||
monotonic_t t = ss->timestamp - prev_timestamp;
|
||||
total_time_between_events += t * weight;
|
||||
ts_weight += weight;
|
||||
}
|
||||
prev_timestamp = ss->timestamp;
|
||||
}
|
||||
deque_clear(&s.samples);
|
||||
if (ts_weight <= 0) return;
|
||||
s.timer_interval = (monotonic_t)(total_time_between_events / ts_weight);
|
||||
if (total_weight <= 0) return;
|
||||
double dy = total_dy / total_weight, dx = total_dx / total_weight;
|
||||
add_velocity(dx * s.velocity_scale, dy * s.velocity_scale);
|
||||
if (false) timed_debug_print(
|
||||
"momentum scroll: event velocity: %.1f final velocity: %.1f interval: %d ms\n",
|
||||
dy, s.velocity.y, monotonic_t_to_ms(s.timer_interval));
|
||||
if (false) timed_debug_print("momentum scroll: event velocity: %.1f final velocity: %.1f\n", dy, s.velocity.y);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -205,9 +195,8 @@ glfw_handle_scroll_event_for_momentum(
|
||||
s.physical_event.start = 0;
|
||||
}
|
||||
} else {
|
||||
memset(&s.physical_event, 0, sizeof(s.physical_event));
|
||||
s.physical_event.start = now;
|
||||
s.physical_event.displacement.x = 0;
|
||||
s.physical_event.displacement.y = 0;
|
||||
}
|
||||
if (s.window_id && s.window_id != w->id) cancel_existing_scroll(true);
|
||||
if (s.state != PHYSICAL_EVENT_IN_PROGRESS) cancel_existing_scroll(false);
|
||||
|
||||
Reference in New Issue
Block a user