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 38 void SetBitmap(BBitmap* Icon) { fIconBitmap = Icon; } 39 BBitmap* Bitmap() { return fIconBitmap; } 40 41 private: 42 BBitmap* fIconBitmap; 43 }; 44 45 46 // #pragma mark - PasswordAlert 47 48 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 85 PasswordAlert::~PasswordAlert() 86 { 87 } 88 89 90 BBitmap* 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 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 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 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 197 TAlertView::~TAlertView() 198 { 199 delete fIconBitmap; 200 } 201 202 203 void 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