1 /*
2 * Copyright 2003-2010 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Jérôme Duval
7 */
8
9
10 #include "PasswordAlert.h"
11
12 #include <string.h>
13
14 #include <File.h>
15 #include <FindDirectory.h>
16 #include <IconUtils.h>
17 #include <Path.h>
18 #include <Resources.h>
19 #include <Screen.h>
20 #include <View.h>
21
22
23 static const int kWindowIconOffset = 27;
24 static const int kIconStripeWidth = 30;
25 static const int kTextIconOffset = kWindowIconOffset + kIconStripeWidth - 2;
26 static const int kTextTopOffset = 6;
27 static const int kSemTimeOut = 50000;
28
29
30 class TAlertView : public BView {
31 public:
32 TAlertView(BRect frame);
33 TAlertView(BMessage* archive);
34 ~TAlertView();
35
36 virtual void Draw(BRect updateRect);
37
SetBitmap(BBitmap * Icon)38 void SetBitmap(BBitmap* Icon) { fIconBitmap = Icon; }
Bitmap()39 BBitmap* Bitmap() { return fIconBitmap; }
40
41 private:
42 BBitmap* fIconBitmap;
43 };
44
45
46 // #pragma mark - PasswordAlert
47
48
PasswordAlert(const char * title,const char * text)49 PasswordAlert::PasswordAlert(const char* title, const char* text)
50 :
51 BWindow(BRect(0, 0, 450, 45), title, B_MODAL_WINDOW,
52 B_NOT_CLOSABLE | B_NOT_RESIZABLE),
53 fTextControl(NULL),
54 fAlertSem(-1)
55 {
56 // Set up the "_master_" view
57 TAlertView* masterView = new TAlertView(Bounds());
58 masterView->SetBitmap(InitIcon());
59 AddChild(masterView);
60
61 // Set up the text view
62 BRect textControlRect(kTextIconOffset, kTextTopOffset,
63 Bounds().right - 5, Bounds().bottom);
64
65 fTextControl = new BTextControl(textControlRect, "_password_", text,
66 NULL, new BMessage('pass'), B_FOLLOW_ALL);
67 fTextControl->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
68 fTextControl->TextView()->HideTyping(true);
69 fTextControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
70 fTextControl->SetDivider(10 + fTextControl->StringWidth(text));
71
72 masterView->AddChild(fTextControl);
73
74 BRect screenFrame = BScreen(B_MAIN_SCREEN_ID).Frame();
75 BPoint point;
76 point.x = screenFrame.Width() / 2 - Bounds().Width() / 2;
77 point.y = screenFrame.Height() / 2 - Bounds().Height() / 2;
78 if (screenFrame.Contains(point))
79 MoveTo(point);
80
81 fTextControl->MakeFocus();
82 }
83
84
~PasswordAlert()85 PasswordAlert::~PasswordAlert()
86 {
87 }
88
89
90 BBitmap*
InitIcon()91 PasswordAlert::InitIcon()
92 {
93 // The alert icons are in the app_server resources
94 BBitmap* icon = NULL;
95 BPath path;
96 if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) == B_OK) {
97 path.Append("app_server");
98 BFile file;
99 if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK) {
100 BResources resources;
101 if (resources.SetTo(&file) == B_OK) {
102 // Which icon are we trying to load?
103 const char* iconName = "warn";
104
105 // Load the raw icon data
106 size_t size;
107 const void* rawIcon
108 = resources.LoadResource(B_VECTOR_ICON_TYPE, iconName,
109 &size);
110
111 if (rawIcon != NULL) {
112 // Now build the bitmap
113 icon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
114 if (BIconUtils::GetVectorIcon((const uint8*)rawIcon, size,
115 icon) != B_OK) {
116 delete icon;
117 return NULL;
118 }
119 }
120 }
121 }
122 }
123
124 return icon;
125 }
126
127
128 void
Go(BString & password)129 PasswordAlert::Go(BString& password)
130 {
131 fAlertSem = create_sem(0, "AlertSem");
132 if (fAlertSem < B_OK) {
133 Quit();
134 return;
135 }
136
137 // Get the originating window, if it exists
138 BWindow* window
139 = dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
140
141 Show();
142
143 // Heavily modified from TextEntryAlert code; the original didn't let the
144 // blocked window ever draw.
145 if (window != NULL) {
146 status_t result;
147 for (;;) {
148 do {
149 result = acquire_sem_etc(fAlertSem, 1, B_RELATIVE_TIMEOUT,
150 kSemTimeOut);
151 // We've (probably) had our time slice taken away from us
152 } while (result == B_INTERRUPTED);
153
154 if (result == B_BAD_SEM_ID) {
155 // Semaphore was finally nuked in MessageReceived
156 break;
157 }
158 window->UpdateIfNeeded();
159 }
160 } else {
161 // No window to update, so just hang out until we're done.
162 while (acquire_sem(fAlertSem) == B_INTERRUPTED) {
163 ;
164 }
165 }
166
167 // Have to cache the value since we delete on Quit()
168 password = fTextControl->Text();
169 if (Lock())
170 Quit();
171 }
172
173
174 void
MessageReceived(BMessage * msg)175 PasswordAlert::MessageReceived(BMessage* msg)
176 {
177 if (msg->what != 'pass')
178 return BWindow::MessageReceived(msg);
179
180 delete_sem(fAlertSem);
181 fAlertSem = -1;
182 }
183
184
185 // #pragma mark - TAlertView
186
187
TAlertView(BRect frame)188 TAlertView::TAlertView(BRect frame)
189 :
190 BView(frame, "TAlertView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
191 fIconBitmap(NULL)
192 {
193 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
194 }
195
196
~TAlertView()197 TAlertView::~TAlertView()
198 {
199 delete fIconBitmap;
200 }
201
202
203 void
Draw(BRect updateRect)204 TAlertView::Draw(BRect updateRect)
205 {
206 // Here's the fun stuff
207 if (fIconBitmap != NULL) {
208 BRect stripeRect = Bounds();
209 stripeRect.right = kIconStripeWidth;
210 SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
211 FillRect(stripeRect);
212
213 SetDrawingMode(B_OP_ALPHA);
214 DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
215 SetDrawingMode(B_OP_COPY);
216 }
217 }
218