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