1 /* 2 * Copyright 2001-2017 Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval 7 * Axel Dörfler 8 * Jeremy Rand, jrand@magma.ca 9 * John Scipione, jscipione@gmail.com 10 */ 11 12 13 #include <Deskbar.h> 14 #include <Messenger.h> 15 #include <Message.h> 16 #include <View.h> 17 #include <Rect.h> 18 #include <InterfaceDefs.h> 19 #include <Node.h> 20 21 #include <string.h> 22 23 24 // ToDo: in case the BDeskbar methods are called from a Deskbar add-on, 25 // they will currently deadlock most of the time (only those that do 26 // not need a reply will work). 27 // That should be fixed in the Deskbar itself, even if the Be API found 28 // a way around that (that doesn't work too well, BTW) 29 30 // The API in this file should be considered as part of OpenTracker - but 31 // should work with all versions of Tracker available for Haiku. 32 33 34 static const char* kDeskbarSignature = "application/x-vnd.Be-TSKB"; 35 36 static const uint32 kMsgIsAlwaysOnTop = 'gtop'; 37 static const uint32 kMsgAlwaysOnTop = 'stop'; 38 static const uint32 kMsgIsAutoRaise = 'grse'; 39 static const uint32 kMsgAutoRaise = 'srse'; 40 static const uint32 kMsgIsAutoHide = 'ghid'; 41 static const uint32 kMsgAutoHide = 'shid'; 42 43 static const uint32 kMsgAddView = 'icon'; 44 static const uint32 kMsgAddAddOn = 'adon'; 45 static const uint32 kMsgHasItem = 'exst'; 46 static const uint32 kMsgGetItemInfo = 'info'; 47 static const uint32 kMsgCountItems = 'cwnt'; 48 static const uint32 kMsgRemoveItem = 'remv'; 49 static const uint32 kMsgLocation = 'gloc'; 50 static const uint32 kMsgIsExpanded = 'gexp'; 51 static const uint32 kMsgSetLocation = 'sloc'; 52 static const uint32 kMsgExpand = 'sexp'; 53 54 55 status_t 56 get_deskbar_frame(BRect* frame) 57 { 58 BMessenger deskbar(kDeskbarSignature); 59 60 status_t result; 61 62 BMessage request(B_GET_PROPERTY); 63 request.AddSpecifier("Frame"); 64 request.AddSpecifier("Window", "Deskbar"); 65 66 BMessage reply; 67 result = deskbar.SendMessage(&request, &reply); 68 if (result == B_OK) 69 result = reply.FindRect("result", frame); 70 71 return result; 72 } 73 74 75 // #pragma mark - BDeskbar 76 77 78 BDeskbar::BDeskbar() 79 : 80 fMessenger(new BMessenger(kDeskbarSignature)) 81 { 82 } 83 84 85 BDeskbar::~BDeskbar() 86 { 87 delete fMessenger; 88 } 89 90 91 bool 92 BDeskbar::IsRunning() const 93 { 94 return fMessenger->IsValid(); 95 } 96 97 98 // #pragma mark - Item querying methods 99 100 101 BRect 102 BDeskbar::Frame() const 103 { 104 BRect frame(0.0, 0.0, 0.0, 0.0); 105 get_deskbar_frame(&frame); 106 107 return frame; 108 } 109 110 111 deskbar_location 112 BDeskbar::Location(bool* _isExpanded) const 113 { 114 deskbar_location location = B_DESKBAR_RIGHT_TOP; 115 BMessage request(kMsgLocation); 116 BMessage reply; 117 118 if (_isExpanded) 119 *_isExpanded = true; 120 121 if (fMessenger->IsTargetLocal()) { 122 // ToDo: do something about this! 123 // (if we just ask the Deskbar in this case, we would deadlock) 124 return location; 125 } 126 127 if (fMessenger->SendMessage(&request, &reply) == B_OK) { 128 int32 value; 129 if (reply.FindInt32("location", &value) == B_OK) 130 location = static_cast<deskbar_location>(value); 131 132 if (_isExpanded && reply.FindBool("expanded", _isExpanded) != B_OK) 133 *_isExpanded = true; 134 } 135 136 return location; 137 } 138 139 140 status_t 141 BDeskbar::SetLocation(deskbar_location location, bool expanded) 142 { 143 BMessage request(kMsgSetLocation); 144 request.AddInt32("location", static_cast<int32>(location)); 145 request.AddBool("expand", expanded); 146 147 return fMessenger->SendMessage(&request); 148 } 149 150 151 // #pragma mark - Other state methods 152 153 154 bool 155 BDeskbar::IsExpanded() const 156 { 157 BMessage request(kMsgIsExpanded); 158 BMessage reply; 159 bool isExpanded = true; 160 161 if (fMessenger->SendMessage(&request, &reply) == B_OK) 162 reply.FindBool("expanded", &isExpanded); 163 164 return isExpanded; 165 } 166 167 168 status_t 169 BDeskbar::Expand(bool expand) 170 { 171 BMessage request(kMsgExpand); 172 request.AddBool("expand", expand); 173 174 return fMessenger->SendMessage(&request); 175 } 176 177 178 bool 179 BDeskbar::IsAlwaysOnTop() const 180 { 181 BMessage request(kMsgIsAlwaysOnTop); 182 BMessage reply; 183 bool isAlwaysOnTop = false; 184 185 if (fMessenger->SendMessage(&request, &reply) == B_OK) 186 reply.FindBool("always on top", &isAlwaysOnTop); 187 188 return isAlwaysOnTop; 189 } 190 191 192 status_t 193 BDeskbar::SetAlwaysOnTop(bool alwaysOnTop) 194 { 195 BMessage request(kMsgAlwaysOnTop); 196 request.AddBool("always on top", alwaysOnTop); 197 198 return fMessenger->SendMessage(&request); 199 } 200 201 202 bool 203 BDeskbar::IsAutoRaise() const 204 { 205 BMessage request(kMsgIsAutoRaise); 206 BMessage reply; 207 bool isAutoRaise = false; 208 209 if (fMessenger->SendMessage(&request, &reply) == B_OK) 210 reply.FindBool("auto raise", &isAutoRaise); 211 212 return isAutoRaise; 213 } 214 215 216 status_t 217 BDeskbar::SetAutoRaise(bool autoRaise) 218 { 219 BMessage request(kMsgAutoRaise); 220 request.AddBool("auto raise", autoRaise); 221 222 return fMessenger->SendMessage(&request); 223 } 224 225 226 bool 227 BDeskbar::IsAutoHide() const 228 { 229 BMessage request(kMsgIsAutoHide); 230 BMessage reply; 231 bool isAutoHidden = false; 232 233 if (fMessenger->SendMessage(&request, &reply) == B_OK) 234 reply.FindBool("auto hide", &isAutoHidden); 235 236 return isAutoHidden; 237 } 238 239 240 status_t 241 BDeskbar::SetAutoHide(bool autoHide) 242 { 243 BMessage request(kMsgAutoHide); 244 request.AddBool("auto hide", autoHide); 245 246 return fMessenger->SendMessage(&request); 247 } 248 249 250 // #pragma mark - Item querying methods 251 252 253 status_t 254 BDeskbar::GetItemInfo(int32 id, const char** _name) const 255 { 256 if (_name == NULL) 257 return B_BAD_VALUE; 258 259 // Note: Be's implementation returns B_BAD_VALUE if *_name was NULL, 260 // not just if _name was NULL. This doesn't make much sense, so we 261 // do not imitate this behaviour. 262 263 BMessage request(kMsgGetItemInfo); 264 request.AddInt32("id", id); 265 266 BMessage reply; 267 status_t result = fMessenger->SendMessage(&request, &reply); 268 if (result == B_OK) { 269 const char* name; 270 result = reply.FindString("name", &name); 271 if (result == B_OK) { 272 *_name = strdup(name); 273 if (*_name == NULL) 274 result = B_NO_MEMORY; 275 } 276 } 277 278 return result; 279 } 280 281 282 status_t 283 BDeskbar::GetItemInfo(const char* name, int32* _id) const 284 { 285 if (name == NULL) 286 return B_BAD_VALUE; 287 288 BMessage request(kMsgGetItemInfo); 289 request.AddString("name", name); 290 291 BMessage reply; 292 status_t result = fMessenger->SendMessage(&request, &reply); 293 if (result == B_OK) 294 result = reply.FindInt32("id", _id); 295 296 return result; 297 } 298 299 300 bool 301 BDeskbar::HasItem(int32 id) const 302 { 303 BMessage request(kMsgHasItem); 304 request.AddInt32("id", id); 305 306 BMessage reply; 307 if (fMessenger->SendMessage(&request, &reply) == B_OK) 308 return reply.FindBool("exists"); 309 310 return false; 311 } 312 313 314 bool 315 BDeskbar::HasItem(const char* name) const 316 { 317 BMessage request(kMsgHasItem); 318 request.AddString("name", name); 319 320 BMessage reply; 321 if (fMessenger->SendMessage(&request, &reply) == B_OK) 322 return reply.FindBool("exists"); 323 324 return false; 325 } 326 327 328 uint32 329 BDeskbar::CountItems() const 330 { 331 BMessage request(kMsgCountItems); 332 BMessage reply; 333 334 if (fMessenger->SendMessage(&request, &reply) == B_OK) 335 return reply.FindInt32("count"); 336 337 return 0; 338 } 339 340 341 // #pragma mark - Item querying methods 342 343 344 status_t 345 BDeskbar::AddItem(BView* view, int32* _id) 346 { 347 BMessage archive; 348 status_t result = view->Archive(&archive); 349 if (result < B_OK) 350 return result; 351 352 BMessage request(kMsgAddView); 353 request.AddMessage("view", &archive); 354 355 BMessage reply; 356 result = fMessenger->SendMessage(&request, &reply); 357 if (result == B_OK) { 358 if (_id != NULL) 359 result = reply.FindInt32("id", _id); 360 else 361 reply.FindInt32("error", &result); 362 } 363 364 return result; 365 } 366 367 368 status_t 369 BDeskbar::AddItem(entry_ref* addon, int32* _id) 370 { 371 BMessage request(kMsgAddAddOn); 372 request.AddRef("addon", addon); 373 374 BMessage reply; 375 status_t status = fMessenger->SendMessage(&request, &reply); 376 if (status == B_OK) { 377 if (_id != NULL) 378 status = reply.FindInt32("id", _id); 379 else 380 reply.FindInt32("error", &status); 381 } 382 383 return status; 384 } 385 386 387 status_t 388 BDeskbar::RemoveItem(int32 id) 389 { 390 BMessage request(kMsgRemoveItem); 391 request.AddInt32("id", id); 392 393 // ToDo: the Deskbar does not reply to this message, so we don't 394 // know if it really succeeded - we can just acknowledge that the 395 // message was sent to the Deskbar 396 397 return fMessenger->SendMessage(&request); 398 } 399 400 401 status_t 402 BDeskbar::RemoveItem(const char* name) 403 { 404 BMessage request(kMsgRemoveItem); 405 request.AddString("name", name); 406 407 // ToDo: the Deskbar does not reply to this message, so we don't 408 // know if it really succeeded - we can just acknowledge that the 409 // message was sent to the Deskbar 410 411 return fMessenger->SendMessage(&request); 412 } 413