mirror of https://github.com/encounter/SDL.git
Fixed bug 4917 - Wayland: handle discrete pointer axis events
Luis Caceres The current handling of Wayland mouse pointer events only handles wl_pointer.axis events, which, according to the Wayland documentation, deal with mouse wheel scroll events on a continuous scale. While this is reasonable for some input sources (e.g. touchpad two-finger scrolling), it is not for mouse wheel clicks which generate wl_pointer.axis events with large deltas. This patch adds handling for wl_pointer.axis_discrete and wl_pointer.frame events and prefers to report SDL_MouseWheelEvent in discrete units if they are available. This means that for mouse wheel scrolling we count in clicks, but for touchpad two-finger scrolling we still use whatever units Wayland uses. This behaviour is closer to that of the X11 backend. Since these events are only available since version 5 of the wl_seat interface, this patch also checks for this and falls back to the previous behaviour if its not available. I also had to add definitions for some of the pointer and keyboard events specified in versions 2-5 but these are just stubs and do nothing.
This commit is contained in:
parent
68e702b657
commit
67f4478867
|
@ -72,6 +72,15 @@ struct SDL_WaylandInput {
|
|||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *state;
|
||||
} xkb;
|
||||
|
||||
/* information about axis events on current frame */
|
||||
struct {
|
||||
SDL_bool is_x_discrete;
|
||||
float x;
|
||||
|
||||
SDL_bool is_y_discrete;
|
||||
float y;
|
||||
} pointer_curr_axis_info;
|
||||
};
|
||||
|
||||
struct SDL_WaylandTouchPoint {
|
||||
|
@ -361,8 +370,8 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
|
|||
}
|
||||
|
||||
static void
|
||||
pointer_handle_axis_common(struct SDL_WaylandInput *input,
|
||||
uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||
pointer_handle_axis_common_v1(struct SDL_WaylandInput *input,
|
||||
uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||
{
|
||||
SDL_WindowData *window = input->pointer_focus;
|
||||
enum wl_pointer_axis a = axis;
|
||||
|
@ -386,25 +395,104 @@ pointer_handle_axis_common(struct SDL_WaylandInput *input,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_axis_common(struct SDL_WaylandInput *input, SDL_bool discrete,
|
||||
uint32_t axis, wl_fixed_t value)
|
||||
{
|
||||
enum wl_pointer_axis a = axis;
|
||||
|
||||
if (input->pointer_focus) {
|
||||
switch (a) {
|
||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||
if (discrete) {
|
||||
/* this is a discrete axis event so we process it and flag
|
||||
* to ignore future continuous axis events in this frame */
|
||||
input->pointer_curr_axis_info.is_y_discrete = SDL_TRUE;
|
||||
} else if(input->pointer_curr_axis_info.is_y_discrete) {
|
||||
/* this is a continuous axis event and we have already
|
||||
* processed a discrete axis event before so we ignore it */
|
||||
break;
|
||||
}
|
||||
input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(value);
|
||||
break;
|
||||
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||
if (discrete) {
|
||||
/* this is a discrete axis event so we process it and flag
|
||||
* to ignore future continuous axis events in this frame */
|
||||
input->pointer_curr_axis_info.is_x_discrete = SDL_TRUE;
|
||||
} else if(input->pointer_curr_axis_info.is_x_discrete) {
|
||||
/* this is a continuous axis event and we have already
|
||||
* processed a discrete axis event before so we ignore it */
|
||||
break;
|
||||
}
|
||||
input->pointer_curr_axis_info.x = 0 - (float)wl_fixed_to_double(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_axis(void *data, struct wl_pointer *pointer,
|
||||
uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||
{
|
||||
struct SDL_WaylandInput *input = data;
|
||||
|
||||
pointer_handle_axis_common(input, time, axis, value);
|
||||
if(wl_seat_interface.version >= 5)
|
||||
pointer_handle_axis_common(input, SDL_FALSE, axis, value);
|
||||
else
|
||||
pointer_handle_axis_common_v1(input, time, axis, value);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_frame(void *data, struct wl_pointer *pointer)
|
||||
{
|
||||
struct SDL_WaylandInput *input = data;
|
||||
SDL_WindowData *window = input->pointer_focus;
|
||||
float x = input->pointer_curr_axis_info.x, y = input->pointer_curr_axis_info.y;
|
||||
|
||||
/* clear pointer_curr_axis_info for next frame */
|
||||
memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info);
|
||||
|
||||
if(x == 0.0f && y == 0.0f)
|
||||
return;
|
||||
else
|
||||
SDL_SendMouseWheel(window->sdlwindow, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_axis_source(void *data, struct wl_pointer *pointer,
|
||||
uint32_t axis_source)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_axis_stop(void *data, struct wl_pointer *pointer,
|
||||
uint32_t time, uint32_t axis)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_axis_discrete(void *data, struct wl_pointer *pointer,
|
||||
uint32_t axis, int32_t discrete)
|
||||
{
|
||||
struct SDL_WaylandInput *input = data;
|
||||
|
||||
pointer_handle_axis_common(input, SDL_TRUE, axis, wl_fixed_from_int(discrete));
|
||||
}
|
||||
|
||||
|
||||
static const struct wl_pointer_listener pointer_listener = {
|
||||
pointer_handle_enter,
|
||||
pointer_handle_leave,
|
||||
pointer_handle_motion,
|
||||
pointer_handle_button,
|
||||
pointer_handle_axis,
|
||||
NULL, /* frame */
|
||||
NULL, /* axis_source */
|
||||
NULL, /* axis_stop */
|
||||
NULL, /* axis_discrete */
|
||||
pointer_handle_frame, // Version 5
|
||||
pointer_handle_axis_source, // Version 5
|
||||
pointer_handle_axis_stop, // Version 5
|
||||
pointer_handle_axis_discrete, // Version 5
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -604,13 +692,20 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
|||
mods_locked, 0, 0, group);
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
|
||||
int32_t rate, int32_t delay)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static const struct wl_keyboard_listener keyboard_listener = {
|
||||
keyboard_handle_keymap,
|
||||
keyboard_handle_enter,
|
||||
keyboard_handle_leave,
|
||||
keyboard_handle_key,
|
||||
keyboard_handle_modifiers,
|
||||
NULL, /* repeat_info */
|
||||
keyboard_handle_repeat_info, // Version 4
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -621,6 +716,7 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
|
|||
|
||||
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
|
||||
input->pointer = wl_seat_get_pointer(seat);
|
||||
memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info);
|
||||
input->display->pointer = input->pointer;
|
||||
wl_pointer_set_user_data(input->pointer, input);
|
||||
wl_pointer_add_listener(input->pointer, &pointer_listener,
|
||||
|
@ -654,9 +750,15 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static const struct wl_seat_listener seat_listener = {
|
||||
seat_handle_capabilities,
|
||||
NULL, /* name */
|
||||
seat_handle_name, // Version 2
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -906,7 +1008,10 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
|
|||
return;
|
||||
|
||||
input->display = d;
|
||||
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
|
||||
if (wl_seat_interface.version >= 5)
|
||||
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 5);
|
||||
else
|
||||
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
|
||||
input->sx_w = wl_fixed_from_int(0);
|
||||
input->sy_w = wl_fixed_from_int(0);
|
||||
d->input = input;
|
||||
|
|
Loading…
Reference in New Issue