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