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