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