Changed win32 client side cursor warping to be all relative motion

when not on the primary monitor.  This should eliminate the flicker
between virtual display 0,0 and the correct position.  While this
allows the user to confuse synergy by using the client's mouse,
synergy recovers quickly and easily from any confusion.
This commit is contained in:
crs 2003-02-16 19:55:54 +00:00
parent 2fc8780285
commit dd339fe375
1 changed files with 25 additions and 80 deletions

View File

@ -350,35 +350,16 @@ CMSWindowsSecondaryScreen::hideWindow()
void void
CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y) CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
{ {
typedef UINT (WINAPI *SendInput_t)(UINT, LPINPUT, int);
static bool gotSendInput = false;
static SendInput_t SendInput = NULL;
// motion is simple (i.e. it's on the primary monitor) if there // motion is simple (i.e. it's on the primary monitor) if there
// is only one monitor. // is only one monitor.
bool simple = !m_screen->isMultimon(); bool simple = !m_screen->isMultimon();
/* disable attempts to use simple motion with multiple monitors for now
if (!simple) { if (!simple) {
// also simple if motion is within the primary monitor // also simple if motion is within the primary monitor
simple = (x >= 0 && x < GetSystemMetrics(SM_CXSCREEN) && simple = (x >= 0 && x < GetSystemMetrics(SM_CXSCREEN) &&
y >= 0 && y < GetSystemMetrics(SM_CYSCREEN)); y >= 0 && y < GetSystemMetrics(SM_CYSCREEN));
if (!simple && !m_is95Family) {
// also simple if not on windows 95 family since the
// NT family mouse_event() allows absolute moves to
// any monitor.
//
// note -- this is possibly untrue if the primary
// monitor isn't upper-left most so limit it to that
// situation.
SInt32 x0, y0, w, h;
m_screen->getShape(x0, y0, w, h);
simple = (x0 == 0 && y0 == 0);
}
} }
*/
// move the mouse directly to target position on NT family or if // move the mouse directly to target position if motion is simple
// not using multiple monitors.
if (simple) { if (simple) {
SInt32 x0, y0, w, h; SInt32 x0, y0, w, h;
m_screen->getShape(x0, y0, w, h); m_screen->getShape(x0, y0, w, h);
@ -394,39 +375,29 @@ CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
// words, "by design." apparently the designers of windows 2000 // words, "by design." apparently the designers of windows 2000
// we're a little less lazy and did it right. // we're a little less lazy and did it right.
// //
// we use the microsoft recommendation (Q193003): set the absolute // microsoft recommends in Q193003 to absolute position the cursor
// position on the primary monitor, disable mouse acceleration, // somewhere on the primary monitor then relative move to the
// relative move the mouse to the final location, restore mouse // desired location. this doesn't work for us because when the
// acceleration. to avoid one kind of race condition (the user // user drags a scrollbar, a window, etc. it causes the dragged
// clicking the mouse or pressing a key between the absolute and // item to jump back a forth between the position on the primary
// relative move) we'll use SendInput() which guarantees that the // monitor and the desired position. while it always ends up in
// events are delivered uninterrupted. we cannot prevent changes // the right place, the effect is disconcerting.
// to the mouse acceleration at inopportune times, though. if
// SendInput() is unavailable then use mouse_event(); SendInput()
// is not available on Windows 95 and NT 4.0 prior to SP3.
// //
// point-to-activate (x-mouse) doesn't seem to be bothered by the // instead we'll get the cursor's current position and do just a
// absolute/relative combination. a window over the absolute // relative move from there to the desired position. relative
// position (0,0) does *not* get activated (at least not on win2k) // moves are subject to cursor acceleration which we don't want.
// if the relative move puts the cursor elsewhere. similarly, the // so we disable acceleration, do the relative move, then restore
// app under the final mouse position does *not* get deactivated // acceleration. there's a slight chance we'll end up in the
// by the absolute move to 0,0. // wrong place if the user moves the cursor using this system's
// mouse while simultaneously moving the mouse on the server
// system. that defeats the purpose of synergy so we'll assume
// that won't happen. even if it does, the next mouse move will
// correct the position.
else { else {
// lookup SendInput() function
if (!gotSendInput) {
gotSendInput = true;
HINSTANCE user32 = LoadLibrary("user32.dll");
if (user32 != NULL) {
SendInput = reinterpret_cast<SendInput_t>(
GetProcAddress(user32, "SendInput"));
FreeLibrary(user32);
}
}
// save mouse speed & acceleration // save mouse speed & acceleration
int oldSpeed[4]; int oldSpeed[4];
bool accelChanged = bool accelChanged =
SystemParametersInfo(SPI_GETMOUSE,0, oldSpeed,0) && SystemParametersInfo(SPI_GETMOUSE,0, oldSpeed, 0) &&
SystemParametersInfo(SPI_GETMOUSESPEED, 0, oldSpeed + 3, 0); SystemParametersInfo(SPI_GETMOUSESPEED, 0, oldSpeed + 3, 0);
// use 1:1 motion // use 1:1 motion
@ -437,38 +408,12 @@ CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
SystemParametersInfo(SPI_SETMOUSESPEED, 0, newSpeed + 3, 0); SystemParametersInfo(SPI_SETMOUSESPEED, 0, newSpeed + 3, 0);
} }
// send events // get current mouse position
INPUT events[2]; POINT pos;
events[0].type = INPUT_MOUSE; GetCursorPos(&pos);
events[0].mi.dx = 0;
events[0].mi.dy = 0; // move relative to mouse position
events[0].mi.mouseData = 0; mouse_event(MOUSEEVENTF_MOVE, x - pos.x, y - pos.y, 0, 0);
events[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
events[0].mi.time = GetTickCount();
events[0].mi.dwExtraInfo = 0;
events[1].type = INPUT_MOUSE;
events[1].mi.dx = x;
events[1].mi.dy = y;
events[1].mi.mouseData = 0;
events[1].mi.dwFlags = MOUSEEVENTF_MOVE;
events[1].mi.time = events[0].mi.time;
events[1].mi.dwExtraInfo = 0;
if (SendInput != NULL) {
SendInput(sizeof(events) / sizeof(events[0]),
events, sizeof(events[0]));
}
else {
mouse_event(events[0].mi.dwFlags,
events[0].mi.dx,
events[0].mi.dy,
events[0].mi.mouseData,
events[0].mi.dwExtraInfo);
mouse_event(events[1].mi.dwFlags,
events[1].mi.dx,
events[1].mi.dy,
events[1].mi.mouseData,
events[1].mi.dwExtraInfo);
}
// restore mouse speed & acceleration // restore mouse speed & acceleration
if (accelChanged) { if (accelChanged) {