Fixed getting locked to screen after ctrl+alt+del. Also fixed
cursor not being hidden on win32 server when on client screens (which happened when using low-level hooks).
This commit is contained in:
parent
07ed8ebd1c
commit
dc6652a21a
|
@ -319,7 +319,8 @@ CMSWindowsPrimaryScreen::CMSWindowsPrimaryScreen(
|
||||||
m_threadID(0),
|
m_threadID(0),
|
||||||
m_mark(0),
|
m_mark(0),
|
||||||
m_markReceived(0),
|
m_markReceived(0),
|
||||||
m_lowLevel(false)
|
m_lowLevel(false),
|
||||||
|
m_cursorThread(0)
|
||||||
{
|
{
|
||||||
assert(m_receiver != NULL);
|
assert(m_receiver != NULL);
|
||||||
|
|
||||||
|
@ -787,6 +788,13 @@ CMSWindowsPrimaryScreen::preDestroyWindow(HWND)
|
||||||
m_uninstall();
|
m_uninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onAccessibleDesktop()
|
||||||
|
{
|
||||||
|
// get the current keyboard state
|
||||||
|
updateKeys();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsPrimaryScreen::onPreMainLoop()
|
CMSWindowsPrimaryScreen::onPreMainLoop()
|
||||||
{
|
{
|
||||||
|
@ -833,6 +841,18 @@ CMSWindowsPrimaryScreen::onPostClose()
|
||||||
void
|
void
|
||||||
CMSWindowsPrimaryScreen::onPreEnter()
|
CMSWindowsPrimaryScreen::onPreEnter()
|
||||||
{
|
{
|
||||||
|
// show cursor if we hid it
|
||||||
|
if (m_cursorThread != 0) {
|
||||||
|
if (m_threadID != m_cursorThread) {
|
||||||
|
AttachThreadInput(m_threadID, m_cursorThread, TRUE);
|
||||||
|
}
|
||||||
|
ShowCursor(TRUE);
|
||||||
|
if (m_threadID != m_cursorThread) {
|
||||||
|
AttachThreadInput(m_threadID, m_cursorThread, FALSE);
|
||||||
|
}
|
||||||
|
m_cursorThread = 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;
|
||||||
|
@ -869,6 +889,19 @@ CMSWindowsPrimaryScreen::onPostLeave(bool success)
|
||||||
DWORD dummy = 0;
|
DWORD dummy = 0;
|
||||||
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0);
|
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hide the cursor if using low level hooks
|
||||||
|
if (m_lowLevel) {
|
||||||
|
HWND hwnd = GetForegroundWindow();
|
||||||
|
m_cursorThread = GetWindowThreadProcessId(hwnd, NULL);
|
||||||
|
if (m_threadID != m_cursorThread) {
|
||||||
|
AttachThreadInput(m_threadID, m_cursorThread, TRUE);
|
||||||
|
}
|
||||||
|
ShowCursor(FALSE);
|
||||||
|
if (m_threadID != m_cursorThread) {
|
||||||
|
AttachThreadInput(m_threadID, m_cursorThread, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,10 +909,13 @@ void
|
||||||
CMSWindowsPrimaryScreen::createWindow()
|
CMSWindowsPrimaryScreen::createWindow()
|
||||||
{
|
{
|
||||||
// open the desktop and the window
|
// open the desktop and the window
|
||||||
HWND window = m_screen->openDesktop();
|
m_window = m_screen->openDesktop();
|
||||||
if (window == NULL) {
|
if (m_window == NULL) {
|
||||||
throw XScreenOpenFailure();
|
throw XScreenOpenFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we don't ever want our window to activate
|
||||||
|
EnableWindow(m_window, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -892,14 +928,25 @@ CMSWindowsPrimaryScreen::destroyWindow()
|
||||||
bool
|
bool
|
||||||
CMSWindowsPrimaryScreen::showWindow()
|
CMSWindowsPrimaryScreen::showWindow()
|
||||||
{
|
{
|
||||||
// do nothing. we don't need to show a window to capture input.
|
// we don't need a window to capture input but we need a window
|
||||||
|
// to hide the cursor when using low-level hooks. do not try to
|
||||||
|
// take the activation; we want the currently active window to
|
||||||
|
// stay active.
|
||||||
|
if (m_lowLevel) {
|
||||||
|
SetWindowPos(m_window, HWND_TOPMOST, m_xCenter, m_yCenter, 1, 1,
|
||||||
|
SWP_NOACTIVATE);
|
||||||
|
ShowWindow(m_window, SW_SHOWNA);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsPrimaryScreen::hideWindow()
|
CMSWindowsPrimaryScreen::hideWindow()
|
||||||
{
|
{
|
||||||
// do nothing. we don't need to show a window to capture input.
|
// hide our window
|
||||||
|
if (m_lowLevel) {
|
||||||
|
ShowWindow(m_window, SW_HIDE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
virtual void postCreateWindow(HWND);
|
virtual void postCreateWindow(HWND);
|
||||||
virtual void preDestroyWindow(HWND);
|
virtual void preDestroyWindow(HWND);
|
||||||
|
virtual void onAccessibleDesktop();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CPrimaryScreen overrides
|
// CPrimaryScreen overrides
|
||||||
|
@ -101,6 +102,9 @@ private:
|
||||||
// the main loop's thread id
|
// the main loop's thread id
|
||||||
DWORD m_threadID;
|
DWORD m_threadID;
|
||||||
|
|
||||||
|
// my window
|
||||||
|
HWND m_window;
|
||||||
|
|
||||||
// used to discard queued messages that are no longer needed
|
// used to discard queued messages that are no longer needed
|
||||||
UInt32 m_mark;
|
UInt32 m_mark;
|
||||||
UInt32 m_markReceived;
|
UInt32 m_markReceived;
|
||||||
|
@ -128,10 +132,8 @@ private:
|
||||||
SetRelayFunc m_setRelay;
|
SetRelayFunc m_setRelay;
|
||||||
bool m_lowLevel;
|
bool m_lowLevel;
|
||||||
|
|
||||||
// stuff for restoring active window
|
// stuff for hiding the cursor
|
||||||
HWND m_lastForegroundWindow;
|
DWORD m_cursorThread;
|
||||||
HWND m_lastActiveWindow;
|
|
||||||
DWORD m_lastActiveThread;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -68,7 +68,8 @@ CMSWindowsScreen::CMSWindowsScreen(IScreenReceiver* receiver,
|
||||||
m_installScreensaver(NULL),
|
m_installScreensaver(NULL),
|
||||||
m_uninstallScreensaver(NULL),
|
m_uninstallScreensaver(NULL),
|
||||||
m_screensaver(NULL),
|
m_screensaver(NULL),
|
||||||
m_screensaverNotify(false)
|
m_screensaverNotify(false),
|
||||||
|
m_inaccessibleDesktop(false)
|
||||||
{
|
{
|
||||||
assert(s_screen == NULL);
|
assert(s_screen == NULL);
|
||||||
assert(m_receiver != NULL);
|
assert(m_receiver != NULL);
|
||||||
|
@ -384,7 +385,7 @@ CMSWindowsScreen::syncDesktop()
|
||||||
// of sucking up more and more CPU each time it's called (even if
|
// of sucking up more and more CPU each time it's called (even if
|
||||||
// the threads are already attached). since we only expect one
|
// the threads are already attached). since we only expect one
|
||||||
// thread to call this more than once we can save just the last
|
// thread to call this more than once we can save just the last
|
||||||
// the attached thread.
|
// attached thread.
|
||||||
DWORD threadID = GetCurrentThreadId();
|
DWORD threadID = GetCurrentThreadId();
|
||||||
if (threadID != m_lastThreadID && threadID != m_threadID) {
|
if (threadID != m_lastThreadID && threadID != m_threadID) {
|
||||||
m_lastThreadID = threadID;
|
m_lastThreadID = threadID;
|
||||||
|
@ -493,16 +494,27 @@ CMSWindowsScreen::onPreDispatch(const CEvent* event)
|
||||||
if (isCurrentDesktop(desk)) {
|
if (isCurrentDesktop(desk)) {
|
||||||
CloseDesktop(desk);
|
CloseDesktop(desk);
|
||||||
}
|
}
|
||||||
else if (!m_screensaver->isActive()) {
|
else if (m_screensaver->isActive()) {
|
||||||
// don't switch desktops when the screensaver is
|
// don't switch desktops when the screensaver is
|
||||||
// active. we'd most likely switch to the
|
// active. we'd most likely switch to the
|
||||||
// screensaver desktop which would have the side
|
// screensaver desktop which would have the side
|
||||||
// effect of forcing the screensaver to stop.
|
// effect of forcing the screensaver to stop.
|
||||||
switchDesktop(desk);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CloseDesktop(desk);
|
CloseDesktop(desk);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
switchDesktop(desk);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the desktop was inaccessible then notify the
|
||||||
|
// event handler of that.
|
||||||
|
if (m_inaccessibleDesktop) {
|
||||||
|
m_inaccessibleDesktop = false;
|
||||||
|
m_eventHandler->onAccessibleDesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!m_inaccessibleDesktop) {
|
||||||
|
// the desktop has become inaccessible
|
||||||
|
m_inaccessibleDesktop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,13 @@ private:
|
||||||
CMSWindowsScreenSaver* m_screensaver;
|
CMSWindowsScreenSaver* m_screensaver;
|
||||||
bool m_screensaverNotify;
|
bool m_screensaverNotify;
|
||||||
|
|
||||||
|
// true when the current desktop is inaccessible. while
|
||||||
|
// the desktop is inaccessible we won't receive user input
|
||||||
|
// and we'll lose track of the keyboard state. when the
|
||||||
|
// desktop becomes accessible again we'll notify the event
|
||||||
|
// handler of that.
|
||||||
|
bool m_inaccessibleDesktop;
|
||||||
|
|
||||||
static CMSWindowsScreen* s_screen;
|
static CMSWindowsScreen* s_screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -417,6 +417,13 @@ CMSWindowsSecondaryScreen::preDestroyWindow(HWND)
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsSecondaryScreen::onAccessibleDesktop()
|
||||||
|
{
|
||||||
|
// get the current keyboard state
|
||||||
|
updateKeys();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsSecondaryScreen::onPreMainLoop()
|
CMSWindowsSecondaryScreen::onPreMainLoop()
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
virtual void postCreateWindow(HWND);
|
virtual void postCreateWindow(HWND);
|
||||||
virtual void preDestroyWindow(HWND);
|
virtual void preDestroyWindow(HWND);
|
||||||
|
virtual void onAccessibleDesktop();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CSecondaryScreen overrides
|
// CSecondaryScreen overrides
|
||||||
|
|
|
@ -111,10 +111,17 @@ void
|
||||||
hideCursor(DWORD thread)
|
hideCursor(DWORD thread)
|
||||||
{
|
{
|
||||||
// we should be running the context of the window who's cursor
|
// we should be running the context of the window who's cursor
|
||||||
// we want to hide so we shouldn't have to attach thread input.
|
// we want to hide so we shouldn't have to attach thread input
|
||||||
g_cursor = GetCursor();
|
// but we'll check to make sure.
|
||||||
g_cursorThread = thread;
|
g_cursorThread = thread;
|
||||||
SetCursor(NULL);
|
if (g_cursorThread != 0) {
|
||||||
|
DWORD myThread = GetCurrentThreadId();
|
||||||
|
if (myThread != g_cursorThread)
|
||||||
|
AttachThreadInput(myThread, g_cursorThread, TRUE);
|
||||||
|
g_cursor = SetCursor(NULL);
|
||||||
|
if (myThread != g_cursorThread)
|
||||||
|
AttachThreadInput(myThread, g_cursorThread, FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
|
|
@ -37,6 +37,13 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void preDestroyWindow(HWND) = 0;
|
virtual void preDestroyWindow(HWND) = 0;
|
||||||
|
|
||||||
|
//! Notify of newly accessible desktop
|
||||||
|
/*!
|
||||||
|
This is called when the user switched from an inaccessible desktop
|
||||||
|
to an accessible desktop.
|
||||||
|
*/
|
||||||
|
virtual void onAccessibleDesktop() = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
// IScreenEventHandler overrides
|
// IScreenEventHandler overrides
|
||||||
|
|
|
@ -172,12 +172,12 @@ CPrimaryScreen::leave()
|
||||||
// get keyboard state as we leave
|
// get keyboard state as we leave
|
||||||
updateKeys();
|
updateKeys();
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPostLeave(true);
|
|
||||||
|
|
||||||
// warp mouse to center
|
// warp mouse to center
|
||||||
warpCursorToCenter();
|
warpCursorToCenter();
|
||||||
|
|
||||||
|
// subclass hook
|
||||||
|
onPostLeave(true);
|
||||||
|
|
||||||
// local client now active
|
// local client now active
|
||||||
m_active = true;
|
m_active = true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue