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