xref: /haiku/src/servers/input/InputServer.cpp (revision cfc3fa87da824bdf593eb8b817a83b6376e77935)
1 /*
2  * Copyright 2002-2008, 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 status_t
927 InputServer::EnqueueDeviceMessage(BMessage* message)
928 {
929 	CALLED();
930 
931 	BAutolock _(fEventQueueLock);
932 	if (!fEventQueue.AddItem(message))
933 		return B_NO_MEMORY;
934 
935 	if (fEventQueue.CountItems() == 1) {
936 		// notify event loop only if we haven't already done so
937 		write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0);
938 	}
939 	return B_OK;
940 }
941 
942 
943 /*!	Enqueues the message into the method queue.
944 	The message must only be deleted in case this method returns an error.
945 */
946 status_t
947 InputServer::EnqueueMethodMessage(BMessage* message)
948 {
949 	CALLED();
950 	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what >> 24,
951 		message->what >> 16, message->what >> 8, message->what));
952 
953 #ifdef DEBUG
954 	if (message->what == 'IMEV') {
955 		int32 code;
956 		message->FindInt32("be:opcode", &code);
957 		PRINT(("%s be:opcode %li\n", __PRETTY_FUNCTION__, code));
958 	}
959 #endif
960 
961 	BAutolock _(fEventQueueLock);
962 	if (!fMethodQueue.AddItem(message))
963 		return B_NO_MEMORY;
964 
965 	if (fMethodQueue.CountItems() == 1) {
966 		// notify event loop only if we haven't already done so
967 		write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
968 	}
969 	return B_OK;
970 }
971 
972 
973 status_t
974 InputServer::SetNextMethod(bool direction)
975 {
976 	gInputMethodListLocker.Lock();
977 
978 	int32 index = gInputMethodList.IndexOf(fActiveMethod);
979 	index += (direction ? 1 : -1);
980 
981 	if (index < -1)
982 		index = gInputMethodList.CountItems() - 1;
983 	if (index >= gInputMethodList.CountItems())
984 		index = -1;
985 
986 	BInputServerMethod *method = &gKeymapMethod;
987 
988 	if (index != -1)
989 		method = (BInputServerMethod *)gInputMethodList.ItemAt(index);
990 
991 	SetActiveMethod(method);
992 
993 	gInputMethodListLocker.Unlock();
994 	return B_OK;
995 }
996 
997 
998 void
999 InputServer::SetActiveMethod(BInputServerMethod* method)
1000 {
1001 	CALLED();
1002 	if (fActiveMethod)
1003 		fActiveMethod->fOwner->MethodActivated(false);
1004 
1005 	fActiveMethod = method;
1006 
1007 	if (fActiveMethod)
1008 		fActiveMethod->fOwner->MethodActivated(true);
1009 }
1010 
1011 
1012 const BMessenger*
1013 InputServer::MethodReplicant()
1014 {
1015 	return fReplicantMessenger;
1016 }
1017 
1018 
1019 void
1020 InputServer::SetMethodReplicant(const BMessenger* messenger)
1021 {
1022 	fReplicantMessenger = messenger;
1023 }
1024 
1025 
1026 bool
1027 InputServer::EventLoopRunning()
1028 {
1029 	return fEventLooperPort >= B_OK;
1030 }
1031 
1032 
1033 /*!	The fInputDeviceListLocker must be locked when calling this function */
1034 InputDeviceListItem*
1035 InputServer::_FindInputDeviceListItem(BInputServerDevice& device)
1036 {
1037 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1038 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1039 
1040 		if (item->ServerDevice() == &device)
1041 			return item;
1042 	}
1043 
1044 	return NULL;
1045 }
1046 
1047 
1048 status_t
1049 InputServer::GetDeviceInfo(const char* name, input_device_type *_type,
1050 	bool *_isRunning)
1051 {
1052     BAutolock lock(fInputDeviceListLocker);
1053 
1054 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1055 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1056 
1057 		if (item->HasName(name)) {
1058 			if (_type)
1059 				*_type = item->Type();
1060 			if (_isRunning)
1061 				*_isRunning = item->Running();
1062 
1063 			return B_OK;
1064 		}
1065 	}
1066 
1067 	return B_NAME_NOT_FOUND;
1068 }
1069 
1070 
1071 status_t
1072 InputServer::GetDeviceInfos(BMessage *msg)
1073 {
1074 	CALLED();
1075 	BAutolock lock(fInputDeviceListLocker);
1076 
1077 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1078 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1079 		msg->AddString("device", item->Name());
1080 		msg->AddInt32("type", item->Type());
1081 	}
1082 	return B_OK;
1083 }
1084 
1085 
1086 status_t
1087 InputServer::UnregisterDevices(BInputServerDevice& serverDevice,
1088 	input_device_ref **devices)
1089 {
1090     CALLED();
1091     BAutolock lock(fInputDeviceListLocker);
1092 
1093 	if (devices != NULL) {
1094 		// remove the devices as specified only
1095 		input_device_ref *device = NULL;
1096 		for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1097 			for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1098 				InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1099 
1100 				if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) {
1101 					item->Stop();
1102 					fInputDeviceList.RemoveItem(j);
1103 					delete item;
1104 					break;
1105 				}
1106 			}
1107 		}
1108 	} else {
1109 		// remove all devices from this BInputServerObject
1110 		for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1111 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1112 
1113 			if (item->ServerDevice() == &serverDevice) {
1114 				item->Stop();
1115 				fInputDeviceList.RemoveItem(i);
1116 				delete item;
1117 			}
1118 		}
1119 	}
1120 
1121     return B_OK;
1122 }
1123 
1124 
1125 status_t
1126 InputServer::RegisterDevices(BInputServerDevice& serverDevice,
1127 	input_device_ref** devices)
1128 {
1129 	if (devices == NULL)
1130 		return B_BAD_VALUE;
1131 
1132 	BAutolock lock(fInputDeviceListLocker);
1133 
1134 	input_device_ref *device = NULL;
1135 	for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1136 		if (device->type != B_POINTING_DEVICE
1137 			&& device->type != B_KEYBOARD_DEVICE
1138 			&& device->type != B_UNDEFINED_DEVICE)
1139 			continue;
1140 
1141 		// find existing input server device
1142 
1143 		bool found = false;
1144 		for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1145 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1146 
1147 			if (item->HasName(device->name)) {
1148 				PRINT(("RegisterDevices found %s\n", device->name));
1149 				found = true;
1150 				break;
1151 			}
1152 		}
1153 
1154 		if (!found) {
1155 			PRINT(("RegisterDevices not found %s\n", device->name));
1156 			InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice,
1157 				*device);
1158 			if (item != NULL && fInputDeviceList.AddItem(item)) {
1159 				item->Start();
1160 			} else {
1161 				delete item;
1162 				return B_NO_MEMORY;
1163 			}
1164 		}
1165 	}
1166 
1167 	return B_OK;
1168 }
1169 
1170 
1171 status_t
1172 InputServer::StartStopDevices(const char* name, input_device_type type, bool doStart)
1173 {
1174 	CALLED();
1175 	BAutolock lock(fInputDeviceListLocker);
1176 
1177 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1178 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1179 		if (!item)
1180 			continue;
1181 
1182 		if (item->Matches(name, type)) {
1183 			if (!doStart ^ item->Running())
1184 				return B_ERROR;
1185 
1186 			if (doStart)
1187 				item->Start();
1188 			else
1189 				item->Stop();
1190 
1191 			if (name)
1192 				return B_OK;
1193 		}
1194 	}
1195 
1196 	if (name)
1197 		return B_ERROR;
1198 
1199 	return B_OK;
1200 }
1201 
1202 
1203 
1204 status_t
1205 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart)
1206 {
1207 	CALLED();
1208 	BAutolock lock(fInputDeviceListLocker);
1209 
1210 	InputDeviceListItem* item = _FindInputDeviceListItem(serverDevice);
1211 	if (item != NULL) {
1212 		if (!doStart ^ item->Running())
1213 			return B_ERROR;
1214 
1215 		if (doStart)
1216 			item->Start();
1217 		else
1218 			item->Stop();
1219 	}
1220 	EXIT();
1221 
1222 	return B_OK;
1223 }
1224 
1225 
1226 status_t
1227 InputServer::ControlDevices(const char* name, input_device_type type,
1228 	uint32 code, BMessage* message)
1229 {
1230 	CALLED();
1231 	BAutolock lock(fInputDeviceListLocker);
1232 
1233 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1234 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1235 		if (!item)
1236 			continue;
1237 
1238 		if (item->Matches(name, type)) {
1239 			item->Control(code, message);
1240 
1241 			if (name)
1242 				return B_OK;
1243 		}
1244 	}
1245 
1246 	if (name)
1247 		return B_ERROR;
1248 
1249 	return B_OK;
1250 }
1251 
1252 
1253 bool
1254 InputServer::DoMouseAcceleration(int32* _x, int32* _y)
1255 {
1256 	CALLED();
1257 	int32 speed = fMouseSettings.MouseSpeed() >> 15;
1258 
1259 	// ToDo: implement mouse acceleration
1260 	(void)speed;
1261 	//*_y = *_x * speed;
1262 	PRINT(("DoMouse : %ld %ld %ld %ld\n", *_x, *_y, speed, fMouseSettings.MouseSpeed()));
1263 	return true;
1264 }
1265 
1266 
1267 bool
1268 InputServer::SetMousePos(long *, long *, long, long)
1269 {
1270 	CALLED();
1271 	return true;
1272 }
1273 
1274 
1275 bool
1276 InputServer::SetMousePos(long *, long *, BPoint)
1277 {
1278 	CALLED();
1279 	return true;
1280 }
1281 
1282 
1283 bool
1284 InputServer::SetMousePos(long *, long *, float, float)
1285 {
1286 	CALLED();
1287 	return true;
1288 }
1289 
1290 
1291 bool
1292 InputServer::SafeMode()
1293 {
1294 	return fSafeMode;
1295 }
1296 
1297 
1298 status_t
1299 InputServer::_StartEventLoop()
1300 {
1301 	CALLED();
1302 	fEventLooperPort = create_port(100, "input server events");
1303 	if (fEventLooperPort < 0) {
1304 		PRINTERR(("InputServer: create_port error: (0x%x) %s\n",
1305 			fEventLooperPort, strerror(fEventLooperPort)));
1306 		return fEventLooperPort;
1307 	}
1308 
1309 	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1310 		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1311 	if (thread < B_OK || resume_thread(thread) < B_OK) {
1312 		if (thread >= B_OK)
1313 			kill_thread(thread);
1314 		delete_port(fEventLooperPort);
1315 		fEventLooperPort = -1;
1316 		return thread < B_OK ? thread : B_ERROR;
1317 	}
1318 
1319 	return B_OK;
1320 }
1321 
1322 
1323 status_t
1324 InputServer::_EventLooper(void* arg)
1325 {
1326 	InputServer* self = (InputServer*)arg;
1327 	self->_EventLoop();
1328 
1329 	return B_OK;
1330 }
1331 
1332 
1333 void
1334 InputServer::_EventLoop()
1335 {
1336 	while (true) {
1337 		// Block until we find the size of the next message
1338 		ssize_t length = port_buffer_size(fEventLooperPort);
1339 		if (length < B_OK) {
1340 			PRINT(("[Event Looper] port gone, exiting.\n"));
1341 			return;
1342 		}
1343 
1344 		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1345 
1346 		char buffer[length];
1347 		int32 code;
1348 		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1349 		if (err != length) {
1350 			if (err >= 0) {
1351 				PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length));
1352 			} else {
1353 				PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err)));
1354 			}
1355 			continue;
1356 		}
1357 
1358 		EventList events;
1359 		if (fEventQueueLock.Lock()) {
1360 			// move the items to our own list to block the event queue as short as possible
1361 			events.AddList(&fEventQueue);
1362 			fEventQueue.MakeEmpty();
1363 			fEventQueueLock.Unlock();
1364 		}
1365 
1366 		if (length > 0) {
1367 			BMessage* event = new BMessage;
1368 
1369 			if ((err = event->Unflatten(buffer)) < 0) {
1370 				PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
1371 				delete event;
1372 			}
1373 
1374 			events.AddItem(event);
1375 		}
1376 
1377 		// This is where the message should be processed.
1378 
1379 		if (_SanitizeEvents(events)
1380 			&& _MethodizeEvents(events)
1381 			&& _FilterEvents(events))
1382 			_DispatchEvents(events);
1383 	}
1384 }
1385 
1386 
1387 /*!	Frees events from unwanted fields, adds missing fields, and removes
1388 	unwanted events altogether.
1389 	As a side effect, it will also update the internal mouse states.
1390 */
1391 bool
1392 InputServer::_SanitizeEvents(EventList& events)
1393 {
1394 	CALLED();
1395 	int32 index = 0;
1396 	BMessage *event;
1397 
1398 	while ((event = (BMessage*)events.ItemAt(index)) != NULL) {
1399 		switch (event->what) {
1400 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1401 	   		case IS_SCREEN_BOUNDS_UPDATED:
1402 	   		{
1403 				// This is what the R5 app_server sends us when the screen
1404 				// configuration changes
1405 				BRect frame;
1406 				if (event->FindRect("screen_bounds", &frame) != B_OK)
1407 					frame = fScreen.Frame();
1408 
1409 				if (frame != fFrame) {
1410 					fMousePos.x = fMousePos.x * frame.Width() / fFrame.Width();
1411 					fMousePos.y = fMousePos.y * frame.Height() / fFrame.Height();
1412 					fFrame = frame;
1413 				} else {
1414 					// TODO: discard event
1415 				}
1416 
1417 				event->what = B_MOUSE_MOVED;
1418 				event->AddPoint("where", fMousePos);
1419 				// supposed to fall through
1420 			}
1421 #endif
1422 	   		case B_MOUSE_MOVED:
1423 	   		case B_MOUSE_DOWN:
1424 	   		{
1425 	   			int32 buttons;
1426 	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1427 	   				event->AddInt32("buttons", 0);
1428 
1429 	   			// supposed to fall through
1430 	   		}
1431 	   		case B_MOUSE_UP:
1432 	   		{
1433 	   			BPoint where;
1434 				int32 x, y;
1435 				float absX, absY;
1436 
1437 	    		if (event->FindInt32("x", &x) == B_OK
1438 	    			&& event->FindInt32("y", &y) == B_OK) {
1439 					fMousePos.x += x;
1440 					fMousePos.y -= y;
1441 					fMousePos.ConstrainTo(fFrame);
1442 
1443 					event->RemoveName("x");
1444 					event->RemoveName("y");
1445 					event->AddPoint("where", fMousePos);
1446 					event->AddInt32("be:delta_x", x);
1447 					event->AddInt32("be:delta_y", y);
1448 
1449 					PRINT(("new position: %f, %f, %ld, %ld\n",
1450 						fMousePos.x, fMousePos.y, x, y));
1451 	    		} else if (event->FindFloat("x", &absX) == B_OK
1452 	    			&& event->FindFloat("y", &absY) == B_OK) {
1453 	    			// device gives us absolute screen coords
1454 	    			// in range 0..1
1455 	    			// convert to absolute screen pos
1456 	    			// (the message is supposed to contain the original
1457 	    			// absolute coordinates as "be:tablet_x/y")
1458 		   			fMousePos.x = absX * fFrame.Width();
1459 		   			fMousePos.y = absY * fFrame.Height();
1460 					fMousePos.ConstrainTo(fFrame);
1461 
1462 					event->RemoveName("x");
1463 					event->RemoveName("y");
1464 					event->AddPoint("where", fMousePos);
1465 					PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
1466 		   		} else if (event->FindPoint("where", &where) == B_OK) {
1467 		   			fMousePos = where;
1468 					fMousePos.ConstrainTo(fFrame);
1469 
1470 					event->ReplacePoint("where", fMousePos);
1471 					PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
1472 				}
1473 
1474 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1475 				break;
1476 	   		}
1477 			case B_KEY_DOWN:
1478 			case B_UNMAPPED_KEY_DOWN:
1479 				// update or add modifiers
1480 				uint32 modifiers;
1481 				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1482 					fKeyInfo.modifiers = modifiers;
1483 				else
1484 					event->AddInt32("modifiers", fKeyInfo.modifiers);
1485 
1486 				// update or add key states
1487 				const uint8 *data;
1488 				ssize_t size;
1489 				if (event->FindData("states", B_UINT8_TYPE,
1490 						(const void**)&data, &size) == B_OK) {
1491 					PRINT(("updated keyinfo\n"));
1492 					if (size == sizeof(fKeyInfo.key_states))
1493 						memcpy(fKeyInfo.key_states, data, size);
1494 				} else {
1495 					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1496 						sizeof(fKeyInfo.key_states));
1497 				}
1498 				if (fActiveMethod == NULL)
1499 					break;
1500 
1501 				// we scan for Alt+Space key down events which means we change
1502 				// to next input method
1503 				// (pressing "shift" will let us switch to the previous method)
1504 
1505 				PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers,
1506 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1507 
1508 				int8 byte;
1509 				if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0
1510 					&& event->FindInt8("byte", &byte) == B_OK && byte == ' ') {
1511 					SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY);
1512 
1513 					// this event isn't sent to the user
1514 					events.RemoveItemAt(index);
1515 					delete event;
1516 					continue;
1517 				}
1518 				break;
1519 		}
1520 
1521 		index++;
1522 	}
1523 
1524 	return true;
1525 }
1526 
1527 
1528 /*!	Applies the filters of the active input method to the
1529 	incoming events. It will also move the events in the method
1530 	queue to the event list.
1531 */
1532 bool
1533 InputServer::_MethodizeEvents(EventList& events)
1534 {
1535 	CALLED();
1536 
1537 	if (fActiveMethod == NULL)
1538 		return true;
1539 
1540 	int32 count = events.CountItems();
1541 	for (int32 i = 0; i < count;) {
1542 		_FilterEvent(fActiveMethod, events, i, count);
1543 	}
1544 
1545 	{
1546 		// move the method events into the event queue - they are not
1547 		// "methodized" either
1548 		BAutolock _(fEventQueueLock);
1549 		events.AddList(&fMethodQueue);
1550 		fMethodQueue.MakeEmpty();
1551 	}
1552 
1553 	if (!fInputMethodAware) {
1554 		// special handling for non-input-method-aware views
1555 
1556 		int32 newCount = events.CountItems();
1557 			// we may add new events in this loop that don't need to be checked again
1558 
1559 		for (int32 i = 0; i < newCount; i++) {
1560 			BMessage* event = events.ItemAt(i);
1561 
1562 			if (event->what != B_INPUT_METHOD_EVENT)
1563 				continue;
1564 
1565 			SERIAL_PRINT(("IME received\n"));
1566 
1567 			bool removeEvent = true;
1568 
1569 			int32 opcode;
1570 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1571 				bool inlineOnly;
1572 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1573 					inlineOnly = false;
1574 
1575 				if (inlineOnly) {
1576 					BMessage translated;
1577 					bool confirmed;
1578 					if (opcode == B_INPUT_METHOD_CHANGED
1579 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1580 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1581 						// translate event for the non-aware view
1582 						*event = translated;
1583 						removeEvent = false;
1584 					}
1585 				} else {
1586 					if (fInputMethodWindow == NULL
1587 						&& opcode == B_INPUT_METHOD_STARTED)
1588 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1589 
1590 					if (fInputMethodWindow != NULL) {
1591 						EventList newEvents;
1592 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1593 
1594 						if (!newEvents.IsEmpty()) {
1595 							events.AddList(&newEvents);
1596 							opcode = B_INPUT_METHOD_STOPPED;
1597 						}
1598 
1599 						if (opcode == B_INPUT_METHOD_STOPPED) {
1600 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1601 							fInputMethodWindow = NULL;
1602 						}
1603 					}
1604 				}
1605 			}
1606 
1607 			if (removeEvent) {
1608 				// the inline/bottom window has eaten the event
1609 				events.RemoveItemAt(i--);
1610 				delete event;
1611 				newCount--;
1612 			}
1613 		}
1614 	}
1615 
1616 	return events.CountItems() > 0;
1617 }
1618 
1619 
1620 /*!	This method applies all defined filters to each event in the
1621 	supplied list.  The supplied list is modified to reflect the
1622 	output of the filters.
1623 	The method returns true if the filters were applied to all
1624 	events without error and false otherwise.
1625 */
1626 bool
1627 InputServer::_FilterEvents(EventList& events)
1628 {
1629 	CALLED();
1630 	BAutolock _(gInputFilterListLocker);
1631 
1632 	int32 count = gInputFilterList.CountItems();
1633 	int32 eventCount = events.CountItems();
1634 
1635 	for (int32 i = 0; i < count; i++) {
1636 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1637 
1638 		// Apply the current filter to all available event messages.
1639 
1640 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1641 			_FilterEvent(filter, events, eventIndex, eventCount);
1642 		}
1643 	}
1644 
1645 	return eventCount != 0;
1646 }
1647 
1648 
1649 void
1650 InputServer::_DispatchEvents(EventList& events)
1651 {
1652 	CALLED();
1653 
1654 	int32 count = events.CountItems();
1655 
1656 	for (int32 i = 0; i < count; i++) {
1657 		BMessage* event = events.ItemAt(i);
1658 
1659 		// now we must send each event to the app_server
1660 		_DispatchEvent(event);
1661 		delete event;
1662 	}
1663 
1664 	events.MakeEmpty();
1665 }
1666 
1667 
1668 /*!	Applies the given filter to the event list.
1669 	For your convenience, it also alters the \a index and \a count arguments
1670 	ready for the next call to this method.
1671 */
1672 void
1673 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1674 	int32& index, int32& count)
1675 {
1676 	BMessage* event = events.ItemAt(index);
1677 
1678 	BList newEvents;
1679 	filter_result result = filter->Filter(event, &newEvents);
1680 
1681 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1682 		// we no longer need the current event
1683 		events.RemoveItemAt(index);
1684 		delete event;
1685 
1686 		if (result == B_DISPATCH_MESSAGE) {
1687 			// add the new events - but don't methodize them again
1688 			events.AsBList()->AddList(&newEvents, index);
1689 			index += newEvents.CountItems();
1690 			count = events.CountItems();
1691 		} else
1692 			count--;
1693 	} else
1694 		index++;
1695 }
1696 
1697 
1698 status_t
1699 InputServer::_DispatchEvent(BMessage* event)
1700 {
1701 	CALLED();
1702 
1703    	switch (event->what) {
1704 		case B_MOUSE_MOVED:
1705 		case B_MOUSE_DOWN:
1706 		case B_MOUSE_UP:
1707 			if (fCursorBuffer) {
1708 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1709 				fCursorBuffer[0] = (0x3 << 30L)
1710                		| ((uint32)fMousePos.x & 0x7fff) << 15
1711                		| ((uint32)fMousePos.y & 0x7fff);
1712 
1713 				PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0]));
1714                 	release_sem(fCursorSem);
1715 #else
1716 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1717 					| ((uint32)fMousePos.y & 0xffff));
1718 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1719 					release_sem(fCursorSem);
1720 #endif
1721         	}
1722         	break;
1723 
1724 		case B_KEY_DOWN:
1725 		case B_KEY_UP:
1726 		case B_UNMAPPED_KEY_DOWN:
1727 		case B_UNMAPPED_KEY_UP:
1728 		case B_MODIFIERS_CHANGED:
1729 		{
1730 			// update or add modifiers
1731 			uint32 modifiers;
1732 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1733 				fKeyInfo.modifiers = modifiers;
1734 			else
1735 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1736 
1737 			// update or add key states
1738 			const uint8 *data;
1739 			ssize_t size;
1740 			if (event->FindData("states", B_UINT8_TYPE,
1741 					(const void**)&data, &size) == B_OK) {
1742 				PRINT(("updated keyinfo\n"));
1743 				if (size == sizeof(fKeyInfo.key_states))
1744 					memcpy(fKeyInfo.key_states, data, size);
1745 			} else {
1746 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1747 					sizeof(fKeyInfo.key_states));
1748 			}
1749 
1750 			break;
1751 		}
1752 
1753    		default:
1754 			break;
1755 	}
1756 
1757 #if defined(HAIKU_TARGET_PLATFORM_HAIKU)
1758 	BMessenger reply;
1759 	BMessage::Private messagePrivate(event);
1760 	return messagePrivate.SendMessage(fAppServerPort, -1, 0, true, 0, reply);
1761 #else
1762 	ssize_t length = event->FlattenedSize();
1763 	char buffer[length];
1764 	status_t err;
1765 	if ((err = event->Flatten(buffer,length)) < B_OK)
1766 		return err;
1767 
1768 	return write_port(fAppServerPort, 0, buffer, length);
1769 #endif
1770 }
1771 
1772 
1773 //	#pragma mark -
1774 
1775 
1776 extern "C" void
1777 RegisterDevices(input_device_ref** devices)
1778 {
1779 	CALLED();
1780 }
1781 
1782 
1783 BView *
1784 instantiate_deskbar_item()
1785 {
1786 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1787 }
1788 
1789 
1790 //	#pragma mark -
1791 
1792 
1793 int
1794 main(int /*argc*/, char** /*argv*/)
1795 {
1796 	InputServer	*inputServer = new InputServer;
1797 
1798 	inputServer->Run();
1799 	delete inputServer;
1800 
1801 	return 0;
1802 }
1803 
1804 
1805