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