[client/idd] input: avoid replaying absolute position
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled

This commit is contained in:
Geoffrey McRae
2026-08-09 02:07:38 +10:00
parent c89c01ae5a
commit 4367fbc277
3 changed files with 60 additions and 50 deletions

View File

@@ -146,7 +146,7 @@ struct LGMPInput
struct LGMPInputStats stats; struct LGMPInputStats stats;
}; };
static void buildKeyboardPayload(const LGMPInput * input, static bool buildKeyboardPayload(const LGMPInput * input,
KVMFRInputPayload * payload); KVMFRInputPayload * payload);
static bool queueMouse(LGMPInput * input, enum LGMPInputMouseMode mode, static bool queueMouse(LGMPInput * input, enum LGMPInputMouseMode mode,
int32_t x, int32_t y, int32_t wheel, uint32_t buttons, int32_t x, int32_t y, int32_t wheel, uint32_t buttons,
@@ -484,12 +484,6 @@ static bool inputStateHeld(const LGMPInput * input)
return false; return false;
} }
static bool inputStateActive(const LGMPInput * input)
{
return input->mouseMode == LGMP_INPUT_MOUSE_ABSOLUTE ||
inputStateHeld(input);
}
static void discardProtocolState(LGMPInput * input) static void discardProtocolState(LGMPInput * input)
{ {
input->pendingHead = 0; input->pendingHead = 0;
@@ -504,18 +498,19 @@ static void discardProtocolState(LGMPInput * input)
static bool restoreInputState(LGMPInput * input, bool * wake) static bool restoreInputState(LGMPInput * input, bool * wake)
{ {
if (!inputStateActive(input)) if (!inputStateHeld(input))
return true; return true;
if (!claim(input, wake)) if (!claim(input, wake))
return false; return false;
KVMFRInputPayload keyboard = { 0 }; KVMFRInputPayload keyboard = { 0 };
buildKeyboardPayload(input, &keyboard); const bool keyboardHeld = buildKeyboardPayload(input, &keyboard);
if (!queuePayload(input, KVMFR_INPUT_MESSAGE_KEYBOARD, if (keyboardHeld && !queuePayload(input, KVMFR_INPUT_MESSAGE_KEYBOARD,
&keyboard, false, wake)) &keyboard, false, wake))
return false; return false;
if (input->mouseMode != LGMP_INPUT_MOUSE_NONE && if (input->mouseButtons &&
input->mouseMode != LGMP_INPUT_MOUSE_NONE &&
!queueMouse(input, input->mouseMode, 0, 0, 0, !queueMouse(input, input->mouseMode, 0, 0, 0,
input->mouseButtons, false, wake)) input->mouseButtons, false, wake))
return false; return false;
@@ -1087,26 +1082,32 @@ static void inputSetStatusListener(void * opaque,
callback(callbackOpaque, &status); callback(callbackOpaque, &status);
} }
static void buildKeyboardPayload(const LGMPInput * input, static bool buildKeyboardPayload(const LGMPInput * input,
KVMFRInputPayload * payload) KVMFRInputPayload * payload)
{ {
bool held = false;
for (unsigned usage = 224; usage <= 231; ++usage) for (unsigned usage = 224; usage <= 231; ++usage)
if (input->keyState[usage]) if (input->keyState[usage])
{
payload->keyboard.modifiers |= 1U << (usage - 224); payload->keyboard.modifiers |= 1U << (usage - 224);
held = true;
}
unsigned count = 0; unsigned count = 0;
for (unsigned usage = 1; usage < 224; ++usage) for (unsigned usage = 1; usage < 224; ++usage)
{ {
if (!input->keyState[usage]) if (!input->keyState[usage])
continue; continue;
held = true;
if (count == KVMFR_INPUT_KEYBOARD_KEY_COUNT) if (count == KVMFR_INPUT_KEYBOARD_KEY_COUNT)
{ {
memset(payload->keyboard.keys, 1, memset(payload->keyboard.keys, 1,
sizeof(payload->keyboard.keys)); sizeof(payload->keyboard.keys));
return; return true;
} }
payload->keyboard.keys[count++] = (uint8_t)usage; payload->keyboard.keys[count++] = (uint8_t)usage;
} }
return held;
} }
static bool updateKey(void * opaque, int key, bool pressed) static bool updateKey(void * opaque, int key, bool pressed)

View File

@@ -200,17 +200,20 @@ bool CInputPipeServer::QueueResetLocked()
switch (m_mouseMode) switch (m_mouseMode)
{ {
case MouseMode::RELATIVE_INPUT: case MouseMode::RELATIVE_INPUT:
if (!QueueRawLocked( if (m_relativeButtons && !QueueRawLocked(
LG_INPUT_PIPE_MESSAGE_MOUSE_RELATIVE, payload, false)) LG_INPUT_PIPE_MESSAGE_MOUSE_RELATIVE, payload, false))
return false; return false;
break; break;
case MouseMode::ABSOLUTE_INPUT: case MouseMode::ABSOLUTE_INPUT:
payload.mouseAbsolute.x = m_absoluteX; if (m_absoluteButtons)
payload.mouseAbsolute.y = m_absoluteY; {
if (!QueueRawLocked( payload.mouseAbsolute.x = m_absoluteX;
LG_INPUT_PIPE_MESSAGE_MOUSE_ABSOLUTE, payload, false)) payload.mouseAbsolute.y = m_absoluteY;
return false; if (!QueueRawLocked(
LG_INPUT_PIPE_MESSAGE_MOUSE_ABSOLUTE, payload, false))
return false;
}
break; break;
case MouseMode::NONE: case MouseMode::NONE:
@@ -270,7 +273,7 @@ bool CInputPipeServer::SendMouseRelative(
const bool pureMotion = wheel == 0 && buttons == m_relativeButtons; const bool pureMotion = wheel == 0 && buttons == m_relativeButtons;
const bool switching = m_mouseMode == MouseMode::ABSOLUTE_INPUT; const bool switching = m_mouseMode == MouseMode::ABSOLUTE_INPUT;
bool queued = (m_state.load(std::memory_order_relaxed) & 1) != 0; bool queued = (m_state.load(std::memory_order_relaxed) & 1) != 0;
if (queued && switching) if (queued && switching && m_absoluteButtons)
{ {
KVMFRInputPayload neutral = {}; KVMFRInputPayload neutral = {};
neutral.mouseAbsolute.x = m_absoluteX; neutral.mouseAbsolute.x = m_absoluteX;
@@ -317,7 +320,7 @@ bool CInputPipeServer::SendMouseAbsolute(
const bool pureMotion = wheel == 0 && buttons == m_absoluteButtons; const bool pureMotion = wheel == 0 && buttons == m_absoluteButtons;
const bool switching = m_mouseMode == MouseMode::RELATIVE_INPUT; const bool switching = m_mouseMode == MouseMode::RELATIVE_INPUT;
bool queued = (m_state.load(std::memory_order_relaxed) & 1) != 0; bool queued = (m_state.load(std::memory_order_relaxed) & 1) != 0;
if (queued && switching) if (queued && switching && m_relativeButtons)
{ {
const KVMFRInputPayload neutral = {}; const KVMFRInputPayload neutral = {};
queued = QueueRawLocked( queued = QueueRawLocked(

View File

@@ -569,9 +569,10 @@ NTSTATUS CHIDDevice::SubmitReport(
NTSTATUS CHIDDevice::ResetReports() NTSTATUS CHIDDevice::ResetReports()
{ {
UCHAR mouseMode = 0; UCHAR mouseMode = 0;
uint16_t absoluteX = 0; uint32_t mouseButtons = 0;
uint16_t absoluteY = 0; uint16_t absoluteX = 0;
uint16_t absoluteY = 0;
{ {
CSRWSharedLock deviceLock(&s_deviceLock); CSRWSharedLock deviceLock(&s_deviceLock);
HIDDeviceContext * context = s_device; HIDDeviceContext * context = s_device;
@@ -583,6 +584,8 @@ NTSTATUS CHIDDevice::ResetReports()
return STATUS_DEVICE_NOT_READY; return STATUS_DEVICE_NOT_READY;
mouseMode = context->mouseMode; mouseMode = context->mouseMode;
mouseButtons = mouseMode == HID_REPORT_ID_MOUSE_ABSOLUTE ?
context->absoluteButtons : context->relativeButtons;
absoluteX = context->absoluteX; absoluteX = context->absoluteX;
absoluteY = context->absoluteY; absoluteY = context->absoluteY;
context->statistics.resetDiscarded += context->reportCount; context->statistics.resetDiscarded += context->reportCount;
@@ -602,36 +605,39 @@ NTSTATUS CHIDDevice::ResetReports()
}; };
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
switch (mouseMode) if (mouseButtons)
{ {
case HID_REPORT_ID_MOUSE_RELATIVE: switch (mouseMode)
{ {
const HIDMouseRelativeReport relative = { case HID_REPORT_ID_MOUSE_RELATIVE:
HID_REPORT_ID_MOUSE_RELATIVE, {
0, const HIDMouseRelativeReport relative = {
0, HID_REPORT_ID_MOUSE_RELATIVE,
0, 0,
0, 0,
}; 0,
status = SubmitReport(&relative, sizeof(relative)); 0,
break; };
} status = SubmitReport(&relative, sizeof(relative));
break;
}
case HID_REPORT_ID_MOUSE_ABSOLUTE: case HID_REPORT_ID_MOUSE_ABSOLUTE:
{ {
const HIDMouseAbsoluteReport absolute = { const HIDMouseAbsoluteReport absolute = {
HID_REPORT_ID_MOUSE_ABSOLUTE, HID_REPORT_ID_MOUSE_ABSOLUTE,
0, 0,
absoluteX, absoluteX,
absoluteY, absoluteY,
0, 0,
}; };
status = SubmitReport(&absolute, sizeof(absolute)); status = SubmitReport(&absolute, sizeof(absolute));
break; break;
} }
default: default:
break; break;
}
} }
const NTSTATUS keyboardStatus = const NTSTATUS keyboardStatus =