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
37status_t
38get_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", "Deskbar");
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
60BDeskbar::BDeskbar()
61	:
62	fMessenger(new BMessenger(kDeskbarSignature))
63{
64}
65
66
67BDeskbar::~BDeskbar()
68{
69	delete fMessenger;
70}
71
72
73bool
74BDeskbar::IsRunning() const
75{
76	return fMessenger->IsValid();
77}
78
79
80//	#pragma mark - Item querying methods
81
82
83BRect
84BDeskbar::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
93deskbar_location
94BDeskbar::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
122status_t
123BDeskbar::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
136bool
137BDeskbar::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
150status_t
151BDeskbar::Expand(bool expand)
152{
153	BMessage request(kMsgExpand);
154	request.AddBool("expand", expand);
155
156	return fMessenger->SendMessage(&request);
157}
158
159
160bool
161BDeskbar::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
174status_t
175BDeskbar::SetAlwaysOnTop(bool alwaysOnTop)
176{
177	BMessage request(kMsgAlwaysOnTop);
178	request.AddBool("always on top", alwaysOnTop);
179
180	return fMessenger->SendMessage(&request);
181}
182
183
184bool
185BDeskbar::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
198status_t
199BDeskbar::SetAutoRaise(bool autoRaise)
200{
201	BMessage request(kMsgAutoRaise);
202	request.AddBool("auto raise", autoRaise);
203
204	return fMessenger->SendMessage(&request);
205}
206
207
208bool
209BDeskbar::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
222status_t
223BDeskbar::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
235status_t
236BDeskbar::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
264status_t
265BDeskbar::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
282bool
283BDeskbar::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
296bool
297BDeskbar::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
310uint32
311BDeskbar::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
323float
324BDeskbar::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
336float
337BDeskbar::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
352status_t
353BDeskbar::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
376status_t
377BDeskbar::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
395status_t
396BDeskbar::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
409status_t
410BDeskbar::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