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 <FindDirectory.h> 13 #include <File.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 OpenBeOS; 22 // the latter maps 16 different mouse buttons 23 #define R5_COMPATIBLE 1 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() 33 : 34 fWindowPosition(-1, -1) 35 { 36 _RetrieveSettings(); 37 38 fOriginalSettings = fSettings; 39 fOriginalMode = fMode; 40 fOriginalFocusFollowsMouseMode = fFocusFollowsMouseMode; 41 fOriginalAcceptFirstClick = fAcceptFirstClick; 42 } 43 44 45 MouseSettings::~MouseSettings() 46 { 47 _SaveSettings(); 48 } 49 50 51 status_t 52 MouseSettings::_GetSettingsPath(BPath &path) 53 { 54 status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 55 if (status < B_OK) 56 return status; 57 58 path.Append(mouse_settings_file); 59 return B_OK; 60 } 61 62 63 void 64 MouseSettings::_RetrieveSettings() 65 { 66 // retrieve current values 67 68 if (get_mouse_map(&fSettings.map) != B_OK) 69 fprintf(stderr, "error when get_mouse_map\n"); 70 if (get_click_speed(&fSettings.click_speed) != B_OK) 71 fprintf(stderr, "error when get_click_speed\n"); 72 if (get_mouse_speed(&fSettings.accel.speed) != B_OK) 73 fprintf(stderr, "error when get_mouse_speed\n"); 74 if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK) 75 fprintf(stderr, "error when get_mouse_acceleration\n"); 76 if (get_mouse_type(&fSettings.type) != B_OK) 77 fprintf(stderr, "error when get_mouse_type\n"); 78 79 fMode = mouse_mode(); 80 fFocusFollowsMouseMode = focus_follows_mouse_mode(); 81 fAcceptFirstClick = accept_first_click(); 82 83 // also try to load the window position from disk 84 85 BPath path; 86 if (_GetSettingsPath(path) < B_OK) 87 return; 88 89 BFile file(path.Path(), B_READ_ONLY); 90 if (file.InitCheck() < B_OK) 91 return; 92 93 #if R5_COMPATIBLE 94 const off_t kOffset = sizeof(mouse_settings) - sizeof(mouse_map) 95 + sizeof(int32) * 3; 96 // we have to do this because mouse_map counts 16 buttons in OBOS 97 #else 98 const off_t kOffset = sizeof(mouse_settings); 99 #endif 100 101 if (file.ReadAt(kOffset, &fWindowPosition, sizeof(BPoint)) 102 != sizeof(BPoint)) { 103 // set default window position (invalid positions will be 104 // corrected by the application; the window will be centered 105 // in this case) 106 fWindowPosition.x = -1; 107 fWindowPosition.y = -1; 108 } 109 110 #ifdef DEBUG 111 Dump(); 112 #endif 113 } 114 115 116 status_t 117 MouseSettings::_SaveSettings() 118 { 119 BPath path; 120 status_t status = _GetSettingsPath(path); 121 if (status < B_OK) 122 return status; 123 124 BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE); 125 status = file.InitCheck(); 126 if (status < B_OK) 127 return status; 128 129 #if R5_COMPATIBLE 130 const off_t kOffset = sizeof(mouse_settings) - sizeof(mouse_map) 131 + sizeof(int32) * 3; 132 // we have to do this because mouse_map counts 16 buttons in OBOS 133 #else 134 const off_t kOffset = sizeof(mouse_settings); 135 #endif 136 137 file.WriteAt(kOffset, &fWindowPosition, sizeof(BPoint)); 138 139 return B_OK; 140 } 141 142 143 #ifdef DEBUG 144 void 145 MouseSettings::Dump() 146 { 147 printf("type:\t\t%" B_PRId32 " button mouse\n", fSettings.type); 148 printf("map:\t\tleft = %" B_PRIu32 " : middle = %" B_PRIu32 " : right = %" 149 B_PRIu32 "\n", fSettings.map.button[0], fSettings.map.button[2], 150 fSettings.map.button[1], fSettings.map.button[3], 151 fSettings.map.button[4]); 152 printf("click speed:\t%" B_PRId64 "\n", fSettings.click_speed); 153 printf("accel:\t\t%s\n", fSettings.accel.enabled ? "enabled" : "disabled"); 154 printf("accel factor:\t%" B_PRId32 "\n", fSettings.accel.accel_factor); 155 printf("speed:\t\t%" B_PRId32 "\n", fSettings.accel.speed); 156 157 const char *mode = "unknown"; 158 switch (fMode) { 159 case B_NORMAL_MOUSE: 160 mode = "click to focus and raise"; 161 break; 162 case B_CLICK_TO_FOCUS_MOUSE: 163 mode = "click to focus"; 164 break; 165 case B_FOCUS_FOLLOWS_MOUSE: 166 mode = "focus follows mouse"; 167 break; 168 } 169 printf("mouse mode:\t%s\n", mode); 170 171 const char *focus_follows_mouse_mode = "unknown"; 172 switch (fFocusFollowsMouseMode) { 173 case B_NORMAL_FOCUS_FOLLOWS_MOUSE: 174 focus_follows_mouse_mode = "normal"; 175 break; 176 case B_WARP_FOCUS_FOLLOWS_MOUSE: 177 focus_follows_mouse_mode = "warp"; 178 break; 179 case B_INSTANT_WARP_FOCUS_FOLLOWS_MOUSE: 180 focus_follows_mouse_mode = "instant warp"; 181 break; 182 } 183 printf("focus follows mouse mode:\t%s\n", focus_follows_mouse_mode); 184 printf("accept first click:\t%s\n", 185 fAcceptFirstClick ? "enabled" : "disabled"); 186 } 187 #endif 188 189 190 // Resets the settings to the system defaults 191 void 192 MouseSettings::Defaults() 193 { 194 SetClickSpeed(kDefaultClickSpeed); 195 SetMouseSpeed(kDefaultMouseSpeed); 196 SetMouseType(kDefaultMouseType); 197 SetAccelerationFactor(kDefaultAccelerationFactor); 198 SetMouseMode(B_NORMAL_MOUSE); 199 SetFocusFollowsMouseMode(B_NORMAL_FOCUS_FOLLOWS_MOUSE); 200 SetAcceptFirstClick(kDefaultAcceptFirstClick); 201 202 mouse_map map; 203 if (get_mouse_map(&map) == B_OK) { 204 map.button[0] = B_PRIMARY_MOUSE_BUTTON; 205 map.button[1] = B_SECONDARY_MOUSE_BUTTON; 206 map.button[2] = B_TERTIARY_MOUSE_BUTTON; 207 map.button[3] = B_MOUSE_BUTTON(4); 208 map.button[4] = B_MOUSE_BUTTON(5); 209 map.button[5] = B_MOUSE_BUTTON(6); 210 SetMapping(map); 211 } 212 } 213 214 215 // Checks if the settings are different then the system defaults 216 bool 217 MouseSettings::IsDefaultable() 218 { 219 return fSettings.click_speed != kDefaultClickSpeed 220 || fSettings.accel.speed != kDefaultMouseSpeed 221 || fSettings.type != kDefaultMouseType 222 || fSettings.accel.accel_factor != kDefaultAccelerationFactor 223 || fMode != B_NORMAL_MOUSE 224 || fFocusFollowsMouseMode != B_NORMAL_FOCUS_FOLLOWS_MOUSE 225 || fAcceptFirstClick != kDefaultAcceptFirstClick 226 || fSettings.map.button[0] != B_PRIMARY_MOUSE_BUTTON 227 || fSettings.map.button[1] != B_SECONDARY_MOUSE_BUTTON 228 || fSettings.map.button[2] != B_TERTIARY_MOUSE_BUTTON 229 || fSettings.map.button[3] != B_MOUSE_BUTTON(4) 230 || fSettings.map.button[4] != B_MOUSE_BUTTON(5) 231 || fSettings.map.button[5] != B_MOUSE_BUTTON(6); 232 } 233 234 235 // Reverts to the active settings at program startup 236 void 237 MouseSettings::Revert() 238 { 239 SetClickSpeed(fOriginalSettings.click_speed); 240 SetMouseSpeed(fOriginalSettings.accel.speed); 241 SetMouseType(fOriginalSettings.type); 242 SetAccelerationFactor(fOriginalSettings.accel.accel_factor); 243 SetMouseMode(fOriginalMode); 244 SetFocusFollowsMouseMode(fOriginalFocusFollowsMouseMode); 245 SetAcceptFirstClick(fOriginalAcceptFirstClick); 246 247 SetMapping(fOriginalSettings.map); 248 } 249 250 251 // Checks if the settings are different then the original settings 252 bool 253 MouseSettings::IsRevertable() 254 { 255 return fSettings.click_speed != fOriginalSettings.click_speed 256 || fSettings.accel.speed != fOriginalSettings.accel.speed 257 || fSettings.type != fOriginalSettings.type 258 || fSettings.accel.accel_factor != fOriginalSettings.accel.accel_factor 259 || fMode != fOriginalMode 260 || fFocusFollowsMouseMode != fOriginalFocusFollowsMouseMode 261 || fAcceptFirstClick != fOriginalAcceptFirstClick 262 || fSettings.map.button[0] != fOriginalSettings.map.button[0] 263 || fSettings.map.button[1] != fOriginalSettings.map.button[1] 264 || fSettings.map.button[2] != fOriginalSettings.map.button[2] 265 || fSettings.map.button[3] != fOriginalSettings.map.button[3] 266 || fSettings.map.button[4] != fOriginalSettings.map.button[4] 267 || fSettings.map.button[5] != fOriginalSettings.map.button[5]; 268 } 269 270 271 void 272 MouseSettings::SetWindowPosition(BPoint corner) 273 { 274 fWindowPosition = corner; 275 } 276 277 278 void 279 MouseSettings::SetMouseType(int32 type) 280 { 281 if (set_mouse_type(type) == B_OK) 282 fSettings.type = type; 283 else 284 fprintf(stderr, "error when set_mouse_type\n"); 285 } 286 287 288 bigtime_t 289 MouseSettings::ClickSpeed() const 290 { 291 return 1000000LL - fSettings.click_speed; 292 // to correct the Sliders 0-100000 scale 293 } 294 295 296 void 297 MouseSettings::SetClickSpeed(bigtime_t clickSpeed) 298 { 299 clickSpeed = 1000000LL - clickSpeed; 300 301 if (set_click_speed(clickSpeed) == B_OK) 302 fSettings.click_speed = clickSpeed; 303 else 304 fprintf(stderr, "error when set_click_speed\n"); 305 } 306 307 308 void 309 MouseSettings::SetMouseSpeed(int32 speed) 310 { 311 if (set_mouse_speed(speed) == B_OK) 312 fSettings.accel.speed = speed; 313 else 314 fprintf(stderr, "error when set_mouse_speed\n"); 315 } 316 317 318 void 319 MouseSettings::SetAccelerationFactor(int32 factor) 320 { 321 if (set_mouse_acceleration(factor) == B_OK) 322 fSettings.accel.accel_factor = factor; 323 else 324 fprintf(stderr, "error when set_mouse_acceleration\n"); 325 } 326 327 328 uint32 329 MouseSettings::Mapping(int32 index) const 330 { 331 return fSettings.map.button[index]; 332 } 333 334 335 void 336 MouseSettings::Mapping(mouse_map &map) const 337 { 338 map = fSettings.map; 339 } 340 341 342 void 343 MouseSettings::SetMapping(int32 index, uint32 button) 344 { 345 fSettings.map.button[index] = button; 346 if (set_mouse_map(&fSettings.map) != B_OK) 347 fprintf(stderr, "error when set_mouse_map\n"); 348 } 349 350 351 void 352 MouseSettings::SetMapping(mouse_map &map) 353 { 354 if (set_mouse_map(&map) == B_OK) 355 fSettings.map = map; 356 else 357 fprintf(stderr, "error when set_mouse_map\n"); 358 } 359 360 361 void 362 MouseSettings::SetMouseMode(mode_mouse mode) 363 { 364 set_mouse_mode(mode); 365 fMode = mode; 366 } 367 368 369 void 370 MouseSettings::SetFocusFollowsMouseMode(mode_focus_follows_mouse mode) 371 { 372 set_focus_follows_mouse_mode(mode); 373 fFocusFollowsMouseMode = mode; 374 } 375 376 377 void 378 MouseSettings::SetAcceptFirstClick(bool accept_first_click) 379 { 380 set_accept_first_click(accept_first_click); 381 fAcceptFirstClick = accept_first_click; 382 } 383