attempt to fix stuttering when leaving win32 screen. seems to

work but will let testers make the final call.  also fixed
desktop synchronization by setting a variable that was
mistakenly left unset.  and tried to work around an apparent
bug in MsgWaitForMultipleObjects() that prevented the service
from closing down properly.  start/pause/continue/stop
sequence still doesn't shut down correctly.  start/pause/stop
and start/stop work fine.
This commit is contained in:
crs 2002-07-17 17:27:41 +00:00
parent 82cdfb478a
commit 76cc62d133
7 changed files with 108 additions and 96 deletions

View File

@ -1,6 +1,7 @@
#include "CMSWindowsScreen.h" #include "CMSWindowsScreen.h"
#include "CMSWindowsClipboard.h" #include "CMSWindowsClipboard.h"
#include "CMSWindowsScreenSaver.h" #include "CMSWindowsScreenSaver.h"
#include "CPlatform.h"
#include "CClipboard.h" #include "CClipboard.h"
#include "IMSWindowsScreenEventHandler.h" #include "IMSWindowsScreenEventHandler.h"
#include "IScreenReceiver.h" #include "IScreenReceiver.h"
@ -35,6 +36,7 @@ CMSWindowsScreen::CMSWindowsScreen(IScreenReceiver* receiver,
m_class(NULL), m_class(NULL),
m_icon(NULL), m_icon(NULL),
m_cursor(NULL), m_cursor(NULL),
m_is95Family(CPlatform::isWindows95Family()),
m_window(NULL), m_window(NULL),
m_x(0), m_y(0), m_x(0), m_y(0),
m_w(0), m_h(0), m_w(0), m_h(0),
@ -206,7 +208,11 @@ CMSWindowsScreen::mainLoop()
void void
CMSWindowsScreen::exitMainLoop() CMSWindowsScreen::exitMainLoop()
{ {
// post an arbitrary message after the quit because
// MsgWaitForMultipleObjects() is broken and might not wake up if
// just WM_QUIT is in the queue.
PostThreadMessage(m_threadID, WM_QUIT, 0, 0); PostThreadMessage(m_threadID, WM_QUIT, 0, 0);
PostThreadMessage(m_threadID, WM_APP + 1, 0, 0);
} }
void void

View File

@ -187,14 +187,7 @@ mouseHook(int code, WPARAM wParam, LPARAM lParam)
// relay the motion // relay the motion
SInt32 x = (SInt32)info->pt.x; SInt32 x = (SInt32)info->pt.x;
SInt32 y = (SInt32)info->pt.y; SInt32 y = (SInt32)info->pt.y;
if (info->dwExtraInfo == 0x12345678) { PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_MOVE, x, y);
PostThreadMessage(g_threadID,
SYNERGY_MSG_POST_WARP, x, y);
}
else {
PostThreadMessage(g_threadID,
SYNERGY_MSG_MOUSE_MOVE, x, y);
}
} }
return 1; return 1;
} }

View File

