mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-22 08:18:08 +02:00
Another try at pointer frame support on Wayland
This time I think I got the wheel handling correct. At least works with my wheel mouse.
This commit is contained in:
176
glfw/wl_init.c
vendored
176
glfw/wl_init.c
vendored
@@ -35,7 +35,6 @@
|
|||||||
#include "wl_text_input.h"
|
#include "wl_text_input.h"
|
||||||
#include "wayland-text-input-unstable-v3-client-protocol.h"
|
#include "wayland-text-input-unstable-v3-client-protocol.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -152,94 +151,121 @@ static void pointerHandleButton(void* data UNUSED,
|
|||||||
#undef x
|
#undef x
|
||||||
#undef y
|
#undef y
|
||||||
|
|
||||||
static void pointerHandleAxis(void* data UNUSED,
|
#define info (window->wl.pointer_curr_axis_info)
|
||||||
struct wl_pointer* pointer UNUSED,
|
|
||||||
uint32_t time UNUSED,
|
static void
|
||||||
uint32_t axis,
|
pointer_handle_axis_common(enum _GLFWWaylandAxisEvent type, uint32_t axis, wl_fixed_t value) {
|
||||||
wl_fixed_t value)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
double x = 0.0, y = 0.0;
|
|
||||||
if (!window || window->wl.decorations.focus != CENTRAL_WINDOW) return;
|
if (!window || window->wl.decorations.focus != CENTRAL_WINDOW) return;
|
||||||
|
float fval = (float) wl_fixed_to_double(value);
|
||||||
|
|
||||||
assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
|
#define CASE(type, type_const, axis, fval) \
|
||||||
axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
|
case type_const: \
|
||||||
|
if (info.type.axis##_axis_type == AXIS_EVENT_UNKNOWN) { \
|
||||||
|
info.type.axis##_axis_type = type_const; info.type.axis = 0.f; } \
|
||||||
|
info.type.axis += fval; break;
|
||||||
|
|
||||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
|
if (window) {
|
||||||
if (window->wl.axis_discrete_count.x) {
|
switch ((enum wl_pointer_axis)axis) {
|
||||||
window->wl.axis_discrete_count.x--;
|
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||||
return;
|
switch (type) {
|
||||||
|
case AXIS_EVENT_UNKNOWN: break;
|
||||||
|
CASE(discrete, AXIS_EVENT_DISCRETE, y, -fval); // wheel event
|
||||||
|
CASE(discrete, AXIS_EVENT_VALUE120, y, -fval); // wheel event higher res than plain discrete
|
||||||
|
CASE(continuous, AXIS_EVENT_CONTINUOUS, y, -fval); // touchpad, etc. high res
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||||
|
switch (type) {
|
||||||
|
case AXIS_EVENT_UNKNOWN: break;
|
||||||
|
CASE(discrete, AXIS_EVENT_DISCRETE, x, fval); // wheel event
|
||||||
|
CASE(discrete, AXIS_EVENT_VALUE120, x, fval); // wheel event higher res than plain discrete
|
||||||
|
CASE(continuous, AXIS_EVENT_CONTINUOUS, x, fval); // touchpad, etc. high res
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
x = -wl_fixed_to_double(value) * _glfwWaylandWindowScale(window);
|
|
||||||
}
|
}
|
||||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
#undef CASE
|
||||||
if (window->wl.axis_discrete_count.y) {
|
|
||||||
window->wl.axis_discrete_count.y--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
y = -wl_fixed_to_double(value) * _glfwWaylandWindowScale(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputScroll(window, x, y, 1, _glfw.wl.xkb.states.modifiers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleFrame(void* data UNUSED,
|
static void
|
||||||
struct wl_pointer* pointer UNUSED)
|
pointer_handle_axis(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t time, uint32_t axis, wl_fixed_t value) {
|
||||||
{
|
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
if (!window || window->wl.decorations.focus != CENTRAL_WINDOW) return;
|
if (!window) return;
|
||||||
window->wl.axis_discrete_count.x = 0;
|
if (!info.timestamp_ns) info.timestamp_ns = ms_to_monotonic_t(time);
|
||||||
window->wl.axis_discrete_count.y = 0;
|
pointer_handle_axis_common(AXIS_EVENT_CONTINUOUS, axis, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleAxisSource(void* data UNUSED,
|
static void
|
||||||
struct wl_pointer* pointer UNUSED,
|
pointer_handle_frame(void *data UNUSED, struct wl_pointer *pointer UNUSED) {
|
||||||
uint32_t source UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pointerHandleAxisStop(void *data UNUSED,
|
|
||||||
struct wl_pointer *wl_pointer UNUSED,
|
|
||||||
uint32_t time UNUSED,
|
|
||||||
uint32_t axis UNUSED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void pointerHandleAxisDiscrete(void *data UNUSED,
|
|
||||||
struct wl_pointer *wl_pointer UNUSED,
|
|
||||||
uint32_t axis,
|
|
||||||
int32_t discrete)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
double x = 0.0, y = 0.0;
|
if (!window) return;
|
||||||
if (!window || window->wl.decorations.focus != CENTRAL_WINDOW) return;
|
float x = 0, y = 0;
|
||||||
|
int highres = 0;
|
||||||
|
|
||||||
assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
|
if (info.discrete.y_axis_type != AXIS_EVENT_UNKNOWN) {
|
||||||
axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
|
y = info.discrete.y;
|
||||||
|
if (info.discrete.y_axis_type == AXIS_EVENT_VALUE120) y /= 120.f;
|
||||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
|
} else if (info.continuous.y_axis_type != AXIS_EVENT_UNKNOWN) {
|
||||||
x = -discrete;
|
highres = 1;
|
||||||
window->wl.axis_discrete_count.x++;
|
y = info.continuous.y;
|
||||||
}
|
|
||||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
|
||||||
y = -discrete;
|
|
||||||
window->wl.axis_discrete_count.y++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputScroll(window, x, y, 0, _glfw.wl.xkb.states.modifiers);
|
if (info.discrete.x_axis_type != AXIS_EVENT_UNKNOWN) {
|
||||||
|
x = info.discrete.x;
|
||||||
|
if (info.discrete.x_axis_type == AXIS_EVENT_VALUE120) x /= 120.f;
|
||||||
|
} else if (info.continuous.x_axis_type != AXIS_EVENT_UNKNOWN) {
|
||||||
|
highres = 1;
|
||||||
|
x = info.continuous.x;
|
||||||
|
}
|
||||||
|
/* clear pointer_curr_axis_info for next frame */
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
|
||||||
|
if (x != 0.0f || y != 0.0f) {
|
||||||
|
float scale = _glfwWaylandWindowScale(window);
|
||||||
|
y *= scale; x *= scale;
|
||||||
|
_glfwInputScroll(window, x, y, highres, _glfw.wl.xkb.states.modifiers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_handle_axis_source(void* data UNUSED, struct wl_pointer* pointer UNUSED, uint32_t source UNUSED) { }
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_handle_axis_stop(void *data UNUSED, struct wl_pointer *wl_pointer UNUSED, uint32_t time UNUSED, uint32_t axis UNUSED) { }
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_handle_axis_discrete(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t axis, int32_t discrete) {
|
||||||
|
pointer_handle_axis_common(AXIS_EVENT_DISCRETE, axis, wl_fixed_from_int(discrete));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_handle_axis_value120(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t axis, int32_t value120) {
|
||||||
|
pointer_handle_axis_common(AXIS_EVENT_VALUE120, axis, wl_fixed_from_int(value120));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_handle_axis_relative_direction(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t axis UNUSED, uint32_t axis_relative_direction UNUSED) { }
|
||||||
|
|
||||||
|
#undef info
|
||||||
static const struct wl_pointer_listener pointerListener = {
|
static const struct wl_pointer_listener pointerListener = {
|
||||||
pointerHandleEnter,
|
.enter = pointerHandleEnter,
|
||||||
pointerHandleLeave,
|
.leave = pointerHandleLeave,
|
||||||
pointerHandleMotion,
|
.motion = pointerHandleMotion,
|
||||||
pointerHandleButton,
|
.button = pointerHandleButton,
|
||||||
pointerHandleAxis,
|
|
||||||
pointerHandleFrame,
|
.axis = pointer_handle_axis,
|
||||||
pointerHandleAxisSource,
|
.frame = pointer_handle_frame,
|
||||||
pointerHandleAxisStop,
|
.axis_source = pointer_handle_axis_source,
|
||||||
pointerHandleAxisDiscrete,
|
.axis_stop = pointer_handle_axis_stop,
|
||||||
|
.axis_discrete = pointer_handle_axis_discrete,
|
||||||
|
#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
|
||||||
|
.axis_value120 = pointer_handle_axis_value120,
|
||||||
|
#endif
|
||||||
|
#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
|
||||||
|
.axis_relative_direction = pointer_handle_axis_relative_direction,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void keyboardHandleKeymap(void* data UNUSED,
|
static void keyboardHandleKeymap(void* data UNUSED,
|
||||||
@@ -473,7 +499,13 @@ static void registryHandleGlobal(void* data UNUSED,
|
|||||||
{
|
{
|
||||||
if (!_glfw.wl.seat)
|
if (!_glfw.wl.seat)
|
||||||
{
|
{
|
||||||
_glfw.wl.seatVersion = MIN(5u, version);
|
#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
|
||||||
|
_glfw.wl.seatVersion = MIN(WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION, (int)version);
|
||||||
|
#elif defined(WL_POINTER_AXIS_VALUE120_SINCE_VERSION)
|
||||||
|
_glfw.wl.seatVersion = MIN(WL_POINTER_AXIS_VALUE120_SINCE_VERSION, (int)version);
|
||||||
|
#else
|
||||||
|
_glfw.wl.seatVersion = MIN(WL_POINTER_AXIS_DISCRETE_SINCE_VERSION, version);
|
||||||
|
#endif
|
||||||
_glfw.wl.seat =
|
_glfw.wl.seat =
|
||||||
wl_registry_bind(registry, name, &wl_seat_interface,
|
wl_registry_bind(registry, name, &wl_seat_interface,
|
||||||
_glfw.wl.seatVersion);
|
_glfw.wl.seatVersion);
|
||||||
|
|||||||
27
glfw/wl_platform.h
vendored
27
glfw/wl_platform.h
vendored
@@ -146,6 +146,13 @@ enum WaylandWindowPendingState {
|
|||||||
PENDING_STATE_DECORATION = 2
|
PENDING_STATE_DECORATION = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum _GLFWWaylandAxisEvent {
|
||||||
|
AXIS_EVENT_UNKNOWN = 0,
|
||||||
|
AXIS_EVENT_CONTINUOUS = 1,
|
||||||
|
AXIS_EVENT_DISCRETE = 2,
|
||||||
|
AXIS_EVENT_VALUE120 = 3
|
||||||
|
};
|
||||||
|
|
||||||
// Wayland-specific per-window data
|
// Wayland-specific per-window data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWwindowWayland
|
typedef struct _GLFWwindowWayland
|
||||||
@@ -178,6 +185,20 @@ typedef struct _GLFWwindowWayland
|
|||||||
struct zwlr_layer_surface_v1* zwlr_layer_surface_v1;
|
struct zwlr_layer_surface_v1* zwlr_layer_surface_v1;
|
||||||
} layer_shell;
|
} layer_shell;
|
||||||
|
|
||||||
|
/* information about axis events on current frame */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
enum _GLFWWaylandAxisEvent x_axis_type;
|
||||||
|
float x;
|
||||||
|
enum _GLFWWaylandAxisEvent y_axis_type;
|
||||||
|
float y;
|
||||||
|
} discrete, continuous;
|
||||||
|
|
||||||
|
/* Event timestamp in nanoseconds */
|
||||||
|
monotonic_t timestamp_ns;
|
||||||
|
} pointer_curr_axis_info;
|
||||||
|
|
||||||
_GLFWcursor* currentCursor;
|
_GLFWcursor* currentCursor;
|
||||||
double cursorPosX, cursorPosY, allCursorPosX, allCursorPosY;
|
double cursorPosX, cursorPosY, allCursorPosX, allCursorPosY;
|
||||||
|
|
||||||
@@ -255,12 +276,6 @@ typedef struct _GLFWwindowWayland
|
|||||||
|
|
||||||
|
|
||||||
bool maximize_on_first_show;
|
bool maximize_on_first_show;
|
||||||
// counters for ignoring axis events following axis_discrete events in the
|
|
||||||
// same frame along the same axis
|
|
||||||
struct {
|
|
||||||
unsigned int x, y;
|
|
||||||
} axis_discrete_count;
|
|
||||||
|
|
||||||
uint32_t pending_state;
|
uint32_t pending_state;
|
||||||
struct {
|
struct {
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|||||||
Reference in New Issue
Block a user