Fix high DPI breaking edge detection and mouse delta calculation #5030
This commit is contained in:
parent
66335cd6f8
commit
a09bfc5f07
|
@ -31,6 +31,7 @@
|
|||
#include "synergy/App.h"
|
||||
#include "synergy/ArgsBase.h"
|
||||
#include "synergy/ClientApp.h"
|
||||
#include "synergy/DpiHelper.h"
|
||||
#include "mt/Lock.h"
|
||||
#include "mt/Thread.h"
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
|
@ -143,6 +144,11 @@ MSWindowsScreen::MSWindowsScreen(
|
|||
this, &MSWindowsScreen::updateKeysCB),
|
||||
stopOnDeskSwitch);
|
||||
m_keyState = new MSWindowsKeyState(m_desks, getEventTarget(), m_events);
|
||||
|
||||
DpiHelper::calculateDpi(
|
||||
GetSystemMetrics(SM_CXVIRTUALSCREEN),
|
||||
GetSystemMetrics(SM_CYVIRTUALSCREEN));
|
||||
|
||||
updateScreenShape();
|
||||
m_class = createWindowClass();
|
||||
m_window = createWindow(m_class, "Synergy");
|
||||
|
@ -1347,6 +1353,14 @@ MSWindowsScreen::onMouseButton(WPARAM wParam, LPARAM lParam)
|
|||
bool
|
||||
MSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my)
|
||||
{
|
||||
SInt32 originalMX = mx;
|
||||
SInt32 originalMY = my;
|
||||
|
||||
if (DpiHelper::s_dpiScaled) {
|
||||
mx = (SInt32)(mx / DpiHelper::getDpi());
|
||||
my = (SInt32)(my / DpiHelper::getDpi());
|
||||
}
|
||||
|
||||
// compute motion delta (relative to the last known
|
||||
// mouse position)
|
||||
SInt32 x = mx - m_xCursor;
|
||||
|
@ -1370,7 +1384,7 @@ MSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my)
|
|||
// motion on primary screen
|
||||
sendEvent(
|
||||
m_events->forIPrimaryScreen().motionOnPrimary(),
|
||||
MotionInfo::alloc(m_xCursor, m_yCursor));
|
||||
MotionInfo::alloc(originalMX, originalMY));
|
||||
|
||||
if (m_buttons[kButtonLeft] == true && m_draggingStarted == false) {
|
||||
m_draggingStarted = true;
|
||||
|
@ -1527,20 +1541,25 @@ MSWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
|
|||
POINT cursorPos;
|
||||
GetCursorPos(&cursorPos);
|
||||
|
||||
if ((cursorPos.x != x) && (cursorPos.y != y)) {
|
||||
LOG((CLOG_DEBUG "SetCursorPos did not work; using fakeMouseMove instead"));
|
||||
|
||||
// when at Vista/7 login screen, SetCursorPos does not work (which could be
|
||||
// an MS security feature). instead we can use fakeMouseMove, which calls
|
||||
// mouse_event.
|
||||
// IMPORTANT: as of implementing this function, it has an annoying side
|
||||
// effect; instead of the mouse returning to the correct exit point, it
|
||||
// returns to the center of the screen. this could have something to do with
|
||||
// the center screen warping technique used (see comments for onMouseMove
|
||||
// definition).
|
||||
fakeMouseMove(x, y);
|
||||
// there is a bug or round error in SetCursorPos and GetCursorPos on
|
||||
// a high DPI setting. The check here is for Vista/7 login screen.
|
||||
// since this feature is mainly for client, so only check on client.
|
||||
if (!isPrimary()) {
|
||||
if ((cursorPos.x != x) && (cursorPos.y != y)) {
|
||||
LOG((CLOG_DEBUG "SetCursorPos did not work; using fakeMouseMove instead"));
|
||||
LOG((CLOG_DEBUG "cursor pos %d, %d expected pos %d, %d", cursorPos.x, cursorPos.y, x, y));
|
||||
// when at Vista/7 login screen, SetCursorPos does not work (which could be
|
||||
// an MS security feature). instead we can use fakeMouseMove, which calls
|
||||
// mouse_event.
|
||||
// IMPORTANT: as of implementing this function, it has an annoying side
|
||||
// effect; instead of the mouse returning to the correct exit point, it
|
||||
// returns to the center of the screen. this could have something to do with
|
||||
// the center screen warping technique used (see comments for onMouseMove
|
||||
// definition).
|
||||
fakeMouseMove(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// yield the CPU. there's a race condition when warping:
|
||||
// a hardware mouse event occurs
|
||||
// the mouse hook is not called because that process doesn't have the CPU
|
||||
|
@ -1582,16 +1601,25 @@ MSWindowsScreen::ignore() const
|
|||
void
|
||||
MSWindowsScreen::updateScreenShape()
|
||||
{
|
||||
// get shape
|
||||
// get shape and center
|
||||
if (DpiHelper::s_dpiScaled) {
|
||||
m_w = (SInt32)DpiHelper::s_resolutionWidth;
|
||||
m_h = (SInt32)DpiHelper::s_resolutionHeight;
|
||||
|
||||
m_xCenter = (SInt32)DpiHelper::s_primaryWidthCenter;
|
||||
m_yCenter = (SInt32)DpiHelper::s_primaryHeightCenter;
|
||||
}
|
||||
else {
|
||||
m_w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
m_h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
|
||||
m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1;
|
||||
m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1;
|
||||
}
|
||||
|
||||
// get position
|
||||
m_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
m_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||
m_w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
m_h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
|
||||
// get center for cursor
|
||||
m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1;
|
||||
m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1;
|
||||
|
||||
// check for multiple monitors
|
||||
m_multimon = (m_w != GetSystemMetrics(SM_CXSCREEN) ||
|
||||
m_h != GetSystemMetrics(SM_CYSCREEN));
|
||||
|
|
|
@ -51,6 +51,12 @@ public:
|
|||
*/
|
||||
void getJumpCursorPos(SInt32& x, SInt32& y) const;
|
||||
|
||||
//! Get cursor position
|
||||
/*!
|
||||
Return if this proxy is for client or primary.
|
||||
*/
|
||||
virtual bool isPrimary() const { return false; }
|
||||
|
||||
//@}
|
||||
|
||||
// IScreen
|
||||
|
|
|
@ -148,7 +148,7 @@ public:
|
|||
|
||||
virtual synergy::IStream*
|
||||
getStream() const { return NULL; }
|
||||
|
||||
bool isPrimary() const { return true; }
|
||||
private:
|
||||
synergy::Screen* m_screen;
|
||||
bool m_clipboardDirty[kClipboardEnd];
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "synergy/KeyState.h"
|
||||
#include "synergy/Screen.h"
|
||||
#include "synergy/PacketStreamFilter.h"
|
||||
#include "synergy/DpiHelper.h"
|
||||
#include "net/TCPSocket.h"
|
||||
#include "net/IDataSocket.h"
|
||||
#include "net/IListenSocket.h"
|
||||
|
@ -2000,8 +2001,18 @@ Server::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
|||
m_sendFileThread = NULL;
|
||||
}
|
||||
|
||||
SInt32 newX = m_x;
|
||||
SInt32 newY = m_y;
|
||||
|
||||
if (DpiHelper::s_dpiScaled) {
|
||||
// only scale if it's going back to server
|
||||
if (newScreen->isPrimary()) {
|
||||
newX = (SInt32)(newX / DpiHelper::getDpi());
|
||||
newY = (SInt32)(newY / DpiHelper::getDpi());
|
||||
}
|
||||
}
|
||||
// switch screens
|
||||
switchScreen(newScreen, m_x, m_y, false);
|
||||
switchScreen(newScreen, newX, newY, false);
|
||||
}
|
||||
else {
|
||||
// same screen. clamp mouse to edge.
|
||||
|
|
Loading…
Reference in New Issue