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