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