From 33ea737f0b4d7e170142d090195bd747c08de073 Mon Sep 17 00:00:00 2001 From: Rom Walton Date: Mon, 18 Oct 2010 19:21:46 +0000 Subject: [PATCH] - 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 svn path=/trunk/boinc/; revision=22547 --- checkin_notes | 23 +++++++++++++++++++++++ clientgui/BOINCGUIApp.cpp | 11 +++++++---- clientgui/BOINCTaskBar.cpp | 9 +++++++++ clientgui/BOINCTaskBar.h | 1 + clientgui/msw/taskbarex.cpp | 21 ++++++++++++++++++--- clientgui/msw/taskbarex.h | 3 +++ 6 files changed, 61 insertions(+), 7 deletions(-) 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