1/*
2 * Copyright 2004-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		J��r��me Duval
7 *		Andrew McCall (mccall@digitalparadise.co.uk)
8 *		Axel D��rfler, axeld@pinc-software.de
9 */
10
11
12#include "MouseSettings.h"
13
14#include <stdio.h>
15
16#include <FindDirectory.h>
17#include <File.h>
18#include <Path.h>
19#include <View.h>
20
21
22static const bigtime_t kDefaultClickSpeed = 500000;
23static const int32 kDefaultMouseSpeed = 65536;
24static const int32 kDefaultMouseType = 3;	// 3 button mouse
25static const int32 kDefaultAccelerationFactor = 65536;
26static const bool kDefaultAcceptFirstClick = true;
27
28
29
30MouseSettings::MouseSettings()
31{
32	Defaults();
33
34#ifdef DEBUG
35	Dump();
36#endif
37
38	fOriginalSettings = fSettings;
39	fOriginalMode = fMode;
40	fOriginalFocusFollowsMouseMode = fFocusFollowsMouseMode;
41	fOriginalAcceptFirstClick = fAcceptFirstClick;
42}
43
44
45MouseSettings::MouseSettings(mouse_settings* originalSettings)
46{
47	Defaults();
48	fMode = mouse_mode();
49	fAcceptFirstClick = accept_first_click();
50
51	fOriginalSettings = *originalSettings;
52	fSettings = *originalSettings;
53
54#ifdef DEBUG
55	Dump();
56#endif
57
58	fOriginalMode = fMode;
59	fOriginalFocusFollowsMouseMode = fFocusFollowsMouseMode;
60	fOriginalAcceptFirstClick = fAcceptFirstClick;
61}
62
63
64MouseSettings::~MouseSettings()
65{
66}
67
68
69status_t
70MouseSettings::GetSettingsPath(BPath &path)
71{
72	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
73	if (status < B_OK)
74		return status;
75
76	path.Append(mouse_settings_file);
77	return B_OK;
78}
79
80
81void
82MouseSettings::RetrieveSettings()
83{
84	// retrieve current values
85
86	fMode = mouse_mode();
87	fAcceptFirstClick = accept_first_click();
88	Defaults();
89
90	// also try to load the window position from disk
91
92	BPath path;
93	if (GetSettingsPath(path) < B_OK)
94		return;
95
96	BFile file(path.Path(), B_READ_ONLY);
97	if (file.InitCheck() < B_OK)
98		return;
99
100	if (file.ReadAt(0, &fSettings, sizeof(mouse_settings))
101			!= sizeof(mouse_settings)) {
102		Defaults();
103	}
104
105	if ((fSettings.click_speed == 0)
106		|| (fSettings.type == 0)) {
107		Defaults();
108	}
109}
110
111
112#ifdef DEBUG
113void
114MouseSettings::Dump()
115{
116	printf("type:\t\t%" B_PRId32 " button mouse\n", fSettings.type);
117	printf("map:\t\tleft = %" B_PRIu32 " : middle = %" B_PRIu32 " : "
118		"right = %" B_PRIu32 "\n",
119		fSettings.map.button[0], fSettings.map.button[2],
120		fSettings.map.button[1]);
121	printf("click speed:\t%" B_PRId64 "\n", fSettings.click_speed);
122	printf("accel:\t\t%s\n", fSettings.accel.enabled
123		? "enabled" : "disabled");
124	printf("accel factor:\t%" B_PRId32 "\n", fSettings.accel.accel_factor);
125	printf("speed:\t\t%" B_PRId32 "\n", fSettings.accel.speed);
126
127	const char *mode = "unknown";
128	switch (fMode) {
129		case B_NORMAL_MOUSE:
130			mode = "activate";
131			break;
132		case B_CLICK_TO_FOCUS_MOUSE:
133			mode = "focus";
134			break;
135		case B_FOCUS_FOLLOWS_MOUSE:
136			mode = "auto-focus";
137			break;
138	}
139	printf("mouse mode:\t%s\n", mode);
140
141	const char *focus_follows_mouse_mode = "unknown";
142	switch (fFocusFollowsMouseMode) {
143		case B_NORMAL_FOCUS_FOLLOWS_MOUSE:
144			focus_follows_mouse_mode = "normal";
145			break;
146		case B_WARP_FOCUS_FOLLOWS_MOUSE:
147			focus_follows_mouse_mode = "warp";
148			break;
149		case B_INSTANT_WARP_FOCUS_FOLLOWS_MOUSE:
150			focus_follows_mouse_mode = "instant warp";
151			break;
152	}
153	printf("focus follows mouse mode:\t%s\n", focus_follows_mouse_mode);
154	printf("accept first click:\t%s\n", fAcceptFirstClick
155		? "enabled" : "disabled");
156}
157#endif
158
159
160/**	Resets the settings to the system defaults
161 */
162
163void
164MouseSettings::Defaults()
165{
166	SetClickSpeed(kDefaultClickSpeed);
167	SetMouseSpeed(kDefaultMouseSpeed);
168	SetMouseType(kDefaultMouseType);
169	SetAccelerationFactor(kDefaultAccelerationFactor);
170	SetMouseMode(B_NORMAL_MOUSE);
171	SetFocusFollowsMouseMode(B_NORMAL_FOCUS_FOLLOWS_MOUSE);
172	SetAcceptFirstClick(kDefaultAcceptFirstClick);
173
174	for (int i = 0; i < B_MAX_MOUSE_BUTTONS; i++)
175		fSettings.map.button[i] = B_MOUSE_BUTTON(i + 1);
176}
177
178
179void
180MouseSettings::SetMouseType(int32 type)
181{
182	fSettings.type = type;
183}
184
185
186bigtime_t
187MouseSettings::ClickSpeed() const
188{
189	return fSettings.click_speed;
190}
191
192
193void
194MouseSettings::SetClickSpeed(bigtime_t clickSpeed)
195{
196	fSettings.click_speed = clickSpeed;
197}
198
199
200void
201MouseSettings::SetMouseSpeed(int32 speed)
202{
203	fSettings.accel.speed = speed;
204}
205
206
207void
208MouseSettings::SetAccelerationFactor(int32 factor)
209{
210	fSettings.accel.accel_factor = factor;
211}
212
213
214uint32
215MouseSettings::Mapping(int32 index) const
216{
217	return fSettings.map.button[index];
218}
219
220
221void
222MouseSettings::Mapping(mouse_map &map) const
223{
224	map = fSettings.map;
225}
226
227
228void
229MouseSettings::SetMapping(int32 index, uint32 button)
230{
231	fSettings.map.button[index] = button;
232}
233
234
235void
236MouseSettings::SetMapping(mouse_map &map)
237{
238	fSettings.map = map;
239}
240
241
242void
243MouseSettings::SetMouseMode(mode_mouse mode)
244{
245	fMode = mode;
246}
247
248
249void
250MouseSettings::SetFocusFollowsMouseMode(mode_focus_follows_mouse mode)
251{
252	fFocusFollowsMouseMode = mode;
253}
254
255
256void
257MouseSettings::SetAcceptFirstClick(bool acceptFirstClick)
258{
259	fAcceptFirstClick = acceptFirstClick;
260}
261
262
263/* MultiMouseSettings functions */
264
265MultipleMouseSettings::MultipleMouseSettings()
266{
267	fDeprecatedMouseSettings = NULL;
268	RetrieveSettings();
269
270#ifdef DEBUG
271	Dump();
272#endif
273}
274
275
276MultipleMouseSettings::~MultipleMouseSettings()
277{
278	SaveSettings();
279
280#ifdef DEBUG
281	Dump();
282#endif
283
284	std::map<BString, MouseSettings*>::iterator itr;
285	for (itr = fMouseSettingsObject.begin(); itr != fMouseSettingsObject.end();
286		++itr)
287		delete itr->second;
288
289	delete fDeprecatedMouseSettings;
290}
291
292
293status_t
294MultipleMouseSettings::GetSettingsPath(BPath &path)
295{
296	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
297	if (status < B_OK)
298		return status;
299
300	path.Append(mouse_settings_file);
301	return B_OK;
302}
303
304
305void
306MultipleMouseSettings::RetrieveSettings()
307{
308	BPath path;
309	if (GetSettingsPath(path) < B_OK)
310		return;
311
312	BFile file(path.Path(), B_READ_ONLY);
313	if (file.InitCheck() < B_OK)
314		return;
315
316	BMessage message;
317
318	if (message.Unflatten(&file) == B_OK) {
319		int i = 0;
320		BString deviceName;
321		mouse_settings* settings;
322		ssize_t size = 0;
323
324		while (message.FindString("mouseDevice", i, &deviceName) == B_OK) {
325			message.FindData("mouseSettings", B_ANY_TYPE, i,
326				(const void**)&settings, &size);
327			MouseSettings* mouseSettings = new MouseSettings(settings);
328			fMouseSettingsObject.insert(std::pair<BString, MouseSettings*>
329				(deviceName, mouseSettings));
330			i++;
331		}
332	} else {
333		fDeprecatedMouseSettings = new MouseSettings();
334		fDeprecatedMouseSettings->RetrieveSettings();
335	}
336}
337
338
339status_t
340MultipleMouseSettings::Archive(BMessage* into, bool deep) const
341{
342	std::map<BString, MouseSettings*>::const_iterator itr;
343	for (itr = fMouseSettingsObject.begin(); itr != fMouseSettingsObject.end();
344		++itr) {
345		into->AddString("mouseDevice", itr->first);
346		into->AddData("mouseSettings", B_ANY_TYPE, itr->second->GetSettings(),
347			sizeof(*(itr->second->GetSettings())));
348	}
349
350	return B_OK;
351}
352
353
354status_t
355MultipleMouseSettings::SaveSettings()
356{
357	BPath path;
358	status_t status = GetSettingsPath(path);
359	if (status < B_OK)
360		return status;
361
362	BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
363	status = file.InitCheck();
364	if (status != B_OK)
365		return status;
366
367	BMessage message;
368	Archive(&message, true);
369	message.Flatten(&file);
370
371	return B_OK;
372}
373
374
375void
376MultipleMouseSettings::Defaults()
377{
378	std::map<BString, MouseSettings*>::iterator itr;
379	for (itr = fMouseSettingsObject.begin(); itr != fMouseSettingsObject.end();
380		++itr) {
381		itr->second->Defaults();
382	}
383}
384
385
386#ifdef DEBUG
387void
388MultipleMouseSettings::Dump()
389{
390	std::map<BString, MouseSettings*>::iterator itr;
391	for (itr = fMouseSettingsObject.begin();
392		itr != fMouseSettingsObject.end(); ++itr) {
393		printf("mouse_name:\t%s\n", itr->first.String());
394		itr->second->Dump();
395		printf("\n");
396	}
397
398}
399#endif
400
401
402MouseSettings*
403MultipleMouseSettings::AddMouseSettings(BString mouse_name)
404{
405	if(fDeprecatedMouseSettings != NULL) {
406		MouseSettings* RetrievedSettings = new (std::nothrow) MouseSettings
407			(*fDeprecatedMouseSettings);
408
409		if (RetrievedSettings != NULL) {
410			fMouseSettingsObject.insert(std::pair<BString, MouseSettings*>
411				(mouse_name, RetrievedSettings));
412
413			return RetrievedSettings;
414		}
415	}
416
417	std::map<BString, MouseSettings*>::iterator itr;
418	itr = fMouseSettingsObject.find(mouse_name);
419
420	if (itr != fMouseSettingsObject.end())
421		return GetMouseSettings(mouse_name);
422
423	MouseSettings* settings = new (std::nothrow) MouseSettings();
424
425	if(settings != NULL) {
426		fMouseSettingsObject.insert(std::pair<BString, MouseSettings*>
427			(mouse_name, settings));
428		return settings;
429	}
430	return NULL;
431}
432
433
434MouseSettings*
435MultipleMouseSettings::GetMouseSettings(BString mouse_name)
436{
437	std::map<BString, MouseSettings*>::iterator itr;
438	itr = fMouseSettingsObject.find(mouse_name);
439
440	if (itr != fMouseSettingsObject.end())
441		return itr->second;
442	return NULL;
443 }
444
445