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