mirror of https://github.com/BOINC/boinc.git
MGR: Multiple fixes to Async GUI RPCs, message polling, task bar tooltip updates
svn path=/trunk/boinc/; revision=16196
This commit is contained in:
parent
bc35ee14cf
commit
655301bfda
|
@ -8311,3 +8311,24 @@ David 12 Oct 2008
|
|||
|
||||
html/user/
|
||||
create_profile.php
|
||||
|
||||
Charlie 13 Oct 2008
|
||||
- MGR: Multiple fixes to Async GUI RPCs:
|
||||
- Reject most events during RPC Wait dialog. This should
|
||||
eliminate most asserts due to undesired recursion in
|
||||
CMainDocument::RequestRPC().
|
||||
- Always update message list every second, even when in other
|
||||
view tabs or when manager is minimized.
|
||||
- Eliminate separate task bar update timer, update with other
|
||||
periodic RPCs.
|
||||
- Always update task information in task bar icon tooltip when
|
||||
user hovers mouse over task bar icon.
|
||||
- Improve enabling / disabling of task bar icon menu items.
|
||||
|
||||
clientgui/
|
||||
AsyncRPC.cpp,.h
|
||||
BOINCGUIApp.cpp,.h
|
||||
BOINCTaskBar.cpp,.h
|
||||
Events.h
|
||||
MainDocument.cpp,.h
|
||||
|
|
@ -451,15 +451,17 @@ int CMainDocument::RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority) {
|
|||
// a dialog allowing the user to cancel.
|
||||
if (request.rpcType == RPC_TYPE_WAIT_FOR_COMPLETION) {
|
||||
// TODO: proper handling if a second user request is received while first is pending ??
|
||||
// CBOINCGUIApp::FilterEvent() blocks eventrs during our "Please
|
||||
// Wait" dialog, which could cause undesirable recursion here
|
||||
if (m_bWaitingForRPC) {
|
||||
wxLogMessage(wxT("Second user RPC request while another was pending"));
|
||||
//wxASSERT(false);
|
||||
wxASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
m_bWaitingForRPC = true;
|
||||
// Don't show dialog if RPC completes before RPC_WAIT_DLG_DELAY
|
||||
wxStopWatch Dlgdelay = wxStopWatch();
|
||||
m_RPCWaitDlg = new AsyncRPCDlg();
|
||||
m_bWaitingForRPC = true;
|
||||
do {
|
||||
// Simulate handling of CRPCFinishedEvent but don't allow any other events (so no user activity)
|
||||
// Allow RPC thread to run while we wait for it
|
||||
|
@ -514,6 +516,7 @@ int CMainDocument::RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority) {
|
|||
RPC_requests.clear();
|
||||
current_rpc_request.clear();
|
||||
m_bNeedRefresh = false;
|
||||
m_bNeedTaskBarRefresh = false;
|
||||
|
||||
// We will be reconnected to the same client (if possible) by
|
||||
// CBOINCDialUpManager::OnPoll() and CNetworkConnection::Poll().
|
||||
|
@ -594,15 +597,21 @@ void CMainDocument::HandleCompletedRPC() {
|
|||
*(current_rpc_request.resultPtr) = retval;
|
||||
}
|
||||
|
||||
if (current_rpc_request.rpcType == RPC_TYPE_ASYNC_WITH_REFRESH_AFTER) {
|
||||
if (!retval) {
|
||||
m_bNeedRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Post-processing
|
||||
if (! retval) {
|
||||
switch (current_rpc_request.which_rpc) {
|
||||
if (current_rpc_request.rpcType == RPC_TYPE_ASYNC_WITH_REFRESH_AFTER) {
|
||||
if (!retval) {
|
||||
m_bNeedRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_rpc_request.rpcType == RPC_TYPE_ASYNC_WITH_UPDATE_TASKBAR_ICON_AFTER) {
|
||||
if (!retval) {
|
||||
m_bNeedTaskBarRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (current_rpc_request.which_rpc) {
|
||||
case RPC_GET_STATE:
|
||||
if (current_rpc_request.exchangeBuf && !retval) {
|
||||
CC_STATE* arg1 = (CC_STATE*)current_rpc_request.arg1;
|
||||
|
@ -742,6 +751,21 @@ void CMainDocument::HandleCompletedRPC() {
|
|||
}
|
||||
}
|
||||
|
||||
if (m_bNeedTaskBarRefresh && !m_bWaitingForRPC) {
|
||||
m_bNeedTaskBarRefresh = false;
|
||||
CTaskBarIcon* pTaskbar = wxGetApp().GetTaskBarIcon();
|
||||
|
||||
if (pTaskbar) {
|
||||
CTaskbarEvent event(wxEVT_TASKBAR_REFRESH, pTaskbar);
|
||||
pTaskbar->ProcessEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// CachedMessageUpdate() does not do any RPCs, so it is safe here
|
||||
if (current_rpc_request.rpcType == RPC_TYPE_ASYNC_WITH_UPDATE_MESSAGE_LIST_AFTER) {
|
||||
CachedMessageUpdate();
|
||||
}
|
||||
|
||||
current_rpc_request.clear();
|
||||
|
||||
// Start the next RPC request.
|
||||
|
|
|
@ -90,9 +90,15 @@ enum ASYNC_RPC_TYPE {
|
|||
// Periodic RPC: post request on queue and return immediately
|
||||
// (requested due to a timer interrupt.)
|
||||
RPC_TYPE_ASYNC_NO_REFRESH,
|
||||
// Periodic RPCas above, but on completion also process a
|
||||
// Periodic RPC as above, but on completion also process a
|
||||
// wxEVT_FRAME_REFRESHVIEW event to refresh the display.
|
||||
RPC_TYPE_ASYNC_WITH_REFRESH_AFTER,
|
||||
// Periodic RPC as above, but on completion also update message
|
||||
// list by calling CMainDocument::CachedMessageUpdate().
|
||||
RPC_TYPE_ASYNC_WITH_UPDATE_MESSAGE_LIST_AFTER,
|
||||
// Periodic RPC as above, but on completion also process a
|
||||
// wxEVT_TASKBAR_REFRESH event to refresh the taskbar icon.
|
||||
RPC_TYPE_ASYNC_WITH_UPDATE_TASKBAR_ICON_AFTER,
|
||||
NUM_RPC_TYPES
|
||||
|
||||
};
|
||||
|
|
|
@ -865,8 +865,34 @@ bool CBOINCGUIApp::IsModalDialogDisplayed() {
|
|||
if (wxDynamicCast(wxWindow::FindWindowById(ID_ANYDIALOG), wxDialog)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_pDocument) {
|
||||
if (m_pDocument->WaitingForRPC()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Prevent recursive entry of CMainDocument::RequestRPC()
|
||||
int CBOINCGUIApp::FilterEvent(wxEvent &event) {
|
||||
if (!m_pDocument) return -1;
|
||||
if (!m_pDocument->WaitingForRPC()) return -1;
|
||||
|
||||
// If in RPC Please Wait dialog, reject all events except
|
||||
// RPC Finished or those for that dialog or its children.
|
||||
if (event.GetEventType() == wxEVT_RPC_FINISHED) return -1;
|
||||
|
||||
wxDialog* theRPCWaitDialog = m_pDocument->GetRPCWaitDialog();
|
||||
wxObject * theObject = event.GetEventObject();
|
||||
while (theObject) {
|
||||
if (! theObject->IsKindOf(CLASSINFO(wxWindow))) break;
|
||||
if (theObject == theRPCWaitDialog) return -1;
|
||||
theObject = ((wxWindow*)theObject)->GetParent();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *BOINC_RCSID_487cbf3018 = "$Id$";
|
||||
|
|
|
@ -157,6 +157,7 @@ public:
|
|||
int x = wxDefaultCoord, int y = wxDefaultCoord);
|
||||
|
||||
bool IsModalDialogDisplayed();
|
||||
int FilterEvent(wxEvent &event);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
|
@ -41,12 +41,12 @@
|
|||
|
||||
|
||||
DEFINE_EVENT_TYPE(wxEVT_TASKBAR_RELOADSKIN)
|
||||
|
||||
DEFINE_EVENT_TYPE(wxEVT_TASKBAR_REFRESH)
|
||||
|
||||
BEGIN_EVENT_TABLE(CTaskBarIcon, wxTaskBarIconEx)
|
||||
EVT_IDLE(CTaskBarIcon::OnIdle)
|
||||
EVT_CLOSE(CTaskBarIcon::OnClose)
|
||||
EVT_TIMER(ID_TB_TIMER, CTaskBarIcon::OnRefresh)
|
||||
EVT_TASKBAR_REFRESH(CTaskBarIcon::OnRefresh)
|
||||
EVT_TASKBAR_RELOADSKIN(CTaskBarIcon::OnReloadSkin)
|
||||
EVT_TASKBAR_LEFT_DCLICK(CTaskBarIcon::OnLButtonDClick)
|
||||
EVT_MENU(wxID_OPEN, CTaskBarIcon::OnOpen)
|
||||
|
@ -88,19 +88,11 @@ CTaskBarIcon::CTaskBarIcon(wxString title, wxIcon* icon, wxIcon* iconDisconnecte
|
|||
m_dtLastHoverDetected = wxDateTime((time_t)0);
|
||||
|
||||
m_bMouseButtonPressed = false;
|
||||
|
||||
m_pRefreshTimer = new wxTimer(this, ID_TB_TIMER);
|
||||
m_pRefreshTimer->Start(1000); // Send event every second
|
||||
}
|
||||
|
||||
|
||||
CTaskBarIcon::~CTaskBarIcon() {
|
||||
RemoveIcon();
|
||||
|
||||
if (m_pRefreshTimer) {
|
||||
m_pRefreshTimer->Stop();
|
||||
delete m_pRefreshTimer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,7 +120,7 @@ void CTaskBarIcon::OnClose(wxCloseEvent& event) {
|
|||
}
|
||||
|
||||
|
||||
void CTaskBarIcon::OnRefresh(wxTimerEvent& WXUNUSED(event)) {
|
||||
void CTaskBarIcon::OnRefresh(CTaskbarEvent& WXUNUSED(event)) {
|
||||
wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnRefresh - Function Begin"));
|
||||
|
||||
CMainDocument* pDoc = wxGetApp().GetDocument();
|
||||
|
@ -643,7 +635,7 @@ void CTaskBarIcon::AdjustMenuItems(wxMenu* pMenu) {
|
|||
|
||||
for (loc = 0; loc < pMenu->GetMenuItemCount(); loc++) {
|
||||
pMenuItem = pMenu->FindItemByPosition(loc);
|
||||
if (is_dialog_detected) {
|
||||
if (is_dialog_detected && (pMenuItem->GetId() != wxID_OPEN)) {
|
||||
pMenuItem->Enable(false);
|
||||
} else {
|
||||
pMenuItem->Enable(!(pMenuItem->IsSeparator()));
|
||||
|
@ -680,11 +672,15 @@ void CTaskBarIcon::AdjustMenuItems(wxMenu* pMenu) {
|
|||
pMenu->Enable(ID_TB_SUSPEND, false);
|
||||
} else {
|
||||
pMenu->Check(ID_TB_SUSPEND, true);
|
||||
if (!is_dialog_detected) {
|
||||
pMenu->Enable(ID_TB_SUSPEND, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pMenu->Check(ID_TB_SUSPEND, false);
|
||||
if (!is_dialog_detected) {
|
||||
pMenu->Enable(ID_TB_SUSPEND, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
|
||||
void OnIdle(wxIdleEvent& event);
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnRefresh(wxTimerEvent& event);
|
||||
void OnRefresh(CTaskbarEvent& event);
|
||||
void OnReloadSkin(CTaskbarEvent& event);
|
||||
|
||||
void OnMouseMove(wxTaskBarIconEvent& event);
|
||||
|
@ -80,8 +80,6 @@ public:
|
|||
private:
|
||||
wxDateTime m_dtLastHoverDetected;
|
||||
|
||||
wxTimer* m_pRefreshTimer;
|
||||
|
||||
bool m_bMouseButtonPressed;
|
||||
|
||||
void ResetTaskBar();
|
||||
|
@ -116,9 +114,11 @@ public:
|
|||
|
||||
BEGIN_DECLARE_EVENT_TYPES()
|
||||
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_RELOADSKIN, 10100 )
|
||||
DECLARE_EVENT_TYPE( wxEVT_TASKBAR_REFRESH, 10101 )
|
||||
END_DECLARE_EVENT_TYPES()
|
||||
|
||||
#define EVT_TASKBAR_RELOADSKIN(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_TASKBAR_RELOADSKIN, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
|
||||
#define EVT_TASKBAR_REFRESH(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_TASKBAR_REFRESH, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
#define ID_SIMPLE_PREFERENCES 6606
|
||||
#define ID_SIMPLE_MESSAGESVIEW 6607
|
||||
#define ID_SIMPLE_SYNCHRONIZE 6608
|
||||
#define ID_TB_TIMER 6800
|
||||
#define ID_TB_SUSPEND 6801
|
||||
#define ID_LIST_BASE 7000
|
||||
#define ID_LIST_PROJECTSVIEW 7000
|
||||
|
|
|
@ -431,6 +431,7 @@ int CMainDocument::OnInit() {
|
|||
m_RPCWaitDlg = NULL;
|
||||
m_bWaitingForRPC = false;
|
||||
m_bNeedRefresh = false;
|
||||
m_bNeedTaskBarRefresh = false;
|
||||
current_rpc_request.clear();
|
||||
|
||||
m_RPCThread = new RPCThread(this);
|
||||
|
@ -775,9 +776,6 @@ void CMainDocument::RunPeriodicRPCs() {
|
|||
|
||||
int currentTabView = wxGetApp().GetCurrentViewPage();
|
||||
|
||||
// TODO: modify SimpleGUI to not do direct RPC calls when hidden / minimized
|
||||
if (! ((currentTabView & VW_SGUI) || pFrame->IsShown()) ) return;
|
||||
|
||||
// Several functions (such as Abort, Reset, Detach) display an
|
||||
// "Are you sure?" dialog before passing a pointer to a result
|
||||
// or project in a demand RPC call. If Periodic RPCs continue
|
||||
|
@ -787,7 +785,7 @@ void CMainDocument::RunPeriodicRPCs() {
|
|||
//
|
||||
// Note that this depends on using wxGetApp().SafeMessageBox()
|
||||
// instead of wxMessageBox in all tab views.
|
||||
if (wxGetApp().IsModalDialogDisplayed() && !(currentTabView & VW_SMSG)) {
|
||||
if (wxGetApp().IsModalDialogDisplayed() && (currentTabView != (VW_SGUI | VW_SMSG)) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -802,13 +800,30 @@ void CMainDocument::RunPeriodicRPCs() {
|
|||
request.which_rpc = RPC_GET_CC_STATUS;
|
||||
request.arg1 = &async_status_buf;
|
||||
request.exchangeBuf = &status;
|
||||
request.rpcType = RPC_TYPE_ASYNC_NO_REFRESH;
|
||||
request.rpcType = RPC_TYPE_ASYNC_WITH_UPDATE_TASKBAR_ICON_AFTER;
|
||||
request.completionTime = &m_dtCachedCCStatusTimestamp;
|
||||
request.resultPtr = &m_iGet_status_rpc_result;
|
||||
|
||||
RequestRPC(request);
|
||||
}
|
||||
|
||||
// *********** RPC_GET_MESSAGES **************
|
||||
|
||||
request.clear();
|
||||
request.which_rpc = RPC_GET_MESSAGES;
|
||||
// m_iMessageSequenceNumber could change between request and execution
|
||||
// of RPC, so pass in a pointer rather than its value
|
||||
request.arg1 = &m_iMessageSequenceNumber;
|
||||
request.arg2 = &messages;
|
||||
// request.arg2 = &async_messages_buf;
|
||||
// request.exchangeBuf = &messages;
|
||||
request.rpcType = (currentTabView & VW_MSGS) ?
|
||||
RPC_TYPE_ASYNC_WITH_REFRESH_AFTER : RPC_TYPE_ASYNC_WITH_UPDATE_MESSAGE_LIST_AFTER;
|
||||
request.completionTime = NULL;
|
||||
request.resultPtr = &m_iGet_messages_rpc_result;
|
||||
|
||||
RequestRPC(request);
|
||||
|
||||
ts = dtNow - m_dtCachedStateTimestamp;
|
||||
if (ts.GetSeconds() >= STATERPC_INTERVAL) {
|
||||
|
||||
|
@ -835,7 +850,10 @@ void CMainDocument::RunPeriodicRPCs() {
|
|||
|
||||
RequestRPC(request);
|
||||
}
|
||||
|
||||
|
||||
// TODO: modify SimpleGUI to not do direct RPC calls when hidden / minimized
|
||||
if (! ((currentTabView & VW_SGUI) || pFrame->IsShown()) ) return;
|
||||
|
||||
// *********** RPC_GET_PROJECT_STATUS1 **************
|
||||
|
||||
if (currentTabView & VW_PROJ) {
|
||||
|
@ -852,7 +870,7 @@ void CMainDocument::RunPeriodicRPCs() {
|
|||
RequestRPC(request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *********** RPC_GET_RESULTS **************
|
||||
|
||||
if (currentTabView & VW_TASK) {
|
||||
|
@ -887,26 +905,6 @@ void CMainDocument::RunPeriodicRPCs() {
|
|||
}
|
||||
}
|
||||
|
||||
// *********** RPC_GET_MESSAGES **************
|
||||
|
||||
if (currentTabView & (VW_MSGS | VW_SGUI)) {
|
||||
request.clear();
|
||||
request.which_rpc = RPC_GET_MESSAGES;
|
||||
// m_iMessageSequenceNumber could change between request and execution
|
||||
// of RPC, so pass in a pointer rather than its value
|
||||
request.arg1 = &m_iMessageSequenceNumber;
|
||||
request.arg2 = &messages;
|
||||
// request.arg2 = &async_messages_buf;
|
||||
// request.exchangeBuf = &messages;
|
||||
|
||||
request.rpcType = (currentTabView & VW_SGUI) ?
|
||||
RPC_TYPE_ASYNC_NO_REFRESH : RPC_TYPE_ASYNC_WITH_REFRESH_AFTER;
|
||||
request.completionTime = NULL;
|
||||
request.resultPtr = &m_iGet_messages_rpc_result;
|
||||
|
||||
RequestRPC(request);
|
||||
}
|
||||
|
||||
// *********** RPC_GET_STATISTICS **************
|
||||
|
||||
if (currentTabView & VW_STAT) {
|
||||
|
@ -1700,6 +1698,7 @@ int CMainDocument::WorkAbort(std::string& strProjectURL, std::string& strName) {
|
|||
|
||||
|
||||
// Call this only when message buffer is stable
|
||||
// Note: This must not call any rpcs.
|
||||
int CMainDocument::CachedMessageUpdate() {
|
||||
static bool in_this_func = false;
|
||||
|
||||
|
|
|
@ -180,10 +180,12 @@ public:
|
|||
void HandleCompletedRPC();
|
||||
ASYNC_RPC_REQUEST* GetCurrentRPCRequest() { return ¤t_rpc_request; }
|
||||
bool WaitingForRPC() { return m_bWaitingForRPC; }
|
||||
wxDialog* GetRPCWaitDialog() { return m_RPCWaitDlg; }
|
||||
// void TestAsyncRPC(); // For testing Async RPCs
|
||||
RPCThread* m_RPCThread;
|
||||
wxCriticalSection m_critsect;
|
||||
bool m_bNeedRefresh;
|
||||
bool m_bNeedTaskBarRefresh;
|
||||
|
||||
private:
|
||||
int CopyProjectsToStateFile(PROJECTS& p, CC_STATE& state);
|
||||
|
|
Loading…
Reference in New Issue