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