registrar: Rewrite shutdown dialog to just use a BAlert.

Now that BAlerts can have custom buttons and change icons during
runtime, we need not maintain a custom "clone" of the BAlert logic
here in the registrar.

While at it, use ComposeIconSize to get larger icons on HiDPI.

This fixes #15704 as BAlerts already use the layout API,
while this logic did not.
This commit is contained in:
Augustin Cavalier
2022-08-26 21:27:54 -04:00
parent f5fcee0157
commit 67ca14e889
+76 -224
View File
@@ -22,6 +22,7 @@
#include <Autolock.h> #include <Autolock.h>
#include <Bitmap.h> #include <Bitmap.h>
#include <Button.h> #include <Button.h>
#include <ControlLook.h>
#include <Catalog.h> #include <Catalog.h>
#include <File.h> #include <File.h>
#include <Message.h> #include <Message.h>
@@ -30,8 +31,6 @@
#include <Roster.h> // for B_REQUEST_QUIT #include <Roster.h> // for B_REQUEST_QUIT
#include <Screen.h> #include <Screen.h>
#include <String.h> #include <String.h>
#include <TextView.h>
#include <View.h>
#include <Window.h> #include <Window.h>
#include <TokenSpace.h> #include <TokenSpace.h>
@@ -73,13 +72,9 @@ static const bigtime_t kNonAppQuitTimeout = 500000; // 0.5 s
// the shutdown window before closing it automatically. // the shutdown window before closing it automatically.
static const bigtime_t kDisplayAbortingAppTimeout = 3000000; // 3 s static const bigtime_t kDisplayAbortingAppTimeout = 3000000; // 3 s
static const int kStripeWidth = 30;
static const int kIconVSpacing = 6;
static const int kIconSize = 32;
// The speed of the animation played when an application is blocked on a modal // The speed of the animation played when an application is blocked on a modal
// panel. // panel.
static const bigtime_t kIconAnimateInterval = 50000; // 0.05 s static const bigtime_t kIconAnimateInterval = 50000 * B_LARGE_ICON; // 0.05 s
// message what fields (must not clobber the registrar's message namespace) // message what fields (must not clobber the registrar's message namespace)
enum { enum {
@@ -233,20 +228,39 @@ private:
}; };
class ShutdownProcess::ShutdownWindow : public BWindow { class ShutdownProcess::ShutdownWindow : public BAlert {
public: public:
ShutdownWindow() ShutdownWindow()
: BWindow(BRect(0, 0, 200, 100), B_TRANSLATE("Shutdown status"), :
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, BAlert(),
B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_MINIMIZABLE
| B_NOT_ZOOMABLE | B_NOT_CLOSABLE, B_ALL_WORKSPACES),
fKillAppMessage(NULL), fKillAppMessage(NULL),
fCurrentApp(-1) fCurrentApp(-1),
fCurrentIconBitmap(NULL),
fNormalIconBitmap(NULL),
fTintedIconBitmap(NULL),
fAnimationActive(false),
fAnimationWorker(-1),
fCurrentAnimationRow(-1),
fAnimationLightenPhase(true)
{ {
SetTitle(B_TRANSLATE("Shutdown status"));
SetWorkspaces(B_ALL_WORKSPACES);
SetLook(B_TITLED_WINDOW_LOOK);
SetFlags(Flags() | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE);
SetButtonWidth(B_WIDTH_AS_USUAL);
SetType(B_EMPTY_ALERT);
} }
~ShutdownWindow() ~ShutdownWindow()
{ {
atomic_set(&fAnimationActive, false);
wait_for_thread(fAnimationWorker, NULL);
delete fNormalIconBitmap;
delete fTintedIconBitmap;
for (int32 i = 0; AppInfo* info = (AppInfo*)fAppInfos.ItemAt(i); i++) { for (int32 i = 0; AppInfo* info = (AppInfo*)fAppInfos.ItemAt(i); i++) {
delete info; delete info;
} }
@@ -259,35 +273,9 @@ public:
status_t Init(BMessenger target) status_t Init(BMessenger target)
{ {
// create the views
// root view
fRootView = new(nothrow) TAlertView(BRect(0, 0, 10, 10), "app icons",
B_FOLLOW_NONE, 0);
if (!fRootView)
return B_NO_MEMORY;
fRootView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
AddChild(fRootView);
// 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->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
fTextView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
fTextView->MakeEditable(false);
fTextView->MakeSelectable(false);
fTextView->SetWordWrap(false);
fRootView->AddChild(fTextView);
// kill app button // kill app button
fKillAppButton = new(nothrow) BButton(BRect(0, 0, 10, 10), "kill app", AddButton(B_TRANSLATE("Kill application"));
B_TRANSLATE("Kill application"), NULL, B_FOLLOW_NONE); fKillAppButton = ButtonAt(CountButtons() - 1);
if (!fKillAppButton)
return B_NO_MEMORY;
fRootView->AddChild(fKillAppButton);
BMessage* message = new BMessage(MSG_KILL_APPLICATION); BMessage* message = new BMessage(MSG_KILL_APPLICATION);
if (!message) if (!message)
@@ -298,12 +286,8 @@ public:
fKillAppButton->SetTarget(target); fKillAppButton->SetTarget(target);
// cancel shutdown button // cancel shutdown button
fCancelShutdownButton = new(nothrow) BButton(BRect(0, 0, 10, 10), AddButton(B_TRANSLATE("Cancel shutdown"));
"cancel shutdown", B_TRANSLATE("Cancel shutdown"), NULL, fCancelShutdownButton = ButtonAt(CountButtons() - 1);
B_FOLLOW_NONE);
if (!fCancelShutdownButton)
return B_NO_MEMORY;
fRootView->AddChild(fCancelShutdownButton);
message = new BMessage(MSG_CANCEL_SHUTDOWN); message = new BMessage(MSG_CANCEL_SHUTDOWN);
if (!message) if (!message)
@@ -312,12 +296,9 @@ public:
fCancelShutdownButton->SetTarget(target); fCancelShutdownButton->SetTarget(target);
// reboot system button // reboot system button
fRebootSystemButton = new(nothrow) BButton(BRect(0, 0, 10, 10), AddButton(B_TRANSLATE("Restart system"));
"reboot", B_TRANSLATE("Restart system"), NULL, B_FOLLOW_NONE); fRebootSystemButton = ButtonAt(CountButtons() - 1);
if (!fRebootSystemButton)
return B_NO_MEMORY;
fRebootSystemButton->Hide(); fRebootSystemButton->Hide();
fRootView->AddChild(fRebootSystemButton);
message = new BMessage(MSG_REBOOT_SYSTEM); message = new BMessage(MSG_REBOOT_SYSTEM);
if (!message) if (!message)
@@ -326,12 +307,9 @@ public:
fRebootSystemButton->SetTarget(target); fRebootSystemButton->SetTarget(target);
// aborted OK button // aborted OK button
fAbortedOKButton = new(nothrow) BButton(BRect(0, 0, 10, 10), AddButton(B_TRANSLATE("OK"));
"ok", B_TRANSLATE("OK"), NULL, B_FOLLOW_NONE); fAbortedOKButton = ButtonAt(CountButtons() - 1);
if (!fAbortedOKButton)
return B_NO_MEMORY;
fAbortedOKButton->Hide(); fAbortedOKButton->Hide();
fRootView->AddChild(fAbortedOKButton);
message = new BMessage(MSG_CANCEL_SHUTDOWN); message = new BMessage(MSG_CANCEL_SHUTDOWN);
if (!message) if (!message)
@@ -339,83 +317,6 @@ public:
fAbortedOKButton->SetMessage(message); fAbortedOKButton->SetMessage(message);
fAbortedOKButton->SetTarget(target); fAbortedOKButton->SetTarget(target);
// compute the sizes
static const int kHSpacing = 10;
static const int kVSpacing = 10;
static const int kInnerHSpacing = 5;
static const int kInnerVSpacing = 8;
// buttons
fKillAppButton->ResizeToPreferred();
fCancelShutdownButton->ResizeToPreferred();
fRebootSystemButton->MakeDefault(true);
fRebootSystemButton->ResizeToPreferred();
fAbortedOKButton->MakeDefault(true);
fAbortedOKButton->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;
int defaultButtonHeight
= fRebootSystemButton->Frame().IntegerHeight() + 1;
// text view
fTextView->SetText("two\nlines");
int textHeight = (int)fTextView->TextHeight(0, 1) + 1;
int rightPartX = kStripeWidth + kIconSize / 2 + 1;
int textX = rightPartX + kInnerHSpacing;
int textY = kVSpacing;
int buttonsY = textY + textHeight + kInnerVSpacing;
int nonDefaultButtonsY = buttonsY
+ (defaultButtonHeight - buttonHeight) / 2;
int rightPartWidth = 2 * buttonWidth + kInnerHSpacing;
int width = rightPartX + rightPartWidth + kHSpacing;
int height = buttonsY + defaultButtonHeight + kVSpacing;
// now layout the views
// text view
fTextView->MoveTo(textX, textY);
fTextView->ResizeTo(rightPartWidth + rightPartX - textX - 1,
textHeight - 1);
fTextView->SetTextRect(fTextView->Bounds());
fTextView->SetWordWrap(true);
// buttons
fKillAppButton->MoveTo(rightPartX, nonDefaultButtonsY);
fKillAppButton->ResizeTo(buttonWidth - 1, buttonHeight - 1);
fCancelShutdownButton->MoveTo(
rightPartX + buttonWidth + kInnerVSpacing - 1,
nonDefaultButtonsY);
fCancelShutdownButton->ResizeTo(buttonWidth - 1, buttonHeight - 1);
fRebootSystemButton->MoveTo(
(width - fRebootSystemButton->Frame().IntegerWidth()) / 2,
buttonsY);
fAbortedOKButton->MoveTo(
(width - fAbortedOKButton->Frame().IntegerWidth()) / 2,
buttonsY);
// set the root view and window size
fRootView->ResizeTo(width - 1, height - 1);
ResizeTo(width - 1, height - 1);
// move the window to the same position as BAlerts
BScreen screen(this);
BRect screenFrame = screen.Frame();
MoveTo(screenFrame.left + (screenFrame.Width() - width) / 2.0,
screenFrame.top + screenFrame.Height() / 4.0 - ceilf(height / 3.0));
return B_OK; return B_OK;
} }
@@ -456,16 +357,11 @@ public:
AppInfo* info = (team >= 0 ? _AppInfoFor(team) : NULL); AppInfo* info = (team >= 0 ? _AppInfoFor(team) : NULL);
fCurrentApp = team; fCurrentApp = team;
fRootView->SetAppInfo(info); SetAppInfo(info);
fKillAppMessage->ReplaceInt32("team", team); fKillAppMessage->ReplaceInt32("team", team);
} }
void SetText(const char* text)
{
fTextView->SetText(text);
}
void SetCancelShutdownButtonEnabled(bool enable) void SetCancelShutdownButtonEnabled(bool enable)
{ {
fCancelShutdownButton->SetEnabled(enable); fCancelShutdownButton->SetEnabled(enable);
@@ -480,12 +376,13 @@ public:
fKillAppButton->Show(); fKillAppButton->Show();
else else
fKillAppButton->Hide(); fKillAppButton->Hide();
ResizeToPreferred();
} }
} }
void SetWaitAnimationEnabled(bool enable) void SetWaitAnimationEnabled(bool enable)
{ {
fRootView->IconWaitAnimationEnabled(enable); IconWaitAnimationEnabled(enable);
} }
void SetWaitForShutdown() void SetWaitForShutdown()
@@ -496,8 +393,9 @@ public:
fRebootSystemButton->Show(); fRebootSystemButton->Show();
SetTitle(B_TRANSLATE("System is shut down")); SetTitle(B_TRANSLATE("System is shut down"));
fTextView->SetText( SetText(
B_TRANSLATE("It's now safe to turn off the computer.")); B_TRANSLATE("It's now safe to turn off the computer."));
ResizeToPreferred();
} }
void SetWaitForAbortedOK() void SetWaitForAbortedOK()
@@ -506,8 +404,7 @@ public:
fCancelShutdownButton->Hide(); fCancelShutdownButton->Hide();
fAbortedOKButton->MakeDefault(true); fAbortedOKButton->MakeDefault(true);
fAbortedOKButton->Show(); fAbortedOKButton->Show();
// TODO: Temporary work-around for a Haiku bug. ResizeToPreferred();
fAbortedOKButton->Invalidate();
SetTitle(B_TRANSLATE("Shutdown aborted")); SetTitle(B_TRANSLATE("Shutdown aborted"));
} }
@@ -542,88 +439,43 @@ private:
return (index >= 0 ? (AppInfo*)fAppInfos.ItemAt(index) : NULL); return (index >= 0 ? (AppInfo*)fAppInfos.ItemAt(index) : NULL);
} }
class TAlertView : public BView { private:
public:
TAlertView(BRect frame, const char* name, uint32 resizeMask,
uint32 flags)
:
BView(frame, name, resizeMask, flags | B_WILL_DRAW),
fCurrentIconBitmap(NULL),
fNormalIconBitmap(NULL),
fTintedIconBitmap(NULL),
fAnimationActive(false),
fAnimationWorker(-1),
fCurrentAnimationRow(-1),
fAnimationLightenPhase(true)
{
}
~TAlertView()
{
atomic_set(&fAnimationActive, false);
wait_for_thread(fAnimationWorker, NULL);
delete fCurrentIconBitmap;
delete fNormalIconBitmap;
delete fTintedIconBitmap;
}
virtual void Draw(BRect updateRect)
{
BRect stripeRect = Bounds();
stripeRect.right = kStripeWidth;
SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
FillRect(stripeRect);
if (fCurrentIconBitmap != NULL && fCurrentIconBitmap->IsValid()) {
if (fCurrentIconBitmap->ColorSpace() == B_RGBA32) {
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
} else
SetDrawingMode(B_OP_OVER);
DrawBitmap(fCurrentIconBitmap,
BPoint(kStripeWidth - kIconSize / 2, kIconVSpacing));
}
}
void SetAppInfo(AppInfo* info) void SetAppInfo(AppInfo* info)
{ {
IconWaitAnimationEnabled(false); IconWaitAnimationEnabled(false);
BAutolock lock(Window()); BAutolock lock(this);
if (!lock.IsLocked()) if (!lock.IsLocked())
return; return;
delete fCurrentIconBitmap;
fCurrentIconBitmap = NULL;
delete fNormalIconBitmap; delete fNormalIconBitmap;
fNormalIconBitmap = NULL; fNormalIconBitmap = NULL;
delete fTintedIconBitmap; delete fTintedIconBitmap;
fTintedIconBitmap = NULL; fTintedIconBitmap = NULL;
// We do not delete the present fCurrentIconBitmap as the BAlert owns it.
fCurrentIconBitmap = NULL;
if (info != NULL && info->appIcon != NULL if (info != NULL && info->appIcon != NULL
&& info->appIcon->IsValid()) { && info->appIcon->IsValid()) {
fCurrentIconBitmap = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32); fCurrentIconBitmap = new BBitmap(info->appIcon->Bounds(), B_RGBA32);
if (fCurrentIconBitmap == NULL if (fCurrentIconBitmap == NULL
|| fCurrentIconBitmap->ImportBits(info->appIcon) != B_OK) { || fCurrentIconBitmap->ImportBits(info->appIcon) != B_OK) {
delete fCurrentIconBitmap; delete fCurrentIconBitmap;
fCurrentIconBitmap = NULL; fCurrentIconBitmap = NULL;
} else
SetIcon(fCurrentIconBitmap);
} }
} }
Invalidate();
}
void IconWaitAnimationEnabled(bool enable) void IconWaitAnimationEnabled(bool enable)
{ {
if (atomic_get(&fAnimationActive) == enable) if (atomic_get(&fAnimationActive) == enable)
return; return;
BAutolock lock(Window()); BAutolock lock(this);
if (!lock.IsLocked()) if (!lock.IsLocked())
return; return;
@@ -637,7 +489,7 @@ private:
delete fNormalIconBitmap; delete fNormalIconBitmap;
fNormalIconBitmap = NULL; fNormalIconBitmap = NULL;
fNormalIconBitmap = new BBitmap(BRect(0, 0, 31, 31), fNormalIconBitmap = new BBitmap(fCurrentIconBitmap->Bounds(),
B_BITMAP_NO_SERVER_LINK, B_RGBA32); B_BITMAP_NO_SERVER_LINK, B_RGBA32);
if (fNormalIconBitmap == NULL if (fNormalIconBitmap == NULL
@@ -655,7 +507,7 @@ private:
delete fTintedIconBitmap; delete fTintedIconBitmap;
fTintedIconBitmap = NULL; fTintedIconBitmap = NULL;
fTintedIconBitmap = new BBitmap(BRect(0, 0, 31, 31), fTintedIconBitmap = new BBitmap(fNormalIconBitmap->Bounds(),
B_BITMAP_NO_SERVER_LINK, B_RGBA32); B_BITMAP_NO_SERVER_LINK, B_RGBA32);
if (fTintedIconBitmap == NULL if (fTintedIconBitmap == NULL
@@ -718,13 +570,14 @@ private:
private: private:
status_t _AnimateWaitIcon() status_t _AnimateWaitIcon()
{ {
int32 lastHeight = 1;
while (atomic_get(&fAnimationActive)) { while (atomic_get(&fAnimationActive)) {
if (LockLooperWithTimeout(kIconAnimateInterval) != B_OK) if (LockWithTimeout(kIconAnimateInterval / lastHeight) != B_OK)
continue; continue;
lastHeight = fCurrentIconBitmap->Bounds().IntegerHeight();
if (fCurrentAnimationRow < 0) { if (fCurrentAnimationRow < 0) {
fCurrentAnimationRow = fCurrentAnimationRow = lastHeight;
fCurrentIconBitmap->Bounds().IntegerHeight();
fAnimationLightenPhase = !fAnimationLightenPhase; fAnimationLightenPhase = !fAnimationLightenPhase;
} }
@@ -738,11 +591,10 @@ private:
fCurrentAnimationRow--; fCurrentAnimationRow--;
Invalidate(); ChildAt(0)->Invalidate();
UnlockLooper(); Unlock();
snooze(kIconAnimateInterval / lastHeight);
snooze(kIconAnimateInterval);
} }
return B_OK; return B_OK;
@@ -750,10 +602,19 @@ private:
static status_t _AnimateWaitIconWorker(void* cookie) static status_t _AnimateWaitIconWorker(void* cookie)
{ {
TAlertView* ourView = (TAlertView*)cookie; ShutdownWindow* ourView = (ShutdownWindow*)cookie;
return ourView->_AnimateWaitIcon(); return ourView->_AnimateWaitIcon();
} }
private:
BList fAppInfos;
BButton* fKillAppButton;
BButton* fCancelShutdownButton;
BButton* fRebootSystemButton;
BButton* fAbortedOKButton;
BMessage* fKillAppMessage;
team_id fCurrentApp;
private: private:
BBitmap* fCurrentIconBitmap; BBitmap* fCurrentIconBitmap;
BBitmap* fNormalIconBitmap; BBitmap* fNormalIconBitmap;
@@ -764,18 +625,6 @@ private:
bool fAnimationLightenPhase; bool fAnimationLightenPhase;
}; };
private:
BList fAppInfos;
TAlertView* fRootView;
BTextView* fTextView;
BButton* fKillAppButton;
BButton* fCancelShutdownButton;
BButton* fRebootSystemButton;
BButton* fAbortedOKButton;
BMessage* fKillAppMessage;
team_id fCurrentApp;
};
// #pragma mark - // #pragma mark -
@@ -1132,7 +981,7 @@ ShutdownProcess::_SetShowShutdownWindow(bool show)
if (show == fWindow->IsHidden()) { if (show == fWindow->IsHidden()) {
if (show) if (show)
fWindow->Show(); fWindow->Go(NULL);
else else
fWindow->Hide(); fWindow->Hide();
} }
@@ -1197,12 +1046,15 @@ ShutdownProcess::_AddShutdownWindowApps(AppInfoList& infos)
} }
// get the application icon // get the application icon
BBitmap* appIcon = new(nothrow) BBitmap(BRect(0, 0, 31, 31), BBitmap* appIcon = new(nothrow) BBitmap(
BRect(BPoint(0, 0), be_control_look->ComposeIconSize(B_LARGE_ICON)),
B_BITMAP_NO_SERVER_LINK, B_RGBA32); B_BITMAP_NO_SERVER_LINK, B_RGBA32);
if (appIcon != NULL) { if (appIcon != NULL) {
error = appIcon->InitCheck(); error = appIcon->InitCheck();
if (error == B_OK) if (error == B_OK) {
error = appFileInfo.GetTrackerIcon(appIcon, B_LARGE_ICON); error = appFileInfo.GetTrackerIcon(appIcon,
(icon_size)(appIcon->Bounds().IntegerWidth() + 1));
}
if (error != B_OK) { if (error != B_OK) {
delete appIcon; delete appIcon;
appIcon = NULL; appIcon = NULL;