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
get_deskbar_frame(BRect * frame)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
BDeskbar()60 BDeskbar::BDeskbar()
61 :
62 fMessenger(new BMessenger(kDeskbarSignature))
63 {
64 }
65
66
~BDeskbar()67 BDeskbar::~BDeskbar()
68 {
69 delete fMessenger;
70 }
71
72
73 bool
IsRunning() const74 BDeskbar::IsRunning() const
75 {
76 return fMessenger->IsValid();
77 }
78
79
80 // #pragma mark - Item querying methods
81
82
83 BRect
Frame() const84 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
Location(bool * _isExpanded) const94 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
SetLocation(deskbar_location location,bool expanded)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
IsExpanded() const137 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
Expand(bool expand)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
IsAlwaysOnTop() const161 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
SetAlwaysOnTop(bool alwaysOnTop)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
IsAutoRaise() const185 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
SetAutoRaise(bool autoRaise)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
IsAutoHide() const209 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
SetAutoHide(bool autoHide)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
GetItemInfo(int32 id,const char ** _name) const236 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
GetItemInfo(const char * name,int32 * _id) const265 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
HasItem(int32 id) const283 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
HasItem(const char * name) const297 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
CountItems() const311 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
MaxItemWidth() const324 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
MaxItemHeight() const337 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
AddItem(BView * view,int32 * _id)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
AddItem(entry_ref * addon,int32 * _id)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
RemoveItem(int32 id)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
RemoveItem(const char * name)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