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:
crs 2003-05-17 20:58:27 +00:00
parent 07ed8ebd1c
commit dc6652a21a
9 changed files with 111 additions and 21 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
} }
} }

View File

@ -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;
}; };

View File

@ -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()
{ {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;