From 16b2a83b4113cc7d6a05fa8811f1310474ab2720 Mon Sep 17 00:00:00 2001 From: Rom Walton Date: Thu, 18 Aug 2011 09:56:11 +0000 Subject: [PATCH] - WINSCR: Based on feedback from WCG about the screensaver lock-up problem attempt to provoke Windows into redrawing the primary display. It turns out that the screensaver image is a ghost image, so create a blank top-most window and close it after the graphics application has been terminated. clientscr/ screensaver_win.cpp, .h svn path=/trunk/boinc/; revision=24013 --- checkin_notes | 10 +++ clientscr/screensaver_win.cpp | 139 ++++++++++++++++++++++++++++++++++ clientscr/screensaver_win.h | 5 ++ 3 files changed, 154 insertions(+) diff --git a/checkin_notes b/checkin_notes index ddc44e21f1..410c425c62 100644 --- a/checkin_notes +++ b/checkin_notes @@ -4916,3 +4916,13 @@ Charlie 12 Aug 2011 mac_installer/ AddRemoveUser.cpp PostInstall.cpp + +Rom 18 Aug 2011 + - WINSCR: Based on feedback from WCG about the screensaver lock-up + problem attempt to provoke Windows into redrawing the primary + display. It turns out that the screensaver image is a ghost + image, so create a blank top-most window and close it after + the graphics application has been terminated. + + clientscr/ + screensaver_win.cpp, .h diff --git a/clientscr/screensaver_win.cpp b/clientscr/screensaver_win.cpp index 4657e38804..b00742ba05 100644 --- a/clientscr/screensaver_win.cpp +++ b/clientscr/screensaver_win.cpp @@ -91,6 +91,13 @@ INT WINAPI WinMain( BOINCTRACE("WinMain - Cleanup Screensaver Resources\n"); BOINCSS.Cleanup(); + // Resetting the primary display. We need to do this because abnormally + // terminating grtaphics applications can sometimes leave a ghosted image + // on the primary display which leaves users believing that their machines + // are locked up. + BOINCTRACE("WinMain - Reset Primary Display\n"); + BOINCSS.ResetPrimaryDisplay(); + // Cleanup the Windows sockets interface. BOINCTRACE("WinMain - Cleanup Winsock Resources\n"); WSACleanup(); @@ -1227,6 +1234,71 @@ HRESULT CScreensaver::CreateSaverWindow() { +// Register and create the appropriate window(s) +// +HRESULT CScreensaver::ResetPrimaryDisplay() { + // Register an appropriate window class for the primary display + WNDCLASS cls; + cls.hCursor = LoadCursor(NULL, IDC_ARROW); + cls.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON)); + cls.lpszMenuName = NULL; + cls.lpszClassName = _T("BOINCPrimaryResetWndClass"); + cls.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); + cls.hInstance = m_hInstance; + cls.style = CS_VREDRAW|CS_HREDRAW; + cls.lpfnWndProc = ResetProcStub; + cls.cbWndExtra = 0; + cls.cbClsExtra = 0; + RegisterClass(&cls); + + // Create the window + INTERNALMONITORINFO* pMonitorInfo; + pMonitorInfo = &m_Monitors[0]; + + pMonitorInfo->hWnd = CreateWindowEx( + NULL, + _T("BOINCPrimaryResetWndClass"), + m_strWindowTitle, + WS_VISIBLE | WS_POPUP, + pMonitorInfo->rcScreen.left, + pMonitorInfo->rcScreen.top, + pMonitorInfo->rcScreen.right - pMonitorInfo->rcScreen.left, + pMonitorInfo->rcScreen.bottom - pMonitorInfo->rcScreen.top, + NULL, + NULL, + m_hInstance, + this + ); + + if (pMonitorInfo->hWnd == NULL) { + return E_FAIL; + } + + SetTimer(pMonitorInfo->hWnd, 2, 250, NULL); + + if (m_hWnd == NULL) { + return E_FAIL; + } + + // Message pump + BOOL bGotMsg; + MSG msg; + msg.message = WM_NULL; + while (msg.message != WM_QUIT) { + bGotMsg = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + if (bGotMsg) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + Sleep(10); + } + } + + return S_OK; +} + + + // Run the screensaver graphics - may be preview, test or full-on mode // HRESULT CScreensaver::DoSaver() { @@ -1578,6 +1650,61 @@ LRESULT CScreensaver::GenericSaverProc( +// Handle window messages for resetting the primary display. +// +LRESULT CScreensaver::ResetProc( + HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam +) { + DWORD dwMonitor = 0; + +#ifdef _DEBUG + for(DWORD iIndex = 0; iIndex < m_dwNumMonitors; iIndex++) { + if (hWnd == m_Monitors[iIndex].hWnd ) { + dwMonitor = iIndex; + } + } + BOINCTRACE(_T("CScreensaver::ResetProc [%d] hWnd '%d' uMsg '%X' wParam '%d' lParam '%d'\n"), dwMonitor, hWnd, uMsg, wParam, lParam); +#endif + + switch (uMsg) { + case WM_TIMER: + BOINCTRACE(_T("CScreensaver::ResetProc Received WM_TIMER\n")); + switch (wParam) { + case 1: + KillTimer(hWnd, 1); + CloseWindow(hWnd); + return 0; + break; + } + break; + case WM_PAINT: + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + RECT rc; + GetClientRect(hWnd,&rc); + FillRect(ps.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); + EndPaint(hWnd, &ps); + return 0; + break; + + case WM_CLOSE: + BOINCTRACE(_T("CScreensaver::ResetProc Received WM_CLOSE\n")); + break; + } + + if (WM_SETTIMER == uMsg) { + BOINCTRACE(_T("CScreensaver::ResetProc Received WM_SETTIMER\n")); + // All initialization messages have gone through. Allow + // 500ms of idle time, then proceed with initialization. + SetTimer(hWnd, 1, 250, NULL); + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + + + DWORD CScreensaver::ConvertSliderPositionToTime( DWORD dwPosition ) { return dwTableSliderPositionToTime[dwPosition]; } @@ -1738,6 +1865,18 @@ LRESULT CALLBACK CScreensaver::GenericSaverProcStub( +// This function forwards all window messages to ResetProc, which has +// access to the "this" pointer. +// +LRESULT CALLBACK CScreensaver::ResetProcStub( + HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam +) { + return gspScreensaver->ResetProc(hWnd, uMsg, wParam, lParam); +} + + + + INT_PTR CALLBACK CScreensaver::ConfigureDialogProcStub( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { diff --git a/clientscr/screensaver_win.h b/clientscr/screensaver_win.h index 56fbaa8b60..c5eb36ed7f 100644 --- a/clientscr/screensaver_win.h +++ b/clientscr/screensaver_win.h @@ -213,6 +213,9 @@ protected: // // Presentation layer // +public: + HRESULT ResetPrimaryDisplay(); + protected: HRESULT CreateSaverWindow(); VOID UpdateErrorBox(); @@ -225,6 +228,7 @@ protected: VOID DoPaint( HWND hwnd, HDC hdc, LPPAINTSTRUCT lpps ); LRESULT SaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); LRESULT GenericSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + LRESULT ResetProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); DWORD ConvertSliderPositionToTime( DWORD dwPosition ); DWORD ConvertTimeToSliderPosition( DWORD dwMinutes ); @@ -235,6 +239,7 @@ protected: static LRESULT CALLBACK SaverProcStub( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static LRESULT CALLBACK GenericSaverProcStub( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + static LRESULT CALLBACK ResetProcStub( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static INT_PTR CALLBACK ConfigureDialogProcStub( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); protected: