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