diff --git a/uppsrc/CtrlCore/Ctrl.cpp b/uppsrc/CtrlCore/Ctrl.cpp index bff89505f..1a7c55860 100644 --- a/uppsrc/CtrlCore/Ctrl.cpp +++ b/uppsrc/CtrlCore/Ctrl.cpp @@ -36,6 +36,8 @@ int64 Ctrl::eventid; Ctrl *Ctrl::LoopCtrl; int Ctrl::LoopLevel; +int64 Ctrl::EventLoopNo; +int64 Ctrl::EndSessionLoopNo; bool Ctrl::MemoryCheck; diff --git a/uppsrc/CtrlCore/CtrlCore.h b/uppsrc/CtrlCore/CtrlCore.h index 8c9638fa7..f1c880102 100644 --- a/uppsrc/CtrlCore/CtrlCore.h +++ b/uppsrc/CtrlCore/CtrlCore.h @@ -470,6 +470,8 @@ private: static bool painting; static int LoopLevel; static Ctrl *LoopCtrl; + static int64 EventLoopNo; + static int64 EndSessionLoopNo; static int64 eventid; static Ptr defferedSetFocus; diff --git a/uppsrc/CtrlCore/TopWin32.cpp b/uppsrc/CtrlCore/TopWin32.cpp index bd6c91476..d9774ac6a 100644 --- a/uppsrc/CtrlCore/TopWin32.cpp +++ b/uppsrc/CtrlCore/TopWin32.cpp @@ -41,10 +41,6 @@ LRESULT TopWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) inloop = InLoop(); WhenClose(); return inloop ? !InLoop() : !IsOpen(); - case WM_ENDSESSION: - EndSession() = true; - PostQuitMessage(0); - return 0; #endif case WM_CLOSE: if(IsEnabled()) { diff --git a/uppsrc/CtrlCore/TopWindow.cpp b/uppsrc/CtrlCore/TopWindow.cpp index b20ea0d84..ae948be63 100644 --- a/uppsrc/CtrlCore/TopWindow.cpp +++ b/uppsrc/CtrlCore/TopWindow.cpp @@ -76,20 +76,28 @@ void TopWindow::SyncTitle() ICall(THISBACK(SyncTitle0)); } +void TopWindow::DefaultBreak() +{ + if(FindAction(IDCANCEL)) + RejectBreak(IDCANCEL); + else + if(FindAction(IDNO)) + RejectBreak(IDNO); + else + if(FindAction(IDEXIT)) + AcceptBreak(IDEXIT); + else + if(FindAction(IDYES)) + AcceptBreak(IDYES); + else + AcceptBreak(IDOK); +} + void TopWindow::Close() { if(InLoop()) { if(!InCurrentLoop()) return; - if(FindAction(IDCANCEL)) - RejectBreak(IDCANCEL); - else - if(FindAction(IDEXIT)) - AcceptBreak(IDEXIT); - else - if(FindAction(IDYES)) - AcceptBreak(IDYES); - else - AcceptBreak(IDOK); + DefaultBreak(); return; } backup.Clear(); @@ -321,9 +329,14 @@ int TopWindow::Run(bool appmodal) LLOG("EnableCtrls[" << e << "] = " << UPP::Name(disabled[e])); #endif EnableCtrls(disabled); + if(IsNull(exitcode)) { + WhenClose(); + if(IsNull(exitcode)) + DefaultBreak(); + } int q = exitcode; inloop = pinloop; - exitcode = pexitcode; + exitcode = pexitcode; LLOG("TopWindow::Run() = " << q << " -> " << typeid(*this).name()); #ifdef GUI_WIN LLOG("Focus = " << UPP::Name(GetFocusCtrl()) << ", raw " << (void *)::GetFocus()); diff --git a/uppsrc/CtrlCore/TopWindow.h b/uppsrc/CtrlCore/TopWindow.h index 8c8ee8233..78445da64 100644 --- a/uppsrc/CtrlCore/TopWindow.h +++ b/uppsrc/CtrlCore/TopWindow.h @@ -62,6 +62,8 @@ private: void FixIcons(); + void DefaultBreak(); + enum { MINIMIZED, MAXIMIZED, OVERLAPPED }; WString title; diff --git a/uppsrc/CtrlCore/Win32Ctrl.h b/uppsrc/CtrlCore/Win32Ctrl.h index 1508ce164..24b4c25c0 100644 --- a/uppsrc/CtrlCore/Win32Ctrl.h +++ b/uppsrc/CtrlCore/Win32Ctrl.h @@ -16,8 +16,8 @@ private: public: static Event ExitLoopEvent; - static bool& EndSession(); - static bool IsEndSession() { return EndSession(); } + static bool endsession; + static void EndSession(); static HINSTANCE hInstance; protected: diff --git a/uppsrc/CtrlCore/Win32GuiA.h b/uppsrc/CtrlCore/Win32GuiA.h index 3f2d16365..39e09bcfa 100644 --- a/uppsrc/CtrlCore/Win32GuiA.h +++ b/uppsrc/CtrlCore/Win32GuiA.h @@ -22,7 +22,6 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdS UPP::coreCmdLine__() = UPP::SplitCmdLine__(UPP::FromSystemCharset(lpCmdLine)); \ UPP::AppInitEnvironment__(); \ GuiMainFn_(); \ - UPP::Ctrl::CloseTopCtrls(); \ UPP::UsrLog("---------- About to delete this log..."); \ UPP::DeleteUsrLog(); \ UPP::Ctrl::ExitWin32(); \ diff --git a/uppsrc/CtrlCore/Win32Wnd.cpp b/uppsrc/CtrlCore/Win32Wnd.cpp index d19f5d2bb..28690cd3a 100644 --- a/uppsrc/CtrlCore/Win32Wnd.cpp +++ b/uppsrc/CtrlCore/Win32Wnd.cpp @@ -4,15 +4,15 @@ NAMESPACE_UPP -#define LLOG(x) // LOG(x) +#define LLOG(x) // DLOG(x) #define LOGTIMING 0 #ifdef _DEBUG #define LOGMESSAGES 0 #endif -#define ELOGW(x) // RLOG(GetSysTime() << ": " << x) // Only activate in MT! -#define ELOG(x) // RLOG(GetSysTime() << ": " << x) +#define ELOGW(x) // RLOG(GetSysTime() << ": " << x) // Only activate in MT! +#define ELOG(x) // RLOG(GetSysTime() << ": " << x) template<> unsigned GetHashValue(const HWND& h) @@ -65,9 +65,9 @@ static BOOL CALLBACK sDumpWindow(HWND hwnd, LPARAM lParam) { void DumpWindowOrder(bool aliens) { #ifndef PLATFORM_WINCE - LLOG("DumpWindowOrder" << BeginIndent); + LLOG("DumpWindowOrder" << LOG_BEGIN); EnumChildWindows(NULL, &sDumpWindow, (LPARAM)(aliens ? 1 : 0)); - LLOG(EndIndent << "//DumpWindowOrder"); + LLOG(LOG_END << "//DumpWindowOrder"); #endif } @@ -92,7 +92,20 @@ Event Ctrl::ExitLoopEvent; #endif #endif -GLOBAL_VAR(bool, Ctrl::EndSession) +bool Ctrl::endsession; + +void Ctrl::EndSession() +{ + GuiLock __; + EndSessionLoopNo = EventLoopNo; + endsession = true; +} + +template +void AutoCast(U& a, V b) +{ + a = (U)b; +} #ifndef flagDLL #ifndef PLATFORM_WINCE @@ -102,13 +115,30 @@ LRESULT CALLBACK Ctrl::OverwatchWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR ELOGW("WM_USER"); PostQuitMessage(0); } + if(msg == WM_QUERYENDSESSION) { + static BOOL (WINAPI *ShutdownBlockReasonCreate)(HWND hWnd, LPCWSTR pwszReason); + static BOOL (WINAPI *ShutdownBlockReasonDestroy)(HWND hWnd); + ONCELOCK { + if(HMODULE hDLL = LoadLibrary ("user32")) { + AutoCast(ShutdownBlockReasonCreate, GetProcAddress(hDLL, "ShutdownBlockReasonCreate")); + AutoCast(ShutdownBlockReasonDestroy, GetProcAddress(hDLL, "ShutdownBlockReasonCreate")); + } + } + if(ShutdownBlockReasonCreate) + ShutdownBlockReasonCreate(hwnd, ~WString(t_("waiting for user response"))); + EndSession(); + ELOGW("WM_QUERYENDSESSION 1"); + OverwatchEndSession.Wait(); + if(ShutdownBlockReasonDestroy) + ShutdownBlockReasonDestroy(hwnd); + ELOGW("WM_QUERYENDSESSION 2"); + return TRUE; + } if(msg == WM_ENDSESSION) { - EndSession() = true; + EndSession(); ELOGW("WM_ENDSESSION 1"); ExitLoopEvent.Set(); ELOGW("WM_ENDSESSION 2"); - OverwatchEndSession.Wait(); - ELOGW("WM_ENDSESSION 3"); } return DefWindowProc(hwnd, msg, wParam, lParam); } @@ -320,10 +350,13 @@ void Ctrl::ExitWin32() { RenderAllFormats(); + TopWindow::ShutdownWindows(); + CloseTopCtrls(); + OleUninitialize(); sFinished = true; - + for(int i = 0; i < hotkey.GetCount(); i++) if(hotkey[i]) UnregisterHotKey(NULL, i); @@ -514,7 +547,7 @@ void Ctrl::Create0(Ctrl::CreateBox *cr) { GuiLock __; ASSERT(IsMainThread()); - LLOG("Ctrl::Create(parent = " << (void *)parent << ") in " <style, FALSE, cr->exstyle); @@ -558,7 +591,7 @@ void Ctrl::Create0(Ctrl::CreateBox *cr) ::ShowWindow(top->hwnd, visible ? cr->show : SW_HIDE); // ::UpdateWindow(hwnd); StateH(OPEN); - LLOG(EndIndent << "//Ctrl::Create in " <hwnd, (LPDROPTARGET) (top->dndtgt = NewUDropTarget(this))); CancelMode(); RefreshLayoutDeep(); @@ -585,7 +618,7 @@ void Ctrl::WndFree() LLOG("Ctrl::WndFree->SetFocus " << UPP::Name(Ctrl::CtrlFromHWND(owner))); ::SetFocus(owner); } - LLOG(EndIndent << "//Ctrl::WndFree() in " <hwnd) { HWND hwnd = top->hwnd; @@ -807,8 +840,6 @@ bool Ctrl::ProcessEvent(bool *quit) ASSERT(IsMainThread()); if(DoCall()) return false; - if(EndSession()) - return false; if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle()) ReleaseCtrlCapture(); MSG msg; @@ -844,7 +875,7 @@ void Ctrl::EventLoop0(Ctrl *ctrl) ASSERT(IsMainThread()); ASSERT(LoopLevel == 0 || ctrl); LoopLevel++; - LLOG("Entering event loop at level " << LoopLevel << BeginIndent); + LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN); Ptr ploop; if(ctrl) { ploop = LoopCtrl; @@ -853,13 +884,13 @@ void Ctrl::EventLoop0(Ctrl *ctrl) } bool quit = false; + int64 loopno = ++EventLoopNo; ProcessEvents(&quit); - while(!EndSession() && !quit && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount())) + while(loopno > EndSessionLoopNo && !quit && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount())) { // LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / GuiSleep"); SyncCaret(); GuiSleep(1000); - if(EndSession()) break; // LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / ProcessEvents"); ProcessEvents(&quit); // LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / after ProcessEvents"); @@ -868,7 +899,7 @@ void Ctrl::EventLoop0(Ctrl *ctrl) if(ctrl) LoopCtrl = ploop; LoopLevel--; - LLOG(EndIndent << "Leaving event loop "); + LLOG(LOG_END << "Leaving event loop "); } void Ctrl::GuiSleep0(int ms) @@ -876,9 +907,6 @@ void Ctrl::GuiSleep0(int ms) GuiLock __; ASSERT(IsMainThread()); ELOG("GuiSleep"); - if(EndSession()) - return; - ELOG("GuiSleep 2"); int level = LeaveGMutexAll(); #if !defined(flagDLL) && !defined(PLATFORM_WINCE) if(!OverwatchThread) { @@ -1102,10 +1130,10 @@ bool Ctrl::IsWndForeground() const void Ctrl::WndEnable0(bool *b) { GuiLock __; - LLOG("Ctrl::WndEnable(" << b << ") in " << UPP::Name(this) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + LLOG("Ctrl::WndEnable(" << (b && *b) << ") in " << UPP::Name(this) << ", focusCtrlWnd = " << UPP::Name(~focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); if(*b) ReleaseCapture(); - LLOG("//Ctrl::WndEnable(" << b << ") -> false " < false " <inloop = true; } - while(ctrl ? ctrl->InLoop() && ctrl->IsOpen() : GetTopCtrls().GetCount()) { + while(loopno > EndSessionLoopNo && (ctrl ? ctrl->InLoop() && ctrl->IsOpen() : GetTopCtrls().GetCount())) { XEvent event; fd_set fdset; FD_ZERO(&fdset);