seat: support lo-res clients using hi-res backends

When the selected backend supports high-resolution scroll but the client
doesn't, we need to accumulate value120 deltas until we can notify a
discrete event.

In addition, add a expire time so accumulated deltas are reset after a
period of inactivity.
This commit is contained in:
José Expósito 2021-09-20 19:47:49 +02:00
parent 47e79a78ad
commit d1e70dc133
3 changed files with 44 additions and 2 deletions

View file

@ -53,6 +53,13 @@ struct wlr_seat_client {
// for use by wlr_seat_client_{next_serial,validate_event_serial}
struct wlr_serial_ringset serials;
bool needs_touch_frame;
// when the backend supports high-resolution scroll but the client doesn't,
// accumulate deltas until we can notify a discrete event.
int32_t acc_vertical_value120;
int32_t acc_horizontal_value120;
double acc_axis;
uint32_t last_value120_time;
};
struct wlr_touch_point {

View file

@ -135,6 +135,10 @@ static void seat_handle_bind(struct wl_client *client, void *_wlr_seat,
seat_client->client = client;
seat_client->seat = wlr_seat;
seat_client->acc_vertical_value120 = 0;
seat_client->acc_horizontal_value120 = 0;
seat_client->acc_axis = 0;
seat_client->last_value120_time = 0;
wl_list_init(&seat_client->resources);
wl_list_init(&seat_client->pointers);
wl_list_init(&seat_client->keyboards);

View file

@ -10,6 +10,8 @@
#include "util/signal.h"
#include "util/array.h"
#define VALUE120_ACC_EXPIRE_TIME 1000 // milliseconds
static void default_pointer_enter(struct wlr_seat_pointer_grab *grab,
struct wlr_surface *surface, double sx, double sy) {
wlr_seat_pointer_enter(grab->seat, surface, sx, sy);
@ -341,6 +343,22 @@ void wlr_seat_pointer_send_axis_value120(struct wlr_seat *wlr_seat,
send_source = true;
}
bool send_axis = true;
wl_fixed_t axis_value = wl_fixed_from_double(delta);
if (time - client->last_value120_time > VALUE120_ACC_EXPIRE_TIME) {
client->acc_vertical_value120 = 0;
client->acc_horizontal_value120 = 0;
client->acc_axis = 0;
}
int32_t *acc_value = (orientation == WLR_AXIS_ORIENTATION_VERTICAL) ?
&client->acc_vertical_value120 :
&client->acc_horizontal_value120;
*acc_value += delta_value120;
client->acc_axis += delta;
client->last_value120_time = time;
struct wl_resource *resource;
wl_resource_for_each(resource, &client->pointers) {
if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
@ -357,11 +375,24 @@ void wlr_seat_pointer_send_axis_value120(struct wlr_seat *wlr_seat,
if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) {
wl_pointer_send_axis_value120(resource, orientation,
delta_value120);
} else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) {
send_axis = (abs(*acc_value) >= 120);
if (send_axis) {
int32_t discrete = (*acc_value / 120);
*acc_value -= (discrete * 120);
axis_value = wl_fixed_from_double(client->acc_axis);
client->acc_axis = 0;
wl_pointer_send_axis_discrete(resource, orientation,
discrete);
}
}
}
wl_pointer_send_axis(resource, time, orientation,
wl_fixed_from_double(delta));
if (send_axis) {
wl_pointer_send_axis(resource, time, orientation, axis_value);
}
} else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) {
wl_pointer_send_axis_stop(resource, time, orientation);
}