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