1 /* 2 * Copyright 2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Weirauch, dev@m-phasis.de 7 */ 8 9 10 #include "DeskbarReplicant.h" 11 12 #include <Alert.h> 13 #include <Application.h> 14 #include <Bitmap.h> 15 #include <Deskbar.h> 16 #include <IconUtils.h> 17 #include <MenuItem.h> 18 #include <Message.h> 19 #include <PopUpMenu.h> 20 #include <Resources.h> 21 #include <Roster.h> 22 #include <String.h> 23 24 #include <bluetoothserver_p.h> 25 26 extern "C" _EXPORT BView *instantiate_deskbar_item(void); 27 status_t our_image(image_info& image); 28 29 const uint32 kMsgOpenBluetoothPreferences = 'obtp'; 30 const uint32 kMsgQuitBluetoothServer = 'qbts'; 31 32 const char* kDeskbarItemName = "BluetoothServerReplicant"; 33 const char* kClassName = "DeskbarReplicant"; 34 35 // #pragma mark - 36 37 38 DeskbarReplicant::DeskbarReplicant(BRect frame, int32 resizingMode) 39 : BView(frame, kDeskbarItemName, resizingMode, 40 B_WILL_DRAW | B_FRAME_EVENTS) 41 { 42 _Init(); 43 } 44 45 46 DeskbarReplicant::DeskbarReplicant(BMessage* archive) 47 : BView(archive) 48 { 49 _Init(); 50 } 51 52 53 DeskbarReplicant::~DeskbarReplicant() 54 { 55 } 56 57 58 void 59 DeskbarReplicant::_Init() 60 { 61 fIcon = NULL; 62 63 image_info info; 64 if (our_image(info) != B_OK) 65 return; 66 67 BFile file(info.name, B_READ_ONLY); 68 if (file.InitCheck() < B_OK) 69 return; 70 71 BResources resources(&file); 72 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 73 if (resources.InitCheck() < B_OK) 74 return; 75 #endif 76 77 size_t size; 78 const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, 79 "tray_icon", &size); 80 if (data != NULL) { 81 BBitmap* icon = new BBitmap(Bounds(), B_RGBA32); 82 if (icon->InitCheck() == B_OK 83 && BIconUtils::GetVectorIcon((const uint8 *)data, 84 size, icon) == B_OK) { 85 fIcon = icon; 86 } else 87 delete icon; 88 } 89 } 90 91 92 DeskbarReplicant * 93 DeskbarReplicant::Instantiate(BMessage* archive) 94 { 95 if (!validate_instantiation(archive, kClassName)) 96 return NULL; 97 98 return new DeskbarReplicant(archive); 99 } 100 101 102 status_t 103 DeskbarReplicant::Archive(BMessage* archive, bool deep) const 104 { 105 status_t status = BView::Archive(archive, deep); 106 if (status == B_OK) 107 status = archive->AddString("add_on", BLUETOOTH_SIGNATURE); 108 if (status == B_OK) 109 status = archive->AddString("class", kClassName); 110 111 return status; 112 } 113 114 115 void 116 DeskbarReplicant::AttachedToWindow() 117 { 118 BView::AttachedToWindow(); 119 AdoptParentColors(); 120 121 SetLowColor(ViewColor()); 122 } 123 124 125 void 126 DeskbarReplicant::Draw(BRect updateRect) 127 { 128 if (!fIcon) { 129 /* At least display something... */ 130 rgb_color lowColor = LowColor(); 131 SetLowColor(0, 113, 187, 255); 132 FillRoundRect(Bounds().InsetBySelf(3.f, 0.f), 5.f, 7.f, B_SOLID_LOW); 133 SetLowColor(lowColor); 134 } else { 135 SetDrawingMode(B_OP_ALPHA); 136 DrawBitmap(fIcon); 137 SetDrawingMode(B_OP_COPY); 138 } 139 } 140 141 142 void 143 DeskbarReplicant::MessageReceived(BMessage* msg) 144 { 145 switch (msg->what) { 146 case kMsgOpenBluetoothPreferences: 147 be_roster->Launch(BLUETOOTH_APP_SIGNATURE); 148 break; 149 150 case kMsgQuitBluetoothServer: 151 _QuitBluetoothServer(); 152 break; 153 154 default: 155 BView::MessageReceived(msg); 156 } 157 } 158 159 160 void 161 DeskbarReplicant::MouseDown(BPoint where) 162 { 163 BPoint point; 164 uint32 buttons; 165 GetMouse(&point, &buttons); 166 if (!(buttons & B_SECONDARY_MOUSE_BUTTON)) { 167 return; 168 } 169 170 BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 171 172 menu->AddItem(new BMenuItem("Settings" B_UTF8_ELLIPSIS, 173 new BMessage(kMsgOpenBluetoothPreferences))); 174 175 // TODO show list of known/paired devices 176 177 menu->AddItem(new BMenuItem("Quit", 178 new BMessage(kMsgQuitBluetoothServer))); 179 180 menu->SetTargetForItems(this); 181 ConvertToScreen(&point); 182 menu->Go(point, true, true, true); 183 } 184 185 186 void 187 DeskbarReplicant::_QuitBluetoothServer() 188 { 189 if (!be_roster->IsRunning(BLUETOOTH_SIGNATURE)) { 190 // The server isn't running, so remove ourself 191 BDeskbar deskbar; 192 deskbar.RemoveItem(kDeskbarItemName); 193 194 return; 195 } 196 status_t status = BMessenger(BLUETOOTH_SIGNATURE).SendMessage( 197 B_QUIT_REQUESTED); 198 if (status < B_OK) { 199 _ShowErrorAlert("Stopping the Bluetooth server failed.", status); 200 } 201 } 202 203 204 void 205 DeskbarReplicant::_ShowErrorAlert(BString msg, status_t status) 206 { 207 msg << "\n\nError: " << strerror(status); 208 BAlert* alert = new BAlert("Bluetooth error", msg.String(), "OK"); 209 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 210 alert->Go(NULL); 211 } 212 213 // #pragma mark - 214 215 216 extern "C" _EXPORT BView * 217 instantiate_deskbar_item(void) 218 { 219 return new DeskbarReplicant(BRect(0, 0, 15, 15), 220 B_FOLLOW_LEFT | B_FOLLOW_TOP); 221 } 222 223 // #pragma mark - 224 225 226 status_t 227 our_image(image_info& image) 228 { 229 int32 cookie = 0; 230 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) { 231 if ((char *)our_image >= (char *)image.text 232 && (char *)our_image <= (char *)image.text + image.text_size) 233 return B_OK; 234 } 235 236 return B_ERROR; 237 } 238