1/*
2 Touchpad sensitivity filter
3 Most windows/mac/etc laptops have a sensitivity filter/mechanism
4 which protects the user from accidently rubbing the
5 touchpad while typing and thus deleting text or moving
6 the cursor to a new insertion point. I've been grousing
7 about this to myself for months, and finally decided to
8 write something for BeOS which other people might benefit
9 from.
10
11 Just an input_server add_on. I wrote it in < hour. Works on
12 my inspiron 3500, but I imagine it would work fine on any BeOS
13 machine. Not that desktops would benefit. Compiled under 4.5.2
14
15 Do what you want with it. Enjoy.
16
17 --Shamyl Zakariya
18 --March 22 2000
19 --zakariya@earthlink.net
20
21 Note:
22 reads Touchpad_settings file in home/config/settings .
23 padblocker_threshold value represents the delay between the last
24 B_KEY_UP message and when the filter will allow
25 a B_MOUSE_DOWN message. Eg, if less than _threshold has
26 transpired between a B_KEY_DOWN and a B_MOUSE_DOWN, the mouse
27 down event will be skipped, cast into oblivion.
28
29 Kudos to the people at Be for making this kind of thing
30 so damnably easy to do. Bravo!
31
32 And a hearty thanks to Magnus Landahl for his superb
33 debug console, without which I wouldn't have ever known if
34 this damn thing worked at all.
35
36*/
37
38
39#include <stdlib.h>
40#include <string.h>
41#include <ctype.h>
42#include <input/touchpad_settings.h>
43#include <Debug.h>
44#include <List.h>
45#include <Message.h>
46#include <OS.h>
47#include <StorageKit.h>
48
49#include <add-ons/input_server/InputServerFilter.h>
50
51#if DEBUG
52#	define LOG(text...) PRINT((text))
53#else
54#	define LOG(text...)
55#endif
56
57//#define Z_DEBUG 1
58
59
60#if Z_DEBUG
61#include <BeDC.h>
62#endif
63
64extern "C" _EXPORT BInputServerFilter* instantiate_input_filter();
65
66class PadBlocker : public BInputServerFilter
67{
68	public:
69		PadBlocker();
70		virtual ~PadBlocker();
71		virtual	filter_result Filter(BMessage *message, BList *outList);
72
73	private:
74		bigtime_t 			_lastKeyUp; //timestamp of last B_KEY_DOWN
75		bigtime_t 			_threshold;
76		status_t			GetSettingsPath(BPath& path);
77		BPoint				fWindowPosition;
78};
79
80
81status_t
82PadBlocker::GetSettingsPath(BPath &path)
83{
84	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
85	if (status < B_OK)
86		return status;
87
88	return path.Append(TOUCHPAD_SETTINGS_FILE);
89}
90
91
92PadBlocker::PadBlocker()
93{
94	_lastKeyUp = 0;
95	_threshold = 300; //~one third of a second?
96
97	touchpad_settings settings;
98
99	#if Z_DEBUG
100	BeDC dc("PadBlocker");
101	#endif
102	BPath path;
103	status_t status = GetSettingsPath(path);
104	if (status == B_OK)
105	{
106
107		BFile settingsFile(path.Path(), B_READ_ONLY);
108		status = settingsFile.InitCheck();
109		if (status == B_OK)
110		{
111
112			if (settingsFile.Read(&settings, sizeof(touchpad_settings))
113				!= sizeof(touchpad_settings)) {
114				LOG("failed to load settings\n");
115				status = B_ERROR;
116			}
117			if (settingsFile.Read(&fWindowPosition, sizeof(BPoint))
118				!= sizeof(BPoint)) {
119				LOG("failed to load settings\n");
120				status = B_ERROR;
121			}
122		}
123	}
124
125	//load settings file
126
127	if (status == B_OK)
128	{
129		#if Z_DEBUG
130		dc.SendMessage("Settings file Exists");
131		#endif
132		_threshold = settings.padblocker_threshold;
133	}
134
135
136
137	_threshold *= 1000; //I'd rather keep the number in the file in thousandths
138
139	#ifdef Z_DEBUG
140	dc.SendInt(_threshold, "Touchpad threshold.");
141	#endif
142}
143
144
145PadBlocker::~PadBlocker()
146{
147}
148
149
150filter_result PadBlocker::Filter(BMessage *message, BList *outList)
151{
152	filter_result res = B_DISPATCH_MESSAGE;
153
154	switch (message->what)
155	{
156		case B_KEY_UP: case B_KEY_DOWN:
157		{
158			_lastKeyUp = system_time();	//update timestamp
159			break;
160		}
161
162		case B_MOUSE_DOWN:
163		{
164			// do nothing if disabled
165			if (_threshold == 0)
166				break;
167
168			bigtime_t now = system_time();
169			// if less than the threshold has passed, tell input server
170			// to ignore this message
171			if ((now - _lastKeyUp) < _threshold) res = B_SKIP_MESSAGE;
172			break;
173		}
174
175		default:
176		{
177			//we don't want to mess with anybody else
178			break;
179		}
180	}
181
182	#if Z_DEBUG
183	if (res == B_SKIP_MESSAGE)
184	{
185		BeDC dc("PadBlocker");
186		dc.SendMessage("Skipping mouse down event");
187	}
188	#endif
189
190	return (res);
191}
192
193
194//*************************************************************************
195//Exported instantiator
196
197BInputServerFilter* instantiate_input_filter()
198{
199	return new (std::nothrow) PadBlocker();
200}
201