- 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
This commit is contained in:
Rom Walton 2010-10-18 19:21:46 +00:00
parent 020a4d4ed1
commit 33ea737f0b
6 changed files with 61 additions and 7 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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