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