@ -19,10 +19,13 @@
#define SYNERGY_MSG_MARK WM_APP + 0x0011 // mark id; <unused> #define SYNERGY_MSG_MARK WM_APP + 0x0011 // mark id; <unused>
#define SYNERGY_MSG_KEY WM_APP + 0x0012 // vk code; key data #define SYNERGY_MSG_KEY WM_APP + 0x0012 // vk code; key data
#define SYNERGY_MSG_MOUSE_BUTTON WM_APP + 0x0013 // button msg; <unused> #define SYNERGY_MSG_MOUSE_BUTTON WM_APP + 0x0013 // button msg; <unused>
#define SYNERGY_MSG_MOUSE_MOVE WM_APP + 0x0014 // x; y #define SYNERGY_MSG_MOUSE_WHEEL WM_APP + 0x0014 // delta; <unused>
#define SYNERGY_MSG_POST_WARP WM_APP + 0x0015 // x; y #define SYNERGY_MSG_MOUSE_MOVE WM_APP + 0x0015 // x; y
#define SYNERGY_MSG_MOUSE_WHEEL WM_APP + 0x0016 // delta; <unused> #define SYNERGY_MSG_POST_WARP WM_APP + 0x0016 // <unused>; <unused>
#define SYNERGY_MSG_SCREEN_SAVER WM_APP + 0x0017 // activated; <unused> #define SYNERGY_MSG_PRE_WARP WM_APP + 0x0017 // x; y
#define SYNERGY_MSG_SCREEN_SAVER WM_APP + 0x0018 // activated; <unused>
#define SYNERGY_MSG_INPUT_FIRST SYNERGY_MSG_KEY
#define SYNERGY_MSG_INPUT_LAST SYNERGY_MSG_PRE_WARP
extern "C" { extern "C" {

View File

@ -19,8 +19,7 @@ CMSWindowsPrimaryScreen::CMSWindowsPrimaryScreen(
m_threadID(0), m_threadID(0),
m_window(NULL), m_window(NULL),
m_mark(0), m_mark(0),
m_markReceived(0), m_markReceived(0)
m_mouseMoveIgnore(0)
{ {
assert(m_receiver != NULL); assert(m_receiver != NULL);
@ -71,9 +70,15 @@ CMSWindowsPrimaryScreen::reconfigure(UInt32 activeSides)
void void
CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y) CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
{ {
// set the cursor position without generating an event // warp mouse
// FIXME -- doesn't this generate an event anyway? warpCursorNoFlush(x, y);
SetCursorPos(x, y);
// remove all input events before and including warp
MSG msg;
while (PeekMessage(&msg, NULL, SYNERGY_MSG_INPUT_FIRST,
SYNERGY_MSG_INPUT_LAST, PM_REMOVE)) {
// do nothing
}
// save position as last position // save position as last position
m_x = x; m_x = x;
@ -165,7 +170,7 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
case SYNERGY_MSG_KEY: case SYNERGY_MSG_KEY:
// ignore message if posted prior to last mark change // ignore message if posted prior to last mark change
if (m_markReceived == m_mark) { if (!ignore()) {
KeyModifierMask mask; KeyModifierMask mask;
const KeyID key = mapKey(msg->wParam, msg->lParam, &mask); const KeyID key = mapKey(msg->wParam, msg->lParam, &mask);
if (key != kKeyNone) { if (key != kKeyNone) {
@ -201,7 +206,7 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
case SYNERGY_MSG_MOUSE_BUTTON: case SYNERGY_MSG_MOUSE_BUTTON:
// ignore message if posted prior to last mark change // ignore message if posted prior to last mark change
if (m_markReceived == m_mark) { if (!ignore()) {
static const int s_vkButton[] = { static const int s_vkButton[] = {
0, // kButtonNone 0, // kButtonNone
VK_LBUTTON, // kButtonLeft, etc. VK_LBUTTON, // kButtonLeft, etc.
@ -236,53 +241,65 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
case SYNERGY_MSG_MOUSE_WHEEL: case SYNERGY_MSG_MOUSE_WHEEL:
// ignore message if posted prior to last mark change // ignore message if posted prior to last mark change
if (m_markReceived == m_mark) { if (!ignore()) {
log((CLOG_ERR "event: button wheel delta=%d %d", msg->wParam, msg->lParam)); log((CLOG_DEBUG1 "event: button wheel delta=%d %d", msg->wParam, msg->lParam));
m_receiver->onMouseWheel(msg->wParam); m_receiver->onMouseWheel(msg->wParam);
} }
return true; return true;
case SYNERGY_MSG_PRE_WARP:
{
// save position to compute delta of next motion
m_x = static_cast<SInt32>(msg->wParam);
m_y = static_cast<SInt32>(msg->lParam);
// we warped the mouse. discard events until we find the
// matching post warp event. see warpCursorNoFlush() for
// where the events are sent. we discard the matching
// post warp event and can be sure we've skipped the warp
// event.
MSG msg;
do {
GetMessage(&msg, NULL, SYNERGY_MSG_MOUSE_MOVE,
SYNERGY_MSG_POST_WARP);
} while (msg.message != SYNERGY_MSG_POST_WARP);
return true;
}
case SYNERGY_MSG_POST_WARP:
log((CLOG_WARN "unmatched post warp"));
return true;
case SYNERGY_MSG_MOUSE_MOVE: case SYNERGY_MSG_MOUSE_MOVE:
// ignore message if posted prior to last mark change // ignore message if posted prior to last mark change
if (m_markReceived == m_mark) { if (!ignore()) {
SInt32 x = static_cast<SInt32>(msg->wParam); // compute motion delta (relative to the last known
SInt32 y = static_cast<SInt32>(msg->lParam); // mouse position)
SInt32 x = static_cast<SInt32>(msg->wParam) - m_x;
SInt32 y = static_cast<SInt32>(msg->lParam) - m_y;
// save position to compute delta of next motion
m_x = static_cast<SInt32>(msg->wParam);
m_y = static_cast<SInt32>(msg->lParam);
if (!isActive()) { if (!isActive()) {
m_receiver->onMouseMovePrimary(x, y); // motion on primary screen
m_receiver->onMouseMovePrimary(m_x, m_y);
} }
else { else {
// compute motion delta. this is relative to the // motion on secondary screen. warp mouse back to
// last known mouse position. // center.
x -= m_x; if (x != 0 || y != 0) {
y -= m_y; // back to center
warpCursorNoFlush(m_xCenter, m_yCenter);
// save position to compute delta of next motion // send motion
m_x = static_cast<SInt32>(msg->wParam); m_receiver->onMouseMoveSecondary(x, y);
m_y = static_cast<SInt32>(msg->lParam);
// ignore if the mouse didn't move or we're ignoring
// motion.
if (m_mouseMoveIgnore == 0) {
if (x != 0 || y != 0) {
// back to center
warpCursorToCenter();
// send motion
m_receiver->onMouseMoveSecondary(x, y);
}
}
else {
// ignored one more motion event
--m_mouseMoveIgnore;
} }
} }
} }
return true; return true;
case SYNERGY_MSG_POST_WARP:
m_x = static_cast<SInt32>(msg->wParam);
m_y = static_cast<SInt32>(msg->lParam);
return true;
} }
return false; return false;
@ -414,9 +431,6 @@ CMSWindowsPrimaryScreen::onPreEnter()
{ {
assert(m_window != NULL); assert(m_window != NULL);
// reset motion ignore count
m_mouseMoveIgnore = 0;
// enable ctrl+alt+del, alt+tab, etc // enable ctrl+alt+del, alt+tab, etc
if (m_is95Family) { if (m_is95Family) {
DWORD dummy = 0; DWORD dummy = 0;
@ -450,23 +464,11 @@ CMSWindowsPrimaryScreen::onPostLeave(bool success)
// relay all mouse and keyboard events // relay all mouse and keyboard events
m_setRelay(true); m_setRelay(true);
// ignore this many mouse motion events (not including the already
// queued events). on (at least) the win2k login desktop, one
// motion event is reported using a position from before the above
// warpCursor(). i don't know why it does that and other desktops
// don't have the same problem. anyway, simply ignoring that event
// works around it.
// FIXME -- is this true now that we're using mouse_event?
m_mouseMoveIgnore = 1;
// disable ctrl+alt+del, alt+tab, etc // disable ctrl+alt+del, alt+tab, etc
if (m_is95Family) { if (m_is95Family) {
DWORD dummy = 0; DWORD dummy = 0;
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0); SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0);
} }
// discard messages until after the warp
nextMark();
} }
} }
@ -550,16 +552,21 @@ CMSWindowsPrimaryScreen::hideWindow()
void void
CMSWindowsPrimaryScreen::warpCursorToCenter() CMSWindowsPrimaryScreen::warpCursorToCenter()
{ {
// warp to center. the extra info tells the hook DLL to send warpCursor(m_xCenter, m_yCenter);
// SYNERGY_MSG_POST_WARP instead of SYNERGY_MSG_MOUSE_MOVE. }
SInt32 x, y, w, h;
m_screen->getShape(x, y, w, h); void
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, CMSWindowsPrimaryScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
(DWORD)((65535.99 * (m_xCenter - x)) / (w - 1)), {
(DWORD)((65535.99 * (m_yCenter - y)) / (h - 1)), // send an event that we can recognize before the mouse warp
0, PostThreadMessage(m_threadID, SYNERGY_MSG_PRE_WARP, x, y);
0x12345678);
// FIXME -- ignore mouse until we get warp notification? // warp mouse. hopefully this inserts a mouse motion event
// between the previous message and the following message.
SetCursorPos(x, y);
// send an event that we can recognize after the mouse warp
PostThreadMessage(m_threadID, SYNERGY_MSG_POST_WARP, 0, 0);
} }
void void
@ -572,6 +579,12 @@ CMSWindowsPrimaryScreen::nextMark()
PostThreadMessage(m_threadID, SYNERGY_MSG_MARK, m_mark, 0); PostThreadMessage(m_threadID, SYNERGY_MSG_MARK, m_mark, 0);
} }
bool
CMSWindowsPrimaryScreen::ignore() const
{
return (m_mark != m_markReceived);
}
static const KeyID g_virtualKey[] = static const KeyID g_virtualKey[] =
{ {
/* 0x00 */ kKeyNone, // reserved /* 0x00 */ kKeyNone, // reserved
@ -984,15 +997,14 @@ CMSWindowsPrimaryScreen::mapKey(
// set shift state required to generate key // set shift state required to generate key
BYTE keys[256]; BYTE keys[256];
memset(keys, 0, sizeof(keys)); memset(keys, 0, sizeof(keys));
// FIXME -- surely these masks should be different in each if expression
if (vkCode & 0x0100) { if (vkCode & 0x0100) {
keys[VK_SHIFT] = 0x80; keys[VK_SHIFT] = 0x80;
} }
if (vkCode & 0x0100) { if (vkCode & 0x0200) {
keys[VK_CONTROL] = 0x80; keys[VK_CONTROL] = 0x80;
} }
if (vkCode & 0x0100) { if (vkCode & 0x0400) {
keys[VK_MENU] = 0x80; keys[VK_MENU] = 0x80;
} }
// strip shift state off of virtual key code // strip shift state off of virtual key code

View File

@ -56,9 +56,15 @@ protected:
private: private:
void enterNoWarp(); void enterNoWarp();
// warp cursor without discarding queued events
void warpCursorNoFlush(SInt32 x, SInt32 y);
// discard posted messages // discard posted messages
void nextMark(); void nextMark();
// test if event should be ignored
bool ignore() const;
// key and button queries // key and button queries
KeyID mapKey(WPARAM keycode, LPARAM info, KeyID mapKey(WPARAM keycode, LPARAM info,
KeyModifierMask* maskOut); KeyModifierMask* maskOut);
@ -91,9 +97,6 @@ private:
// position of center pixel of screen // position of center pixel of screen
SInt32 m_xCenter, m_yCenter; SInt32 m_xCenter, m_yCenter;
// used to ignore mouse motion
SInt32 m_mouseMoveIgnore;
// hook library stuff // hook library stuff
HINSTANCE m_hookLibrary; HINSTANCE m_hookLibrary;
InitFunc m_init; InitFunc m_init;

View File

@ -155,19 +155,12 @@ CPrimaryScreen::leave()
// get keyboard state as we leave // get keyboard state as we leave
updateKeys(); updateKeys();
// warp mouse to center
warpCursorToCenter();
// FIXME -- this doesn't match the win32 version. that just does
// the warp while we flush the input queue until we find the warp
// and we discard that too. would prefer to at least match our
// own warping when we receive MotionNotify; that just does the
// warp. however, the win32 version sometimes stutters when
// leaving and perhaps this is why. hmm, win32 does ignore the
// events until after the warp (via the mark).
// subclass hook // subclass hook
onPostLeave(true); onPostLeave(true);
// warp mouse to center
warpCursorToCenter();
// local client now active // local client now active
m_active = true; m_active = true;

View File

@ -47,7 +47,9 @@ public:
// primary screen are linked to clients. // primary screen are linked to clients.
virtual void reconfigure(UInt32 activeSides) = 0; virtual void reconfigure(UInt32 activeSides) = 0;
// warp the cursor to the given absolute coordinates // warp the cursor to the given absolute coordinates. also
// discard input events up to and including the warp before
// returning.
virtual void warpCursor(SInt32 x, SInt32 y) = 0; virtual void warpCursor(SInt32 x, SInt32 y) = 0;
// set the screen's clipboard contents. this is usually called // set the screen's clipboard contents. this is usually called