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 BRect 81 BDeskbar::Frame(void) const 82 { 83 BRect frame(0.0, 0.0, 0.0, 0.0); 84 get_deskbar_frame(&frame); 85 86 return frame; 87 } 88 89 90 deskbar_location 91 BDeskbar::Location(bool *_isExpanded) const 92 { 93 deskbar_location location = B_DESKBAR_RIGHT_TOP; 94 BMessage request(kMsgLocation); 95 BMessage reply; 96 97 if (_isExpanded) 98 *_isExpanded = true; 99 100 if (fMessenger->IsTargetLocal()) { 101 // ToDo: do something about this! 102 // (if we just ask the Deskbar in this case, we would deadlock) 103 return location; 104 } 105 106 if (fMessenger->SendMessage(&request, &reply) == B_OK) { 107 int32 value; 108 if (reply.FindInt32("location", &value) == B_OK) 109 location = static_cast<deskbar_location>(value); 110 111 if (_isExpanded 112 && reply.FindBool("expanded", _isExpanded) != B_OK) 113 *_isExpanded = true; 114 } 115 116 return location; 117 } 118 119 120 status_t 121 BDeskbar::SetLocation(deskbar_location location, bool expanded) 122 { 123 BMessage request(kMsgSetLocation); 124 request.AddInt32("location", static_cast<int32>(location)); 125 request.AddBool("expand", expanded); 126 127 return fMessenger->SendMessage(&request); 128 } 129 130 131 bool 132 BDeskbar::IsExpanded(void) const 133 { 134 BMessage request(kMsgIsExpanded); 135 BMessage reply; 136 bool isExpanded; 137 138 if (fMessenger->SendMessage(&request, &reply) != B_OK 139 || reply.FindBool("expanded", &isExpanded) != B_OK) 140 isExpanded = true; 141 142 return isExpanded; 143 } 144 145 146 status_t 147 BDeskbar::Expand(bool expand) 148 { 149 BMessage request(kMsgExpand); 150 request.AddBool("expand", expand); 151 152 return fMessenger->SendMessage(&request); 153 } 154 155 156 status_t 157 BDeskbar::GetItemInfo(int32 id, const char **_name) const 158 { 159 if (_name == NULL) 160 return B_BAD_VALUE; 161 162 // Note: Be's implementation returns B_BAD_VALUE if *_name was NULL, 163 // not just if _name was NULL. This doesn't make much sense, so we 164 // do not imitate this behaviour. 165 166 BMessage request(kMsgGetItemInfo); 167 request.AddInt32("id", id); 168 169 BMessage reply; 170 status_t result = fMessenger->SendMessage(&request, &reply); 171 if (result == B_OK) { 172 const char *name; 173 result = reply.FindString("name", &name); 174 if (result == B_OK) { 175 *_name = strdup(name); 176 if (*_name == NULL) 177 result = B_NO_MEMORY; 178 } 179 } 180 return result; 181 } 182 183 184 status_t 185 BDeskbar::GetItemInfo(const char *name, int32 *_id) const 186 { 187 if (name == NULL) 188 return B_BAD_VALUE; 189 190 BMessage request(kMsgGetItemInfo); 191 request.AddString("name", name); 192 193 BMessage reply; 194 status_t result = fMessenger->SendMessage(&request, &reply); 195 if (result == B_OK) 196 result = reply.FindInt32("id", _id); 197 198 return result; 199 } 200 201 202 bool 203 BDeskbar::HasItem(int32 id) const 204 { 205 BMessage request(kMsgHasItem); 206 request.AddInt32("id", id); 207 208 BMessage reply; 209 if (fMessenger->SendMessage(&request, &reply) == B_OK) 210 return reply.FindBool("exists"); 211 212 return false; 213 } 214 215 216 bool 217 BDeskbar::HasItem(const char *name) const 218 { 219 BMessage request(kMsgHasItem); 220 request.AddString("name", name); 221 222 BMessage reply; 223 if (fMessenger->SendMessage(&request, &reply) == B_OK) 224 return reply.FindBool("exists"); 225 226 return false; 227 } 228 229 230 uint32 231 BDeskbar::CountItems(void) const 232 { 233 BMessage request(kMsgCountItems); 234 BMessage reply; 235 236 if (fMessenger->SendMessage(&request, &reply) == B_OK) 237 return reply.FindInt32("count"); 238 239 return 0; 240 } 241 242 243 status_t 244 BDeskbar::AddItem(BView *view, int32 *_id) 245 { 246 BMessage archive; 247 status_t result = view->Archive(&archive); 248 if (result < B_OK) 249 return result; 250 251 BMessage request(kMsgAddView); 252 request.AddMessage("view", &archive); 253 254 BMessage reply; 255 result = fMessenger->SendMessage(&request, &reply); 256 if (result == B_OK) { 257 if (_id != NULL) 258 result = reply.FindInt32("id", _id); 259 else 260 reply.FindInt32("error", &result); 261 } 262 263 return result; 264 } 265 266 267 status_t 268 BDeskbar::AddItem(entry_ref *addon, int32 *_id) 269 { 270 BMessage request(kMsgAddAddOn); 271 request.AddRef("addon", addon); 272 273 // Note: to make Deskbar items persistent, they need to have the attribute 274 // set. The Deskbar will remove the attribute automatically when needed. 275 // ToDo: move this functionality into the Deskbar itself! 276 277 BNode node; 278 status_t status = node.SetTo(addon); 279 if (status < B_OK) 280 return status; 281 282 if ((status = node.WriteAttr("be:deskbar_item_status", B_STRING_TYPE, 283 0, "enabled", strlen("enabled"))) < B_OK) 284 return status; 285 286 BMessage reply; 287 status = fMessenger->SendMessage(&request, &reply); 288 if (status == B_OK) { 289 if (_id != NULL) 290 status = reply.FindInt32("id", _id); 291 else 292 reply.FindInt32("error", &status); 293 } 294 295 return status; 296 } 297 298 299 status_t 300 BDeskbar::RemoveItem(int32 id) 301 { 302 BMessage request(kMsgRemoveItem); 303 request.AddInt32("id", id); 304 305 // ToDo: the Deskbar does not reply to this message, so we don't 306 // know if it really succeeded - we can just acknowledge that the 307 // message was sent to the Deskbar 308 309 return fMessenger->SendMessage(&request); 310 } 311 312 313 status_t 314 BDeskbar::RemoveItem(const char *name) 315 { 316 BMessage request(kMsgRemoveItem); 317 request.AddString("name", name); 318 319 // ToDo: the Deskbar does not reply to this message, so we don't 320 // know if it really succeeded - we can just acknowledge that the 321 // message was sent to the Deskbar 322 323 return fMessenger->SendMessage(&request); 324 325 } 326 327