xref: /haiku/src/servers/app/CursorManager.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 /*
2  * Copyright 2001-2005, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  */
8 
9 /**	Handles the system's cursor infrastructure */
10 
11 
12 #include <Directory.h>
13 #include <String.h>
14 
15 #include "CursorData.h"
16 #include "CursorManager.h"
17 #include "HaikuSystemCursor.h"
18 #include "ServerCursor.h"
19 #include "ServerConfig.h"
20 #include "ServerTokenSpace.h"
21 
22 
23 //! Initializes the CursorManager
24 CursorManager::CursorManager()
25  :	BLocker("CursorManager")
26 {
27 	// Set system cursors to "unassigned"
28 	// ToDo: decide about default cursor
29 
30 #if 1
31 	fDefaultCursor = new ServerCursor(kHaikuCursorBits, kHaikuCursorWidth,
32 		kHaikuCursorHeight, kHaikuCursorFormat);
33 	// we just happen to know where the hotspot is
34 	fDefaultCursor->SetHotSpot(BPoint(1, 0));
35 #else
36 	fDefaultCursor = new ServerCursor(default_cursor_data);
37 	AddCursor(fDefaultCursor);
38 #endif
39 
40 	fTextCursor = new ServerCursor(default_text_data);
41 	AddCursor(fTextCursor);
42 
43 	fMoveCursor = new ServerCursor(default_move_data);
44 	AddCursor(fMoveCursor);
45 
46 	fDragCursor = new ServerCursor(default_drag_data);
47 	AddCursor(fDragCursor);
48 
49 	fResizeCursor = new ServerCursor(default_resize_data);
50 	AddCursor(fResizeCursor);
51 
52 	fNWSECursor = new ServerCursor(default_resize_nwse_data);
53 	AddCursor(fNWSECursor);
54 
55 	fNESWCursor = new ServerCursor(default_resize_nesw_data);
56 	AddCursor(fNESWCursor);
57 
58 	fNSCursor = new ServerCursor(default_resize_ns_data);
59 	AddCursor(fNSCursor);
60 
61 	fEWCursor = new ServerCursor(default_resize_ew_data);
62 	AddCursor(fEWCursor);
63 }
64 
65 
66 //! Does all the teardown
67 CursorManager::~CursorManager()
68 {
69 	for (int32 i = 0; i < fCursorList.CountItems(); i++) {
70 		ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(i);
71 		if (cursor)
72 			delete cursor;
73 	}
74 
75 	// Note that it is not necessary to remove and delete the system
76 	// cursors. These cursors are kept in the list with a empty application
77 	// signature so they cannot be removed very easily except via
78 	// SetCursor(cursor_which). At shutdown, they are removed with the
79 	// above loop.
80 }
81 
82 
83 /*!
84 	\brief Registers a cursor with the manager.
85 	\param sc ServerCursor object to register
86 	\return The token assigned to the cursor or B_ERROR if sc is NULL
87 */
88 int32
89 CursorManager::AddCursor(ServerCursor* cursor)
90 {
91 	if (!cursor)
92 		return B_ERROR;
93 
94 	Lock();
95 
96 	fCursorList.AddItem(cursor);
97 	int32 token = fTokenSpace.NewToken(B_SERVER_TOKEN, cursor);
98 	cursor->fToken = token;
99 
100 	Unlock();
101 	return token;
102 }
103 
104 
105 /*!
106 	\brief Removes a cursor from the internal list and deletes it
107 	\param token ID value of the cursor to be deleted
108 
109 	If the cursor is not found, this call does nothing
110 */
111 void
112 CursorManager::DeleteCursor(int32 token)
113 {
114 	Lock();
115 
116 	for (int32 i = 0; i < fCursorList.CountItems(); i++) {
117 		ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(i);
118 
119 		if (cursor && cursor->fToken == token) {
120 			fCursorList.RemoveItem(i);
121 			delete cursor;
122 			break;
123 		}
124 	}
125 
126 	Unlock();
127 }
128 
129 
130 /*!
131 	\brief Removes and deletes all of an application's cursors
132 	\param signature Signature to which the cursors belong
133 */
134 void
135 CursorManager::RemoveAppCursors(team_id team)
136 {
137 	Lock();
138 
139 	int32 index = 0;
140 	while (index < fCursorList.CountItems()) {
141 		ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(index);
142 		if (!cursor)
143 			break;
144 
145 		if (cursor->OwningTeam() == team) {
146 			fCursorList.RemoveItem(index);
147 			delete cursor;
148 		} else
149 			index++;
150 	}
151 
152 	Unlock();
153 }
154 
155 
156 /*!
157 	\brief Sets all the cursors from a specified CursorSet
158 	\param path Path to the cursor set
159 
160 	All cursors in the set will be assigned. If the set does not specify a
161 	cursor for a particular cursor specifier, it will remain unchanged.
162 	This function will fail if passed a NULL path, an invalid path, or the
163 	path to a non-CursorSet file.
164 */
165 void
166 CursorManager::SetCursorSet(const char *path)
167 {
168 	Lock();
169 	CursorSet cursorSet(NULL);
170 
171 	if (!path || cursorSet.Load(path) != B_OK)
172 		return;
173 
174 	ServerCursor *cursor = NULL;
175 
176 	if (cursorSet.FindCursor(B_CURSOR_DEFAULT, &cursor) == B_OK) {
177 		if (fDefaultCursor)
178 			delete fDefaultCursor;
179 		fDefaultCursor = cursor;
180 	}
181 
182 	if (cursorSet.FindCursor(B_CURSOR_TEXT, &cursor) == B_OK) {
183 		if (fTextCursor)
184 			delete fTextCursor;
185 		fTextCursor = cursor;
186 	}
187 
188 	if (cursorSet.FindCursor(B_CURSOR_MOVE, &cursor) == B_OK) {
189 		if (fMoveCursor)
190 			delete fMoveCursor;
191 		fMoveCursor = cursor;
192 	}
193 
194 	if (cursorSet.FindCursor(B_CURSOR_DRAG, &cursor) == B_OK) {
195 		if (fDragCursor)
196 			delete fDragCursor;
197 		fDragCursor = cursor;
198 	}
199 
200 	if (cursorSet.FindCursor(B_CURSOR_RESIZE, &cursor) == B_OK) {
201 		if (fResizeCursor)
202 			delete fResizeCursor;
203 		fResizeCursor = cursor;
204 	}
205 
206 	if (cursorSet.FindCursor(B_CURSOR_RESIZE_NWSE, &cursor) == B_OK) {
207 		if (fNWSECursor)
208 			delete fNWSECursor;
209 		fNWSECursor = cursor;
210 	}
211 
212 	if (cursorSet.FindCursor(B_CURSOR_RESIZE_NESW, &cursor) == B_OK) {
213 		if (fNESWCursor)
214 			delete fNESWCursor;
215 		fNESWCursor = cursor;
216 	}
217 
218 	if (cursorSet.FindCursor(B_CURSOR_RESIZE_NS, &cursor) == B_OK) {
219 		if (fNSCursor)
220 			delete fNSCursor;
221 		fNSCursor = cursor;
222 	}
223 
224 	if (cursorSet.FindCursor(B_CURSOR_RESIZE_EW, &cursor) == B_OK) {
225 		if (fEWCursor)
226 			delete fEWCursor;
227 		fEWCursor = cursor;
228 	}
229 
230 	Unlock();
231 }
232 
233 
234 /*!
235 	\brief Acquire the cursor which is used for a particular system cursor
236 	\param which Which system cursor to get
237 	\return Pointer to the particular cursor used or NULL if which is
238 	invalid or the cursor has not been assigned
239 */
240 ServerCursor *
241 CursorManager::GetCursor(cursor_which which)
242 {
243 	ServerCursor *cursor = NULL;
244 	Lock();
245 
246 	switch (which) {
247 		case B_CURSOR_DEFAULT:
248 			cursor = fDefaultCursor;
249 			break;
250 
251 		case B_CURSOR_TEXT:
252 			cursor = fTextCursor;
253 			break;
254 
255 		case B_CURSOR_MOVE:
256 			cursor = fMoveCursor;
257 			break;
258 
259 		case B_CURSOR_DRAG:
260 			cursor = fDragCursor;
261 			break;
262 
263 		case B_CURSOR_RESIZE:
264 			cursor = fResizeCursor;
265 			break;
266 
267 		case B_CURSOR_RESIZE_NWSE:
268 			cursor = fNWSECursor;
269 			break;
270 
271 		case B_CURSOR_RESIZE_NESW:
272 			cursor = fNESWCursor;
273 			break;
274 
275 		case B_CURSOR_RESIZE_NS:
276 			cursor = fNSCursor;
277 			break;
278 
279 		case B_CURSOR_RESIZE_EW:
280 			cursor = fEWCursor;
281 			break;
282 
283 		default:
284 			break;
285 	}
286 
287 	Unlock();
288 	return cursor;
289 }
290 
291 
292 /*!
293 	\brief Gets the current system cursor value
294 	\return The current cursor value or CURSOR_OTHER if some non-system cursor
295 */
296 cursor_which
297 CursorManager::GetCursorWhich()
298 {
299 	Lock();
300 
301 	// ToDo: Where is fCurrentWhich set?
302 	cursor_which which;
303 	which = fCurrentWhich;
304 
305 	Unlock();
306 	return which;
307 }
308 
309 
310 /*!
311 	\brief Sets the specified system cursor to the a particular cursor
312 	\param which Which system cursor to change
313 	\param token The ID of the cursor to become the new one
314 
315 	A word of warning: once a cursor has been assigned to the system, the
316 	system will take ownership of the cursor and deleting the cursor
317 	will have no effect on the system.
318 */
319 void
320 CursorManager::ChangeCursor(cursor_which which, int32 token)
321 {
322 	Lock();
323 
324 	// Find the cursor, based on the token
325 	ServerCursor *cursor = FindCursor(token);
326 
327 	// Did we find a cursor with this token?
328 	if (!cursor) {
329 		Unlock();
330 		return;
331 	}
332 
333 	// Do the assignment
334 	switch (which) {
335 		case B_CURSOR_DEFAULT:
336 			delete fDefaultCursor;
337 			fDefaultCursor = cursor;
338 			break;
339 
340 		case B_CURSOR_TEXT:
341 			delete fTextCursor;
342 			fTextCursor = cursor;
343 			break;
344 
345 		case B_CURSOR_MOVE:
346 			delete fMoveCursor;
347 			fMoveCursor = cursor;
348 			break;
349 
350 		case B_CURSOR_DRAG:
351 			delete fDragCursor;
352 			fDragCursor = cursor;
353 			break;
354 
355 		case B_CURSOR_RESIZE:
356 			delete fResizeCursor;
357 			fResizeCursor = cursor;
358 			break;
359 
360 		case B_CURSOR_RESIZE_NWSE:
361 			delete fNWSECursor;
362 			fNWSECursor = cursor;
363 			break;
364 
365 		case B_CURSOR_RESIZE_NESW:
366 			delete fNESWCursor;
367 			fNESWCursor = cursor;
368 			break;
369 
370 		case B_CURSOR_RESIZE_NS:
371 			delete fNSCursor;
372 			fNSCursor = cursor;
373 			break;
374 
375 		case B_CURSOR_RESIZE_EW:
376 			delete fEWCursor;
377 			fEWCursor = cursor;
378 			break;
379 
380 		default:
381 			Unlock();
382 			return;
383 	}
384 
385 	if (cursor->GetAppSignature())
386 		cursor->SetAppSignature("");
387 
388 	fCursorList.RemoveItem(cursor);
389 	Unlock();
390 }
391 
392 
393 /*!
394 	\brief Internal function which finds the cursor with a particular ID
395 	\param token ID of the cursor to find
396 	\return The cursor or NULL if not found
397 */
398 ServerCursor *
399 CursorManager::FindCursor(int32 token)
400 {
401 	ServerCursor* cursor;
402 	if (gTokenSpace.GetToken(token, kCursorToken, (void**)&cursor) == B_OK)
403 		return cursor;
404 
405 	return NULL;
406 }
407 
408 
409 //! Sets the cursors to the defaults and saves them to CURSOR_SETTINGS_DIR/"d
410 void
411 CursorManager::SetDefaults()
412 {
413 	Lock();
414 	CursorSet cursorSet("Default");
415 	cursorSet.AddCursor(B_CURSOR_DEFAULT, default_cursor_data);
416 	cursorSet.AddCursor(B_CURSOR_TEXT, default_text_data);
417 	cursorSet.AddCursor(B_CURSOR_MOVE, default_move_data);
418 	cursorSet.AddCursor(B_CURSOR_DRAG, default_drag_data);
419 	cursorSet.AddCursor(B_CURSOR_RESIZE, default_resize_data);
420 	cursorSet.AddCursor(B_CURSOR_RESIZE_NWSE, default_resize_nwse_data);
421 	cursorSet.AddCursor(B_CURSOR_RESIZE_NESW, default_resize_nesw_data);
422 	cursorSet.AddCursor(B_CURSOR_RESIZE_NS, default_resize_ns_data);
423 	cursorSet.AddCursor(B_CURSOR_RESIZE_EW, default_resize_ew_data);
424 
425 	BDirectory dir;
426 	if (dir.SetTo(CURSOR_SET_DIR) == B_ENTRY_NOT_FOUND)
427 		create_directory(CURSOR_SET_DIR, 0777);
428 
429 	BString string(CURSOR_SET_DIR);
430 	string += "Default";
431 	cursorSet.Save(string.String(), B_CREATE_FILE | B_FAIL_IF_EXISTS);
432 
433 	SetCursorSet(string.String());
434 	Unlock();
435 }
436