diff --git a/src/servers/registrar/ShutdownProcess.cpp b/src/servers/registrar/ShutdownProcess.cpp index 5250869b63..93763f485f 100644 --- a/src/servers/registrar/ShutdownProcess.cpp +++ b/src/servers/registrar/ShutdownProcess.cpp @@ -14,18 +14,26 @@ #include #include +#include #include +#include +#include +#include #include #include #include #include // for B_REQUEST_QUIT +#include +#include +#include +#include #include #include - -#ifdef __HAIKU__ -#include -#endif + +#ifdef __HAIKU__ +#include +#endif #include "AppInfoListMessagingTargetSet.h" #include "Debug.h" @@ -54,8 +62,11 @@ static const bigtime_t NON_APPS_QUIT_TIMEOUT = 500000; // 0.5 s // message what fields enum { - MSG_PHASE_TIMED_OUT = 'phto', - MSG_DONE = 'done', + MSG_PHASE_TIMED_OUT = 'phto', + MSG_DONE = 'done', + MSG_KILL_APPLICATION = 'kill', + MSG_CANCEL_SHUTDOWN = 'cncl', + MSG_REBOOT_SYSTEM = 'rbot', }; // internal events @@ -65,6 +76,8 @@ enum { TIMEOUT_EVENT, USER_APP_QUIT_EVENT, SYSTEM_APP_QUIT_EVENT, + KILL_APP_EVENT, + REBOOT_SYSTEM_EVENT, }; // phases @@ -182,6 +195,429 @@ private: }; +// ShutdownWindow +class ShutdownProcess::ShutdownWindow : public BWindow { +public: + ShutdownWindow() + : BWindow(BRect(0, 0, 200, 100), "Shutdown Status", + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_MINIMIZABLE + | B_NOT_ZOOMABLE | B_NOT_CLOSABLE, B_ALL_WORKSPACES), + fKillAppMessage(NULL) + { + } + + ~ShutdownWindow() + { + for (int32 i = 0; AppInfo *info = (AppInfo*)fAppInfos.ItemAt(i); i++) + delete info; + } + + status_t Init(BMessenger target) + { + // create the views + + // root view + BView *rootView = new(nothrow) BView(BRect(0, 0, 100, 15), "app icons", + B_FOLLOW_NONE, 0); + if (!rootView) + return B_NO_MEMORY; + rootView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(rootView); + + // app icons view + fAppIconsView = new(nothrow) AppIconsView(fAppInfos); + if (!fAppIconsView) + return B_NO_MEMORY; + rootView->AddChild(fAppIconsView); + + // current app icon view + fCurrentAppIconView = new(nothrow) CurrentAppIconView; + if (!fCurrentAppIconView) + return B_NO_MEMORY; + rootView->AddChild(fCurrentAppIconView); + + // text view + fTextView = new(nothrow) BTextView(BRect(0, 0, 10, 10), "text", + BRect(0, 0, 10, 10), B_FOLLOW_NONE); + if (!fTextView) + return B_NO_MEMORY; + fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fTextView->MakeEditable(false); + fTextView->MakeSelectable(false); + fTextView->SetWordWrap(true); + rootView->AddChild(fTextView); + + // kill app button + fKillAppButton = new(nothrow) BButton(BRect(0, 0, 10, 10), "kill app", + "Kill Application", NULL, B_FOLLOW_NONE); + if (!fKillAppButton) + return B_NO_MEMORY; + rootView->AddChild(fKillAppButton); + + BMessage *message = new BMessage(MSG_KILL_APPLICATION); + if (!message) + return B_NO_MEMORY; + message->AddInt32("team", -1); + fKillAppMessage = message; + fKillAppButton->SetMessage(message); + fKillAppButton->SetTarget(target); + + // cancel shutdown button + fCancelShutdownButton = new(nothrow) BButton(BRect(0, 0, 10, 10), + "cancel shutdown", "Cancel Shutdown", NULL, B_FOLLOW_NONE); + if (!fCancelShutdownButton) + return B_NO_MEMORY; + rootView->AddChild(fCancelShutdownButton); + + message = new BMessage(MSG_CANCEL_SHUTDOWN); + if (!message) + return B_NO_MEMORY; + fCancelShutdownButton->SetMessage(message); + fCancelShutdownButton->SetTarget(target); + + // reboot system button + fRebootSystemButton = new(nothrow) BButton(BRect(0, 0, 10, 10), + "reboot", "Reboot System", NULL, B_FOLLOW_NONE); + if (!fRebootSystemButton) + return B_NO_MEMORY; + fRebootSystemButton->Hide(); + rootView->AddChild(fRebootSystemButton); + + message = new BMessage(MSG_REBOOT_SYSTEM); + if (!message) + return B_NO_MEMORY; + fRebootSystemButton->SetMessage(message); + fRebootSystemButton->SetTarget(target); + + // compute the sizes + static const int kHSpacing = 10; + static const int kVSpacing = 10; + static const int kInnerHSpacing = 5; + static const int kInnerVSpacing = 5; + + // buttons + fKillAppButton->ResizeToPreferred(); + fCancelShutdownButton->ResizeToPreferred(); + fRebootSystemButton->ResizeToPreferred(); + + BRect rect(fKillAppButton->Frame()); + int buttonWidth = rect.IntegerWidth() + 1; + int buttonHeight = rect.IntegerHeight() + 1; + + rect = fCancelShutdownButton->Frame(); + if (rect.IntegerWidth() >= buttonWidth) + buttonWidth = rect.IntegerWidth() + 1; + + // text view + fTextView->SetText("two\nlines"); + int textHeight = (int)fTextView->TextHeight(0, 2) + 1; + + // app icons view + int appIconsHeight = fAppIconsView->Frame().IntegerHeight() + 1; + + // current app icon view + int currentAppIconWidth = fCurrentAppIconView->Frame().IntegerWidth() + + 1; + int currentAppIconHeight = fCurrentAppIconView->Frame().IntegerHeight() + + 1; + + int currentAppIconX = kHSpacing; + int rightPartX = currentAppIconX + currentAppIconWidth + kInnerHSpacing; + int appIconsY = kVSpacing; + int textY = appIconsY + appIconsHeight + kInnerVSpacing; + int buttonsY = textY + textHeight + kInnerVSpacing; + int rightPartWidth = 2 * buttonWidth + kInnerHSpacing; + int width = rightPartX + rightPartWidth + kHSpacing; + int height = buttonsY + buttonHeight + kVSpacing; + + // now layout the views + + // current app icon view + fCurrentAppIconView->MoveTo(currentAppIconX, + textY + (textHeight - currentAppIconHeight) / 2); + + // app icons view + fAppIconsView->MoveTo(rightPartX, kVSpacing); + fAppIconsView->ResizeTo(rightPartWidth - 1, appIconsHeight - 1); + + // text view + fTextView->MoveTo(rightPartX, textY); + fTextView->ResizeTo(rightPartWidth - 1, textHeight - 1); + fTextView->SetTextRect(fTextView->Bounds()); + + // buttons + fKillAppButton->MoveTo(rightPartX, buttonsY); + fKillAppButton->ResizeTo(buttonWidth - 1, buttonHeight - 1); + + fCancelShutdownButton->MoveTo( + rightPartX + buttonWidth + kInnerVSpacing - 1, + buttonsY); + fCancelShutdownButton->ResizeTo(buttonWidth - 1, buttonHeight - 1); + + fRebootSystemButton->MoveTo( + (width - fRebootSystemButton->Frame().IntegerWidth()) / 2, + buttonsY); + + // set the root view and window size + rootView->ResizeTo(width - 1, height - 1); + ResizeTo(width - 1, height - 1); + + // center the window on screen + BScreen screen; + if (screen.IsValid()) { + BRect screenFrame = screen.Frame(); + int screenWidth = screenFrame.IntegerWidth() + 1; + int screenHeight = screenFrame.IntegerHeight() + 1; + MoveTo((screenWidth - width) / 2, (screenHeight - height) / 2); + } else { + MoveTo(20, 20); + } + + return B_OK; + } + + status_t AddApp(team_id team, BBitmap *miniIcon, BBitmap *largeIcon) + { + AppInfo *info = new(nothrow) AppInfo; + if (!info) { + delete miniIcon; + delete largeIcon; + return B_NO_MEMORY; + } + + info->team = team; + info->miniIcon = miniIcon; + info->largeIcon = largeIcon; + + if (!fAppInfos.AddItem(info)) { + delete info; + return B_NO_MEMORY; + } + + fAppIconsView->Invalidate(); + + return B_OK; + } + + void RemoveApp(team_id team) + { + int32 index = _AppInfoIndexOf(team); + if (index < 0) + return; + + AppInfo *info = (AppInfo*)fAppInfos.RemoveItem(index); + delete info; + + fAppIconsView->Invalidate(); + } + + void SetCurrentApp(team_id team) + { + AppInfo *info = (team >= 0 ? _AppInfoFor(team) : NULL); + + fCurrentAppIconView->SetAppInfo(info); + + fKillAppMessage->ReplaceInt32("team", team); + } + + void SetText(const char *text) + { + fTextView->SetText(text); + } + + void SetCancelShutdownButtonEnabled(bool enable) + { + fCancelShutdownButton->SetEnabled(enable); + } + + void SetKillAppButtonEnabled(bool enable) + { + if (enable != fKillAppButton->IsEnabled()) { + fKillAppButton->SetEnabled(enable); + + if (enable) + fKillAppButton->Show(); + else + fKillAppButton->Hide(); + } + } + + void SetWaitForShutdown() + { + fAppIconsView->Hide(); + fCurrentAppIconView->Hide(); + fKillAppButton->Hide(); + fCancelShutdownButton->Hide(); + fRebootSystemButton->Show(); + // TODO: Temporary work-around for a Haiku bug. + fRebootSystemButton->Invalidate(); + + SetTitle("System is Shut Down"); + fTextView->SetText("It's now safe to turn off the computer."); + } + +private: + struct AppInfo { + team_id team; + BBitmap *miniIcon; + BBitmap *largeIcon; + + ~AppInfo() + { + delete miniIcon; + delete largeIcon; + } + }; + + int32 _AppInfoIndexOf(team_id team) + { + for (int32 i = 0; AppInfo *info = (AppInfo*)fAppInfos.ItemAt(i); i++) { + if (info->team == team) + return i; + } + + return -1; + } + + AppInfo *_AppInfoFor(team_id team) + { + int32 index = _AppInfoIndexOf(team); + return (index >= 0 ? (AppInfo*)fAppInfos.ItemAt(index) : NULL); + } + + class AppIconsView : public BView { + public: + AppIconsView(const BList &appInfos) + : BView(BRect(0, 0, 100, 15), "app icons", B_FOLLOW_NONE, + B_WILL_DRAW), + fAppInfos(appInfos), + fIconSize(16), + fInnerSpacing(4), + fEllipsisWidth(0) + { + SetViewColor(B_TRANSPARENT_32_BIT); + fBackground = ui_color(B_PANEL_BACKGROUND_COLOR); + } + + virtual void Draw(BRect updateRect) + { + // find out, how many icons we can draw + BRect bounds = Bounds(); + int width = bounds.IntegerWidth() + 1; + int maxIcons = (width + fInnerSpacing) + / (fIconSize + fInnerSpacing); + int minIcons = (width - _EllipsisWidth()) + / (fIconSize + fInnerSpacing); + + int iconsToDraw = fAppInfos.CountItems(); + bool drawEllipsis = false; + if (iconsToDraw > maxIcons) { + iconsToDraw = minIcons; + drawEllipsis = true; + } + + // set colors + SetLowColor(fBackground); + rgb_color black = { 0, 0, 0, 255 }; + SetHighColor(black); + + // draw the icons + int lastX = 0; + for (int i = 0; i < iconsToDraw; i++) { + int x = lastX + (i > 0 ? fInnerSpacing : 0); + int nextX = x + fIconSize; + + // clear background + FillRect(BRect(lastX, 0, nextX - 1, bounds.bottom), + B_SOLID_LOW); + + // draw the icon + SetDrawingMode(B_OP_OVER); + AppInfo *info = (AppInfo*)fAppInfos.ItemAt(i); + if (info->miniIcon) + DrawBitmap(info->miniIcon, BPoint(x, 0)); + + lastX = nextX; + } + + // clear remaining space + FillRect(BRect(lastX, 0, bounds.right, bounds.bottom), B_SOLID_LOW); + + // draw ellipsis, if necessary + if (drawEllipsis) { + int x = lastX + fInnerSpacing; + int y = (fIconSize + 1) / 2; + DrawString(B_UTF8_ELLIPSIS, BPoint(x, y)); + } + } + + private: + int _EllipsisWidth() + { + // init lazily + if (fEllipsisWidth <= 0) { + BFont font; + GetFont(&font); + + fEllipsisWidth = (int)font.StringWidth(B_UTF8_ELLIPSIS); + } + + return fEllipsisWidth; + } + + private: + const BList &fAppInfos; + rgb_color fBackground; + int fIconSize; + int fInnerSpacing; + int fEllipsisWidth; + }; + + class CurrentAppIconView : public BView { + public: + CurrentAppIconView() + : BView(BRect(0, 0, 31, 31), "current app icon", B_FOLLOW_NONE, + B_WILL_DRAW), + fAppInfo(NULL) + { + SetViewColor(B_TRANSPARENT_32_BIT); + fBackground = ui_color(B_PANEL_BACKGROUND_COLOR); + } + + virtual void Draw(BRect updateRect) + { + if (fAppInfo && fAppInfo->largeIcon) { + DrawBitmap(fAppInfo->largeIcon, BPoint(0, 0)); + } else { + SetLowColor(fBackground); + FillRect(Bounds(), B_SOLID_LOW); + } + } + + void SetAppInfo(AppInfo *info) + { + fAppInfo = info; + Invalidate(); + } + + private: + const AppInfo *fAppInfo; + rgb_color fBackground; + }; + +private: + BList fAppInfos; + AppIconsView *fAppIconsView; + CurrentAppIconView *fCurrentAppIconView; + BTextView *fTextView; + BButton *fKillAppButton; + BButton *fCancelShutdownButton; + BButton *fRebootSystemButton; + BMessage *fKillAppMessage; +}; + + // #pragma mark - // constructor @@ -199,13 +635,20 @@ ShutdownProcess::ShutdownProcess(TRoster *roster, EventQueue *eventQueue) fWorker(-1), fCurrentPhase(INVALID_PHASE), fShutdownError(B_ERROR), - fHasGUI(false) + fHasGUI(false), + fWindow(NULL) { } // destructor ShutdownProcess::~ShutdownProcess() { + // terminate the GUI + if (fHasGUI) { + fWindow->Lock(); + fWindow->Quit(); + } + // remove and delete the quit request reply handler if (fQuitRequestReplyHandler) { BAutolock _(this); @@ -295,9 +738,6 @@ ShutdownProcess::Init(BMessage *request) // TODO: sort the system apps by descending registration time - // display alert - // TODO:... - // start the worker thread fWorker = spawn_thread(_WorkerEntry, "shutdown worker", B_NORMAL_PRIORITY, this); @@ -378,6 +818,38 @@ ShutdownProcess::MessageReceived(BMessage *message) break; } + case MSG_KILL_APPLICATION: + { + team_id team; + if (message->FindInt32("team", &team) != B_OK) + break; + + BAutolock _(fWorkerLock); + + // post the event + _PushEvent(KILL_APP_EVENT, team, fCurrentPhase); + + break; + } + + case MSG_CANCEL_SHUTDOWN: + { + BAutolock _(fWorkerLock); + + // post the event + _PushEvent(TIMEOUT_EVENT, -1, fCurrentPhase); + + break; + } + + case MSG_REBOOT_SYSTEM: + { + // post the event + _PushEvent(REBOOT_SYSTEM_EVENT, -1, INVALID_PHASE); + + break; + } + case MSG_DONE: { // notify the registrar that we're done @@ -453,6 +925,180 @@ ShutdownProcess::_UnlockAppLists() fWorkerLock.Unlock(); } +// _SetShowShutdownWindow +void +ShutdownProcess::_SetShowShutdownWindow(bool show) +{ + if (fHasGUI) { + BAutolock _(fWindow); + + if (show == fWindow->IsHidden()) { + if (show) + fWindow->Show(); + else + fWindow->Hide(); + } + } +} + +// _InitShutdownWindow +void +ShutdownProcess::_InitShutdownWindow() +{ + // prepare the window + if (fHasGUI) { + fWindow = new(nothrow) ShutdownWindow; + if (fWindow != NULL) { + status_t error = fWindow->Init(BMessenger(this)); + if (error != B_OK) { + delete fWindow; + fWindow = NULL; + } + } + + // add the applications + if (fWindow) { + BAutolock _(fWorkerLock); + _AddShutdownWindowApps(fUserApps); + _AddShutdownWindowApps(fSystemApps); + } else { + WARNING(("ShutdownProcess::Init(): Failed to create or init " + "shutdown window.")); + + fHasGUI = false; + } + } +} + +// _AddShutdownWindowApps +void +ShutdownProcess::_AddShutdownWindowApps(AppInfoList &infos) +{ + if (!fHasGUI) + return; + + for (AppInfoList::Iterator it = infos.It(); it.IsValid(); ++it) { + RosterAppInfo *info = *it; + + // init an app file info + BFile file; + status_t error = file.SetTo(&info->ref, B_READ_ONLY); + if (error != B_OK) { + WARNING(("ShutdownProcess::_AddShutdownWindowApps(): Failed to " + "open file for app %s: %s\n", info->signature, + strerror(error))); + continue; + } + + BAppFileInfo appFileInfo; + error = appFileInfo.SetTo(&file); + if (error != B_OK) { + WARNING(("ShutdownProcess::_AddShutdownWindowApps(): Failed to " + "init app file info for app %s: %s\n", info->signature, + strerror(error))); + } + + // get the application icons + + // mini icon + BBitmap *miniIcon = new(nothrow) BBitmap(BRect(0, 0, 15, 15), B_CMAP8); + if (miniIcon != NULL) { + error = miniIcon->InitCheck(); + if (error == B_OK) + error = appFileInfo.GetTrackerIcon(miniIcon, B_MINI_ICON); + if (error != B_OK) { + delete miniIcon; + miniIcon = NULL; + } + } + + // mini icon + BBitmap *largeIcon = new(nothrow) BBitmap(BRect(0, 0, 31, 31), B_CMAP8); + if (largeIcon != NULL) { + error = largeIcon->InitCheck(); + if (error == B_OK) + error = appFileInfo.GetTrackerIcon(largeIcon, B_LARGE_ICON); + if (error != B_OK) { + delete largeIcon; + largeIcon = NULL; + } + } + + // add the app + error = fWindow->AddApp(info->team, miniIcon, largeIcon); + if (error != B_OK) { + WARNING(("ShutdownProcess::_AddShutdownWindowApps(): Failed to " + "add app to the shutdown window: %s\n", strerror(error))); + } + } +} + +// _RemoveShutdownWindowApp +void +ShutdownProcess::_RemoveShutdownWindowApp(team_id team) +{ + if (fHasGUI) { + BAutolock _(fWindow); + + fWindow->RemoveApp(team); + } +} + +// _SetShutdownWindowCurrentApp +void +ShutdownProcess::_SetShutdownWindowCurrentApp(team_id team) +{ + if (fHasGUI) { + BAutolock _(fWindow); + + fWindow->SetCurrentApp(team); + } +} + +// _SetShutdownWindowText +void +ShutdownProcess::_SetShutdownWindowText(const char *text) +{ + if (fHasGUI) { + BAutolock _(fWindow); + + fWindow->SetText(text); + } +} + +// _SetShutdownWindowCancelButtonEnabled +void +ShutdownProcess::_SetShutdownWindowCancelButtonEnabled(bool enabled) +{ + if (fHasGUI) { + BAutolock _(fWindow); + + fWindow->SetCancelShutdownButtonEnabled(enabled); + } +} + +// _SetShutdownWindowKillButtonEnabled +void +ShutdownProcess::_SetShutdownWindowKillButtonEnabled(bool enabled) +{ + if (fHasGUI) { + BAutolock _(fWindow); + + fWindow->SetKillAppButtonEnabled(enabled); + } +} + +// _SetShutdownWindowWaitForShutdown +void +ShutdownProcess::_SetShutdownWindowWaitForShutdown() +{ + if (fHasGUI) { + BAutolock _(fWindow); + + fWindow->SetWaitForShutdown(); + } +} + // _NegativeQuitRequestReply void ShutdownProcess::_NegativeQuitRequestReply(thread_id thread) @@ -556,6 +1202,10 @@ ShutdownProcess::_GetNextEvent(uint32 &eventType, thread_id &team, int32 &phase, break; } + // notify the window, if an app has been removed + if (eventType == USER_APP_QUIT_EVENT || eventType == SYSTEM_APP_QUIT_EVENT) + _RemoveShutdownWindowApp(team); + return B_OK; } @@ -594,8 +1244,15 @@ ShutdownProcess::_WorkerDoShutdown() { PRINT(("ShutdownProcess::_WorkerDoShutdown()\n")); - // TODO: Set alert text to "Tidying things up a bit". - PRINT((" sync()...\n")); + // make the shutdown window ready and show it + _InitShutdownWindow(); + _SetShutdownWindowCurrentApp(-1); + _SetShutdownWindowText("Tidying things up a bit."); + _SetShutdownWindowCancelButtonEnabled(true); + _SetShutdownWindowKillButtonEnabled(false); + _SetShowShutdownWindow(true); + + // sync sync(); // phase 1: terminate the user apps @@ -619,15 +1276,35 @@ ShutdownProcess::_WorkerDoShutdown() PRINT((" _kern_shutdown() failed\n")); - // shutdown failed: This can happen for power off mode -- reboot will - // always work. We close the alert, and display a new one with - // a "Reboot System" button. + // shutdown failed: This can happen for power off mode -- reboot should + // always work. if (fHasGUI) { - // TODO:... - } else { - // there's no GUI: we enter the kernel debugger instead - // TODO:... + _SetShutdownWindowWaitForShutdown(); + + // wait for the reboot event + uint32 event; + do { + team_id team; + int32 phase; + status_t error = _GetNextEvent(event, team, phase, true); + if (error != B_OK) + break; + } while (event != REBOOT_SYSTEM_EVENT); + + #ifdef __HAIKU__ + _kern_shutdown(true); + #endif } + + // either there's no GUI or reboot failed: we enter the kernel debugger + // instead + #ifdef __HAIKU__ +// TODO: Introduce the syscall. +// while (true) { +// _kern_kernel_debugger("The system is shut down. It's now safe to turn " +// "off the computer."); +// } + #endif } // _QuitUserApps @@ -636,7 +1313,7 @@ ShutdownProcess::_QuitUserApps() { PRINT(("ShutdownProcess::_QuitUserApps()\n")); - // TODO: Set alert text to "Asking user applications to quit" + _SetShutdownWindowText("Asking user applications to quit."); // prepare the shutdown message BMessage message; @@ -735,8 +1412,6 @@ ShutdownProcess::_KillUserApps() return; } - // TODO: Set alert text... - // TODO: check whether the app blocks on a modal alert if (false) { // ... @@ -766,7 +1441,7 @@ ShutdownProcess::_QuitSystemApps() { PRINT(("ShutdownProcess::_QuitSystemApps()\n")); - // TODO: Disable the abort button. + _SetShutdownWindowCancelButtonEnabled(false); // check one last time for abort events uint32 event; @@ -804,12 +1479,15 @@ ShutdownProcess::_QuitSystemApps() AppInfoList &list = fSystemApps; team_id team = -1; port_id port = -1; + char appName[B_FILE_NAME_LENGTH]; if (!list.IsEmpty()) { RosterAppInfo *info = *list.It(); team = info->team; port = info->port; + strcpy(appName, info->ref.name); } + _UnlockAppLists(); if (team < 0) { @@ -817,7 +1495,11 @@ ShutdownProcess::_QuitSystemApps() return; } - // TODO: Set alert text... + // set window text + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "Asking \"%s\" to quit.", appName); + _SetShutdownWindowText(buffer); + _SetShutdownWindowCurrentApp(team); // send the shutdown message to the app PRINT((" sending team %ld (port: %ld) a shutdown message\n", team, @@ -851,8 +1533,6 @@ ShutdownProcess::_QuitSystemApps() } while (event != NO_EVENT); - // TODO: Set alert text... - // TODO: check whether the app blocks on a modal alert if (false) { // ... @@ -882,7 +1562,7 @@ ShutdownProcess::_QuitNonApps() { PRINT(("ShutdownProcess::_QuitNonApps()\n")); - // TODO: Set alert text... + _SetShutdownWindowText("Asking other processes to quit."); // iterate through the remaining teams and send them the HUP signal int32 cookie = 0; diff --git a/src/servers/registrar/ShutdownProcess.h b/src/servers/registrar/ShutdownProcess.h index 8384d39058..9234fc9515 100644 --- a/src/servers/registrar/ShutdownProcess.h +++ b/src/servers/registrar/ShutdownProcess.h @@ -47,6 +47,16 @@ private: bool _LockAppLists(); void _UnlockAppLists(); + void _InitShutdownWindow(); + void _SetShowShutdownWindow(bool show); + void _AddShutdownWindowApps(AppInfoList &infos); + void _RemoveShutdownWindowApp(team_id team); + void _SetShutdownWindowCurrentApp(team_id team); + void _SetShutdownWindowText(const char *text); + void _SetShutdownWindowCancelButtonEnabled(bool enabled); + void _SetShutdownWindowKillButtonEnabled(bool enabled); + void _SetShutdownWindowWaitForShutdown(); + static status_t _WorkerEntry(void *data); status_t _Worker(); @@ -62,6 +72,7 @@ private: class InternalEvent; struct InternalEventList; class QuitRequestReplyHandler; + class ShutdownWindow; friend class QuitRequestReplyHandler; @@ -81,6 +92,7 @@ private: int32 fCurrentPhase; status_t fShutdownError; bool fHasGUI; + ShutdownWindow *fWindow; }; #endif // SHUTDOWN_PROCESS_H