[client] input: use absolute transport positioning

This commit is contained in:
Geoffrey McRae
2026-08-09 01:23:30 +10:00
parent 27a938e741
commit 3e38c62050
5 changed files with 104 additions and 7 deletions

View File

@@ -139,6 +139,8 @@ void app_updateCursorPos(double x, double y)
if (app_isOverlayMode())
g_state.io->MousePos = (ImVec2) { x, y };
else
core_handleMouseAbsolute();
}
void app_updateMouseState(void)
@@ -267,6 +269,7 @@ void app_handleEnterEvent(bool entered)
return;
g_cursor.realign = true;
core_handleMouseAbsolute();
}
else
{
@@ -471,6 +474,7 @@ void app_handleButtonPress(int button)
if (!core_inputEnabled() || !g_cursor.inView || !g_cursor.viewReq)
return;
core_handleMouseAbsolute();
if (!lgInput_mousePress(button))
DEBUG_ERROR("app_handleButtonPress: failed to send message");
}
@@ -662,6 +666,9 @@ void app_handleMouseBasic(void)
if (!core_inputEnabled())
return;
if (lgInput_supports(LG_INPUT_SUPPORT_MOUSE_ABSOLUTE))
return;
const bool inView =
g_cursor.pos.x >= g_state.dstRect.x &&
g_cursor.pos.x < g_state.dstRect.x + g_state.dstRect.w &&

View File

@@ -282,6 +282,8 @@ void core_handleGrabEvent(bool active)
finishExit();
applyView(active, false);
if (active)
core_handleMouseAbsolute();
}
void core_setGrab(bool enable)
@@ -692,6 +694,38 @@ void core_handleGuestMouseUpdate(void)
);
}
void core_handleMouseAbsolute(void)
{
if (g_cursor.grab || !g_cursor.inWindow || !g_cursor.valid ||
!g_state.haveSrcSize || !g_state.posInfoValid ||
!g_state.focused || g_cursor.realigning ||
app_isOverlayMode() || !core_inputEnabled() ||
!lgInput_supports(LG_INPUT_SUPPORT_MOUSE_ABSOLUTE))
return;
const bool inView = isInView();
if (g_cursor.viewReq != inView || g_cursor.inView != inView)
core_setCursorInView(inView);
if (!inView || !g_cursor.inView || !g_cursor.viewReq)
return;
struct DoublePoint guest;
util_localCurToGuest(&guest);
const uint32_t width = g_state.srcSize.x;
const uint32_t height = g_state.srcSize.y;
const uint32_t x = round(util_clamp(guest.x, 0, width - 1));
const uint32_t y = round(util_clamp(guest.y, 0, height - 1));
MTRACE("absolute local=%.3f,%.3f guest=%u,%u size=%ux%u",
g_cursor.pos.x, g_cursor.pos.y, x, y, width, height);
if (!lgInput_mousePosition(x, y, width, height))
DEBUG_ERROR("failed to send absolute mouse position message");
else
g_cursor.realign = false;
}
void core_handleMouseGrabbed(double ex, double ey)
{
const bool active = g_cursor.grab && g_state.ds->isPointerCaptured();
@@ -730,10 +764,15 @@ void core_handleMouseNormal(double ex, double ey)
"inView=%d", ex, ey, g_cursor.guest.x, g_cursor.guest.y,
g_cursor.guest.valid, g_cursor.inWindow, g_cursor.inView);
const bool absolute =
lgInput_supports(LG_INPUT_SUPPORT_MOUSE_ABSOLUTE);
// prevent cursor handling outside of capture if the position is not known
if (!g_cursor.guest.valid)
{
if (app_guestIsWindows())
if (absolute)
core_handleMouseAbsolute();
else if (app_guestIsWindows())
{
// wiggle the mouse when the guest has not provided any information, we need
// to do this because windows doesn't enable a cursor at all until it has
@@ -793,7 +832,16 @@ void core_handleMouseNormal(double ex, double ey)
}
/* if we have been instructed to realign */
if (g_cursor.realign)
if (g_cursor.realign && absolute)
{
g_cursor.realign = false;
core_handleMouseAbsolute();
if (!g_cursor.inView)
return;
testExit = false;
}
else if (g_cursor.realign)
{
struct DoublePoint guest;
util_localCurToGuest(&guest);
@@ -956,6 +1004,9 @@ fallback:
}
}
if (absolute)
return;
int x, y;
util_cursorToInt(ex, ey, &x, &y);

View File

@@ -39,6 +39,7 @@ void core_stopCursorThread(void);
bool core_startFrameThread(void);
void core_stopFrameThread(void);
void core_handleGuestMouseUpdate(void);
void core_handleMouseAbsolute(void);
void core_handleMouseGrabbed(double ex, double ey);
void core_handleMouseNormal(double ex, double ey);
void core_resetOverlayInputState(void);

View File

@@ -50,6 +50,7 @@ set_tests_properties(wayland-motion-tests PROPERTIES
add_executable(mouse-tests
mouse_test.c
../src/core.c
../src/input.c
../src/util.c
)
target_compile_definitions(mouse-tests PRIVATE

View File

@@ -20,6 +20,7 @@
#include "app.h"
#include "core.h"
#include "input.h"
#include "main.h"
#include "test.h"
#include "util.h"
@@ -241,17 +242,44 @@ void app_mouseTrace(const char * file, unsigned int line,
(void)format;
}
bool lgInput_available(void)
static bool inputSupports(void * opaque, LG_InputSupport support)
{
return g_params.useSpiceInput;
(void)opaque;
(void)support;
return false;
}
bool lgInput_mouseMotion(int32_t x, int32_t y)
static bool inputKey(void * opaque, int key)
{
(void)opaque;
(void)key;
return true;
}
static bool inputMouseMotion(void * opaque, int32_t x, int32_t y)
{
(void)opaque;
push(EV_MOTION, x, y, false);
return true;
}
static bool inputMouseButton(void * opaque, unsigned int button)
{
(void)opaque;
(void)button;
return true;
}
static const LG_InputOps inputOps = {
.name = "test",
.supports = inputSupports,
.keyDown = inputKey,
.keyUp = inputKey,
.mouseMotion = inputMouseMotion,
.mousePress = inputMouseButton,
.mouseRelease = inputMouseButton,
};
static void reset(void)
{
memset(&m, 0, sizeof(m));
@@ -280,8 +308,7 @@ static void reset(void)
.h = 80,
};
g_params.useSpiceInput = true;
g_params.scaleMouseInput = true;
g_params.scaleMouseInput = true;
g_cursor.inWindow = true;
g_cursor.inView = true;
@@ -843,23 +870,33 @@ static const struct Test tests[] = {
int main(int argc, char ** argv)
{
lgInput_init();
lgInput_setFallback(&inputOps, NULL);
if (argc == 2)
{
for (unsigned int i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
if (strcmp(argv[1], tests[i].name) == 0)
{
tests[i].run();
lgInput_free();
return 0;
}
fprintf(stderr, "unknown test: %s\n", argv[1]);
lgInput_free();
return EXIT_FAILURE;
}
if (argc != 1)
{
lgInput_free();
return EXIT_FAILURE;
}
for (unsigned int i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
tests[i].run();
lgInput_free();
return 0;
}