xref: /haiku/src/kits/interface/Deskbar.cpp (revision b08627f310bb2e80bca50176e7a758182384735a)
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