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]); 151 printf("click speed:\t%" B_PRId64 "\n", fSettings.click_speed); 152 printf("accel:\t\t%s\n", fSettings.accel.enabled ? "enabled" : "disabled"); 153 printf("accel factor:\t%" B_PRId32 "\n", fSettings.accel.accel_factor); 154 printf("speed:\t\t%" B_PRId32 "\n", fSettings.accel.speed); 155 156 const char *mode = "unknown"; 157 switch (fMode) { 158 case B_NORMAL_MOUSE: 159 mode = "click to focus and raise"; 160 break; 161 case B_CLICK_TO_FOCUS_MOUSE: 162 mode = "click to focus"; 163 break; 164 case B_FOCUS_FOLLOWS_MOUSE: 165 mode = "focus follows mouse"; 166 break; 167 } 168 printf("mouse mode:\t%s\n", mode); 169 170 const char *focus_follows_mouse_mode = "unknown"; 171 switch (fFocusFollowsMouseMode) { 172 case B_NORMAL_FOCUS_FOLLOWS_MOUSE: 173 focus_follows_mouse_mode = "normal"; 174 break; 175 case B_WARP_FOCUS_FOLLOWS_MOUSE: 176 focus_follows_mouse_mode = "warp"; 177 break; 178 case B_INSTANT_WARP_FOCUS_FOLLOWS_MOUSE: 179 focus_follows_mouse_mode = "instant warp"; 180 break; 181 } 182 printf("focus follows mouse mode:\t%s\n", focus_follows_mouse_mode); 183 printf("accept first click:\t%s\n", 184 fAcceptFirstClick ? "enabled" : "disabled"); 185 } 186 #endif 187 188 189 // Resets the settings to the system defaults 190 void 191 MouseSettings::Defaults() 192 { 193 SetClickSpeed(kDefaultClickSpeed); 194 SetMouseSpeed(kDefaultMouseSpeed); 195 SetMouseType(kDefaultMouseType); 196 SetAccelerationFactor(kDefaultAccelerationFactor); 197 SetMouseMode(B_NORMAL_MOUSE); 198 SetFocusFollowsMouseMode(B_NORMAL_FOCUS_FOLLOWS_MOUSE); 199 SetAcceptFirstClick(kDefaultAcceptFirstClick); 200 201 mouse_map map; 202 if (get_mouse_map(&map) == B_OK) { 203 map.button[0] = B_PRIMARY_MOUSE_BUTTON; 204 map.button[1] = B_SECONDARY_MOUSE_BUTTON; 205 map.button[2] = B_TERTIARY_MOUSE_BUTTON; 206 SetMapping(map); 207 } 208 } 209 210 211 // Checks if the settings are different then the system defaults 212 bool 213 MouseSettings::IsDefaultable() 214 { 215 return fSettings.click_speed != kDefaultClickSpeed 216 || fSettings.accel.speed != kDefaultMouseSpeed 217 || fSettings.type != kDefaultMouseType 218 || fSettings.accel.accel_factor != kDefaultAccelerationFactor 219 || fMode != B_NORMAL_MOUSE 220 || fFocusFollowsMouseMode != B_NORMAL_FOCUS_FOLLOWS_MOUSE 221 || fAcceptFirstClick != kDefaultAcceptFirstClick 222 || fSettings.map.button[0] != B_PRIMARY_MOUSE_BUTTON 223 || fSettings.map.button[1] != B_SECONDARY_MOUSE_BUTTON 224 || fSettings.map.button[2] != B_TERTIARY_MOUSE_BUTTON; 225 } 226 227 228 // Reverts to the active settings at program startup 229 void 230 MouseSettings::Revert() 231 { 232 SetClickSpeed(fOriginalSettings.click_speed); 233 SetMouseSpeed(fOriginalSettings.accel.speed); 234 SetMouseType(fOriginalSettings.type); 235 SetAccelerationFactor(fOriginalSettings.accel.accel_factor); 236 SetMouseMode(fOriginalMode); 237 SetFocusFollowsMouseMode(fOriginalFocusFollowsMouseMode); 238 SetAcceptFirstClick(fOriginalAcceptFirstClick); 239 240 SetMapping(fOriginalSettings.map); 241 } 242 243 244 // Checks if the settings are different then the original settings 245 bool 246 MouseSettings::IsRevertable() 247 { 248 return fSettings.click_speed != fOriginalSettings.click_speed 249 || fSettings.accel.speed != fOriginalSettings.accel.speed 250 || fSettings.type != fOriginalSettings.type 251 || fSettings.accel.accel_factor != fOriginalSettings.accel.accel_factor 252 || fMode != fOriginalMode 253 || fFocusFollowsMouseMode != fOriginalFocusFollowsMouseMode 254 || fAcceptFirstClick != fOriginalAcceptFirstClick 255 || fSettings.map.button[0] != fOriginalSettings.map.button[0] 256 || fSettings.map.button[1] != fOriginalSettings.map.button[1] 257 || fSettings.map.button[2] != fOriginalSettings.map.button[2]; 258 } 259 260 261 void 262 MouseSettings::SetWindowPosition(BPoint corner) 263 { 264 fWindowPosition = corner; 265 } 266 267 268 void 269 MouseSettings::SetMouseType(int32 type) 270 { 271 if (set_mouse_type(type) == B_OK) 272 fSettings.type = type; 273 else 274 fprintf(stderr, "error when set_mouse_type\n"); 275 } 276 277 278 bigtime_t 279 MouseSettings::ClickSpeed() const 280 { 281 return 1000000LL - fSettings.click_speed; 282 // to correct the Sliders 0-100000 scale 283 } 284 285 286 void 287 MouseSettings::SetClickSpeed(bigtime_t clickSpeed) 288 { 289 clickSpeed = 1000000LL - clickSpeed; 290 291 if (set_click_speed(clickSpeed) == B_OK) 292 fSettings.click_speed = clickSpeed; 293 else 294 fprintf(stderr, "error when set_click_speed\n"); 295 } 296 297 298 void 299 MouseSettings::SetMouseSpeed(int32 speed) 300 { 301 if (set_mouse_speed(speed) == B_OK) 302 fSettings.accel.speed = speed; 303 else 304 fprintf(stderr, "error when set_mouse_speed\n"); 305 } 306 307 308 void 309 MouseSettings::SetAccelerationFactor(int32 factor) 310 { 311 if (set_mouse_acceleration(factor) == B_OK) 312 fSettings.accel.accel_factor = factor; 313 else 314 fprintf(stderr, "error when set_mouse_acceleration\n"); 315 } 316 317 318 uint32 319 MouseSettings::Mapping(int32 index) const 320 { 321 return fSettings.map.button[index]; 322 } 323 324 325 void 326 MouseSettings::Mapping(mouse_map &map) const 327 { 328 map = fSettings.map; 329 } 330 331 332 void 333 MouseSettings::SetMapping(int32 index, uint32 button) 334 { 335 fSettings.map.button[index] = button; 336 if (set_mouse_map(&fSettings.map) != B_OK) 337 fprintf(stderr, "error when set_mouse_map\n"); 338 } 339 340 341 void 342 MouseSettings::SetMapping(mouse_map &map) 343 { 344 if (set_mouse_map(&map) == B_OK) 345 fSettings.map = map; 346 else 347 fprintf(stderr, "error when set_mouse_map\n"); 348 } 349 350 351 void 352 MouseSettings::SetMouseMode(mode_mouse mode) 353 { 354 set_mouse_mode(mode); 355 fMode = mode; 356 } 357 358 359 void 360 MouseSettings::SetFocusFollowsMouseMode(mode_focus_follows_mouse mode) 361 { 362 set_focus_follows_mouse_mode(mode); 363 fFocusFollowsMouseMode = mode; 364 } 365 366 367 void 368 MouseSettings::SetAcceptFirstClick(bool accept_first_click) 369 { 370 set_accept_first_click(accept_first_click); 371 fAcceptFirstClick = accept_first_click; 372 } 373