1/*
2 * Copyright 2002-2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "InputServer.h"
8#include "InputServerTypes.h"
9#include "BottomlineWindow.h"
10#include "MethodReplicant.h"
11
12#include <safemode_defs.h>
13#include <syscalls.h>
14
15#include <AppServerLink.h>
16#include <MessagePrivate.h>
17#include <ObjectListPrivate.h>
18#include <RosterPrivate.h>
19
20#include <Autolock.h>
21#include <Deskbar.h>
22#include <Directory.h>
23#include <driver_settings.h>
24#include <Entry.h>
25#include <File.h>
26#include <FindDirectory.h>
27#include <Locker.h>
28#include <Message.h>
29#include <OS.h>
30#include <Path.h>
31#include <Roster.h>
32#include <String.h>
33
34#include <stdio.h>
35
36#include "SystemKeymap.h"
37	// this is an automatically generated file
38
39#include <ServerProtocol.h>
40
41using std::nothrow;
42
43
44// Global InputServer member variables.
45
46InputServer* gInputServer;
47
48BList InputServer::gInputFilterList;
49BLocker InputServer::gInputFilterListLocker("is_filter_queue_sem");
50
51BList InputServer::gInputMethodList;
52BLocker InputServer::gInputMethodListLocker("is_method_queue_sem");
53
54KeymapMethod InputServer::gKeymapMethod;
55
56
57extern "C" _EXPORT BView* instantiate_deskbar_item();
58
59
60// #pragma mark - InputDeviceListItem
61
62
63InputDeviceListItem::InputDeviceListItem(BInputServerDevice& serverDevice,
64		const input_device_ref& device)
65	:
66	fServerDevice(&serverDevice),
67	fDevice(),
68	fRunning(false)
69{
70	fDevice.name = strdup(device.name);
71	fDevice.type = device.type;
72	fDevice.cookie = device.cookie;
73}
74
75
76InputDeviceListItem::~InputDeviceListItem()
77{
78	free(fDevice.name);
79}
80
81
82void
83InputDeviceListItem::Start()
84{
85	PRINT(("  Starting: %s\n", fDevice.name));
86	status_t err = fServerDevice->Start(fDevice.name, fDevice.cookie);
87	if (err != B_OK) {
88		PRINTERR(("      error: %s (%lx)\n", strerror(err), err));
89	}
90	fRunning = err == B_OK;
91}
92
93
94void
95InputDeviceListItem::Stop()
96{
97	PRINT(("  Stopping: %s\n", fDevice.name));
98	fServerDevice->Stop(fDevice.name, fDevice.cookie);
99	fRunning = false;
100}
101
102
103void
104InputDeviceListItem::Control(uint32 code, BMessage* message)
105{
106	fServerDevice->Control(fDevice.name, fDevice.cookie, code, message);
107}
108
109
110bool
111InputDeviceListItem::HasName(const char* name) const
112{
113	if (name == NULL)
114		return false;
115
116	return !strcmp(name, fDevice.name);
117}
118
119
120bool
121InputDeviceListItem::HasType(input_device_type type) const
122{
123	return type == fDevice.type;
124}
125
126
127bool
128InputDeviceListItem::Matches(const char* name, input_device_type type) const
129{
130	if (name != NULL)
131		return HasName(name);
132
133	return HasType(type);
134}
135
136
137//	#pragma mark -
138
139
140InputServer::InputServer()
141	: BApplication(INPUTSERVER_SIGNATURE),
142	fSafeMode(false),
143	fKeyboardID(0),
144	fInputDeviceListLocker("input server device list"),
145	fKeyboardSettings(),
146	fMouseSettings(),
147	fChars(NULL),
148	fScreen(B_MAIN_SCREEN_ID),
149	fEventQueueLock("input server event queue"),
150	fReplicantMessenger(NULL),
151	fInputMethodWindow(NULL),
152	fInputMethodAware(false),
153	fCursorSem(-1),
154	fAppServerPort(-1),
155	fCursorArea(-1)
156{
157	CALLED();
158	gInputServer = this;
159
160	set_thread_priority(find_thread(NULL), B_URGENT_DISPLAY_PRIORITY);
161		// elevate priority for client interaction
162
163	_StartEventLoop();
164
165	char parameter[32];
166	size_t parameterLength = sizeof(parameter);
167
168	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter,
169			&parameterLength) == B_OK) {
170		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
171			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
172			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
173			fSafeMode = true;
174	}
175
176	if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter,
177			&parameterLength) == B_OK) {
178		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
179			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
180			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
181			fSafeMode = true;
182	}
183
184	_InitKeyboardMouseStates();
185
186	fAddOnManager = new(std::nothrow) ::AddOnManager(SafeMode());
187	if (fAddOnManager != NULL) {
188		// We need to Run() the AddOnManager looper after having loaded
189		// the initial add-ons, otherwise we may deadlock when the looper
190		// thread for some reason already receives node monitor notifications
191		// while we are still locked ourselves and are executing LoadState()
192		// at the same time (which may lock the add-on looper thread).
193		// NOTE: At first sight this may look like we may loose node monitor
194		// notifications while the thread is not yet running, but in fact those
195		// message should just pile up and be processed later.
196		fAddOnManager->LoadState();
197		fAddOnManager->Run();
198	}
199
200	BMessenger messenger(this);
201	BRoster().StartWatching(messenger, B_REQUEST_LAUNCHED);
202}
203
204
205InputServer::~InputServer()
206{
207	CALLED();
208	if (fAddOnManager->Lock())
209		fAddOnManager->Quit();
210
211	_ReleaseInput(NULL);
212}
213
214
215void
216InputServer::ArgvReceived(int32 argc, char** argv)
217{
218	CALLED();
219	if (2 == argc && (0 == strcmp("-q", argv[1]))) {
220		PRINT(("InputServer::ArgvReceived - Restarting ...\n"));
221		status_t quit_status = B_OK;
222		BMessenger msgr = BMessenger(INPUTSERVER_SIGNATURE, -1, &quit_status);
223		if (B_OK == quit_status) {
224			msgr.SendMessage(B_QUIT_REQUESTED);
225		} else {
226			PRINTERR(("Unable to send Quit message to running InputServer.\n"));
227		}
228	}
229}
230
231
232void
233InputServer::_InitKeyboardMouseStates()
234{
235	CALLED();
236	// This is where we determine the screen resolution from the app_server and find the center of the screen
237	// fMousePos is then set to the center of the screen.
238
239	fFrame = fScreen.Frame();
240	if (fFrame == BRect(0, 0, 0, 0))
241		fFrame = BRect(0, 0, 799, 599);
242	fMousePos = BPoint((int32)((fFrame.right + 1) / 2),
243		(int32)((fFrame.bottom + 1) / 2));
244
245	memset(&fKeyInfo, 0, sizeof(fKeyInfo));
246
247	if (_LoadKeymap() != B_OK)
248		_LoadSystemKeymap();
249
250	BMessage msg(B_MOUSE_MOVED);
251	HandleSetMousePosition(&msg, &msg);
252
253	fActiveMethod = &gKeymapMethod;
254}
255
256
257status_t
258InputServer::_LoadKeymap()
259{
260	BPath path;
261	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
262		return B_BAD_VALUE;
263
264	path.Append("Key_map");
265
266	status_t err;
267
268	BFile file(path.Path(), B_READ_ONLY);
269	if ((err = file.InitCheck()) != B_OK)
270		return err;
271
272	if (file.Read(&fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys))
273		return B_BAD_VALUE;
274
275	for (uint32 i = 0; i < sizeof(fKeys) / 4; i++)
276		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
277
278	if (file.Read(&fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32))
279		return B_BAD_VALUE;
280
281	fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize);
282	if (fCharsSize <= 0)
283		return B_BAD_VALUE;
284
285	delete[] fChars;
286	fChars = new (nothrow) char[fCharsSize];
287	if (fChars == NULL)
288		return B_NO_MEMORY;
289
290	if (file.Read(fChars, fCharsSize) != (signed)fCharsSize)
291		return B_BAD_VALUE;
292
293	return B_OK;
294}
295
296
297status_t
298InputServer::_LoadSystemKeymap()
299{
300	delete[] fChars;
301	fKeys = kSystemKeymap;
302	fCharsSize = kSystemKeyCharsSize;
303	fChars = new (nothrow) char[fCharsSize];
304	if (fChars == NULL)
305		return B_NO_MEMORY;
306
307	memcpy(fChars, kSystemKeyChars, fCharsSize);
308
309	// TODO: why are we doing this?
310	return _SaveKeymap(true);
311}
312
313
314status_t
315InputServer::_SaveKeymap(bool isDefault)
316{
317	// we save this keymap to file
318	BPath path;
319	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
320		return B_BAD_VALUE;
321
322	path.Append("Key_map");
323
324	BFile file;
325	status_t err = file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
326	if (err != B_OK) {
327		PRINTERR(("error %s\n", strerror(err)));
328		return err;
329	}
330
331	for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) {
332		((uint32*)&fKeys)[i] = B_HOST_TO_BENDIAN_INT32(((uint32*)&fKeys)[i]);
333	}
334
335	if ((err = file.Write(&fKeys, sizeof(fKeys))) < (ssize_t)sizeof(fKeys))
336		return err;
337
338	for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) {
339		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
340	}
341
342	uint32 size = B_HOST_TO_BENDIAN_INT32(fCharsSize);
343
344	if ((err = file.Write(&size, sizeof(uint32))) < (ssize_t)sizeof(uint32))
345		return B_BAD_VALUE;
346
347	if ((err = file.Write(fChars, fCharsSize)) < (ssize_t)fCharsSize)
348		return err;
349
350	// don't bother reporting an error if this fails, since this isn't fatal
351	// the keymap will still be functional, and will just be identified as (Current) in prefs instead of its
352	// actual name
353	if (isDefault)
354		file.WriteAttr("keymap:name", B_STRING_TYPE, 0, kSystemKeymapName, strlen(kSystemKeymapName));
355
356	return B_OK;
357}
358
359
360bool
361InputServer::QuitRequested()
362{
363	CALLED();
364	if (!BApplication::QuitRequested())
365		return false;
366
367	PostMessage(SYSTEM_SHUTTING_DOWN);
368
369	bool shutdown = false;
370	CurrentMessage()->FindBool("_shutdown_", &shutdown);
371
372	// Don't actually quit when the system is being shutdown
373	if (shutdown) {
374		return false;
375	} else {
376		fAddOnManager->SaveState();
377
378		delete_port(fEventLooperPort);
379			// the event looper thread will exit after this
380		fEventLooperPort = -1;
381		return true;
382	}
383}
384
385
386void
387InputServer::ReadyToRun()
388{
389	CALLED();
390
391	// say hello to the app_server
392
393	BPrivate::AppServerLink link;
394	link.StartMessage(AS_REGISTER_INPUT_SERVER);
395	link.Flush();
396}
397
398
399status_t
400InputServer::_AcquireInput(BMessage& message, BMessage& reply)
401{
402	// TODO: it currently just gets everything we have
403	area_id area;
404	if (message.FindInt32("cursor area", &area) == B_OK) {
405		// try to clone the area
406		fCursorBuffer = NULL;
407
408		fCursorSem = create_sem(0, "cursor semaphore");
409		if (fCursorSem >= B_OK) {
410			fCursorArea = clone_area("input server cursor", (void**)&fCursorBuffer,
411				B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area);
412		}
413	}
414
415	fAppServerPort = create_port(200, "input server target");
416	if (fAppServerPort < B_OK) {
417		_ReleaseInput(&message);
418		return fAppServerPort;
419	}
420
421	reply.AddBool("has keyboard", true);
422	reply.AddBool("has mouse", true);
423	reply.AddInt32("event port", fAppServerPort);
424
425	if (fCursorBuffer != NULL) {
426		// cursor shared buffer is supported
427		reply.AddInt32("cursor semaphore", fCursorSem);
428	}
429
430	return B_OK;
431}
432
433
434void
435InputServer::_ReleaseInput(BMessage* /*message*/)
436{
437	if (fCursorBuffer != NULL) {
438		fCursorBuffer = NULL;
439		delete_sem(fCursorSem);
440		delete_area(fCursorArea);
441
442		fCursorSem = -1;
443		fCursorArea = -1;
444	}
445
446	delete_port(fAppServerPort);
447}
448
449
450void
451InputServer::MessageReceived(BMessage* message)
452{
453	CALLED();
454
455	BMessage reply;
456	status_t status = B_OK;
457
458	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, (char)(message->what >> 24),
459		(char)(message->what >> 16), (char)(message->what >> 8), (char)message->what));
460
461	switch (message->what) {
462		case IS_SET_METHOD:
463			HandleSetMethod(message);
464			break;
465		case IS_GET_MOUSE_TYPE:
466			status = HandleGetSetMouseType(message, &reply);
467			break;
468		case IS_SET_MOUSE_TYPE:
469			status = HandleGetSetMouseType(message, &reply);
470			break;
471		case IS_GET_MOUSE_ACCELERATION:
472			status = HandleGetSetMouseAcceleration(message, &reply);
473			break;
474		case IS_SET_MOUSE_ACCELERATION:
475			status = HandleGetSetMouseAcceleration(message, &reply);
476			break;
477		case IS_GET_KEY_REPEAT_DELAY:
478			status = HandleGetSetKeyRepeatDelay(message, &reply);
479			break;
480		case IS_SET_KEY_REPEAT_DELAY:
481			status = HandleGetSetKeyRepeatDelay(message, &reply);
482			break;
483		case IS_GET_KEY_INFO:
484			status = HandleGetKeyInfo(message, &reply);
485			break;
486		case IS_GET_MODIFIERS:
487			status = HandleGetModifiers(message, &reply);
488			break;
489		case IS_GET_MODIFIER_KEY:
490			status = HandleGetModifierKey(message, &reply);
491			break;
492		case IS_SET_MODIFIER_KEY:
493			status = HandleSetModifierKey(message, &reply);
494			break;
495		case IS_SET_KEYBOARD_LOCKS:
496			status = HandleSetKeyboardLocks(message, &reply);
497			break;
498		case IS_GET_MOUSE_SPEED:
499			status = HandleGetSetMouseSpeed(message, &reply);
500			break;
501		case IS_SET_MOUSE_SPEED:
502			status = HandleGetSetMouseSpeed(message, &reply);
503			break;
504		case IS_SET_MOUSE_POSITION:
505			status = HandleSetMousePosition(message, &reply);
506			break;
507		case IS_GET_MOUSE_MAP:
508			status = HandleGetSetMouseMap(message, &reply);
509			break;
510		case IS_SET_MOUSE_MAP:
511			status = HandleGetSetMouseMap(message, &reply);
512			break;
513		case IS_GET_KEYBOARD_ID:
514			status = HandleGetSetKeyboardID(message, &reply);
515			break;
516		case IS_SET_KEYBOARD_ID:
517			status = HandleGetSetKeyboardID(message, &reply);
518			break;
519		case IS_GET_CLICK_SPEED:
520			status = HandleGetSetClickSpeed(message, &reply);
521			break;
522		case IS_SET_CLICK_SPEED:
523			status = HandleGetSetClickSpeed(message, &reply);
524			break;
525		case IS_GET_KEY_REPEAT_RATE:
526			status = HandleGetSetKeyRepeatRate(message, &reply);
527			break;
528		case IS_SET_KEY_REPEAT_RATE:
529			status = HandleGetSetKeyRepeatRate(message, &reply);
530			break;
531		case IS_GET_KEY_MAP:
532			status = HandleGetSetKeyMap(message, &reply);
533			break;
534		case IS_RESTORE_KEY_MAP:
535			status = HandleGetSetKeyMap(message, &reply);
536			break;
537		case IS_FOCUS_IM_AWARE_VIEW:
538			status = HandleFocusUnfocusIMAwareView(message, &reply);
539			break;
540		case IS_UNFOCUS_IM_AWARE_VIEW:
541			status = HandleFocusUnfocusIMAwareView(message, &reply);
542			break;
543
544		// app_server communication
545		case IS_ACQUIRE_INPUT:
546			status = _AcquireInput(*message, reply);
547			break;
548		case IS_RELEASE_INPUT:
549			_ReleaseInput(message);
550			return;
551   		case IS_SCREEN_BOUNDS_UPDATED:
552   		{
553			// This is what the R5 app_server sends us when the screen
554			// configuration changes
555			BRect frame;
556			if (message->FindRect("screen_bounds", &frame) != B_OK)
557				frame = fScreen.Frame();
558
559			if (frame == fFrame)
560				break;
561
562			BPoint pos(fMousePos.x * frame.Width() / fFrame.Width(),
563				fMousePos.y * frame.Height() / fFrame.Height());
564			fFrame = frame;
565
566			BMessage set;
567			set.AddPoint("where", pos);
568			HandleSetMousePosition(&set, NULL);
569			break;
570		}
571
572		// device looper related
573		case IS_FIND_DEVICES:
574		case IS_WATCH_DEVICES:
575		case IS_IS_DEVICE_RUNNING:
576		case IS_START_DEVICE:
577		case IS_STOP_DEVICE:
578		case IS_CONTROL_DEVICES:
579		case SYSTEM_SHUTTING_DOWN:
580		case IS_METHOD_REGISTER:
581			fAddOnManager->PostMessage(message);
582			return;
583
584		case IS_SAVE_SETTINGS:
585			fKeyboardSettings.Save();
586			fMouseSettings.SaveSettings();
587			return;
588
589		case IS_SAVE_KEYMAP:
590			_SaveKeymap();
591			return;
592
593		case B_SOME_APP_LAUNCHED:
594		{
595			const char *signature;
596			// TODO: what's this for?
597			if (message->FindString("be:signature", &signature)==B_OK) {
598				PRINT(("input_server : %s\n", signature));
599				if (strcmp(signature, "application/x-vnd.Be-TSKB")==0) {
600
601				}
602			}
603			return;
604		}
605
606		case kMsgAppServerRestarted:
607		{
608			BApplication::MessageReceived(message);
609			BPrivate::AppServerLink link;
610			link.StartMessage(AS_REGISTER_INPUT_SERVER);
611			link.Flush();
612			return;
613		}
614
615		default:
616			return;
617	}
618
619	reply.AddInt32("status", status);
620	message->SendReply(&reply);
621}
622
623
624void
625InputServer::HandleSetMethod(BMessage* message)
626{
627	CALLED();
628	int32 cookie;
629	if (message->FindInt32("cookie", &cookie) != B_OK)
630		return;
631	if (cookie == gKeymapMethod.fOwner->Cookie()) {
632		SetActiveMethod(&gKeymapMethod);
633	} else {
634		BAutolock lock(InputServer::gInputMethodListLocker);
635		for (int32 i = 0; i < gInputMethodList.CountItems(); i++) {
636			BInputServerMethod* method
637				= (BInputServerMethod*)InputServer::gInputMethodList.ItemAt(i);
638			if (method->fOwner->Cookie() == cookie) {
639				PRINT(("%s cookie %" B_PRId32 "\n", __PRETTY_FUNCTION__,
640					cookie));
641				SetActiveMethod(method);
642				break;
643			}
644		}
645	}
646}
647
648
649status_t
650InputServer::HandleGetSetMouseType(BMessage* message, BMessage* reply)
651{
652	int32 type;
653	if (message->FindInt32("mouse_type", &type) == B_OK) {
654		fMouseSettings.SetMouseType(type);
655		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
656
657		BMessage msg(IS_CONTROL_DEVICES);
658		msg.AddInt32("type", B_POINTING_DEVICE);
659		msg.AddInt32("code", B_MOUSE_TYPE_CHANGED);
660		return fAddOnManager->PostMessage(&msg);
661	}
662
663	return reply->AddInt32("mouse_type", fMouseSettings.MouseType());
664}
665
666
667status_t
668InputServer::HandleGetSetMouseAcceleration(BMessage* message,
669	BMessage* reply)
670{
671	int32 factor;
672	if (message->FindInt32("speed", &factor) == B_OK) {
673		fMouseSettings.SetAccelerationFactor(factor);
674		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
675
676		BMessage msg(IS_CONTROL_DEVICES);
677		msg.AddInt32("type", B_POINTING_DEVICE);
678		msg.AddInt32("code", B_MOUSE_ACCELERATION_CHANGED);
679		return fAddOnManager->PostMessage(&msg);
680	}
681
682	return reply->AddInt32("speed", fMouseSettings.AccelerationFactor());
683}
684
685
686status_t
687InputServer::HandleGetSetKeyRepeatDelay(BMessage* message, BMessage* reply)
688{
689	bigtime_t delay;
690	if (message->FindInt64("delay", &delay) == B_OK) {
691		fKeyboardSettings.SetKeyboardRepeatDelay(delay);
692		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
693
694		BMessage msg(IS_CONTROL_DEVICES);
695		msg.AddInt32("type", B_KEYBOARD_DEVICE);
696		msg.AddInt32("code", B_KEY_REPEAT_DELAY_CHANGED);
697		return fAddOnManager->PostMessage(&msg);
698	}
699
700	return reply->AddInt64("delay", fKeyboardSettings.KeyboardRepeatDelay());
701}
702
703
704status_t
705InputServer::HandleGetKeyInfo(BMessage* message, BMessage* reply)
706{
707	return reply->AddData("key_info", B_ANY_TYPE, &fKeyInfo, sizeof(fKeyInfo));
708}
709
710
711status_t
712InputServer::HandleGetModifiers(BMessage* message, BMessage* reply)
713{
714	return reply->AddInt32("modifiers", fKeyInfo.modifiers);
715}
716
717
718status_t
719InputServer::HandleGetModifierKey(BMessage* message, BMessage* reply)
720{
721	int32 modifier;
722
723	if (message->FindInt32("modifier", &modifier) == B_OK) {
724		switch (modifier) {
725			case B_CAPS_LOCK:
726				return reply->AddInt32("key", fKeys.caps_key);
727			case B_NUM_LOCK:
728				return reply->AddInt32("key", fKeys.num_key);
729			case B_SCROLL_LOCK:
730				return reply->AddInt32("key", fKeys.scroll_key);
731			case B_LEFT_SHIFT_KEY:
732				return reply->AddInt32("key", fKeys.left_shift_key);
733			case B_RIGHT_SHIFT_KEY:
734				return reply->AddInt32("key", fKeys.right_shift_key);
735			case B_LEFT_COMMAND_KEY:
736				return reply->AddInt32("key", fKeys.left_command_key);
737			case B_RIGHT_COMMAND_KEY:
738				return reply->AddInt32("key", fKeys.right_command_key);
739			case B_LEFT_CONTROL_KEY:
740				return reply->AddInt32("key", fKeys.left_control_key);
741			case B_RIGHT_CONTROL_KEY:
742				return reply->AddInt32("key", fKeys.right_control_key);
743			case B_LEFT_OPTION_KEY:
744				return reply->AddInt32("key", fKeys.left_option_key);
745			case B_RIGHT_OPTION_KEY:
746				return reply->AddInt32("key", fKeys.right_option_key);
747			case B_MENU_KEY:
748				return reply->AddInt32("key", fKeys.menu_key);
749		}
750	}
751	return B_ERROR;
752}
753
754
755status_t
756InputServer::HandleSetModifierKey(BMessage* message, BMessage* reply)
757{
758	int32 modifier, key;
759	if (message->FindInt32("modifier", &modifier) == B_OK
760		&& message->FindInt32("key", &key) == B_OK) {
761		switch (modifier) {
762			case B_CAPS_LOCK:
763				fKeys.caps_key = key;
764				break;
765			case B_NUM_LOCK:
766				fKeys.num_key = key;
767				break;
768			case B_SCROLL_LOCK:
769				fKeys.scroll_key = key;
770				break;
771			case B_LEFT_SHIFT_KEY:
772				fKeys.left_shift_key = key;
773				break;
774			case B_RIGHT_SHIFT_KEY:
775				fKeys.right_shift_key = key;
776				break;
777			case B_LEFT_COMMAND_KEY:
778				fKeys.left_command_key = key;
779				break;
780			case B_RIGHT_COMMAND_KEY:
781				fKeys.right_command_key = key;
782				break;
783			case B_LEFT_CONTROL_KEY:
784				fKeys.left_control_key = key;
785				break;
786			case B_RIGHT_CONTROL_KEY:
787				fKeys.right_control_key = key;
788				break;
789			case B_LEFT_OPTION_KEY:
790				fKeys.left_option_key = key;
791				break;
792			case B_RIGHT_OPTION_KEY:
793				fKeys.right_option_key = key;
794				break;
795			case B_MENU_KEY:
796				fKeys.menu_key = key;
797				break;
798			default:
799				return B_ERROR;
800		}
801
802		// TODO: unmap the key ?
803
804		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
805
806		BMessage msg(IS_CONTROL_DEVICES);
807		msg.AddInt32("type", B_KEYBOARD_DEVICE);
808		msg.AddInt32("code", B_KEY_MAP_CHANGED);
809		return fAddOnManager->PostMessage(&msg);
810	}
811
812	return B_ERROR;
813}
814
815
816status_t
817InputServer::HandleSetKeyboardLocks(BMessage* message, BMessage* reply)
818{
819	if (message->FindInt32("locks", (int32*)&fKeys.lock_settings) == B_OK) {
820		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
821
822		BMessage msg(IS_CONTROL_DEVICES);
823		msg.AddInt32("type", B_KEYBOARD_DEVICE);
824		msg.AddInt32("code", B_KEY_LOCKS_CHANGED);
825		return fAddOnManager->PostMessage(&msg);
826	}
827
828	return B_ERROR;
829}
830
831
832status_t
833InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply)
834{
835	int32 speed;
836	if (message->FindInt32("speed", &speed) == B_OK) {
837		fMouseSettings.SetMouseSpeed(speed);
838		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
839
840		BMessage msg(IS_CONTROL_DEVICES);
841		msg.AddInt32("type", B_POINTING_DEVICE);
842		msg.AddInt32("code", B_MOUSE_SPEED_CHANGED);
843		return fAddOnManager->PostMessage(&msg);
844	}
845
846	return reply->AddInt32("speed", fMouseSettings.MouseSpeed());
847}
848
849
850status_t
851InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply)
852{
853	CALLED();
854
855	BPoint where;
856	if (message->FindPoint("where", &where) != B_OK)
857		return B_BAD_VALUE;
858
859	// create a new event for this and enqueue it to the event list just like any other
860
861	BMessage* event = new BMessage(B_MOUSE_MOVED);
862	if (event == NULL)
863		return B_NO_MEMORY;
864
865	event->AddPoint("where", where);
866	event->AddBool("be:set_mouse", true);
867	if (EnqueueDeviceMessage(event) != B_OK) {
868		delete event;
869		return B_NO_MEMORY;
870	}
871
872	return B_OK;
873}
874
875
876status_t
877InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply)
878{
879	mouse_map *map;
880	ssize_t size;
881	if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) {
882		fMouseSettings.SetMapping(*map);
883		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
884
885		BMessage msg(IS_CONTROL_DEVICES);
886		msg.AddInt32("type", B_POINTING_DEVICE);
887		msg.AddInt32("code", B_MOUSE_MAP_CHANGED);
888		return fAddOnManager->PostMessage(&msg);
889	} else {
890		mouse_map map;
891		fMouseSettings.Mapping(map);
892		return reply->AddData("mousemap", B_RAW_TYPE, &map, sizeof(mouse_map));
893	}
894}
895
896
897status_t
898InputServer::HandleGetSetKeyboardID(BMessage* message, BMessage* reply)
899{
900	int16 id;
901	if (message->FindInt16("id", &id) == B_OK) {
902		fKeyboardID = (uint16)id;
903		return B_OK;
904	}
905	return reply->AddInt16("id", fKeyboardID);
906}
907
908
909status_t
910InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply)
911{
912	bigtime_t clickSpeed;
913	if (message->FindInt64("speed", &clickSpeed) == B_OK) {
914		fMouseSettings.SetClickSpeed(clickSpeed);
915		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
916
917		BMessage msg(IS_CONTROL_DEVICES);
918		msg.AddInt32("type", B_POINTING_DEVICE);
919		msg.AddInt32("code", B_CLICK_SPEED_CHANGED);
920		return fAddOnManager->PostMessage(&msg);
921	}
922
923	return reply->AddInt64("speed", fMouseSettings.ClickSpeed());
924}
925
926
927status_t
928InputServer::HandleGetSetKeyRepeatRate(BMessage* message, BMessage* reply)
929{
930	int32 keyRepeatRate;
931	if (message->FindInt32("rate", &keyRepeatRate) == B_OK) {
932		fKeyboardSettings.SetKeyboardRepeatRate(keyRepeatRate);
933		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
934
935		BMessage msg(IS_CONTROL_DEVICES);
936		msg.AddInt32("type", B_KEYBOARD_DEVICE);
937		msg.AddInt32("code", B_KEY_REPEAT_RATE_CHANGED);
938		return fAddOnManager->PostMessage(&msg);
939	}
940
941	return reply->AddInt32("rate", fKeyboardSettings.KeyboardRepeatRate());
942}
943
944
945status_t
946InputServer::HandleGetSetKeyMap(BMessage* message, BMessage* reply)
947{
948	CALLED();
949
950	if (message->what == IS_GET_KEY_MAP) {
951		status_t status = reply->AddData("keymap", B_ANY_TYPE, &fKeys, sizeof(fKeys));
952		if (status == B_OK)
953			status = reply->AddData("key_buffer", B_ANY_TYPE, fChars, fCharsSize);
954
955		return status;
956	}
957
958	if (_LoadKeymap() != B_OK)
959		_LoadSystemKeymap();
960
961	BMessage msg(IS_CONTROL_DEVICES);
962	msg.AddInt32("type", B_KEYBOARD_DEVICE);
963	msg.AddInt32("code", B_KEY_MAP_CHANGED);
964	return fAddOnManager->PostMessage(&msg);
965}
966
967
968status_t
969InputServer::HandleFocusUnfocusIMAwareView(BMessage* message,
970	BMessage* reply)
971{
972	CALLED();
973
974	BMessenger messenger;
975	status_t status = message->FindMessenger("view", &messenger);
976	if (status != B_OK)
977		return status;
978
979	// check if current view is ours
980
981	if (message->what == IS_FOCUS_IM_AWARE_VIEW) {
982		PRINT(("HandleFocusUnfocusIMAwareView : entering\n"));
983		fInputMethodAware = true;
984	} else {
985		PRINT(("HandleFocusUnfocusIMAwareView : leaving\n"));
986		fInputMethodAware = false;
987	}
988
989	return B_OK;
990}
991
992
993/*!	Enqueues the message into the event queue.
994	The message must only be deleted in case this method returns an error.
995*/
996status_t
997InputServer::EnqueueDeviceMessage(BMessage* message)
998{
999	CALLED();
1000
1001	BAutolock _(fEventQueueLock);
1002	if (!fEventQueue.AddItem(message))
1003		return B_NO_MEMORY;
1004
1005	if (fEventQueue.CountItems() == 1) {
1006		// notify event loop only if we haven't already done so
1007		write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0);
1008	}
1009	return B_OK;
1010}
1011
1012
1013/*!	Enqueues the message into the method queue.
1014	The message must only be deleted in case this method returns an error.
1015*/
1016status_t
1017InputServer::EnqueueMethodMessage(BMessage* message)
1018{
1019	CALLED();
1020	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, (char)(message->what >> 24),
1021		(char)(message->what >> 16), (char)(message->what >> 8), (char)message->what));
1022
1023#ifdef DEBUG
1024	if (message->what == 'IMEV') {
1025		int32 code;
1026		message->FindInt32("be:opcode", &code);
1027		PRINT(("%s be:opcode %li\n", __PRETTY_FUNCTION__, code));
1028	}
1029#endif
1030
1031	BAutolock _(fEventQueueLock);
1032	if (!fMethodQueue.AddItem(message))
1033		return B_NO_MEMORY;
1034
1035	if (fMethodQueue.CountItems() == 1) {
1036		// notify event loop only if we haven't already done so
1037		write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
1038	}
1039	return B_OK;
1040}
1041
1042
1043status_t
1044InputServer::SetNextMethod(bool direction)
1045{
1046	gInputMethodListLocker.Lock();
1047
1048	int32 index = gInputMethodList.IndexOf(fActiveMethod);
1049	int32 oldIndex = index;
1050
1051	index += (direction ? 1 : -1);
1052
1053	if (index < -1)
1054		index = gInputMethodList.CountItems() - 1;
1055	if (index >= gInputMethodList.CountItems())
1056		index = -1;
1057
1058	if (index == oldIndex)
1059		return B_BAD_INDEX;
1060
1061	BInputServerMethod *method = &gKeymapMethod;
1062
1063	if (index != -1)
1064		method = (BInputServerMethod *)gInputMethodList.ItemAt(index);
1065
1066	SetActiveMethod(method);
1067
1068	gInputMethodListLocker.Unlock();
1069	return B_OK;
1070}
1071
1072
1073void
1074InputServer::SetActiveMethod(BInputServerMethod* method)
1075{
1076	CALLED();
1077	if (fActiveMethod)
1078		fActiveMethod->fOwner->MethodActivated(false);
1079
1080	fActiveMethod = method;
1081
1082	if (fActiveMethod)
1083		fActiveMethod->fOwner->MethodActivated(true);
1084}
1085
1086
1087const BMessenger*
1088InputServer::MethodReplicant()
1089{
1090	return fReplicantMessenger;
1091}
1092
1093
1094void
1095InputServer::SetMethodReplicant(const BMessenger* messenger)
1096{
1097	fReplicantMessenger = messenger;
1098}
1099
1100
1101bool
1102InputServer::EventLoopRunning()
1103{
1104	return fEventLooperPort >= B_OK;
1105}
1106
1107
1108status_t
1109InputServer::GetDeviceInfo(const char* name, input_device_type *_type,
1110	bool *_isRunning)
1111{
1112    BAutolock lock(fInputDeviceListLocker);
1113
1114	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1115		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1116
1117		if (item->HasName(name)) {
1118			if (_type)
1119				*_type = item->Type();
1120			if (_isRunning)
1121				*_isRunning = item->Running();
1122
1123			return B_OK;
1124		}
1125	}
1126
1127	return B_NAME_NOT_FOUND;
1128}
1129
1130
1131status_t
1132InputServer::GetDeviceInfos(BMessage *msg)
1133{
1134	CALLED();
1135	BAutolock lock(fInputDeviceListLocker);
1136
1137	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1138		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1139		msg->AddString("device", item->Name());
1140		msg->AddInt32("type", item->Type());
1141	}
1142	return B_OK;
1143}
1144
1145
1146status_t
1147InputServer::UnregisterDevices(BInputServerDevice& serverDevice,
1148	input_device_ref **devices)
1149{
1150    CALLED();
1151    BAutolock lock(fInputDeviceListLocker);
1152
1153	if (devices != NULL) {
1154		// remove the devices as specified only
1155		input_device_ref *device = NULL;
1156		for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1157			for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1158				InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1159
1160				if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) {
1161					item->Stop();
1162					if (fInputDeviceList.RemoveItem(j))
1163						delete item;
1164					break;
1165				}
1166			}
1167		}
1168	} else {
1169		// remove all devices from this BInputServerObject
1170		for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1171			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1172
1173			if (item->ServerDevice() == &serverDevice) {
1174				item->Stop();
1175				if (fInputDeviceList.RemoveItem(i))
1176					delete item;
1177			}
1178		}
1179	}
1180
1181    return B_OK;
1182}
1183
1184
1185status_t
1186InputServer::RegisterDevices(BInputServerDevice& serverDevice,
1187	input_device_ref** devices)
1188{
1189	if (devices == NULL)
1190		return B_BAD_VALUE;
1191
1192	BAutolock lock(fInputDeviceListLocker);
1193
1194	input_device_ref *device = NULL;
1195	for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1196		if (device->type != B_POINTING_DEVICE
1197			&& device->type != B_KEYBOARD_DEVICE
1198			&& device->type != B_UNDEFINED_DEVICE)
1199			continue;
1200
1201		// find existing input server device
1202
1203		bool found = false;
1204		for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1205			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1206
1207			if (item->HasName(device->name)) {
1208debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name);
1209				PRINT(("RegisterDevices found %s\n", device->name));
1210				found = true;
1211				break;
1212			}
1213		}
1214
1215		if (!found) {
1216			PRINT(("RegisterDevices not found %s\n", device->name));
1217			InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice,
1218				*device);
1219			if (item != NULL && fInputDeviceList.AddItem(item)) {
1220				item->Start();
1221			} else {
1222				delete item;
1223				return B_NO_MEMORY;
1224			}
1225		}
1226	}
1227
1228	return B_OK;
1229}
1230
1231
1232status_t
1233InputServer::StartStopDevices(const char* name, input_device_type type,
1234	bool doStart)
1235{
1236	CALLED();
1237	BAutolock lock(fInputDeviceListLocker);
1238
1239	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1240		InputDeviceListItem* item
1241			= (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1242		if (!item)
1243			continue;
1244
1245		if (item->Matches(name, type)) {
1246			if (doStart == item->Running()) {
1247				if (name)
1248					return B_OK;
1249				else
1250					continue;
1251			}
1252
1253			if (doStart)
1254				item->Start();
1255			else
1256				item->Stop();
1257
1258			if (name)
1259				return B_OK;
1260		}
1261	}
1262
1263	if (name) {
1264		// item not found
1265		return B_ERROR;
1266	}
1267
1268	return B_OK;
1269}
1270
1271
1272
1273status_t
1274InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart)
1275{
1276	CALLED();
1277	BAutolock lock(fInputDeviceListLocker);
1278
1279	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1280		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1281
1282		if (item->ServerDevice() != &serverDevice)
1283			continue;
1284
1285		if (doStart == item->Running())
1286			continue;
1287
1288		if (doStart)
1289			item->Start();
1290		else
1291			item->Stop();
1292	}
1293
1294	return B_OK;
1295}
1296
1297
1298status_t
1299InputServer::ControlDevices(const char* name, input_device_type type,
1300	uint32 code, BMessage* message)
1301{
1302	CALLED();
1303	BAutolock lock(fInputDeviceListLocker);
1304
1305	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1306		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1307		if (!item)
1308			continue;
1309
1310		if (item->Matches(name, type)) {
1311			item->Control(code, message);
1312
1313			if (name)
1314				return B_OK;
1315		}
1316	}
1317
1318	if (name)
1319		return B_ERROR;
1320
1321	return B_OK;
1322}
1323
1324
1325bool
1326InputServer::DoMouseAcceleration(int32* _x, int32* _y)
1327{
1328	CALLED();
1329	int32 speed = fMouseSettings.MouseSpeed() >> 15;
1330
1331	// ToDo: implement mouse acceleration
1332	(void)speed;
1333	//*_y = *_x * speed;
1334	PRINT(("DoMouse : %ld %ld %ld %ld\n", *_x, *_y, speed, fMouseSettings.MouseSpeed()));
1335	return true;
1336}
1337
1338
1339bool
1340InputServer::SetMousePos(long *, long *, long, long)
1341{
1342	CALLED();
1343	return true;
1344}
1345
1346
1347bool
1348InputServer::SetMousePos(long *, long *, BPoint)
1349{
1350	CALLED();
1351	return true;
1352}
1353
1354
1355bool
1356InputServer::SetMousePos(long *, long *, float, float)
1357{
1358	CALLED();
1359	return true;
1360}
1361
1362
1363bool
1364InputServer::SafeMode()
1365{
1366	return fSafeMode;
1367}
1368
1369
1370status_t
1371InputServer::_StartEventLoop()
1372{
1373	CALLED();
1374	fEventLooperPort = create_port(100, "input server events");
1375	if (fEventLooperPort < 0) {
1376		PRINTERR(("InputServer: create_port error: (0x%lx) %s\n",
1377			fEventLooperPort, strerror(fEventLooperPort)));
1378		return fEventLooperPort;
1379	}
1380
1381	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1382		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1383	if (thread < B_OK || resume_thread(thread) < B_OK) {
1384		if (thread >= B_OK)
1385			kill_thread(thread);
1386		delete_port(fEventLooperPort);
1387		fEventLooperPort = -1;
1388		return thread < B_OK ? thread : B_ERROR;
1389	}
1390
1391	return B_OK;
1392}
1393
1394
1395status_t
1396InputServer::_EventLooper(void* arg)
1397{
1398	InputServer* self = (InputServer*)arg;
1399	self->_EventLoop();
1400
1401	return B_OK;
1402}
1403
1404
1405void
1406InputServer::_EventLoop()
1407{
1408	while (true) {
1409		// Block until we find the size of the next message
1410		ssize_t length = port_buffer_size(fEventLooperPort);
1411		if (length < B_OK) {
1412			PRINT(("[Event Looper] port gone, exiting.\n"));
1413			return;
1414		}
1415
1416		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1417
1418		char buffer[length];
1419		int32 code;
1420		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1421		if (err != length) {
1422			if (err >= 0) {
1423				PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length));
1424			} else {
1425				PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err)));
1426			}
1427			continue;
1428		}
1429
1430		EventList events;
1431		if (fEventQueueLock.Lock()) {
1432			// move the items to our own list to block the event queue as short as possible
1433			events.AddList(&fEventQueue);
1434			fEventQueue.MakeEmpty();
1435			fEventQueueLock.Unlock();
1436		}
1437
1438		if (length > 0) {
1439			BMessage* event = new BMessage;
1440
1441			if ((err = event->Unflatten(buffer)) < 0) {
1442				PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
1443				delete event;
1444				continue;
1445			}
1446
1447			events.AddItem(event);
1448		}
1449
1450		// This is where the message should be processed.
1451
1452		if (_SanitizeEvents(events)
1453			&& _MethodizeEvents(events)
1454			&& _FilterEvents(events)) {
1455			_UpdateMouseAndKeys(events);
1456			_DispatchEvents(events);
1457		}
1458	}
1459}
1460
1461
1462/*!	Updates the internal mouse position and keyboard info. */
1463void
1464InputServer::_UpdateMouseAndKeys(EventList& events)
1465{
1466	for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index);
1467			index++) {
1468		switch (event->what) {
1469			case B_MOUSE_DOWN:
1470			case B_MOUSE_UP:
1471			case B_MOUSE_MOVED:
1472				event->FindPoint("where", &fMousePos);
1473				break;
1474
1475			case B_KEY_DOWN:
1476			case B_UNMAPPED_KEY_DOWN:
1477				// update modifiers
1478				uint32 modifiers;
1479				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1480					fKeyInfo.modifiers = modifiers;
1481
1482				// update key states
1483				const uint8 *data;
1484				ssize_t size;
1485				if (event->FindData("states", B_UINT8_TYPE,
1486						(const void**)&data, &size) == B_OK) {
1487					PRINT(("updated keyinfo\n"));
1488					if (size == sizeof(fKeyInfo.key_states))
1489						memcpy(fKeyInfo.key_states, data, size);
1490				}
1491
1492				if (fActiveMethod == NULL)
1493					break;
1494
1495				// we scan for Alt+Space key down events which means we change
1496				// to next input method
1497				// (pressing "shift" will let us switch to the previous method)
1498
1499				// If there is only one input method, SetNextMethod will return
1500				// B_BAD_INDEX and the event will be forwarded to the user.
1501
1502				PRINT(("SanitizeEvents: %lx, %x\n", fKeyInfo.modifiers,
1503					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1504
1505				uint8 byte;
1506				if (event->FindInt8("byte", (int8*)&byte) < B_OK)
1507					byte = 0;
1508
1509				if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ')
1510						|| byte == B_HANKAKU_ZENKAKU)
1511					&& SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0)
1512							== B_OK) {
1513					// this event isn't sent to the user
1514					events.RemoveItemAt(index);
1515					delete event;
1516					continue;
1517				}
1518				break;
1519		}
1520	}
1521}
1522
1523
1524/*!	Frees events from unwanted fields, adds missing fields, and removes
1525	unwanted events altogether.
1526*/
1527bool
1528InputServer::_SanitizeEvents(EventList& events)
1529{
1530	CALLED();
1531
1532	for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index);
1533			index++) {
1534		switch (event->what) {
1535	   		case B_MOUSE_MOVED:
1536	   		case B_MOUSE_DOWN:
1537	   		{
1538	   			int32 buttons;
1539	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1540	   				event->AddInt32("buttons", 0);
1541
1542	   			// supposed to fall through
1543	   		}
1544	   		case B_MOUSE_UP:
1545	   		{
1546	   			BPoint where;
1547				int32 x, y;
1548				float absX, absY;
1549
1550				if (event->FindInt32("x", &x) == B_OK
1551					&& event->FindInt32("y", &y) == B_OK) {
1552					where.x = fMousePos.x + x;
1553					where.y = fMousePos.y - y;
1554
1555					event->RemoveName("x");
1556					event->RemoveName("y");
1557					event->AddInt32("be:delta_x", x);
1558					event->AddInt32("be:delta_y", y);
1559
1560					PRINT(("new position: %f, %f, %ld, %ld\n",
1561						where.x, where.y, x, y));
1562				} else if (event->FindFloat("x", &absX) == B_OK
1563					&& event->FindFloat("y", &absY) == B_OK) {
1564					// The device gives us absolute screen coords in range 0..1;
1565					// convert them to absolute screen position
1566					// (the message is supposed to contain the original
1567					// absolute coordinates as "be:tablet_x/y").
1568					where.x = absX * fFrame.Width();
1569					where.y = absY * fFrame.Height();
1570
1571					event->RemoveName("x");
1572					event->RemoveName("y");
1573					PRINT(("new position : %f, %f\n", where.x, where.y));
1574				} else if (event->FindPoint("where", &where) == B_OK) {
1575					PRINT(("new position : %f, %f\n", where.x, where.y));
1576				}
1577
1578				// Constrain and filter the mouse coords and add the final
1579				// point to the message.
1580				where.x = roundf(where.x);
1581				where.y = roundf(where.y);
1582				where.ConstrainTo(fFrame);
1583				if (event->ReplacePoint("where", where) != B_OK)
1584					event->AddPoint("where", where);
1585
1586				if (!event->HasInt64("when"))
1587					event->AddInt64("when", system_time());
1588
1589				event->AddInt32("modifiers", fKeyInfo.modifiers);
1590				break;
1591	   		}
1592			case B_KEY_DOWN:
1593			case B_UNMAPPED_KEY_DOWN:
1594				// add modifiers
1595				if (!event->HasInt32("modifiers"))
1596					event->AddInt32("modifiers", fKeyInfo.modifiers);
1597
1598				// add key states
1599				if (!event->HasData("states", B_UINT8_TYPE)) {
1600					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1601						sizeof(fKeyInfo.key_states));
1602				}
1603				break;
1604		}
1605	}
1606
1607	return true;
1608}
1609
1610
1611/*!	Applies the filters of the active input method to the
1612	incoming events. It will also move the events in the method
1613	queue to the event list.
1614*/
1615bool
1616InputServer::_MethodizeEvents(EventList& events)
1617{
1618	CALLED();
1619
1620	if (fActiveMethod == NULL)
1621		return true;
1622
1623	int32 count = events.CountItems();
1624	for (int32 i = 0; i < count;) {
1625		_FilterEvent(fActiveMethod, events, i, count);
1626	}
1627
1628	{
1629		// move the method events into the event queue - they are not
1630		// "methodized" either
1631		BAutolock _(fEventQueueLock);
1632		events.AddList(&fMethodQueue);
1633		fMethodQueue.MakeEmpty();
1634	}
1635
1636	if (!fInputMethodAware) {
1637		// special handling for non-input-method-aware views
1638
1639		int32 newCount = events.CountItems();
1640			// we may add new events in this loop that don't need to be checked again
1641
1642		for (int32 i = 0; i < newCount; i++) {
1643			BMessage* event = events.ItemAt(i);
1644
1645			if (event->what != B_INPUT_METHOD_EVENT)
1646				continue;
1647
1648			SERIAL_PRINT(("IME received\n"));
1649
1650			bool removeEvent = true;
1651
1652			int32 opcode;
1653			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1654				bool inlineOnly;
1655				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1656					inlineOnly = false;
1657
1658				if (inlineOnly) {
1659					BMessage translated;
1660					bool confirmed;
1661					if (opcode == B_INPUT_METHOD_CHANGED
1662						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1663						&& event->FindMessage("be:translated", &translated) == B_OK) {
1664						// translate event for the non-aware view
1665						*event = translated;
1666						removeEvent = false;
1667					}
1668				} else {
1669					if (fInputMethodWindow == NULL
1670						&& opcode == B_INPUT_METHOD_STARTED)
1671						fInputMethodWindow = new (nothrow) BottomlineWindow();
1672
1673					if (fInputMethodWindow != NULL) {
1674						EventList newEvents;
1675						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1676
1677						if (!newEvents.IsEmpty()) {
1678							events.AddList(&newEvents);
1679							opcode = B_INPUT_METHOD_STOPPED;
1680						}
1681
1682						if (opcode == B_INPUT_METHOD_STOPPED) {
1683							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1684							fInputMethodWindow = NULL;
1685						}
1686					}
1687				}
1688			}
1689
1690			if (removeEvent) {
1691				// the inline/bottom window has eaten the event
1692				events.RemoveItemAt(i--);
1693				delete event;
1694				newCount--;
1695			}
1696		}
1697	}
1698
1699	return events.CountItems() > 0;
1700}
1701
1702
1703/*!	This method applies all defined filters to each event in the
1704	supplied list.  The supplied list is modified to reflect the
1705	output of the filters.
1706	The method returns true if the filters were applied to all
1707	events without error and false otherwise.
1708*/
1709bool
1710InputServer::_FilterEvents(EventList& events)
1711{
1712	CALLED();
1713	BAutolock _(gInputFilterListLocker);
1714
1715	int32 count = gInputFilterList.CountItems();
1716	int32 eventCount = events.CountItems();
1717
1718	for (int32 i = 0; i < count; i++) {
1719		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1720
1721		// Apply the current filter to all available event messages.
1722
1723		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1724			_FilterEvent(filter, events, eventIndex, eventCount);
1725		}
1726	}
1727
1728	return eventCount != 0;
1729}
1730
1731
1732void
1733InputServer::_DispatchEvents(EventList& events)
1734{
1735	CALLED();
1736
1737	int32 count = events.CountItems();
1738
1739	for (int32 i = 0; i < count; i++) {
1740		BMessage* event = events.ItemAt(i);
1741
1742		// now we must send each event to the app_server
1743		_DispatchEvent(event);
1744		delete event;
1745	}
1746
1747	events.MakeEmpty();
1748}
1749
1750
1751/*!	Applies the given filter to the event list.
1752	For your convenience, it also alters the \a index and \a count arguments
1753	ready for the next call to this method.
1754*/
1755void
1756InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1757	int32& index, int32& count)
1758{
1759	BMessage* event = events.ItemAt(index);
1760
1761	BList newEvents;
1762	filter_result result = filter->Filter(event, &newEvents);
1763
1764	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1765		// we no longer need the current event
1766		events.RemoveItemAt(index);
1767		delete event;
1768
1769		if (result == B_DISPATCH_MESSAGE) {
1770			EventList addedEvents;
1771			EventList::Private(&addedEvents).AsBList()->AddList(&newEvents);
1772			_SanitizeEvents(addedEvents);
1773			// add the new events - but don't methodize them again
1774			events.AddList(&addedEvents, index);
1775			index += newEvents.CountItems();
1776			count = events.CountItems();
1777		} else
1778			count--;
1779	} else
1780		index++;
1781}
1782
1783
1784status_t
1785InputServer::_DispatchEvent(BMessage* event)
1786{
1787	CALLED();
1788
1789   	switch (event->what) {
1790		case B_MOUSE_MOVED:
1791		case B_MOUSE_DOWN:
1792		case B_MOUSE_UP:
1793			if (fCursorBuffer) {
1794				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1795					| ((uint32)fMousePos.y & 0xffff));
1796				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1797					release_sem(fCursorSem);
1798        	}
1799        	break;
1800
1801		case B_KEY_DOWN:
1802		case B_KEY_UP:
1803		case B_UNMAPPED_KEY_DOWN:
1804		case B_UNMAPPED_KEY_UP:
1805		case B_MODIFIERS_CHANGED:
1806		{
1807			// update or add modifiers
1808			uint32 modifiers;
1809			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1810				fKeyInfo.modifiers = modifiers;
1811			else
1812				event->AddInt32("modifiers", fKeyInfo.modifiers);
1813
1814			// update or add key states
1815			const uint8 *data;
1816			ssize_t size;
1817			if (event->FindData("states", B_UINT8_TYPE,
1818					(const void**)&data, &size) == B_OK) {
1819				PRINT(("updated keyinfo\n"));
1820				if (size == sizeof(fKeyInfo.key_states))
1821					memcpy(fKeyInfo.key_states, data, size);
1822			} else {
1823				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1824					sizeof(fKeyInfo.key_states));
1825			}
1826
1827			break;
1828		}
1829
1830   		default:
1831			break;
1832	}
1833
1834	BMessenger reply;
1835	BMessage::Private messagePrivate(event);
1836	return messagePrivate.SendMessage(fAppServerPort, -1, 0, 0, false, reply);
1837}
1838
1839
1840//	#pragma mark -
1841
1842
1843extern "C" void
1844RegisterDevices(input_device_ref** devices)
1845{
1846	CALLED();
1847}
1848
1849
1850BView *
1851instantiate_deskbar_item()
1852{
1853	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1854}
1855
1856
1857//	#pragma mark -
1858
1859
1860int
1861main(int /*argc*/, char** /*argv*/)
1862{
1863	InputServer	*inputServer = new InputServer;
1864
1865	inputServer->Run();
1866	delete inputServer;
1867
1868	return 0;
1869}
1870
1871
1872