xref: /haiku/src/preferences/input/MouseSettings.cpp (revision 925d9f1909d43f4f31661bf8134761d036ebc887)
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 }