Used MouseKeys accessibility function to show the mouse cursor

on a secondary screen when there's no physical mouse attached to
the system.  Kinda flaky when a mouse is attached or detached but
seems to work well enough when the device is not attached to start
with and not attached while running synergy.
This commit is contained in:
crs 2004-05-02 16:06:04 +00:00
parent 423dd3b718
commit a1bd77f91a
2 changed files with 134 additions and 1 deletions

View File

@ -106,7 +106,9 @@ CMSWindowsScreen::CMSWindowsScreen(bool isPrimary,
m_setMode(NULL), m_setMode(NULL),
m_keyState(NULL), m_keyState(NULL),
m_suspend(suspend), m_suspend(suspend),
m_resume(resume) m_resume(resume),
m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0),
m_showingMouse(false)
{ {
assert(s_instance != NULL); assert(s_instance != NULL);
assert(s_screen == NULL); assert(s_screen == NULL);
@ -125,6 +127,7 @@ CMSWindowsScreen::CMSWindowsScreen(bool isPrimary,
updateScreenShape(); updateScreenShape();
m_class = createWindowClass(); m_class = createWindowClass();
m_window = createWindow(m_class, "Synergy"); m_window = createWindow(m_class, "Synergy");
forceShowCursor();
LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : "")); LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : ""));
LOG((CLOG_DEBUG "window is 0x%08x", m_window)); LOG((CLOG_DEBUG "window is 0x%08x", m_window));
} }
@ -240,6 +243,7 @@ CMSWindowsScreen::disable()
m_nextClipboardWindow = NULL; m_nextClipboardWindow = NULL;
m_isOnScreen = m_isPrimary; m_isOnScreen = m_isPrimary;
forceShowCursor();
} }
void void
@ -259,6 +263,7 @@ CMSWindowsScreen::enter()
// now on screen // now on screen
m_isOnScreen = true; m_isOnScreen = true;
forceShowCursor();
} }
bool bool
@ -292,6 +297,7 @@ CMSWindowsScreen::leave()
// now off screen // now off screen
m_isOnScreen = false; m_isOnScreen = false;
forceShowCursor();
return true; return true;
} }
@ -525,6 +531,36 @@ CMSWindowsScreen::updateKeys()
m_desks->updateKeys(); m_desks->updateKeys();
} }
void
CMSWindowsScreen::fakeKeyDown(KeyID id, KeyModifierMask mask,
KeyButton button)
{
CPlatformScreen::fakeKeyDown(id, mask, button);
updateForceShowCursor();
}
void
CMSWindowsScreen::fakeKeyRepeat(KeyID id, KeyModifierMask mask,
SInt32 count, KeyButton button)
{
CPlatformScreen::fakeKeyRepeat(id, mask, count, button);
updateForceShowCursor();
}
void
CMSWindowsScreen::fakeKeyUp(KeyButton button)
{
CPlatformScreen::fakeKeyUp(button);
updateForceShowCursor();
}
void
CMSWindowsScreen::fakeToggle(KeyModifierMask modifier)
{
CPlatformScreen::fakeToggle(modifier);
updateForceShowCursor();
}
HINSTANCE HINSTANCE
CMSWindowsScreen::openHookLibrary(const char* name) CMSWindowsScreen::openHookLibrary(const char* name)
{ {
@ -829,6 +865,16 @@ CMSWindowsScreen::onEvent(HWND, UINT msg,
} }
*result = TRUE; *result = TRUE;
return true; return true;
case WM_DEVICECHANGE:
forceShowCursor();
break;
case WM_SETTINGCHANGE:
if (wParam == SPI_SETMOUSEKEYS) {
forceShowCursor();
}
break;
} }
return false; return false;
@ -1377,6 +1423,60 @@ CMSWindowsScreen::updateKeysCB(void*)
updateButtons(); updateButtons();
} }
void
CMSWindowsScreen::forceShowCursor()
{
// check for mouse
m_hasMouse = (GetSystemMetrics(SM_MOUSEPRESENT) != 0);
// decide if we should show the mouse
bool showMouse = (!m_hasMouse && !m_isPrimary && m_isOnScreen);
// show/hide the mouse
if (showMouse != m_showingMouse) {
if (showMouse) {
m_oldMouseKeys.cbSize = sizeof(m_oldMouseKeys);
m_gotOldMouseKeys =
(SystemParametersInfo(SPI_GETMOUSEKEYS,
m_oldMouseKeys.cbSize, &m_oldMouseKeys, 0) != 0);
if (m_gotOldMouseKeys) {
m_mouseKeys = m_oldMouseKeys;
m_showingMouse = true;
updateForceShowCursor();
}
}
else {
if (m_gotOldMouseKeys) {
SystemParametersInfo(SPI_SETMOUSEKEYS,
m_oldMouseKeys.cbSize,
&m_oldMouseKeys, SPIF_SENDCHANGE);
m_showingMouse = false;
}
}
}
}
void
CMSWindowsScreen::updateForceShowCursor()
{
DWORD oldFlags = m_mouseKeys.dwFlags;
// turn on MouseKeys
m_mouseKeys.dwFlags = MKF_AVAILABLE | MKF_MOUSEKEYSON;
// make sure MouseKeys is active in whatever state the NumLock is
// not currently in.
if ((m_keyState->getActiveModifiers() & KeyModifierNumLock) != 0) {
m_mouseKeys.dwFlags |= MKF_REPLACENUMBERS;
}
// update MouseKeys
if (oldFlags != m_mouseKeys.dwFlags) {
SystemParametersInfo(SPI_SETMOUSEKEYS,
m_mouseKeys.cbSize, &m_mouseKeys, SPIF_SENDCHANGE);
}
}
LRESULT CALLBACK LRESULT CALLBACK
CMSWindowsScreen::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) CMSWindowsScreen::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {

View File

@ -80,6 +80,12 @@ public:
// IKeyState overrides // IKeyState overrides
virtual void updateKeys(); virtual void updateKeys();
virtual void fakeKeyDown(KeyID id, KeyModifierMask mask,
KeyButton button);
virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask,
SInt32 count, KeyButton button);
virtual void fakeKeyUp(KeyButton button);
virtual void fakeToggle(KeyModifierMask modifier);
// IPlatformScreen overrides // IPlatformScreen overrides
virtual void enable(); virtual void enable();
@ -174,6 +180,16 @@ private:
// job to update the key state // job to update the key state
void updateKeysCB(void*); void updateKeysCB(void*);
// determine whether the mouse is hidden by the system and force
// it to be displayed if user has entered this secondary screen.
void forceShowCursor();
// forceShowCursor uses MouseKeys to show the cursor. since we
// don't actually want MouseKeys behavior we have to make sure
// it applies when NumLock is in whatever state it's not in now.
// this method does that.
void updateForceShowCursor();
// our window proc // our window proc
static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM); static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
@ -250,6 +266,23 @@ private:
IJob* m_suspend; IJob* m_suspend;
IJob* m_resume; IJob* m_resume;
// the system shows the mouse cursor when an internal display count
// is >= 0. this count is maintained per application but there's
// apparently a system wide count added to the application's count.
// this system count is 0 if there's a mouse attached to the system
// and -1 otherwise. the MouseKeys accessibility feature can modify
// this system count by making the system appear to have a mouse.
//
// m_hasMouse is true iff there's a mouse attached to the system or
// MouseKeys is simulating one. we track this so we can force the
// cursor to be displayed when the user has entered this screen.
// m_showingMouse is true when we're doing that.
bool m_hasMouse;
bool m_showingMouse;
bool m_gotOldMouseKeys;
MOUSEKEYS m_mouseKeys;
MOUSEKEYS m_oldMouseKeys;
static CMSWindowsScreen* s_screen; static CMSWindowsScreen* s_screen;
}; };