xref: /haiku/src/servers/input/InputServer.cpp (revision 89755088d790ff4fe36f8aa77dacb2bd15507108)
1 /*
2  * Copyright 2002-2007, 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 
64 extern "C" _EXPORT BView* instantiate_deskbar_item();
65 
66 
67 InputDeviceListItem::InputDeviceListItem(BInputServerDevice& serverDevice,
68 	input_device_ref& device)
69 	:
70 	fServerDevice(&serverDevice),
71 	fDevice(device),
72 	fRunning(false)
73 {
74 }
75 
76 
77 void
78 InputDeviceListItem::Start()
79 {
80 	PRINT(("  Starting: %s\n", fDevice.name));
81 	fServerDevice->Start(fDevice.name, fDevice.cookie);
82 	fRunning = true;
83 }
84 
85 
86 void
87 InputDeviceListItem::Stop()
88 {
89 	PRINT(("  Stopping: %s\n", fDevice.name));
90 	fServerDevice->Stop(fDevice.name, fDevice.cookie);
91 	fRunning = false;
92 }
93 
94 
95 void
96 InputDeviceListItem::Control(uint32 code, BMessage* message)
97 {
98 	fServerDevice->Control(fDevice.name, fDevice.cookie, code, message);
99 }
100 
101 
102 bool
103 InputDeviceListItem::HasName(const char* name) const
104 {
105 	if (name == NULL)
106 		return false;
107 
108 	return !strcmp(name, fDevice.name);
109 }
110 
111 
112 bool
113 InputDeviceListItem::HasType(input_device_type type) const
114 {
115 	return type == fDevice.type;
116 }
117 
118 
119 bool
120 InputDeviceListItem::Matches(const char* name, input_device_type type) const
121 {
122 	if (name != NULL)
123 		return HasName(name);
124 
125 	return HasType(type);
126 }
127 
128 
129 //	#pragma mark -
130 
131 
132 InputServer::InputServer()
133 	: BApplication(INPUTSERVER_SIGNATURE),
134 	fSafeMode(false),
135 	fInputDeviceListLocker("input server device list"),
136 	fKeyboardSettings(),
137 	fMouseSettings(),
138 	fChars(NULL),
139 	fScreen(B_MAIN_SCREEN_ID),
140 	fInputMethodWindow(NULL),
141 	fInputMethodAware(false),
142 	fCursorSem(-1),
143 	fAppServerPort(-1),
144 	fCursorArea(-1)
145 {
146 	CALLED();
147 	gInputServer = this;
148 
149 	_StartEventLoop();
150 
151 	char parameter[32];
152 	size_t parameterLength = sizeof(parameter);
153 
154 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
155 	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, &parameterLength) == B_OK)
156 #else
157 	if (_kget_safemode_option_(B_SAFEMODE_SAFE_MODE, parameter, &parameterLength) == B_OK)
158 #endif
159 	{
160 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
161 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
162 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
163 			fSafeMode = true;
164 	}
165 
166 	gDeviceManager.LoadState();
167 
168 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
169 	if (has_data(find_thread(NULL))) {
170 		PRINT(("HasData == YES\n"));
171 		int32 buffer[2];
172 		thread_id appThreadId;
173 		memset(buffer, 0, sizeof(buffer));
174 		int32 code = receive_data(&appThreadId, buffer, sizeof(buffer));
175 		(void)code;	// suppresses warning in non-debug build
176 		PRINT(("tid : %ld, code :%ld\n", appThreadId, code));
177 		for (int32 i = 0; i < 2; i++) {
178 			PRINT(("data : %lx\n", buffer[i]));
179 		}
180 		fCursorSem = buffer[0];
181 		area_id appArea = buffer[1];
182 
183 		fCursorArea = clone_area("isClone", (void**)&fCursorBuffer,
184 			B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, appArea);
185 		if (fCursorArea < B_OK) {
186 			PRINTERR(("clone_area error : %s\n", strerror(fCloneArea)));
187 		}
188 
189 		fAppServerPort = create_port(100, "is_as");
190 
191 		PRINT(("is_as port :%ld\n", fAppServerPort));
192 
193 		buffer[1] = fEventLooperPort;
194 		buffer[0] = fAppServerPort;
195 
196 		status_t err;
197 		if ((err = send_data(appThreadId, 0, buffer, sizeof(buffer)))!=B_OK)
198 			PRINTERR(("error when send_data %s\n", strerror(err)));
199 	}
200 #endif
201 
202 	_InitKeyboardMouseStates();
203 
204 	fAddOnManager = new AddOnManager(SafeMode());
205 	fAddOnManager->LoadState();
206 
207 	BMessenger messenger(this);
208 	BRoster().StartWatching(messenger, B_REQUEST_LAUNCHED);
209 }
210 
211 
212 InputServer::~InputServer()
213 {
214 	CALLED();
215 	fAddOnManager->Lock();
216 	fAddOnManager->Quit();
217 
218 	_ReleaseInput(NULL);
219 }
220 
221 
222 void
223 InputServer::ArgvReceived(int32 argc, char** argv)
224 {
225 	CALLED();
226 	if (2 == argc && (0 == strcmp("-q", argv[1]))) {
227 		PRINT(("InputServer::ArgvReceived - Restarting ...\n"));
228 		status_t quit_status = B_OK;
229 		BMessenger msgr = BMessenger(INPUTSERVER_SIGNATURE, -1, &quit_status);
230 		if (B_OK == quit_status) {
231 			msgr.SendMessage(B_QUIT_REQUESTED);
232 		} else {
233 			PRINTERR(("Unable to send Quit message to running InputServer.\n"));
234 		}
235 	}
236 }
237 
238 
239 void
240 InputServer::_InitKeyboardMouseStates()
241 {
242 	CALLED();
243 	// This is where we determine the screen resolution from the app_server and find the center of the screen
244 	// fMousePos is then set to the center of the screen.
245 
246 	fFrame = fScreen.Frame();
247 	if (fFrame == BRect(0, 0, 0, 0))
248 		fFrame = BRect(0, 0, 800, 600);
249 	fMousePos = BPoint(fFrame.right / 2, fFrame.bottom / 2);
250 
251 	if (_LoadKeymap() != B_OK)
252 		_LoadSystemKeymap();
253 
254 	BMessage msg(B_MOUSE_MOVED);
255 	HandleSetMousePosition(&msg, &msg);
256 
257 	fActiveMethod = &gKeymapMethod;
258 }
259 
260 
261 status_t
262 InputServer::_LoadKeymap()
263 {
264 	BPath path;
265 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
266 		return B_BAD_VALUE;
267 
268 	path.Append("Key_map");
269 
270 	status_t err;
271 
272 	BFile file(path.Path(), B_READ_ONLY);
273 	if ((err = file.InitCheck()) != B_OK)
274 		return err;
275 
276 	if (file.Read(&fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys))
277 		return B_BAD_VALUE;
278 
279 	for (uint32 i = 0; i < sizeof(fKeys)/4; i++)
280 		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
281 
282 	if (file.Read(&fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32))
283 		return B_BAD_VALUE;
284 
285 	fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize);
286 
287 	delete[] fChars;
288 	fChars = new (nothrow) char[fCharsSize];
289 	if (fChars == NULL)
290 		return B_NO_MEMORY;
291 
292 	if (file.Read(fChars, fCharsSize) != (signed)fCharsSize)
293 		return B_BAD_VALUE;
294 
295 	return B_OK;
296 }
297 
298 
299 status_t
300 InputServer::_LoadSystemKeymap()
301 {
302 	delete[] fChars;
303 	fKeys = kSystemKeymap;
304 	fCharsSize = kSystemKeyCharsSize;
305 	fChars = new (nothrow) char[fCharsSize];
306 	if (fChars == NULL)
307 		return B_NO_MEMORY;
308 
309 	memcpy(fChars, kSystemKeyChars, fCharsSize);
310 
311 	// TODO: why are we doing this?
312 	return _SaveKeymap();
313 }
314 
315 
316 status_t
317 InputServer::_SaveKeymap()
318 {
319 	// we save this keymap to file
320 	BPath path;
321 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
322 		return B_BAD_VALUE;
323 
324 	path.Append("Key_map");
325 
326 	BFile file;
327 	status_t err = file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
328 	if (err != B_OK) {
329 		PRINTERR(("error %s\n", strerror(err)));
330 		return err;
331 	}
332 
333 	for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) {
334 		((uint32*)&fKeys)[i] = B_HOST_TO_BENDIAN_INT32(((uint32*)&fKeys)[i]);
335 	}
336 
337 	if ((err = file.Write(&fKeys, sizeof(fKeys))) < (ssize_t)sizeof(fKeys))
338 		return err;
339 
340 	for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) {
341 		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
342 	}
343 
344 	uint32 size = B_HOST_TO_BENDIAN_INT32(fCharsSize);
345 
346 	if ((err = file.Write(&size, sizeof(uint32))) < (ssize_t)sizeof(uint32))
347 		return B_BAD_VALUE;
348 
349 	if ((err = file.Write(fChars, fCharsSize)) < (ssize_t)fCharsSize)
350 		return err;
351 
352 	return B_OK;
353 }
354 
355 
356 bool
357 InputServer::QuitRequested()
358 {
359 	CALLED();
360 	if (!BApplication::QuitRequested())
361 		return false;
362 
363 	PostMessage(SYSTEM_SHUTTING_DOWN);
364 
365 	bool shutdown = false;
366 	CurrentMessage()->FindBool("_shutdown_", &shutdown);
367 
368 	// Don't actually quit when the system is being shutdown
369 	if (shutdown) {
370 		return false;
371 	} else {
372 		fAddOnManager->SaveState();
373 		gDeviceManager.SaveState();
374 
375 		delete_port(fEventLooperPort);
376 			// the event looper thread will exit after this
377 		fEventLooperPort = -1;
378 		return true;
379 	}
380 }
381 
382 
383 void
384 InputServer::ReadyToRun()
385 {
386 	CALLED();
387 
388 	// say hello to the app_server
389 
390 	BPrivate::AppServerLink link;
391 	link.StartMessage(AS_REGISTER_INPUT_SERVER);
392 	link.Flush();
393 }
394 
395 
396 status_t
397 InputServer::_AcquireInput(BMessage& message, BMessage& reply)
398 {
399 	// TODO: it currently just gets everything we have
400 	area_id area;
401 	if (message.FindInt32("cursor area", &area) == B_OK) {
402 		// try to clone the area
403 		fCursorBuffer = NULL;
404 
405 		fCursorSem = create_sem(0, "cursor semaphore");
406 		if (fCursorSem >= B_OK) {
407 			fCursorArea = clone_area("input server cursor", (void**)&fCursorBuffer,
408 				B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area);
409 		}
410 	}
411 
412 	fAppServerPort = create_port(200, "input server target");
413 	if (fAppServerPort < B_OK) {
414 		_ReleaseInput(&message);
415 		return fAppServerPort;
416 	}
417 
418 	reply.AddBool("has keyboard", true);
419 	reply.AddBool("has mouse", true);
420 	reply.AddInt32("event port", fAppServerPort);
421 
422 	if (fCursorBuffer != NULL) {
423 		// cursor shared buffer is supported
424 		reply.AddInt32("cursor semaphore", fCursorSem);
425 	}
426 
427 	return B_OK;
428 }
429 
430 
431 void
432 InputServer::_ReleaseInput(BMessage* /*message*/)
433 {
434 	if (fCursorBuffer != NULL) {
435 		fCursorBuffer = NULL;
436 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
437 		delete_sem(fCursorSem);
438 #endif
439 		delete_area(fCursorArea);
440 
441 		fCursorSem = -1;
442 		fCursorArea = -1;
443 	}
444 
445 	delete_port(fAppServerPort);
446 }
447 
448 
449 void
450 InputServer::MessageReceived(BMessage* message)
451 {
452 	CALLED();
453 
454 	BMessage reply;
455 	status_t status = B_OK;
456 
457 	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what >> 24,
458 		message->what >> 16, message->what >> 8, message->what));
459 
460 	switch (message->what) {
461 		case IS_SET_METHOD:
462 			HandleSetMethod(message);
463 			break;
464 		case IS_GET_MOUSE_TYPE:
465 			status = HandleGetSetMouseType(message, &reply);
466 			break;
467 		case IS_SET_MOUSE_TYPE:
468 			status = HandleGetSetMouseType(message, &reply);
469 			break;
470 		case IS_GET_MOUSE_ACCELERATION:
471 			status = HandleGetSetMouseAcceleration(message, &reply);
472 			break;
473 		case IS_SET_MOUSE_ACCELERATION:
474 			status = HandleGetSetMouseAcceleration(message, &reply);
475 			break;
476 		case IS_GET_KEY_REPEAT_DELAY:
477 			status = HandleGetSetKeyRepeatDelay(message, &reply);
478 			break;
479 		case IS_SET_KEY_REPEAT_DELAY:
480 			status = HandleGetSetKeyRepeatDelay(message, &reply);
481 			break;
482 		case IS_GET_KEY_INFO:
483 			status = HandleGetKeyInfo(message, &reply);
484 			break;
485 		case IS_GET_MODIFIERS:
486 			status = HandleGetModifiers(message, &reply);
487 			break;
488 		case IS_SET_MODIFIER_KEY:
489 			status = HandleSetModifierKey(message, &reply);
490 			break;
491 		case IS_SET_KEYBOARD_LOCKS:
492 			status = HandleSetKeyboardLocks(message, &reply);
493 			break;
494 		case IS_GET_MOUSE_SPEED:
495 			status = HandleGetSetMouseSpeed(message, &reply);
496 			break;
497 		case IS_SET_MOUSE_SPEED:
498 			status = HandleGetSetMouseSpeed(message, &reply);
499 			break;
500 		case IS_SET_MOUSE_POSITION:
501 			status = HandleSetMousePosition(message, &reply);
502 			break;
503 		case IS_GET_MOUSE_MAP:
504 			status = HandleGetSetMouseMap(message, &reply);
505 			break;
506 		case IS_SET_MOUSE_MAP:
507 			status = HandleGetSetMouseMap(message, &reply);
508 			break;
509 		case IS_GET_KEYBOARD_ID:
510 			status = HandleGetKeyboardID(message, &reply);
511 			break;
512 		case IS_GET_CLICK_SPEED:
513 			status = HandleGetSetClickSpeed(message, &reply);
514 			break;
515 		case IS_SET_CLICK_SPEED:
516 			status = HandleGetSetClickSpeed(message, &reply);
517 			break;
518 		case IS_GET_KEY_REPEAT_RATE:
519 			status = HandleGetSetKeyRepeatRate(message, &reply);
520 			break;
521 		case IS_SET_KEY_REPEAT_RATE:
522 			status = HandleGetSetKeyRepeatRate(message, &reply);
523 			break;
524 		case IS_GET_KEY_MAP:
525 			status = HandleGetSetKeyMap(message, &reply);
526 			break;
527 		case IS_RESTORE_KEY_MAP:
528 			status = HandleGetSetKeyMap(message, &reply);
529 			break;
530 		case IS_FOCUS_IM_AWARE_VIEW:
531 			status = HandleFocusUnfocusIMAwareView(message, &reply);
532 			break;
533 		case IS_UNFOCUS_IM_AWARE_VIEW:
534 			status = HandleFocusUnfocusIMAwareView(message, &reply);
535 			break;
536 
537 		// app_server communication
538 		case IS_ACQUIRE_INPUT:
539 			status = _AcquireInput(*message, reply);
540 			break;
541 		case IS_RELEASE_INPUT:
542 			_ReleaseInput(message);
543 			return;
544    		case IS_SCREEN_BOUNDS_UPDATED:
545    		{
546 			// This is what the R5 app_server sends us when the screen
547 			// configuration changes
548 			BRect frame;
549 			if (message->FindRect("screen_bounds", &frame) != B_OK)
550 				frame = fScreen.Frame();
551 
552 			if (frame == fFrame)
553 				break;
554 
555 			BPoint pos(fMousePos.x * frame.Width() / fFrame.Width(),
556 				fMousePos.y * frame.Height() / fFrame.Height());
557 			fFrame = frame;
558 
559 			BMessage set;
560 			set.AddPoint("where", pos);
561 			HandleSetMousePosition(&set, NULL);
562 			break;
563 		}
564 
565 		// device looper related
566 		case IS_FIND_DEVICES:
567 		case IS_WATCH_DEVICES:
568 		case IS_IS_DEVICE_RUNNING:
569 		case IS_START_DEVICE:
570 		case IS_STOP_DEVICE:
571 		case IS_CONTROL_DEVICES:
572 		case SYSTEM_SHUTTING_DOWN:
573 		case IS_METHOD_REGISTER:
574 			fAddOnManager->PostMessage(message);
575 			return;
576 
577 		case IS_SAVE_SETTINGS:
578 			fKeyboardSettings.Save();
579 			fMouseSettings.SaveSettings();
580 			return;
581 
582 		case IS_SAVE_KEYMAP:
583 			_SaveKeymap();
584 			return;
585 
586 		case B_SOME_APP_LAUNCHED:
587 		{
588 			const char *signature;
589 			// TODO: what's this for?
590 			if (message->FindString("be:signature", &signature)==B_OK) {
591 				PRINT(("input_server : %s\n", signature));
592 				if (strcmp(signature, "application/x-vnd.Be-TSKB")==0) {
593 
594 				}
595 			}
596 			return;
597 		}
598 
599 		default:
600 			return;
601 	}
602 
603 	reply.AddInt32("status", status);
604 	message->SendReply(&reply);
605 }
606 
607 
608 void
609 InputServer::HandleSetMethod(BMessage* message)
610 {
611 	CALLED();
612 	uint32 cookie;
613 	if (message->FindInt32("cookie", (int32*)&cookie) == B_OK) {
614 		BInputServerMethod *method = (BInputServerMethod*)cookie;
615 		PRINT(("%s cookie %p\n", __PRETTY_FUNCTION__, method));
616 		SetActiveMethod(method);
617 	}
618 }
619 
620 
621 status_t
622 InputServer::HandleGetSetMouseType(BMessage* message, BMessage* reply)
623 {
624 	int32 type;
625 	if (message->FindInt32("mouse_type", &type) == B_OK) {
626 		fMouseSettings.SetMouseType(type);
627 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
628 
629 		BMessage msg(IS_CONTROL_DEVICES);
630 		msg.AddInt32("type", B_POINTING_DEVICE);
631 		msg.AddInt32("code", B_MOUSE_TYPE_CHANGED);
632 		return fAddOnManager->PostMessage(&msg);
633 	}
634 
635 	return reply->AddInt32("mouse_type", fMouseSettings.MouseType());
636 }
637 
638 
639 status_t
640 InputServer::HandleGetSetMouseAcceleration(BMessage* message,
641 	BMessage* reply)
642 {
643 	int32 factor;
644 	if (message->FindInt32("speed", &factor) == B_OK) {
645 		fMouseSettings.SetAccelerationFactor(factor);
646 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
647 
648 		BMessage msg(IS_CONTROL_DEVICES);
649 		msg.AddInt32("type", B_POINTING_DEVICE);
650 		msg.AddInt32("code", B_MOUSE_ACCELERATION_CHANGED);
651 		return fAddOnManager->PostMessage(&msg);
652 	}
653 
654 	return reply->AddInt32("speed", fMouseSettings.AccelerationFactor());
655 }
656 
657 
658 status_t
659 InputServer::HandleGetSetKeyRepeatDelay(BMessage* message, BMessage* reply)
660 {
661 	bigtime_t delay;
662 	if (message->FindInt64("delay", &delay) == B_OK) {
663 		fKeyboardSettings.SetKeyboardRepeatDelay(delay);
664 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
665 
666 		BMessage msg(IS_CONTROL_DEVICES);
667 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
668 		msg.AddInt32("code", B_KEY_REPEAT_DELAY_CHANGED);
669 		return fAddOnManager->PostMessage(&msg);
670 	}
671 
672 	return reply->AddInt64("delay", fKeyboardSettings.KeyboardRepeatDelay());
673 }
674 
675 
676 status_t
677 InputServer::HandleGetKeyInfo(BMessage* message, BMessage* reply)
678 {
679 	return reply->AddData("key_info", B_ANY_TYPE, &fKeyInfo, sizeof(fKeyInfo));
680 }
681 
682 
683 status_t
684 InputServer::HandleGetModifiers(BMessage* message, BMessage* reply)
685 {
686 	return reply->AddInt32("modifiers", fKeyInfo.modifiers);
687 }
688 
689 
690 status_t
691 InputServer::HandleSetModifierKey(BMessage* message, BMessage* reply)
692 {
693 	int32 modifier, key;
694 	if (message->FindInt32("modifier", &modifier) == B_OK
695 		&& message->FindInt32("key", &key) == B_OK) {
696 		switch (modifier) {
697 			case B_CAPS_LOCK:
698 				fKeys.caps_key = key;
699 				break;
700 			case B_NUM_LOCK:
701 				fKeys.num_key = key;
702 				break;
703 			case B_SCROLL_LOCK:
704 				fKeys.num_key = key;
705 				break;
706 			case B_LEFT_SHIFT_KEY:
707 				fKeys.left_shift_key = key;
708 				break;
709 			case B_RIGHT_SHIFT_KEY:
710 				fKeys.right_shift_key = key;
711 				break;
712 			case B_LEFT_COMMAND_KEY:
713 				fKeys.left_command_key = key;
714 				break;
715 			case B_RIGHT_COMMAND_KEY:
716 				fKeys.right_command_key = key;
717 				break;
718 			case B_LEFT_CONTROL_KEY:
719 				fKeys.left_control_key = key;
720 				break;
721 			case B_RIGHT_CONTROL_KEY:
722 				fKeys.right_control_key = key;
723 				break;
724 			case B_LEFT_OPTION_KEY:
725 				fKeys.left_option_key = key;
726 				break;
727 			case B_RIGHT_OPTION_KEY:
728 				fKeys.right_option_key = key;
729 				break;
730 			case B_MENU_KEY:
731 				fKeys.menu_key = key;
732 				break;
733 			default:
734 				return B_ERROR;
735 		}
736 
737 		// TODO: unmap the key ?
738 
739 		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
740 
741 		BMessage msg(IS_CONTROL_DEVICES);
742 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
743 		msg.AddInt32("code", B_KEY_MAP_CHANGED);
744 		return fAddOnManager->PostMessage(&msg);
745 	}
746 
747 	return B_ERROR;
748 }
749 
750 
751 status_t
752 InputServer::HandleSetKeyboardLocks(BMessage* message, BMessage* reply)
753 {
754 	if (message->FindInt32("locks", (int32*)&fKeys.lock_settings) == B_OK) {
755 		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
756 
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 				float absX, absY;
1440 
1441 	    		if (event->FindInt32("x", &x) == B_OK
1442 	    			&& event->FindInt32("y", &y) == B_OK) {
1443 					fMousePos.x += x;
1444 					fMousePos.y -= y;
1445 					fMousePos.ConstrainTo(fFrame);
1446 
1447 					event->RemoveName("x");
1448 					event->RemoveName("y");
1449 					event->AddPoint("where", fMousePos);
1450 
1451 					PRINT(("new position: %f, %f, %ld, %ld\n",
1452 						fMousePos.x, fMousePos.y, x, y));
1453 	    		} else if (event->FindFloat("x", &absX) == B_OK
1454 	    			&& event->FindFloat("y", &absY) == B_OK) {
1455 	    			// device gives us absolute screen coords
1456 	    			// in range 0..1
1457 	    			// convert to absolute screen pos
1458 	    			// (the message is supposed to contain the original
1459 	    			// absolute coordinates as "be:tablet_x/y")
1460 		   			fMousePos.x = absX * fFrame.Width();
1461 		   			fMousePos.y = absY * fFrame.Height();
1462 					fMousePos.ConstrainTo(fFrame);
1463 
1464 					event->RemoveName("x");
1465 					event->RemoveName("y");
1466 					event->AddPoint("where", fMousePos);
1467 					PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
1468 		   		} else if (event->FindPoint("where", &where) == B_OK) {
1469 		   			fMousePos = where;
1470 					fMousePos.ConstrainTo(fFrame);
1471 
1472 					event->ReplacePoint("where", fMousePos);
1473 					PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
1474 				}
1475 
1476 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1477 				break;
1478 	   		}
1479 			case B_KEY_DOWN:
1480 			case B_UNMAPPED_KEY_DOWN:
1481 				// update or add modifiers
1482 				uint32 modifiers;
1483 				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1484 					fKeyInfo.modifiers = modifiers;
1485 				else
1486 					event->AddInt32("modifiers", fKeyInfo.modifiers);
1487 
1488 				// update or add key states
1489 				const uint8 *data;
1490 				ssize_t size;
1491 				if (event->FindData("states", B_UINT8_TYPE,
1492 						(const void**)&data, &size) == B_OK) {
1493 					PRINT(("updated keyinfo\n"));
1494 					if (size == sizeof(fKeyInfo.key_states))
1495 						memcpy(fKeyInfo.key_states, data, size);
1496 				} else {
1497 					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1498 						sizeof(fKeyInfo.key_states));
1499 				}
1500 				if (fActiveMethod == NULL)
1501 					break;
1502 
1503 				// we scan for Alt+Space key down events which means we change
1504 				// to next input method
1505 				// (pressing "shift" will let us switch to the previous method)
1506 
1507 				PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers,
1508 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1509 
1510 				int8 byte;
1511 				if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0
1512 					&& event->FindInt8("byte", &byte) == B_OK && byte == ' ') {
1513 					SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY);
1514 
1515 					// this event isn't sent to the user
1516 					events.RemoveItemAt(index);
1517 					delete event;
1518 					continue;
1519 				}
1520 				break;
1521 		}
1522 
1523 		index++;
1524 	}
1525 
1526 	return true;
1527 }
1528 
1529 
1530 /** Applies the filters of the active input method to the
1531  *	incoming events. It will also move the events in the method
1532  *	queue to the event list.
1533  */
1534 
1535 bool
1536 InputServer::_MethodizeEvents(EventList& events)
1537 {
1538 	CALLED();
1539 
1540 	if (fActiveMethod == NULL)
1541 		return true;
1542 
1543 	int32 count = events.CountItems();
1544 	for (int32 i = 0; i < count;) {
1545 		_FilterEvent(fActiveMethod, events, i, count);
1546 	}
1547 
1548 	{
1549 		// move the method events into the event queue - they are not
1550 		// "methodized" either
1551 		BAutolock _(fEventQueueLock);
1552 		events.AddList(&fMethodQueue);
1553 		fMethodQueue.MakeEmpty();
1554 	}
1555 
1556 	if (!fInputMethodAware) {
1557 		// special handling for non-input-method-aware views
1558 
1559 		int32 newCount = events.CountItems();
1560 			// we may add new events in this loop that don't need to be checked again
1561 
1562 		for (int32 i = 0; i < newCount; i++) {
1563 			BMessage* event = events.ItemAt(i);
1564 
1565 			if (event->what != B_INPUT_METHOD_EVENT)
1566 				continue;
1567 
1568 			SERIAL_PRINT(("IME received\n"));
1569 
1570 			bool removeEvent = true;
1571 
1572 			int32 opcode;
1573 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1574 				bool inlineOnly;
1575 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1576 					inlineOnly = false;
1577 
1578 				if (inlineOnly) {
1579 					BMessage translated;
1580 					bool confirmed;
1581 					if (opcode == B_INPUT_METHOD_CHANGED
1582 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1583 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1584 						// translate event for the non-aware view
1585 						*event = translated;
1586 						removeEvent = false;
1587 					}
1588 				} else {
1589 					if (fInputMethodWindow == NULL
1590 						&& opcode == B_INPUT_METHOD_STARTED)
1591 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1592 
1593 					if (fInputMethodWindow != NULL) {
1594 						EventList newEvents;
1595 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1596 
1597 						if (!newEvents.IsEmpty()) {
1598 							events.AddList(&newEvents);
1599 							opcode = B_INPUT_METHOD_STOPPED;
1600 						}
1601 
1602 						if (opcode == B_INPUT_METHOD_STOPPED) {
1603 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1604 							fInputMethodWindow = NULL;
1605 						}
1606 					}
1607 				}
1608 			}
1609 
1610 			if (removeEvent) {
1611 				// the inline/bottom window has eaten the event
1612 				events.RemoveItemAt(i--);
1613 				delete event;
1614 				newCount--;
1615 			}
1616 		}
1617 	}
1618 
1619 	return events.CountItems() > 0;
1620 }
1621 
1622 
1623 /**	This method applies all defined filters to each event in the
1624  *	supplied list.  The supplied list is modified to reflect the
1625  *	output of the filters.
1626  *	The method returns true if the filters were applied to all
1627  *	events without error and false otherwise.
1628  */
1629 
1630 bool
1631 InputServer::_FilterEvents(EventList& events)
1632 {
1633 	CALLED();
1634 	BAutolock _(gInputFilterListLocker);
1635 
1636 	int32 count = gInputFilterList.CountItems();
1637 	int32 eventCount = events.CountItems();
1638 
1639 	for (int32 i = 0; i < count; i++) {
1640 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1641 
1642 		// Apply the current filter to all available event messages.
1643 
1644 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1645 			_FilterEvent(filter, events, eventIndex, eventCount);
1646 		}
1647 	}
1648 
1649 	return eventCount != 0;
1650 }
1651 
1652 
1653 void
1654 InputServer::_DispatchEvents(EventList& events)
1655 {
1656 	CALLED();
1657 
1658 	int32 count = events.CountItems();
1659 
1660 	for (int32 i = 0; i < count; i++) {
1661 		BMessage* event = events.ItemAt(i);
1662 
1663 		// now we must send each event to the app_server
1664 		_DispatchEvent(event);
1665 		delete event;
1666 	}
1667 
1668 	events.MakeEmpty();
1669 }
1670 
1671 
1672 /**	Applies the given filter to the event list.
1673  *	For your convenience, it also alters the \a index and \a count arguments
1674  *	ready for the next call to this method.
1675  */
1676 
1677 void
1678 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1679 	int32& index, int32& count)
1680 {
1681 	BMessage* event = events.ItemAt(index);
1682 
1683 	BList newEvents;
1684 	filter_result result = filter->Filter(event, &newEvents);
1685 
1686 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1687 		// we no longer need the current event
1688 		events.RemoveItemAt(index);
1689 		delete event;
1690 
1691 		if (result == B_DISPATCH_MESSAGE) {
1692 			// add the new events - but don't methodize them again
1693 			events.AsBList()->AddList(&newEvents, index);
1694 			index += newEvents.CountItems();
1695 			count = events.CountItems();
1696 		} else
1697 			count--;
1698 	} else
1699 		index++;
1700 }
1701 
1702 
1703 status_t
1704 InputServer::_DispatchEvent(BMessage* event)
1705 {
1706 	CALLED();
1707 
1708    	switch (event->what) {
1709 		case B_MOUSE_MOVED:
1710 		case B_MOUSE_DOWN:
1711 		case B_MOUSE_UP:
1712 			if (fCursorBuffer) {
1713 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1714 				fCursorBuffer[0] = (0x3 << 30L)
1715                		| ((uint32)fMousePos.x & 0x7fff) << 15
1716                		| ((uint32)fMousePos.y & 0x7fff);
1717 
1718 				PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0]));
1719                 	release_sem(fCursorSem);
1720 #else
1721 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1722 					| ((uint32)fMousePos.y & 0xffff));
1723 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1724 					release_sem(fCursorSem);
1725 #endif
1726         	}
1727         	break;
1728 
1729 		case B_KEY_DOWN:
1730 		case B_KEY_UP:
1731 		case B_UNMAPPED_KEY_DOWN:
1732 		case B_UNMAPPED_KEY_UP:
1733 		case B_MODIFIERS_CHANGED:
1734 		{
1735 			// update or add modifiers
1736 			uint32 modifiers;
1737 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1738 				fKeyInfo.modifiers = modifiers;
1739 			else
1740 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1741 
1742 			// update or add key states
1743 			const uint8 *data;
1744 			ssize_t size;
1745 			if (event->FindData("states", B_UINT8_TYPE,
1746 					(const void**)&data, &size) == B_OK) {
1747 				PRINT(("updated keyinfo\n"));
1748 				if (size == sizeof(fKeyInfo.key_states))
1749 					memcpy(fKeyInfo.key_states, data, size);
1750 			} else {
1751 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1752 					sizeof(fKeyInfo.key_states));
1753 			}
1754 
1755 			break;
1756 		}
1757 
1758    		default:
1759 			break;
1760 	}
1761 
1762 #if defined(HAIKU_TARGET_PLATFORM_HAIKU)
1763 	BMessenger reply;
1764 	BMessage::Private messagePrivate(event);
1765 	return messagePrivate.SendMessage(fAppServerPort, -1, 0, true, 0, reply);
1766 #else
1767 	ssize_t length = event->FlattenedSize();
1768 	char buffer[length];
1769 	status_t err;
1770 	if ((err = event->Flatten(buffer,length)) < B_OK)
1771 		return err;
1772 
1773 	return write_port(fAppServerPort, 0, buffer, length);
1774 #endif
1775 }
1776 
1777 
1778 //	#pragma mark -
1779 
1780 
1781 extern "C" void
1782 RegisterDevices(input_device_ref** devices)
1783 {
1784 	CALLED();
1785 }
1786 
1787 
1788 BView *
1789 instantiate_deskbar_item()
1790 {
1791 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1792 }
1793 
1794 
1795 //	#pragma mark -
1796 
1797 
1798 int
1799 main(int /*argc*/, char** /*argv*/)
1800 {
1801 	InputServer	*inputServer = new InputServer;
1802 
1803 	inputServer->Run();
1804 	delete inputServer;
1805 
1806 	return 0;
1807 }
1808 
1809 
1810