1 /* 2 * Copyright 2019, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Author: 6 * Preetpal Kaur <preetpalok123@gmail.com> 7 */ 8 9 10 #include "MouseSettings.h" 11 12 #include <File.h> 13 #include <FindDirectory.h> 14 #include <Path.h> 15 #include <String.h> 16 #include <View.h> 17 18 #include <stdio.h> 19 20 21 // The R5 settings file differs from that of Haiku; 22 // the latter maps 16 different mouse buttons 23 #define R5_COMPATIBLE 0 24 25 static const bigtime_t kDefaultClickSpeed = 500000; 26 static const int32 kDefaultMouseSpeed = 65536; 27 static const int32 kDefaultMouseType = 3; // 3 button mouse 28 static const int32 kDefaultAccelerationFactor = 65536; 29 static const bool kDefaultAcceptFirstClick = true; 30 31 32 MouseSettings::MouseSettings(BString name) 33 : 34 fName(name) 35 { 36 if (_RetrieveSettings() != B_OK) 37 Defaults(); 38 39 fOriginalSettings = fSettings; 40 fOriginalMode = fMode; 41 fOriginalFocusFollowsMouseMode = fFocusFollowsMouseMode; 42 fOriginalAcceptFirstClick = fAcceptFirstClick; 43 } 44 45 46 MouseSettings::MouseSettings(mouse_settings settings, BString name) 47 : 48 fSettings(settings) 49 { 50 fName = name; 51 52 #ifdef DEBUG 53 Dump(); 54 #endif 55 56 // These are not stored in mouse_settings, get the current values from 57 // app_server 58 // FIXME these should be moved out of the MouseSettings class, since they 59 // are not specific to each mouse, but are global settings. 60 fMode = mouse_mode(); 61 fFocusFollowsMouseMode = focus_follows_mouse_mode(); 62 fAcceptFirstClick = accept_first_click(); 63 64 fOriginalSettings = fSettings; 65 fOriginalMode = fMode; 66 fOriginalFocusFollowsMouseMode = fFocusFollowsMouseMode; 67 fOriginalAcceptFirstClick = fAcceptFirstClick; 68 } 69 70 71 MouseSettings::~MouseSettings() 72 { 73 } 74 75 76 status_t 77 MouseSettings::_GetSettingsPath(BPath& path) 78 { 79 status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 80 if (status < B_OK) 81 return status; 82 83 path.Append(mouse_settings_file); 84 return B_OK; 85 } 86 87 88 status_t 89 MouseSettings::_RetrieveSettings() 90 { 91 // retrieve current values 92 if (get_mouse_map(&fSettings.map) != B_OK) 93 return B_ERROR; 94 if (get_click_speed(&fSettings.click_speed) != B_OK) 95 return B_ERROR; 96 if (get_mouse_speed(fName, &fSettings.accel.speed) != B_OK) 97 return B_ERROR; 98 if (get_mouse_acceleration(fName, &fSettings.accel.accel_factor) != B_OK) 99 return B_ERROR; 100 if (get_mouse_type(fName, &fSettings.type) != B_OK) 101 return B_ERROR; 102 103 fMode = mouse_mode(); 104 fFocusFollowsMouseMode = focus_follows_mouse_mode(); 105 fAcceptFirstClick = accept_first_click(); 106 107 return B_OK; 108 } 109 110 111 status_t 112 MouseSettings::_LoadLegacySettings() 113 { 114 BPath path; 115 if (_GetSettingsPath(path) < B_OK) 116 return B_ERROR; 117 118 BFile file(path.Path(), B_READ_ONLY); 119 if (file.InitCheck() < B_OK) 120 return B_ERROR; 121 122 // Read the settings from the file 123 file.Read((void*)&fSettings, sizeof(mouse_settings)); 124 125 #ifdef DEBUG 126 Dump(); 127 #endif 128 129 return B_OK; 130 } 131 132 133 #ifdef DEBUG 134 void 135 MouseSettings::Dump() 136 { 137 printf("type:\t\t%" B_PRId32 " button mouse\n", fSettings.type); 138 for (int i = 0; i < 5; i++) 139 printf("button[%d]: %" B_PRId32 "\n", i, fSettings.map.button[i]); 140 printf("click speed:\t%" B_PRId64 "\n", fSettings.click_speed); 141 printf("accel:\t\t%s\n", fSettings.accel.enabled ? "enabled" : "disabled"); 142 printf("accel factor:\t%" B_PRId32 "\n", fSettings.accel.accel_factor); 143 printf("speed:\t\t%" B_PRId32 "\n", fSettings.accel.speed); 144 145 const char* mode = "unknown"; 146 switch (fMode) { 147 case B_NORMAL_MOUSE: 148 mode = "click to focus and raise"; 149 break; 150 case B_CLICK_TO_FOCUS_MOUSE: 151 mode = "click to focus"; 152 break; 153 case B_FOCUS_FOLLOWS_MOUSE: 154 mode = "focus follows mouse"; 155 break; 156 } 157 printf("mouse mode:\t%s\n", mode); 158 159 const char* focus_follows_mouse_mode = "unknown"; 160 switch (fFocusFollowsMouseMode) { 161 case B_NORMAL_FOCUS_FOLLOWS_MOUSE: 162 focus_follows_mouse_mode = "normal"; 163 break; 164 case B_WARP_FOCUS_FOLLOWS_MOUSE: 165 focus_follows_mouse_mode = "warp"; 166 break; 167 case B_INSTANT_WARP_FOCUS_FOLLOWS_MOUSE: 168 focus_follows_mouse_mode = "instant warp"; 169 break; 170 } 171 printf("focus follows mouse mode:\t%s\n", focus_follows_mouse_mode); 172 printf("accept first click:\t%s\n", 173 fAcceptFirstClick ? "enabled" : "disabled"); 174 } 175 #endif 176 177 178 // Resets the settings to the system defaults 179 void 180 MouseSettings::Defaults() 181 { 182 SetClickSpeed(kDefaultClickSpeed); 183 SetMouseSpeed(kDefaultMouseSpeed); 184 SetMouseType(kDefaultMouseType); 185 SetAccelerationFactor(kDefaultAccelerationFactor); 186 SetMouseMode(B_NORMAL_MOUSE); 187 SetFocusFollowsMouseMode(B_NORMAL_FOCUS_FOLLOWS_MOUSE); 188 SetAcceptFirstClick(kDefaultAcceptFirstClick); 189 190 mouse_map map; 191 if (get_mouse_map(&map) != B_OK) { 192 // Set some default values 193 map.button[0] = B_PRIMARY_MOUSE_BUTTON; 194 map.button[1] = B_SECONDARY_MOUSE_BUTTON; 195 map.button[2] = B_TERTIARY_MOUSE_BUTTON; 196 map.button[3] = B_MOUSE_BUTTON(4); 197 map.button[4] = B_MOUSE_BUTTON(5); 198 map.button[5] = B_MOUSE_BUTTON(6); 199 } 200 SetMapping(map); 201 } 202 203 204 // Checks if the settings are different then the system defaults 205 bool 206 MouseSettings::IsDefaultable() 207 { 208 return fSettings.click_speed != kDefaultClickSpeed 209 || fSettings.accel.speed != kDefaultMouseSpeed 210 || fSettings.type != kDefaultMouseType 211 || fSettings.accel.accel_factor != kDefaultAccelerationFactor 212 || fMode != B_NORMAL_MOUSE 213 || fFocusFollowsMouseMode != B_NORMAL_FOCUS_FOLLOWS_MOUSE 214 || fAcceptFirstClick != kDefaultAcceptFirstClick 215 || fSettings.map.button[0] != B_PRIMARY_MOUSE_BUTTON 216 || fSettings.map.button[1] != B_SECONDARY_MOUSE_BUTTON 217 || fSettings.map.button[2] != B_TERTIARY_MOUSE_BUTTON 218 || fSettings.map.button[3] != B_MOUSE_BUTTON(4) 219 || fSettings.map.button[4] != B_MOUSE_BUTTON(5) 220 || fSettings.map.button[5] != B_MOUSE_BUTTON(6); 221 } 222 223 224 // Reverts to the active settings at program startup 225 void 226 MouseSettings::Revert() 227 { 228 SetClickSpeed(fOriginalSettings.click_speed); 229 SetMouseSpeed(fOriginalSettings.accel.speed); 230 SetMouseType(fOriginalSettings.type); 231 SetAccelerationFactor(fOriginalSettings.accel.accel_factor); 232 SetMouseMode(fOriginalMode); 233 SetFocusFollowsMouseMode(fOriginalFocusFollowsMouseMode); 234 SetAcceptFirstClick(fOriginalAcceptFirstClick); 235 236 SetMapping(fOriginalSettings.map); 237 } 238 239 240 // Checks if the settings are different then the original settings 241 bool 242 MouseSettings::IsRevertable() 243 { 244 return fSettings.click_speed != fOriginalSettings.click_speed 245 || fSettings.accel.speed != fOriginalSettings.accel.speed 246 || fSettings.type != fOriginalSettings.type 247 || fSettings.accel.accel_factor != fOriginalSettings.accel.accel_factor 248 || fMode != fOriginalMode 249 || fFocusFollowsMouseMode != fOriginalFocusFollowsMouseMode 250 || fAcceptFirstClick != fOriginalAcceptFirstClick 251 || fSettings.map.button[0] != fOriginalSettings.map.button[0] 252 || fSettings.map.button[1] != fOriginalSettings.map.button[1] 253 || fSettings.map.button[2] != fOriginalSettings.map.button[2] 254 || fSettings.map.button[3] != fOriginalSettings.map.button[3] 255 || fSettings.map.button[4] != fOriginalSettings.map.button[4] 256 || fSettings.map.button[5] != fOriginalSettings.map.button[5]; 257 } 258 259 260 void 261 MouseSettings::SetMouseType(int32 type) 262 { 263 if (set_mouse_type(fName, type) == B_OK) 264 fSettings.type = type; 265 } 266 267 268 bigtime_t 269 MouseSettings::ClickSpeed() const 270 { 271 return 1000000LL - fSettings.click_speed; 272 // to correct the Sliders 0-100000 scale 273 } 274 275 276 void 277 MouseSettings::SetClickSpeed(bigtime_t clickSpeed) 278 { 279 clickSpeed = 1000000LL - clickSpeed; 280 281 if (set_click_speed(clickSpeed) == B_OK) 282 fSettings.click_speed = clickSpeed; 283 } 284 285 286 void 287 MouseSettings::SetMouseSpeed(int32 speed) 288 { 289 if (set_mouse_speed(fName, speed) == B_OK) 290 fSettings.accel.speed = speed; 291 } 292 293 294 void 295 MouseSettings::SetAccelerationFactor(int32 factor) 296 { 297 if (set_mouse_acceleration(fName, factor) == B_OK) 298 fSettings.accel.accel_factor = factor; 299 } 300 301 302 uint32 303 MouseSettings::Mapping(int32 index) const 304 { 305 return fSettings.map.button[index]; 306 } 307 308 309 void 310 MouseSettings::Mapping(mouse_map& map) const 311 { 312 map = fSettings.map; 313 } 314 315 316 void 317 MouseSettings::SetMapping(int32 index, uint32 button) 318 { 319 fSettings.map.button[index] = button; 320 set_mouse_map(&fSettings.map); 321 } 322 323 324 void 325 MouseSettings::SetMapping(mouse_map& map) 326 { 327 if (set_mouse_map(&map) == B_OK) 328 fSettings.map = map; 329 } 330 331 332 void 333 MouseSettings::SetMouseMode(mode_mouse mode) 334 { 335 set_mouse_mode(mode); 336 fMode = mode; 337 } 338 339 340 void 341 MouseSettings::SetFocusFollowsMouseMode(mode_focus_follows_mouse mode) 342 { 343 set_focus_follows_mouse_mode(mode); 344 fFocusFollowsMouseMode = mode; 345 } 346 347 348 void 349 MouseSettings::SetAcceptFirstClick(bool accept_first_click) 350 { 351 set_accept_first_click(accept_first_click); 352 fAcceptFirstClick = accept_first_click; 353 } 354 355 356 mouse_settings* 357 MouseSettings::GetSettings() 358 { 359 return &fSettings; 360 } 361 362 363 MultipleMouseSettings::MultipleMouseSettings() 364 { 365 fDeprecatedMouseSettings = NULL; 366 RetrieveSettings(); 367 368 #ifdef DEBUG 369 Dump(); 370 #endif 371 } 372 373 374 MultipleMouseSettings::~MultipleMouseSettings() 375 { 376 SaveSettings(); 377 378 #ifdef DEBUG 379 Dump(); 380 #endif 381 382 std::map<BString, MouseSettings*>::iterator itr; 383 for (itr = fMouseSettingsObject.begin(); itr != fMouseSettingsObject.end(); 384 ++itr) 385 delete itr->second; 386 387 delete fDeprecatedMouseSettings; 388 } 389 390 391 status_t 392 MultipleMouseSettings::GetSettingsPath(BPath& path) 393 { 394 status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 395 if (status < B_OK) 396 return status; 397 398 path.Append(mouse_settings_file); 399 return B_OK; 400 } 401 402 403 void 404 MultipleMouseSettings::RetrieveSettings() 405 { 406 // retrieve current values 407 // also try to load the window position from disk 408 409 BPath path; 410 if (GetSettingsPath(path) < B_OK) 411 return; 412 413 BFile file(path.Path(), B_READ_ONLY); 414 if (file.InitCheck() < B_OK) 415 return; 416 417 BMessage message; 418 419 if (message.Unflatten(&file) == B_OK) { 420 int i = 0; 421 BString deviceName; 422 mouse_settings* settings; 423 ssize_t size = 0; 424 425 while (message.FindString("mouseDevice", i, &deviceName) == B_OK) { 426 message.FindData( 427 "mouseSettings", B_ANY_TYPE, i, (const void**)&settings, &size); 428 MouseSettings* mouseSettings 429 = new MouseSettings(*settings, deviceName); 430 fMouseSettingsObject.insert( 431 std::pair<BString, MouseSettings*>(deviceName, mouseSettings)); 432 i++; 433 } 434 } else { 435 // Does not look like a BMessage, try loading using the old format 436 fDeprecatedMouseSettings = new MouseSettings(""); 437 if (fDeprecatedMouseSettings->_LoadLegacySettings() != B_OK) { 438 delete fDeprecatedMouseSettings; 439 fDeprecatedMouseSettings = NULL; 440 } 441 } 442 } 443 444 445 status_t 446 MultipleMouseSettings::Archive(BMessage* into, bool deep) const 447 { 448 std::map<BString, MouseSettings*>::const_iterator itr; 449 for (itr = fMouseSettingsObject.begin(); itr != fMouseSettingsObject.end(); 450 ++itr) { 451 into->AddString("mouseDevice", itr->first); 452 into->AddData("mouseSettings", B_ANY_TYPE, itr->second->GetSettings(), 453 sizeof(*(itr->second->GetSettings()))); 454 } 455 456 return B_OK; 457 } 458 459 460 status_t 461 MultipleMouseSettings::SaveSettings() 462 { 463 BPath path; 464 status_t status = GetSettingsPath(path); 465 if (status < B_OK) 466 return status; 467 468 BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 469 status = file.InitCheck(); 470 if (status != B_OK) 471 return status; 472 473 BMessage message; 474 Archive(&message, true); 475 message.Flatten(&file); 476 477 return B_OK; 478 } 479 480 481 void 482 MultipleMouseSettings::Defaults() 483 { 484 std::map<BString, MouseSettings*>::iterator itr; 485 for (itr = fMouseSettingsObject.begin(); itr != fMouseSettingsObject.end(); 486 ++itr) { 487 itr->second->Defaults(); 488 } 489 490 } 491 492 493 #ifdef DEBUG 494 void 495 MultipleMouseSettings::Dump() 496 { 497 std::map<BString, MouseSettings*>::iterator itr; 498 for (itr = fMouseSettingsObject.begin(); itr != fMouseSettingsObject.end(); 499 ++itr) { 500 printf("mouse_name:\t%s\n", itr->first.String()); 501 itr->second->Dump(); 502 printf("\n"); 503 } 504 } 505 #endif 506 507 508 MouseSettings* 509 MultipleMouseSettings::AddMouseSettings(BString mouse_name) 510 { 511 if (fDeprecatedMouseSettings != NULL) { 512 MouseSettings* RetrievedSettings = new(std::nothrow) MouseSettings( 513 *(fDeprecatedMouseSettings->GetSettings()), mouse_name); 514 515 if (RetrievedSettings != NULL) { 516 fMouseSettingsObject.insert(std::pair<BString, MouseSettings*>( 517 mouse_name, RetrievedSettings)); 518 519 return RetrievedSettings; 520 } 521 } 522 523 MouseSettings* settings = GetMouseSettings(mouse_name); 524 if (settings) 525 return settings; 526 527 settings = new(std::nothrow) MouseSettings(mouse_name); 528 if (settings == NULL) 529 return NULL; 530 531 fMouseSettingsObject.insert( 532 std::pair<BString, MouseSettings*>(mouse_name, settings)); 533 return settings; 534 } 535 536 537 MouseSettings* 538 MultipleMouseSettings::GetMouseSettings(BString mouse_name) 539 { 540 std::map<BString, MouseSettings*>::iterator itr; 541 itr = fMouseSettingsObject.find(mouse_name); 542 543 if (itr != fMouseSettingsObject.end()) 544 return itr->second; 545 return NULL; 546 } 547