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