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