xref: /haiku/src/servers/input/InputServer.cpp (revision d284f7cc43cc0d1106c3b0c40e62c58107648573)
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::SafeMode()
1310 {
1311 	char parameter[32];
1312 	size_t parameterLength = sizeof(parameter);
1313 
1314 	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter,
1315 			&parameterLength) == B_OK) {
1316 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
1317 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
1318 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) {
1319 			return true;
1320 		}
1321 	}
1322 
1323 	if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter,
1324 			&parameterLength) == B_OK) {
1325 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
1326 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
1327 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) {
1328 			return true;
1329 		}
1330 	}
1331 
1332 	return false;
1333 }
1334 
1335 
1336 status_t
1337 InputServer::_StartEventLoop()
1338 {
1339 	CALLED();
1340 	fEventLooperPort = create_port(100, "input server events");
1341 	if (fEventLooperPort < 0) {
1342 		PRINTERR(("InputServer: create_port error: (0x%lx) %s\n",
1343 			fEventLooperPort, strerror(fEventLooperPort)));
1344 		return fEventLooperPort;
1345 	}
1346 
1347 	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1348 		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1349 	if (thread < B_OK || resume_thread(thread) < B_OK) {
1350 		if (thread >= B_OK)
1351 			kill_thread(thread);
1352 		delete_port(fEventLooperPort);
1353 		fEventLooperPort = -1;
1354 		return thread < B_OK ? thread : B_ERROR;
1355 	}
1356 
1357 	return B_OK;
1358 }
1359 
1360 
1361 status_t
1362 InputServer::_EventLooper(void* arg)
1363 {
1364 	InputServer* self = (InputServer*)arg;
1365 	self->_EventLoop();
1366 
1367 	return B_OK;
1368 }
1369 
1370 
1371 void
1372 InputServer::_EventLoop()
1373 {
1374 	while (true) {
1375 		// Block until we find the size of the next message
1376 		ssize_t length = port_buffer_size(fEventLooperPort);
1377 		if (length < B_OK) {
1378 			PRINT(("[Event Looper] port gone, exiting.\n"));
1379 			return;
1380 		}
1381 
1382 		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1383 
1384 		char buffer[length];
1385 		int32 code;
1386 		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1387 		if (err != length) {
1388 			if (err >= 0) {
1389 				PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length));
1390 			} else {
1391 				PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err)));
1392 			}
1393 			continue;
1394 		}
1395 
1396 		EventList events;
1397 		if (fEventQueueLock.Lock()) {
1398 			// move the items to our own list to block the event queue as short as possible
1399 			events.AddList(&fEventQueue);
1400 			fEventQueue.MakeEmpty();
1401 			fEventQueueLock.Unlock();
1402 		}
1403 
1404 		if (length > 0) {
1405 			BMessage* event = new BMessage;
1406 
1407 			if ((err = event->Unflatten(buffer)) < 0) {
1408 				PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
1409 				delete event;
1410 				continue;
1411 			}
1412 
1413 			events.AddItem(event);
1414 		}
1415 
1416 		// This is where the message should be processed.
1417 
1418 		if (_SanitizeEvents(events)
1419 			&& _MethodizeEvents(events)
1420 			&& _FilterEvents(events)) {
1421 			_UpdateMouseAndKeys(events);
1422 			_DispatchEvents(events);
1423 		}
1424 	}
1425 }
1426 
1427 
1428 /*!	Updates the internal mouse position and keyboard info. */
1429 void
1430 InputServer::_UpdateMouseAndKeys(EventList& events)
1431 {
1432 	for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index);
1433 			index++) {
1434 		switch (event->what) {
1435 			case B_MOUSE_DOWN:
1436 			case B_MOUSE_UP:
1437 			case B_MOUSE_MOVED:
1438 				event->FindPoint("where", &fMousePos);
1439 				break;
1440 
1441 			case B_KEY_DOWN:
1442 			case B_UNMAPPED_KEY_DOWN:
1443 				// update modifiers
1444 				uint32 modifiers;
1445 				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1446 					fKeyInfo.modifiers = modifiers;
1447 
1448 				// update key states
1449 				const uint8 *data;
1450 				ssize_t size;
1451 				if (event->FindData("states", B_UINT8_TYPE,
1452 						(const void**)&data, &size) == B_OK) {
1453 					PRINT(("updated keyinfo\n"));
1454 					if (size == sizeof(fKeyInfo.key_states))
1455 						memcpy(fKeyInfo.key_states, data, size);
1456 				}
1457 
1458 				if (fActiveMethod == NULL)
1459 					break;
1460 
1461 				// we scan for Alt+Space key down events which means we change
1462 				// to next input method
1463 				// (pressing "shift" will let us switch to the previous method)
1464 
1465 				// If there is only one input method, SetNextMethod will return
1466 				// B_BAD_INDEX and the event will be forwarded to the user.
1467 
1468 				PRINT(("SanitizeEvents: %lx, %x\n", fKeyInfo.modifiers,
1469 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1470 
1471 				uint8 byte;
1472 				if (event->FindInt8("byte", (int8*)&byte) < B_OK)
1473 					byte = 0;
1474 
1475 				if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ')
1476 						|| byte == B_HANKAKU_ZENKAKU)
1477 					&& SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0)
1478 							== B_OK) {
1479 					// this event isn't sent to the user
1480 					events.RemoveItemAt(index);
1481 					delete event;
1482 					continue;
1483 				}
1484 				break;
1485 		}
1486 	}
1487 }
1488 
1489 
1490 /*!	Frees events from unwanted fields, adds missing fields, and removes
1491 	unwanted events altogether.
1492 */
1493 bool
1494 InputServer::_SanitizeEvents(EventList& events)
1495 {
1496 	CALLED();
1497 
1498 	for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index);
1499 			index++) {
1500 		switch (event->what) {
1501 	   		case B_MOUSE_MOVED:
1502 	   		case B_MOUSE_DOWN:
1503 	   		{
1504 	   			int32 buttons;
1505 	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1506 	   				event->AddInt32("buttons", 0);
1507 
1508 	   			// supposed to fall through
1509 	   		}
1510 	   		case B_MOUSE_UP:
1511 	   		{
1512 	   			BPoint where;
1513 				int32 x, y;
1514 				float absX, absY;
1515 
1516 				if (event->FindInt32("x", &x) == B_OK
1517 					&& event->FindInt32("y", &y) == B_OK) {
1518 					where.x = fMousePos.x + x;
1519 					where.y = fMousePos.y - y;
1520 
1521 					event->RemoveName("x");
1522 					event->RemoveName("y");
1523 					event->AddInt32("be:delta_x", x);
1524 					event->AddInt32("be:delta_y", y);
1525 
1526 					PRINT(("new position: %f, %f, %ld, %ld\n",
1527 						where.x, where.y, x, y));
1528 				} else if (event->FindFloat("x", &absX) == B_OK
1529 					&& event->FindFloat("y", &absY) == B_OK) {
1530 					// The device gives us absolute screen coords in range 0..1;
1531 					// convert them to absolute screen position
1532 					// (the message is supposed to contain the original
1533 					// absolute coordinates as "be:tablet_x/y").
1534 					where.x = absX * fFrame.Width();
1535 					where.y = absY * fFrame.Height();
1536 
1537 					event->RemoveName("x");
1538 					event->RemoveName("y");
1539 					PRINT(("new position : %f, %f\n", where.x, where.y));
1540 				} else if (event->FindPoint("where", &where) == B_OK) {
1541 					PRINT(("new position : %f, %f\n", where.x, where.y));
1542 				}
1543 
1544 				// Constrain and filter the mouse coords and add the final
1545 				// point to the message.
1546 				where.x = roundf(where.x);
1547 				where.y = roundf(where.y);
1548 				where.ConstrainTo(fFrame);
1549 				if (event->ReplacePoint("where", where) != B_OK)
1550 					event->AddPoint("where", where);
1551 
1552 				if (!event->HasInt64("when"))
1553 					event->AddInt64("when", system_time());
1554 
1555 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1556 				break;
1557 	   		}
1558 			case B_KEY_DOWN:
1559 			case B_UNMAPPED_KEY_DOWN:
1560 				// add modifiers
1561 				if (!event->HasInt32("modifiers"))
1562 					event->AddInt32("modifiers", fKeyInfo.modifiers);
1563 
1564 				// add key states
1565 				if (!event->HasData("states", B_UINT8_TYPE)) {
1566 					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1567 						sizeof(fKeyInfo.key_states));
1568 				}
1569 				break;
1570 		}
1571 	}
1572 
1573 	return true;
1574 }
1575 
1576 
1577 /*!	Applies the filters of the active input method to the
1578 	incoming events. It will also move the events in the method
1579 	queue to the event list.
1580 */
1581 bool
1582 InputServer::_MethodizeEvents(EventList& events)
1583 {
1584 	CALLED();
1585 
1586 	if (fActiveMethod == NULL)
1587 		return true;
1588 
1589 	int32 count = events.CountItems();
1590 	for (int32 i = 0; i < count;) {
1591 		_FilterEvent(fActiveMethod, events, i, count);
1592 	}
1593 
1594 	{
1595 		// move the method events into the event queue - they are not
1596 		// "methodized" either
1597 		BAutolock _(fEventQueueLock);
1598 		events.AddList(&fMethodQueue);
1599 		fMethodQueue.MakeEmpty();
1600 	}
1601 
1602 	if (!fInputMethodAware) {
1603 		// special handling for non-input-method-aware views
1604 
1605 		int32 newCount = events.CountItems();
1606 			// we may add new events in this loop that don't need to be checked again
1607 
1608 		for (int32 i = 0; i < newCount; i++) {
1609 			BMessage* event = events.ItemAt(i);
1610 
1611 			if (event->what != B_INPUT_METHOD_EVENT)
1612 				continue;
1613 
1614 			SERIAL_PRINT(("IME received\n"));
1615 
1616 			bool removeEvent = true;
1617 
1618 			int32 opcode;
1619 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1620 				bool inlineOnly;
1621 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1622 					inlineOnly = false;
1623 
1624 				if (inlineOnly) {
1625 					BMessage translated;
1626 					bool confirmed;
1627 					if (opcode == B_INPUT_METHOD_CHANGED
1628 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1629 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1630 						// translate event for the non-aware view
1631 						*event = translated;
1632 						removeEvent = false;
1633 					}
1634 				} else {
1635 					if (fInputMethodWindow == NULL
1636 						&& opcode == B_INPUT_METHOD_STARTED)
1637 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1638 
1639 					if (fInputMethodWindow != NULL) {
1640 						EventList newEvents;
1641 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1642 
1643 						if (!newEvents.IsEmpty()) {
1644 							events.AddList(&newEvents);
1645 							opcode = B_INPUT_METHOD_STOPPED;
1646 						}
1647 
1648 						if (opcode == B_INPUT_METHOD_STOPPED) {
1649 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1650 							fInputMethodWindow = NULL;
1651 						}
1652 					}
1653 				}
1654 			}
1655 
1656 			if (removeEvent) {
1657 				// the inline/bottom window has eaten the event
1658 				events.RemoveItemAt(i--);
1659 				delete event;
1660 				newCount--;
1661 			}
1662 		}
1663 	}
1664 
1665 	return events.CountItems() > 0;
1666 }
1667 
1668 
1669 /*!	This method applies all defined filters to each event in the
1670 	supplied list.  The supplied list is modified to reflect the
1671 	output of the filters.
1672 	The method returns true if the filters were applied to all
1673 	events without error and false otherwise.
1674 */
1675 bool
1676 InputServer::_FilterEvents(EventList& events)
1677 {
1678 	CALLED();
1679 	BAutolock _(gInputFilterListLocker);
1680 
1681 	int32 count = gInputFilterList.CountItems();
1682 	int32 eventCount = events.CountItems();
1683 
1684 	for (int32 i = 0; i < count; i++) {
1685 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1686 
1687 		// Apply the current filter to all available event messages.
1688 
1689 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1690 			_FilterEvent(filter, events, eventIndex, eventCount);
1691 		}
1692 	}
1693 
1694 	return eventCount != 0;
1695 }
1696 
1697 
1698 void
1699 InputServer::_DispatchEvents(EventList& events)
1700 {
1701 	CALLED();
1702 
1703 	int32 count = events.CountItems();
1704 
1705 	for (int32 i = 0; i < count; i++) {
1706 		BMessage* event = events.ItemAt(i);
1707 
1708 		// now we must send each event to the app_server
1709 		_DispatchEvent(event);
1710 		delete event;
1711 	}
1712 
1713 	events.MakeEmpty();
1714 }
1715 
1716 
1717 /*!	Applies the given filter to the event list.
1718 	For your convenience, it also alters the \a index and \a count arguments
1719 	ready for the next call to this method.
1720 */
1721 void
1722 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1723 	int32& index, int32& count)
1724 {
1725 	BMessage* event = events.ItemAt(index);
1726 
1727 	BList newEvents;
1728 	filter_result result = filter->Filter(event, &newEvents);
1729 
1730 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1731 		// we no longer need the current event
1732 		events.RemoveItemAt(index);
1733 		delete event;
1734 
1735 		if (result == B_DISPATCH_MESSAGE) {
1736 			EventList addedEvents;
1737 			EventList::Private(&addedEvents).AsBList()->AddList(&newEvents);
1738 			_SanitizeEvents(addedEvents);
1739 			// add the new events - but don't methodize them again
1740 			events.AddList(&addedEvents, index);
1741 			index += newEvents.CountItems();
1742 			count = events.CountItems();
1743 		} else
1744 			count--;
1745 	} else
1746 		index++;
1747 }
1748 
1749 
1750 status_t
1751 InputServer::_DispatchEvent(BMessage* event)
1752 {
1753 	CALLED();
1754 
1755    	switch (event->what) {
1756 		case B_MOUSE_MOVED:
1757 		case B_MOUSE_DOWN:
1758 		case B_MOUSE_UP:
1759 			if (fCursorBuffer) {
1760 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1761 					| ((uint32)fMousePos.y & 0xffff));
1762 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1763 					release_sem(fCursorSem);
1764         	}
1765         	break;
1766 
1767 		case B_KEY_DOWN:
1768 		case B_KEY_UP:
1769 		case B_UNMAPPED_KEY_DOWN:
1770 		case B_UNMAPPED_KEY_UP:
1771 		case B_MODIFIERS_CHANGED:
1772 		{
1773 			// update or add modifiers
1774 			uint32 modifiers;
1775 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1776 				fKeyInfo.modifiers = modifiers;
1777 			else
1778 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1779 
1780 			// update or add key states
1781 			const uint8 *data;
1782 			ssize_t size;
1783 			if (event->FindData("states", B_UINT8_TYPE,
1784 					(const void**)&data, &size) == B_OK) {
1785 				PRINT(("updated keyinfo\n"));
1786 				if (size == sizeof(fKeyInfo.key_states))
1787 					memcpy(fKeyInfo.key_states, data, size);
1788 			} else {
1789 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1790 					sizeof(fKeyInfo.key_states));
1791 			}
1792 
1793 			break;
1794 		}
1795 
1796    		default:
1797 			break;
1798 	}
1799 
1800 	BMessenger reply;
1801 	BMessage::Private messagePrivate(event);
1802 	return messagePrivate.SendMessage(fAppServerPort, fAppServerTeam, 0, 0,
1803 		false, reply);
1804 }
1805 
1806 
1807 //	#pragma mark -
1808 
1809 
1810 extern "C" void
1811 RegisterDevices(input_device_ref** devices)
1812 {
1813 	CALLED();
1814 }
1815 
1816 
1817 BView *
1818 instantiate_deskbar_item()
1819 {
1820 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1821 }
1822 
1823 
1824 //	#pragma mark -
1825 
1826 
1827 int
1828 main(int /*argc*/, char** /*argv*/)
1829 {
1830 	InputServer	*inputServer = new InputServer;
1831 
1832 	inputServer->Run();
1833 	delete inputServer;
1834 
1835 	return 0;
1836 }
1837