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