fix(client): restore relative cursor positions locally
Avoid stale server enter coordinates in relative mouse mode by saving and reusing the client's local cursor position around leave and enter. Store Windows restore positions per desktop so UAC and secure desktop transitions do not reuse normal desktop coordinates. This affects relative mouse movement restore behavior while preserving the existing center-on-leave path.
This commit is contained in:
parent
8420d61d34
commit
16141d7156
4 changed files with 89 additions and 4 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016, 2026 Synergy App Ltd
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -154,6 +154,9 @@ void Client::handshakeComplete()
|
|||
{
|
||||
m_ready = true;
|
||||
m_screen->enable();
|
||||
if (m_relativeMouseMoves && !m_hasRelativeRestorePosition) {
|
||||
saveRelativeRestorePosition();
|
||||
}
|
||||
sendEvent(EventTypes::ClientConnected);
|
||||
}
|
||||
|
||||
|
|
@ -195,12 +198,20 @@ void Client::getCursorPos(int32_t &x, int32_t &y) const
|
|||
void Client::enter(int32_t xAbs, int32_t yAbs, uint32_t, KeyModifierMask mask, bool)
|
||||
{
|
||||
m_active = true;
|
||||
if (m_relativeMouseMoves && m_hasRelativeRestorePosition) {
|
||||
xAbs = m_relativeRestoreX;
|
||||
yAbs = m_relativeRestoreY;
|
||||
LOG_VERBOSE("using relative restore position: %d,%d", xAbs, yAbs);
|
||||
}
|
||||
m_screen->mouseMove(xAbs, yAbs);
|
||||
m_screen->enter(mask);
|
||||
}
|
||||
|
||||
bool Client::leave()
|
||||
{
|
||||
if (m_relativeMouseMoves) {
|
||||
saveRelativeRestorePosition();
|
||||
}
|
||||
m_active = false;
|
||||
|
||||
m_screen->leave();
|
||||
|
|
@ -283,6 +294,8 @@ void Client::screensaver(bool activate)
|
|||
|
||||
void Client::resetOptions()
|
||||
{
|
||||
m_relativeMouseMoves = false;
|
||||
m_hasRelativeRestorePosition = false;
|
||||
m_screen->resetOptions();
|
||||
}
|
||||
|
||||
|
|
@ -303,6 +316,14 @@ void Client::setOptions(const OptionsList &options)
|
|||
if (index != options.end()) {
|
||||
m_maximumClipboardSize = *index;
|
||||
}
|
||||
} else if (id == kOptionRelativeMouseMoves) {
|
||||
index++;
|
||||
if (index != options.end()) {
|
||||
m_relativeMouseMoves = (*index != 0);
|
||||
if (m_relativeMouseMoves && m_ready && !m_hasRelativeRestorePosition) {
|
||||
saveRelativeRestorePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +335,13 @@ void Client::setOptions(const OptionsList &options)
|
|||
m_screen->setOptions(options);
|
||||
}
|
||||
|
||||
void Client::saveRelativeRestorePosition()
|
||||
{
|
||||
m_screen->getCursorPos(m_relativeRestoreX, m_relativeRestoreY);
|
||||
m_hasRelativeRestorePosition = true;
|
||||
LOG_VERBOSE("saved relative restore position: %d,%d", m_relativeRestoreX, m_relativeRestoreY);
|
||||
}
|
||||
|
||||
std::string Client::getName() const
|
||||
{
|
||||
return m_name;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016, 2026 Synergy App Ltd
|
||||
* SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -155,6 +155,7 @@ public:
|
|||
std::string getName() const override;
|
||||
|
||||
private:
|
||||
void saveRelativeRestorePosition();
|
||||
void sendClipboard(ClipboardID);
|
||||
void sendEvent(deskflow::EventTypes);
|
||||
void sendConnectionFailedEvent(const char *msg);
|
||||
|
|
@ -200,6 +201,10 @@ private:
|
|||
IEventQueue *m_events = nullptr;
|
||||
bool m_useSecureNetwork = false;
|
||||
bool m_enableClipboard = true;
|
||||
bool m_relativeMouseMoves = false;
|
||||
bool m_hasRelativeRestorePosition = false;
|
||||
int32_t m_relativeRestoreX = 0;
|
||||
int32_t m_relativeRestoreY = 0;
|
||||
size_t m_maximumClipboardSize = INT_MAX;
|
||||
size_t m_resolvedAddressesCount = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
|
||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -181,6 +181,10 @@ void MSWindowsDesks::leave(HKL keyLayout)
|
|||
void MSWindowsDesks::resetOptions()
|
||||
{
|
||||
m_leaveForegroundOption = false;
|
||||
m_relativeMouseMoves = false;
|
||||
for (auto &entry : m_desks) {
|
||||
entry.second->m_hasRelativeRestorePosition = false;
|
||||
}
|
||||
}
|
||||
|
||||
void MSWindowsDesks::setOptions(const OptionsList &options)
|
||||
|
|
@ -189,6 +193,8 @@ void MSWindowsDesks::setOptions(const OptionsList &options)
|
|||
if (options[i] == kOptionWin32KeepForeground) {
|
||||
m_leaveForegroundOption = (options[i + 1] != 0);
|
||||
LOG_VERBOSE("%s the foreground window", m_leaveForegroundOption ? "don\'t grab" : "grab");
|
||||
} else if (options[i] == kOptionRelativeMouseMoves) {
|
||||
m_relativeMouseMoves = (options[i + 1] != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -309,6 +315,39 @@ void MSWindowsDesks::fakeMouseWheel(int32_t xDelta, int32_t yDelta) const
|
|||
sendMessage(DESKFLOW_MSG_FAKE_WHEEL, xDelta, yDelta);
|
||||
}
|
||||
|
||||
void MSWindowsDesks::saveRelativeRestorePosition(Desk *desk) const
|
||||
{
|
||||
POINT pos{0, 0};
|
||||
if (!GetCursorPos(&pos)) {
|
||||
LOG_DEBUG(
|
||||
"could not save relative restore position on desk \"%ls\", error: %lu", desk->m_name.c_str(), GetLastError()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
desk->m_relativeRestoreX = pos.x;
|
||||
desk->m_relativeRestoreY = pos.y;
|
||||
desk->m_hasRelativeRestorePosition = true;
|
||||
LOG_VERBOSE(
|
||||
"saved relative restore position on desk \"%ls\": %+d,%+d", desk->m_name.c_str(), desk->m_relativeRestoreX,
|
||||
desk->m_relativeRestoreY
|
||||
);
|
||||
}
|
||||
|
||||
bool MSWindowsDesks::restoreRelativeCursorPosition(Desk *desk) const
|
||||
{
|
||||
if (!desk->m_hasRelativeRestorePosition) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_VERBOSE(
|
||||
"restoring relative cursor position on desk \"%ls\": %+d,%+d", desk->m_name.c_str(), desk->m_relativeRestoreX,
|
||||
desk->m_relativeRestoreY
|
||||
);
|
||||
deskMouseMove(desk->m_relativeRestoreX, desk->m_relativeRestoreY);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MSWindowsDesks::sendMessage(UINT msg, WPARAM wParam, LPARAM lParam) const
|
||||
{
|
||||
if (m_activeDesk != nullptr && m_activeDesk->m_window != nullptr) {
|
||||
|
|
@ -496,6 +535,9 @@ void MSWindowsDesks::deskEnter(Desk *desk)
|
|||
{
|
||||
if (!m_isPrimary) {
|
||||
ReleaseCapture();
|
||||
if (m_relativeMouseMoves) {
|
||||
restoreRelativeCursorPosition(desk);
|
||||
}
|
||||
}
|
||||
|
||||
setCursorVisibility(true);
|
||||
|
|
@ -519,6 +561,10 @@ void MSWindowsDesks::deskEnter(Desk *desk)
|
|||
|
||||
void MSWindowsDesks::deskLeave(Desk *desk, HKL keyLayout)
|
||||
{
|
||||
if (!m_isPrimary && m_relativeMouseMoves) {
|
||||
saveRelativeRestorePosition(desk);
|
||||
}
|
||||
|
||||
setCursorVisibility(false);
|
||||
|
||||
if (m_isPrimary) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers
|
||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
|
||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
|
|
@ -187,6 +187,9 @@ private:
|
|||
HWND m_window;
|
||||
HWND m_foregroundWindow;
|
||||
bool m_lowLevel;
|
||||
bool m_hasRelativeRestorePosition = false;
|
||||
int32_t m_relativeRestoreX = 0;
|
||||
int32_t m_relativeRestoreY = 0;
|
||||
};
|
||||
using Desks = std::map<std::wstring, Desk *>;
|
||||
|
||||
|
|
@ -201,6 +204,8 @@ private:
|
|||
// message handlers
|
||||
void deskMouseMove(int32_t x, int32_t y) const;
|
||||
void deskMouseRelativeMove(int32_t dx, int32_t dy) const;
|
||||
void saveRelativeRestorePosition(Desk *desk) const;
|
||||
bool restoreRelativeCursorPosition(Desk *desk) const;
|
||||
void deskEnter(Desk *desk);
|
||||
void deskLeave(Desk *desk, HKL keyLayout);
|
||||
void deskThread(const void *vdesk);
|
||||
|
|
@ -276,6 +281,7 @@ private:
|
|||
|
||||
// options
|
||||
bool m_leaveForegroundOption;
|
||||
bool m_relativeMouseMoves = false;
|
||||
|
||||
IEventQueue *m_events;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue