mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-10 09:11:31 +00:00
[client] input: add display server behaviour tests
Extract input policy from the Wayland and X11 protocol handlers. Exercise both implementations against literal Wayland event traces.
This commit is contained in:
@@ -19,6 +19,7 @@ add_library(displayserver_Wayland STATIC
|
||||
icon.c
|
||||
idle.c
|
||||
input.c
|
||||
input_event.c
|
||||
output.c
|
||||
poll.c
|
||||
presentation.c
|
||||
|
||||
@@ -240,7 +240,7 @@ void waylandSetPointer(LG_DSPointer pointer)
|
||||
wlWm.cursorHotY = wlWm.cursorHot[pointer].y;
|
||||
MTRACE("set id=%d surface=%p hot=%d,%d scale=%d entered=%d",
|
||||
pointer, (void *)wlWm.cursor, wlWm.cursorHotX, wlWm.cursorHotY,
|
||||
wlWm.cursorScale, wlWm.pointerInSurface);
|
||||
wlWm.cursorScale, wlWm.input.pointerInSurface);
|
||||
if (wlWm.pointer)
|
||||
wl_pointer_set_cursor(wlWm.pointer, wlWm.pointerEnterSerial, wlWm.cursor, wlWm.cursorHotX, wlWm.cursorHotY);
|
||||
}
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
#include "app.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
const double WL_SCROLL_STEP = 15.0;
|
||||
const double WL_HALF_SCROLL_STEP = WL_SCROLL_STEP / 2.0;
|
||||
|
||||
#define MTRACE(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
@@ -59,6 +56,93 @@ static uint32_t proxyId(void * proxy)
|
||||
return proxy ? wl_proxy_get_id(proxy) : 0;
|
||||
}
|
||||
|
||||
static void inputPosition(void * opaque, double x, double y)
|
||||
{
|
||||
(void)opaque;
|
||||
app_updateCursorPos(x, y);
|
||||
}
|
||||
|
||||
static void inputRelative(void * opaque, double x, double y,
|
||||
double rawX, double rawY)
|
||||
{
|
||||
(void)opaque;
|
||||
app_handleMouseRelative(x, y, rawX, rawY);
|
||||
}
|
||||
|
||||
static void inputButton(void * opaque, unsigned int button, bool pressed)
|
||||
{
|
||||
(void)opaque;
|
||||
if (pressed)
|
||||
app_handleButtonPress(button);
|
||||
else
|
||||
app_handleButtonRelease(button);
|
||||
}
|
||||
|
||||
static void inputWheel(void * opaque, double motion)
|
||||
{
|
||||
(void)opaque;
|
||||
app_handleWheelMotion(motion);
|
||||
}
|
||||
|
||||
static void inputKey(void * opaque, int scancode, bool pressed)
|
||||
{
|
||||
(void)opaque;
|
||||
if (pressed)
|
||||
app_handleKeyPress(scancode);
|
||||
else
|
||||
app_handleKeyRelease(scancode);
|
||||
}
|
||||
|
||||
static void inputText(void * opaque, const char * text)
|
||||
{
|
||||
(void)opaque;
|
||||
/* Test overlay state after the key callback, matching the native event
|
||||
* handler's ordering. */
|
||||
if (app_isOverlayMode())
|
||||
app_handleKeyboardTyped(text);
|
||||
}
|
||||
|
||||
static void inputModifiers(void * opaque, bool ctrl, bool shift, bool alt,
|
||||
bool super)
|
||||
{
|
||||
(void)opaque;
|
||||
app_handleKeyboardModifiers(ctrl, shift, alt, super);
|
||||
}
|
||||
|
||||
static void inputLEDs(void * opaque, bool numLock, bool capsLock,
|
||||
bool scrollLock)
|
||||
{
|
||||
(void)opaque;
|
||||
app_handleKeyboardLEDs(numLock, capsLock, scrollLock);
|
||||
}
|
||||
|
||||
static void inputEnter(void * opaque, bool entered)
|
||||
{
|
||||
(void)opaque;
|
||||
app_handleEnterEvent(entered);
|
||||
}
|
||||
|
||||
static void inputFocus(void * opaque, bool focused)
|
||||
{
|
||||
(void)opaque;
|
||||
if (!focused)
|
||||
waylandCBInvalidate();
|
||||
app_handleFocusEvent(focused);
|
||||
}
|
||||
|
||||
static const LG_DSInputSink inputSink = {
|
||||
.position = inputPosition,
|
||||
.relative = inputRelative,
|
||||
.button = inputButton,
|
||||
.wheel = inputWheel,
|
||||
.key = inputKey,
|
||||
.text = inputText,
|
||||
.modifiers = inputModifiers,
|
||||
.leds = inputLEDs,
|
||||
.enter = inputEnter,
|
||||
.focus = inputFocus,
|
||||
};
|
||||
|
||||
// Mouse-handling listeners.
|
||||
|
||||
static void pointerMotionHandler(void * data, struct wl_pointer * pointer,
|
||||
@@ -68,7 +152,7 @@ static void pointerMotionHandler(void * data, struct wl_pointer * pointer,
|
||||
wl_fixed_to_double(syW));
|
||||
MTRACE("abs time=%u pos=%.3f,%.3f", time, wlWm.motion.x,
|
||||
wlWm.motion.y);
|
||||
app_updateCursorPos(wlWm.motion.x, wlWm.motion.y);
|
||||
wlInputPointerMotion(&wlWm.input, wlWm.motion.x, wlWm.motion.y);
|
||||
}
|
||||
|
||||
static void pointerEnterHandler(void * data, struct wl_pointer * pointer,
|
||||
@@ -79,18 +163,15 @@ static void pointerEnterHandler(void * data, struct wl_pointer * pointer,
|
||||
surface == wlWm.surface, (void *)surface, serial,
|
||||
wl_fixed_to_double(sxW), wl_fixed_to_double(syW));
|
||||
|
||||
if (surface != wlWm.surface)
|
||||
if (!wlInputPointerEnter(&wlWm.input, surface == wlWm.surface))
|
||||
return;
|
||||
|
||||
wlWm.pointerInSurface = true;
|
||||
app_handleEnterEvent(true);
|
||||
|
||||
wl_pointer_set_cursor(pointer, serial, wlWm.cursor, wlWm.cursorHotX, wlWm.cursorHotY);
|
||||
wlWm.pointerEnterSerial = serial;
|
||||
|
||||
wlMotionAbs(&wlWm.motion, wl_fixed_to_double(sxW),
|
||||
wl_fixed_to_double(syW));
|
||||
app_updateCursorPos(wlWm.motion.x, wlWm.motion.y);
|
||||
wlInputPointerMotion(&wlWm.input, wlWm.motion.x, wlWm.motion.y);
|
||||
}
|
||||
|
||||
static void pointerLeaveHandler(void * data, struct wl_pointer * pointer,
|
||||
@@ -99,76 +180,21 @@ static void pointerLeaveHandler(void * data, struct wl_pointer * pointer,
|
||||
MTRACE("leave main=%d surface=%p serial=%u",
|
||||
surface == wlWm.surface, (void *)surface, serial);
|
||||
|
||||
if (surface != wlWm.surface)
|
||||
return;
|
||||
|
||||
wlWm.pointerInSurface = false;
|
||||
app_handleEnterEvent(false);
|
||||
wlInputPointerLeave(&wlWm.input, surface == wlWm.surface);
|
||||
}
|
||||
|
||||
static void pointerAxisHandler(void * data, struct wl_pointer * pointer,
|
||||
uint32_t serial, uint32_t axis, wl_fixed_t value)
|
||||
{
|
||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||
return;
|
||||
|
||||
double delta = wl_fixed_to_double(value);
|
||||
|
||||
wlWm.scrollState += delta;
|
||||
|
||||
while (wlWm.scrollState > WL_HALF_SCROLL_STEP)
|
||||
{
|
||||
app_handleButtonPress(5 /* SPICE_MOUSE_BUTTON_DOWN */);
|
||||
app_handleButtonRelease(5 /* SPICE_MOUSE_BUTTON_DOWN */);
|
||||
wlWm.scrollState -= WL_SCROLL_STEP;
|
||||
}
|
||||
|
||||
while (wlWm.scrollState < -WL_HALF_SCROLL_STEP)
|
||||
{
|
||||
app_handleButtonPress(4 /* SPICE_MOUSE_BUTTON_UP */);
|
||||
app_handleButtonRelease(4 /* SPICE_MOUSE_BUTTON_UP */);
|
||||
wlWm.scrollState += WL_SCROLL_STEP;
|
||||
}
|
||||
|
||||
app_handleWheelMotion(delta / WL_SCROLL_STEP);
|
||||
}
|
||||
|
||||
static int mapWaylandButton(uint32_t button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case BTN_LEFT:
|
||||
return 1;
|
||||
case BTN_MIDDLE:
|
||||
return 2;
|
||||
case BTN_RIGHT:
|
||||
return 3;
|
||||
case BTN_SIDE:
|
||||
return 6;
|
||||
case BTN_EXTRA:
|
||||
return 7;
|
||||
case BTN_FORWARD:
|
||||
return 8;
|
||||
case BTN_BACK:
|
||||
return 9;
|
||||
case BTN_TASK:
|
||||
return 10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
wlInputPointerAxis(&wlWm.input,
|
||||
axis == WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_to_double(value));
|
||||
}
|
||||
|
||||
static void pointerButtonHandler(void *data, struct wl_pointer *pointer,
|
||||
uint32_t serial, uint32_t time, uint32_t button, uint32_t stateW)
|
||||
{
|
||||
button = mapWaylandButton(button);
|
||||
if (!button)
|
||||
return;
|
||||
|
||||
if (stateW == WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
app_handleButtonPress(button);
|
||||
else
|
||||
app_handleButtonRelease(button);
|
||||
wlInputPointerButton(&wlWm.input, button,
|
||||
stateW == WL_POINTER_BUTTON_STATE_PRESSED);
|
||||
}
|
||||
|
||||
static const struct wl_pointer_listener pointerListener = {
|
||||
@@ -223,21 +249,18 @@ static void relativePointerMotionHandler(void * data,
|
||||
wl_fixed_t dxW, wl_fixed_t dyW, wl_fixed_t dxUnaccelW,
|
||||
wl_fixed_t dyUnaccelW)
|
||||
{
|
||||
if (!atomic_load_explicit(&wlWm.lockActive, memory_order_acquire))
|
||||
return;
|
||||
|
||||
const bool active =
|
||||
atomic_load_explicit(&wlWm.lockActive, memory_order_acquire);
|
||||
const double dx = wl_fixed_to_double(dxW);
|
||||
const double dy = wl_fixed_to_double(dyW);
|
||||
MTRACE("rel time=%u:%u delta=%.3f,%.3f raw=%.3f,%.3f "
|
||||
"pos=%.3f,%.3f", timeHi, timeLo, dx, dy,
|
||||
wl_fixed_to_double(dxUnaccelW), wl_fixed_to_double(dyUnaccelW),
|
||||
wlWm.motion.x, wlWm.motion.y);
|
||||
const double rawX = wl_fixed_to_double(dxUnaccelW);
|
||||
const double rawY = wl_fixed_to_double(dyUnaccelW);
|
||||
if (active)
|
||||
MTRACE("rel time=%u:%u delta=%.3f,%.3f raw=%.3f,%.3f "
|
||||
"pos=%.3f,%.3f", timeHi, timeLo, dx, dy, rawX, rawY,
|
||||
wlWm.motion.x, wlWm.motion.y);
|
||||
|
||||
app_handleMouseRelative(
|
||||
dx,
|
||||
dy,
|
||||
wl_fixed_to_double(dxUnaccelW),
|
||||
wl_fixed_to_double(dyUnaccelW));
|
||||
wlInputRelativeMotion(&wlWm.input, active, dx, dy, rawX, rawY);
|
||||
}
|
||||
|
||||
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
|
||||
@@ -314,51 +337,46 @@ static void keyboardEnterHandler(void * data, struct wl_keyboard * keyboard,
|
||||
uint32_t serial, struct wl_surface * surface, struct wl_array * keys)
|
||||
{
|
||||
if (surface != wlWm.surface)
|
||||
{
|
||||
wlInputKeyboardEnter(&wlWm.input, false, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
wlWm.focusedOnSurface = true;
|
||||
app_handleFocusEvent(true);
|
||||
wlWm.keyboardEnterSerial = serial;
|
||||
|
||||
uint32_t * key;
|
||||
wl_array_for_each(key, keys)
|
||||
app_handleKeyPress(*key);
|
||||
wlInputKeyboardEnter(&wlWm.input, true, keys->data,
|
||||
keys->size / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
static void keyboardLeaveHandler(void * data, struct wl_keyboard * keyboard,
|
||||
uint32_t serial, struct wl_surface * surface)
|
||||
{
|
||||
if (surface != wlWm.surface)
|
||||
return;
|
||||
|
||||
wlWm.focusedOnSurface = false;
|
||||
waylandCBInvalidate();
|
||||
app_handleFocusEvent(false);
|
||||
wlInputKeyboardLeave(&wlWm.input, surface == wlWm.surface);
|
||||
}
|
||||
|
||||
static void keyboardKeyHandler(void * data, struct wl_keyboard * keyboard,
|
||||
uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
|
||||
{
|
||||
if (!wlWm.focusedOnSurface)
|
||||
if (!wlWm.input.focused)
|
||||
return;
|
||||
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
app_handleKeyPress(key);
|
||||
else
|
||||
app_handleKeyRelease(key);
|
||||
|
||||
if (!wlWm.xkbState || !app_isOverlayMode() || state != WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
const bool pressed = state == WL_KEYBOARD_KEY_STATE_PRESSED;
|
||||
if (!wlWm.xkbState || !pressed)
|
||||
{
|
||||
wlInputKeyboardKey(&wlWm.input, key, pressed, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
key += 8; // xkb scancode is evdev scancode + 8
|
||||
int size = xkb_state_key_get_utf8(wlWm.xkbState, key, NULL, 0);
|
||||
|
||||
const xkb_keycode_t xkbKey = key + 8;
|
||||
const int size = xkb_state_key_get_utf8(wlWm.xkbState, xkbKey, NULL, 0);
|
||||
if (size <= 0)
|
||||
{
|
||||
wlInputKeyboardKey(&wlWm.input, key, true, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[size + 1];
|
||||
xkb_state_key_get_utf8(wlWm.xkbState, key, buffer, size + 1);
|
||||
app_handleKeyboardTyped(buffer);
|
||||
xkb_state_key_get_utf8(wlWm.xkbState, xkbKey, buffer, size + 1);
|
||||
wlInputKeyboardKey(&wlWm.input, key, true, buffer);
|
||||
}
|
||||
|
||||
static void keyboardModifiersHandler(void * data,
|
||||
@@ -369,18 +387,24 @@ static void keyboardModifiersHandler(void * data,
|
||||
return;
|
||||
|
||||
xkb_state_update_mask(wlWm.xkbState, modsDepressed, modsLatched, modsLocked, 0, 0, group);
|
||||
app_handleKeyboardModifiers(
|
||||
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0,
|
||||
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE) > 0,
|
||||
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE) > 0,
|
||||
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0
|
||||
);
|
||||
const bool ctrl = xkb_state_mod_name_is_active(wlWm.xkbState,
|
||||
XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0;
|
||||
const bool shift = xkb_state_mod_name_is_active(wlWm.xkbState,
|
||||
XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE) > 0;
|
||||
const bool alt = xkb_state_mod_name_is_active(wlWm.xkbState,
|
||||
XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE) > 0;
|
||||
const bool super = xkb_state_mod_name_is_active(wlWm.xkbState,
|
||||
XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0;
|
||||
|
||||
app_handleKeyboardLEDs(
|
||||
xkb_state_led_name_is_active(wlWm.xkbState, XKB_LED_NAME_NUM) > 0,
|
||||
xkb_state_led_name_is_active(wlWm.xkbState, XKB_LED_NAME_CAPS) > 0,
|
||||
xkb_state_led_name_is_active(wlWm.xkbState, XKB_LED_NAME_SCROLL) > 0
|
||||
);
|
||||
const bool numLock = xkb_state_led_name_is_active(wlWm.xkbState,
|
||||
XKB_LED_NAME_NUM) > 0;
|
||||
const bool capsLock = xkb_state_led_name_is_active(wlWm.xkbState,
|
||||
XKB_LED_NAME_CAPS) > 0;
|
||||
const bool scrollLock = xkb_state_led_name_is_active(wlWm.xkbState,
|
||||
XKB_LED_NAME_SCROLL) > 0;
|
||||
|
||||
wlInputKeyboardState(&wlWm.input, ctrl, shift, alt, super,
|
||||
numLock, capsLock, scrollLock);
|
||||
}
|
||||
|
||||
static const struct wl_keyboard_listener keyboardListener = {
|
||||
@@ -468,13 +492,10 @@ static void waylandCleanUpPointer(bool notify)
|
||||
|
||||
wl_pointer_destroy(wlWm.pointer);
|
||||
wlWm.pointer = NULL;
|
||||
wlWm.pointerInSurface = false;
|
||||
});
|
||||
|
||||
MLOG(lockSeq, "lock destroy id=%u why=pointer", lockId);
|
||||
|
||||
if (notify)
|
||||
app_handleEnterEvent(false);
|
||||
wlInputPointerDisconnect(&wlWm.input, notify);
|
||||
}
|
||||
|
||||
// Seat-handling listeners.
|
||||
@@ -531,6 +552,8 @@ static const struct wl_seat_listener seatListener = {
|
||||
|
||||
bool waylandInputInit(bool allowNoInput)
|
||||
{
|
||||
wlInputInit(&wlWm.input, &inputSink, NULL);
|
||||
|
||||
if (!wlWm.seat)
|
||||
{
|
||||
MTRACE("input seat=0 allowNone=%d", allowNoInput);
|
||||
@@ -672,7 +695,7 @@ void waylandWarpPointer(int x, int y, bool exiting)
|
||||
{
|
||||
const int reqX = x;
|
||||
const int reqY = y;
|
||||
if (!wlWm.pointerInSurface)
|
||||
if (!wlWm.input.pointerInSurface)
|
||||
{
|
||||
MTRACE("warp drop=surface target=%d,%d exit=%d", x, y, exiting);
|
||||
return;
|
||||
@@ -737,8 +760,7 @@ void waylandWarpPointer(int x, int y, bool exiting)
|
||||
|
||||
void waylandRealignPointer(void)
|
||||
{
|
||||
if (wlWm.pointerInSurface)
|
||||
app_updateCursorPos(wlWm.motion.x, wlWm.motion.y);
|
||||
wlInputRealignPointer(&wlWm.input, wlWm.motion.x, wlWm.motion.y);
|
||||
}
|
||||
|
||||
void waylandGuestPointerUpdated(double x, double y, double localX,
|
||||
|
||||
179
client/displayservers/Wayland/input_event.c
Normal file
179
client/displayservers/Wayland/input_event.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "input_event.h"
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <string.h>
|
||||
|
||||
static const double WL_SCROLL_STEP = 15.0;
|
||||
static const double WL_HALF_SCROLL_STEP = 7.5;
|
||||
|
||||
void wlInputInit(WaylandInput * input, const LG_DSInputSink * sink,
|
||||
void * opaque)
|
||||
{
|
||||
memset(input, 0, sizeof(*input));
|
||||
input->sink = sink;
|
||||
input->opaque = opaque;
|
||||
}
|
||||
|
||||
bool wlInputPointerEnter(WaylandInput * input, bool mainSurface)
|
||||
{
|
||||
if (!mainSurface)
|
||||
return false;
|
||||
|
||||
input->pointerInSurface = true;
|
||||
input->sink->enter(input->opaque, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wlInputPointerLeave(WaylandInput * input, bool mainSurface)
|
||||
{
|
||||
if (!mainSurface)
|
||||
return false;
|
||||
|
||||
input->pointerInSurface = false;
|
||||
input->sink->enter(input->opaque, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void wlInputPointerDisconnect(WaylandInput * input, bool notify)
|
||||
{
|
||||
input->pointerInSurface = false;
|
||||
if (notify)
|
||||
input->sink->enter(input->opaque, false);
|
||||
}
|
||||
|
||||
void wlInputPointerMotion(WaylandInput * input, double x, double y)
|
||||
{
|
||||
input->sink->position(input->opaque, x, y);
|
||||
}
|
||||
|
||||
static unsigned int mapButton(uint32_t button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case BTN_LEFT:
|
||||
return 1;
|
||||
case BTN_MIDDLE:
|
||||
return 2;
|
||||
case BTN_RIGHT:
|
||||
return 3;
|
||||
case BTN_SIDE:
|
||||
return 6;
|
||||
case BTN_EXTRA:
|
||||
return 7;
|
||||
case BTN_FORWARD:
|
||||
return 8;
|
||||
case BTN_BACK:
|
||||
return 9;
|
||||
case BTN_TASK:
|
||||
return 10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wlInputPointerButton(WaylandInput * input, uint32_t button,
|
||||
bool pressed)
|
||||
{
|
||||
const unsigned int mapped = mapButton(button);
|
||||
if (mapped)
|
||||
input->sink->button(input->opaque, mapped, pressed);
|
||||
}
|
||||
|
||||
void wlInputPointerAxis(WaylandInput * input, bool vertical, double delta)
|
||||
{
|
||||
if (!vertical)
|
||||
return;
|
||||
|
||||
input->scrollState += delta;
|
||||
|
||||
while (input->scrollState > WL_HALF_SCROLL_STEP)
|
||||
{
|
||||
input->sink->button(input->opaque, 5, true);
|
||||
input->sink->button(input->opaque, 5, false);
|
||||
input->scrollState -= WL_SCROLL_STEP;
|
||||
}
|
||||
|
||||
while (input->scrollState < -WL_HALF_SCROLL_STEP)
|
||||
{
|
||||
input->sink->button(input->opaque, 4, true);
|
||||
input->sink->button(input->opaque, 4, false);
|
||||
input->scrollState += WL_SCROLL_STEP;
|
||||
}
|
||||
|
||||
input->sink->wheel(input->opaque, delta / WL_SCROLL_STEP);
|
||||
}
|
||||
|
||||
void wlInputRelativeMotion(WaylandInput * input, bool active,
|
||||
double x, double y, double rawX, double rawY)
|
||||
{
|
||||
if (active)
|
||||
input->sink->relative(input->opaque, x, y, rawX, rawY);
|
||||
}
|
||||
|
||||
void wlInputRealignPointer(WaylandInput * input, double x, double y)
|
||||
{
|
||||
if (input->pointerInSurface)
|
||||
input->sink->position(input->opaque, x, y);
|
||||
}
|
||||
|
||||
bool wlInputKeyboardEnter(WaylandInput * input, bool mainSurface,
|
||||
const uint32_t * keys, size_t count)
|
||||
{
|
||||
if (!mainSurface)
|
||||
return false;
|
||||
|
||||
input->focused = true;
|
||||
input->sink->focus(input->opaque, true);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
input->sink->key(input->opaque, keys[i], true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wlInputKeyboardLeave(WaylandInput * input, bool mainSurface)
|
||||
{
|
||||
if (!mainSurface)
|
||||
return false;
|
||||
|
||||
input->focused = false;
|
||||
input->sink->focus(input->opaque, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void wlInputKeyboardKey(WaylandInput * input, uint32_t key, bool pressed,
|
||||
const char * text)
|
||||
{
|
||||
if (!input->focused)
|
||||
return;
|
||||
|
||||
input->sink->key(input->opaque, key, pressed);
|
||||
if (pressed && text && *text)
|
||||
input->sink->text(input->opaque, text);
|
||||
}
|
||||
|
||||
void wlInputKeyboardState(WaylandInput * input,
|
||||
bool ctrl, bool shift, bool alt, bool super,
|
||||
bool numLock, bool capsLock, bool scrollLock)
|
||||
{
|
||||
input->sink->modifiers(input->opaque, ctrl, shift, alt, super);
|
||||
input->sink->leds(input->opaque, numLock, capsLock, scrollLock);
|
||||
}
|
||||
63
client/displayservers/Wayland/input_event.h
Normal file
63
client/displayservers/Wayland/input_event.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_LG_WAYLAND_INPUT_EVENT_
|
||||
#define _H_LG_WAYLAND_INPUT_EVENT_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../input.h"
|
||||
|
||||
typedef struct WaylandInput
|
||||
{
|
||||
const LG_DSInputSink * sink;
|
||||
void * opaque;
|
||||
double scrollState;
|
||||
bool pointerInSurface;
|
||||
bool focused;
|
||||
}
|
||||
WaylandInput;
|
||||
|
||||
void wlInputInit(WaylandInput * input, const LG_DSInputSink * sink,
|
||||
void * opaque);
|
||||
|
||||
bool wlInputPointerEnter(WaylandInput * input, bool mainSurface);
|
||||
bool wlInputPointerLeave(WaylandInput * input, bool mainSurface);
|
||||
void wlInputPointerDisconnect(WaylandInput * input, bool notify);
|
||||
void wlInputPointerMotion(WaylandInput * input, double x, double y);
|
||||
void wlInputPointerButton(WaylandInput * input, uint32_t button,
|
||||
bool pressed);
|
||||
void wlInputPointerAxis(WaylandInput * input, bool vertical, double delta);
|
||||
void wlInputRelativeMotion(WaylandInput * input, bool active,
|
||||
double x, double y, double rawX, double rawY);
|
||||
void wlInputRealignPointer(WaylandInput * input, double x, double y);
|
||||
|
||||
bool wlInputKeyboardEnter(WaylandInput * input, bool mainSurface,
|
||||
const uint32_t * keys, size_t count);
|
||||
bool wlInputKeyboardLeave(WaylandInput * input, bool mainSurface);
|
||||
void wlInputKeyboardKey(WaylandInput * input, uint32_t key, bool pressed,
|
||||
const char * text);
|
||||
void wlInputKeyboardState(WaylandInput * input,
|
||||
bool ctrl, bool shift, bool alt, bool super,
|
||||
bool numLock, bool capsLock, bool scrollLock);
|
||||
|
||||
#endif
|
||||
@@ -57,6 +57,7 @@
|
||||
|
||||
#include "scale.h"
|
||||
#include "motion.h"
|
||||
#include "input_event.h"
|
||||
|
||||
typedef void (*WaylandPollCallback)(uint32_t events, void * opaque);
|
||||
typedef void (*WaylandPollCleanup)(void * opaque);
|
||||
@@ -128,8 +129,7 @@ struct WaylandDSState
|
||||
{
|
||||
_Atomic(bool) lockActive;
|
||||
bool keyboardGrabbed;
|
||||
bool pointerInSurface;
|
||||
bool focusedOnSurface;
|
||||
WaylandInput input;
|
||||
|
||||
WL_DesktopOps * desktop;
|
||||
|
||||
@@ -147,7 +147,6 @@ struct WaylandDSState
|
||||
bool configured;
|
||||
bool warpSupport;
|
||||
struct WlMotion motion;
|
||||
double scrollState;
|
||||
|
||||
#if defined(ENABLE_EGL) || defined(ENABLE_OPENGL)
|
||||
struct wl_egl_window * eglWindow;
|
||||
|
||||
Reference in New Issue
Block a user