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