diff --git a/checkin_notes b/checkin_notes index 85a1de524b..d7a3ff5cea 100644 --- a/checkin_notes +++ b/checkin_notes @@ -7433,3 +7433,26 @@ David 16 Oct 2010 forum_rss.inc client/ sim.cpp + +Rom 16 Oct 2010 + - MGR(WIN): While it is a perfectly valid thing to use FindWindow() and + ShowWindow() on an application frame to restore an application from + a minimized state or a hidden state on Windows(75% of the UI test + automation would fail at Microsoft without this ability), it appeartly + isn't for other platforms. wxWidgets is or appears to be tracking window + state internally, which leads to problems when the OS restores the window + and the rest of the framework doesn't know about that change in state. + Certain window events were being ignored (like WM_CLOSE, menu selection + events, etc.). So replace the previous mechinism for bringing an existing + instance of the BOINC Manager to the foreground by creating a new global + window message which is tracked by the system tray icon. When the new + global message is fired make sure the CBOINCGUIApp::SetActiveGUI() function + is called to restore the window state which in turn updates all the internal + framework data structures. + + clientgui/ + BOINCGUIApp.cpp + clientgui/ + BOINCTaskBar.cpp, .h + clientgui/msw/ + taskbarex.cpp, .h diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index 0e41f22557..18ab27528d 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -674,10 +674,7 @@ void CBOINCGUIApp::DetectAccessibilityEnabled() { /// bool CBOINCGUIApp::DetectDuplicateInstance() { #ifdef __WXMSW__ - HWND hWnd = ::FindWindow(NULL, m_pSkinManager->GetAdvanced()->GetApplicationName().c_str()); - if (hWnd) { - ::ShowWindow(hWnd, SW_SHOW); - ::SetForegroundWindow(hWnd); + if (CTaskBarIcon::FireAppRestore()) { return true; } #endif @@ -1039,11 +1036,17 @@ bool CBOINCGUIApp::SetActiveGUI(int iGUISelection, bool bShowWindow) { if (m_pFrame && !m_pFrame->IsShown() && bShowWindow) { m_pFrame->Show(); m_pFrame->Raise(); +#ifdef __WXMSW__ + ::SetForegroundWindow((HWND)m_pFrame->GetHWND()); +#endif } // Raise the frame to the top of the Z order if needed if (m_pFrame && m_pFrame->IsShown() && bShowWindow) { m_pFrame->Raise(); +#ifdef __WXMSW__ + ::SetForegroundWindow((HWND)m_pFrame->GetHWND()); +#endif } m_iGUISelected = iGUISelection; diff --git a/clientgui/BOINCTaskBar.cpp b/clientgui/BOINCTaskBar.cpp index e0527e052d..10fa9af52b 100644 --- a/clientgui/BOINCTaskBar.cpp +++ b/clientgui/BOINCTaskBar.cpp @@ -70,6 +70,7 @@ BEGIN_EVENT_TABLE(CTaskBarIcon, wxTaskBarIconEx) #ifdef __WXMSW__ EVT_TASKBAR_SHUTDOWN(CTaskBarIcon::OnShutdown) + EVT_TASKBAR_APPRESTORE(CTaskBarIcon::OnAppRestore) #endif #ifdef __WXMAC__ @@ -298,6 +299,14 @@ void CTaskBarIcon::OnShutdown(wxTaskBarIconExEvent& event) { wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnShutdown - Function End")); } +void CTaskBarIcon::OnAppRestore(wxTaskBarIconExEvent& event) { + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnAppRestore - Function Begin")); + + ResetTaskBar(); + wxGetApp().ShowInterface(); + + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnAppRestore - Function End")); +} #endif diff --git a/clientgui/BOINCTaskBar.h b/clientgui/BOINCTaskBar.h index c648b56d8b..c8a7b3deb7 100644 --- a/clientgui/BOINCTaskBar.h +++ b/clientgui/BOINCTaskBar.h @@ -53,6 +53,7 @@ public: void OnNotificationClick(wxTaskBarIconExEvent& event); void OnNotificationTimeout(wxTaskBarIconExEvent& event); + void OnAppRestore(wxTaskBarIconExEvent& event); void OnShutdown(wxTaskBarIconExEvent& event); void OnLButtonDClick(wxTaskBarIconEvent& event); void OnRButtonDown(wxTaskBarIconEvent& event); diff --git a/clientgui/msw/taskbarex.cpp b/clientgui/msw/taskbarex.cpp index e39be0496e..86c9fce7f7 100644 --- a/clientgui/msw/taskbarex.cpp +++ b/clientgui/msw/taskbarex.cpp @@ -44,9 +44,10 @@ LRESULT APIENTRY wxTaskBarIconExWindowProc( HWND hWnd, unsigned msg, UINT wParam wxChar* wxTaskBarExWindowClass = (wxChar*) wxT("wxTaskBarExWindowClass"); wxChar* wxTaskBarExWindow = (wxChar*) wxT("wxTaskBarExWindow"); -const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(wxT("TaskbarCreated")); -const UINT WM_TASKBARMESSAGE = ::RegisterWindowMessage(wxT("TaskbarMessage")); -const UINT WM_TASKBARSHUTDOWN = ::RegisterWindowMessage(wxT("TaskbarShutdown")); +const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(wxT("TaskbarCreated")); +const UINT WM_TASKBARMESSAGE = ::RegisterWindowMessage(wxT("TaskbarMessage")); +const UINT WM_TASKBARSHUTDOWN = ::RegisterWindowMessage(wxT("TaskbarShutdown")); +const UINT WM_TASKBARAPPRESTORE = ::RegisterWindowMessage(wxT("TaskbarAppRestore")); DEFINE_EVENT_TYPE( wxEVT_TASKBAR_CREATED ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_CONTEXT_MENU ) @@ -57,6 +58,7 @@ DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_HIDE ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_TIMEOUT ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_USERCLICK ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_SHUTDOWN ) +DEFINE_EVENT_TYPE( wxEVT_TASKBAR_APPRESTORE ) IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIconEx, wxEvtHandler) @@ -252,6 +254,15 @@ bool wxTaskBarIconEx::PopupMenu(wxMenu *menu) return rval; } +bool wxTaskBarIconEx::FireAppRestore() +{ + HWND hWnd = ::FindWindow(wxTaskBarExWindowClass, NULL); + if (hWnd) { + ::SendMessage(hWnd, WM_TASKBARAPPRESTORE, NULL, NULL); + return true; + } + return false; +} WXHWND wxTaskBarIconEx::CreateTaskBarWindow( wxChar* szWindowTitle ) { @@ -326,6 +337,10 @@ long wxTaskBarIconEx::WindowProc( WXHWND hWnd, unsigned int msg, unsigned int wP { eventType = wxEVT_TASKBAR_SHUTDOWN; } + else if ( WM_TASKBARAPPRESTORE == msg ) + { + eventType = wxEVT_TASKBAR_APPRESTORE; + } else if ( WM_TASKBARMESSAGE == msg ) { switch (lParam) diff --git a/clientgui/msw/taskbarex.h b/clientgui/msw/taskbarex.h index 0cde25c076..267ba6551b 100644 --- a/clientgui/msw/taskbarex.h +++ b/clientgui/msw/taskbarex.h @@ -76,6 +76,7 @@ public: virtual void UpdateIcon(); bool PopupMenu(wxMenu *menu); + static bool FireAppRestore(); // Implementation WXHWND CreateTaskBarWindow( wxChar* szWindowTitle ); @@ -118,6 +119,7 @@ BEGIN_DECLARE_EVENT_TYPES() DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_TIMEOUT, 1563 ) DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_USERCLICK, 1564 ) DECLARE_EVENT_TYPE( wxEVT_TASKBAR_SHUTDOWN, 1565 ) + DECLARE_EVENT_TYPE( wxEVT_TASKBAR_APPRESTORE, 1566 ) END_DECLARE_EVENT_TYPES() typedef void (wxEvtHandler::*wxTaskBarIconExEventFunction)(wxTaskBarIconExEvent&); @@ -137,6 +139,7 @@ typedef void (wxEvtHandler::*wxTaskBarIconExEventFunction)(wxTaskBarIconExEvent& #define EVT_TASKBAR_BALLOON_TIMEOUT(fn) wx__DECLARE_TASKBAREXEVT(BALLOON_TIMEOUT, fn) #define EVT_TASKBAR_CONTEXT_USERCLICK(fn) wx__DECLARE_TASKBAREXEVT(BALLOON_USERCLICK, fn) #define EVT_TASKBAR_SHUTDOWN(fn) wx__DECLARE_TASKBAREXEVT(SHUTDOWN, fn) +#define EVT_TASKBAR_APPRESTORE(fn) wx__DECLARE_TASKBAREXEVT(APPRESTORE, fn) #endif