xref: /haiku/src/servers/input/InputServer.cpp (revision b9a5b9a6ee494261f2882bfc0ee9fde92282bef6)
1 /*
2  * Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "InputServer.h"
8 #include "InputServerTypes.h"
9 #include "BottomlineWindow.h"
10 #include "kb_mouse_driver.h"
11 #include "MethodReplicant.h"
12 
13 #include <AppServerLink.h>
14 #include <MessagePrivate.h>
15 
16 #include <Autolock.h>
17 #include <Deskbar.h>
18 #include <Directory.h>
19 #include <Entry.h>
20 #include <File.h>
21 #include <FindDirectory.h>
22 #include <Locker.h>
23 #include <Message.h>
24 #include <OS.h>
25 #include <Path.h>
26 #include <Roster.h>
27 #include <String.h>
28 #include <driver_settings.h>
29 
30 #include <stdio.h>
31 
32 #include "SystemKeymap.h"
33 	// this is an automatically generated file
34 
35 #include <ServerProtocol.h>
36 
37 using std::nothrow;
38 
39 
40 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
41 extern "C" status_t _kern_get_safemode_option(const char *parameter,
42 	char *buffer, size_t *_bufferSize);
43 #else
44 extern "C" status_t _kget_safemode_option_(const char *parameter,
45 	char *buffer, size_t *_bufferSize);
46 #endif
47 
48 
49 // Global InputServer member variables.
50 
51 InputServer* gInputServer;
52 
53 BList InputServer::gInputFilterList;
54 BLocker InputServer::gInputFilterListLocker("is_filter_queue_sem");
55 
56 BList InputServer::gInputMethodList;
57 BLocker InputServer::gInputMethodListLocker("is_method_queue_sem");
58 
59 DeviceManager InputServer::gDeviceManager;
60 
61 KeymapMethod InputServer::gKeymapMethod;
62 
63 #if DEBUG == 2
64 FILE *InputServer::sLogFile = NULL;
65 #endif
66 
67 
68 extern "C" _EXPORT BView* instantiate_deskbar_item();
69 
70 
71 InputDeviceListItem::InputDeviceListItem(BInputServerDevice& serverDevice,
72 	input_device_ref& device)
73 	:
74 	fServerDevice(&serverDevice),
75 	fDevice(device),
76 	fRunning(false)
77 {
78 }
79 
80 
81 void
82 InputDeviceListItem::Start()
83 {
84 	PRINT(("  Starting: %s\n", fDevice.name));
85 	fServerDevice->Start(fDevice.name, fDevice.cookie);
86 	fRunning = true;
87 }
88 
89 
90 void
91 InputDeviceListItem::Stop()
92 {
93 	PRINT(("  Stopping: %s\n", fDevice.name));
94 	fServerDevice->Stop(fDevice.name, fDevice.cookie);
95 	fRunning = false;
96 }
97 
98 
99 void
100 InputDeviceListItem::Control(uint32 code, BMessage* message)
101 {
102 	fServerDevice->Control(fDevice.name, fDevice.cookie, code, message);
103 }
104 
105 
106 bool
107 InputDeviceListItem::HasName(const char* name) const
108 {
109 	if (name == NULL)
110 		return false;
111 
112 	return !strcmp(name, fDevice.name);
113 }
114 
115 
116 bool
117 InputDeviceListItem::HasType(input_device_type type) const
118 {
119 	return type == fDevice.type;
120 }
121 
122 
123 bool
124 InputDeviceListItem::Matches(const char* name, input_device_type type) const
125 {
126 	if (name != NULL)
127 		return HasName(name);
128 
129 	return HasType(type);
130 }
131 
132 
133 //	#pragma mark -
134 
135 
136 InputServer::InputServer()
137 	: BApplication(INPUTSERVER_SIGNATURE),
138 	fSafeMode(false),
139 	fInputDeviceListLocker("input server device list"),
140 	fKeyboardSettings(),
141 	fMouseSettings(),
142 	fChars(NULL),
143 	fScreen(B_MAIN_SCREEN_ID),
144 	fInputMethodWindow(NULL),
145 	fInputMethodAware(false),
146 	fCursorSem(-1),
147 	fAppServerPort(-1),
148 	fCursorArea(-1)
149 {
150 #if DEBUG == 2
151 	if (sLogFile == NULL)
152 		sLogFile = fopen("/var/log/input_server.log", "a");
153 #endif
154 
155 	CALLED();
156 	gInputServer = this;
157 
158 	_StartEventLoop();
159 
160 	char parameter[32];
161 	size_t parameterLength = sizeof(parameter);
162 
163 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
164 	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, &parameterLength) == B_OK)
165 #else
166 	if (_kget_safemode_option_(B_SAFEMODE_SAFE_MODE, parameter, &parameterLength) == B_OK)
167 #endif
168 	{
169 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
170 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
171 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
172 			fSafeMode = true;
173 	}
174 
175 	gDeviceManager.LoadState();
176 
177 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
178 	if (has_data(find_thread(NULL))) {
179 		PRINT(("HasData == YES\n"));
180 		int32 buffer[2];
181 		thread_id appThreadId;
182 		memset(buffer, 0, sizeof(buffer));
183 		int32 code = receive_data(&appThreadId, buffer, sizeof(buffer));
184 		(void)code;	// suppresses warning in non-debug build
185 		PRINT(("tid : %ld, code :%ld\n", appThreadId, code));
186 		for (int32 i = 0; i < 2; i++) {
187 			PRINT(("data : %lx\n", buffer[i]));
188 		}
189 		fCursorSem = buffer[0];
190 		area_id appArea = buffer[1];
191 
192 		fCursorArea = clone_area("isClone", (void**)&fCursorBuffer,
193 			B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, appArea);
194 		if (fCursorArea < B_OK) {
195 			PRINTERR(("clone_area error : %s\n", strerror(fCloneArea)));
196 		}
197 
198 		fAppServerPort = create_port(100, "is_as");
199 
200 		PRINT(("is_as port :%ld\n", fAppServerPort));
201 
202 		buffer[1] = fEventLooperPort;
203 		buffer[0] = fAppServerPort;
204 
205 		status_t err;
206 		if ((err = send_data(appThreadId, 0, buffer, sizeof(buffer)))!=B_OK)
207 			PRINTERR(("error when send_data %s\n", strerror(err)));
208 	}
209 #endif
210 
211 	_InitKeyboardMouseStates();
212 
213 	fAddOnManager = new AddOnManager(SafeMode());
214 	fAddOnManager->LoadState();
215 
216 	BMessenger messenger(this);
217 	BRoster().StartWatching(messenger, B_REQUEST_LAUNCHED);
218 }
219 
220 
221 InputServer::~InputServer()
222 {
223 	CALLED();
224 	fAddOnManager->Lock();
225 	fAddOnManager->Quit();
226 
227 	_ReleaseInput(NULL);
228 
229 #if DEBUG == 2
230 	fclose(sLogFile);
231 #endif
232 }
233 
234 
235 void
236 InputServer::ArgvReceived(int32 argc, char** argv)
237 {
238 	CALLED();
239 	if (2 == argc && (0 == strcmp("-q", argv[1]))) {
240 		PRINT(("InputServer::ArgvReceived - Restarting ...\n"));
241 		status_t quit_status = B_OK;
242 		BMessenger msgr = BMessenger(INPUTSERVER_SIGNATURE, -1, &quit_status);
243 		if (B_OK == quit_status) {
244 			msgr.SendMessage(B_QUIT_REQUESTED);
245 		} else {
246 			PRINTERR(("Unable to send Quit message to running InputServer.\n"));
247 		}
248 	}
249 }
250 
251 
252 void
253 InputServer::_InitKeyboardMouseStates()
254 {
255 	CALLED();
256 	// This is where we determine the screen resolution from the app_server and find the center of the screen
257 	// fMousePos is then set to the center of the screen.
258 
259 	fFrame = fScreen.Frame();
260 	if (fFrame == BRect(0, 0, 0, 0))
261 		fFrame = BRect(0, 0, 800, 600);
262 	fMousePos = BPoint(fFrame.right / 2, fFrame.bottom / 2);
263 
264 	if (_LoadKeymap() != B_OK)
265 		_LoadSystemKeymap();
266 
267 	BMessage msg(B_MOUSE_MOVED);
268 	HandleSetMousePosition(&msg, &msg);
269 
270 	fActiveMethod = &gKeymapMethod;
271 }
272 
273 
274 status_t
275 InputServer::_LoadKeymap()
276 {
277 	BPath path;
278 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
279 		return B_BAD_VALUE;
280 
281 	path.Append("Key_map");
282 
283 	status_t err;
284 
285 	BFile file(path.Path(), B_READ_ONLY);
286 	if ((err = file.InitCheck()) != B_OK)
287 		return err;
288 
289 	if (file.Read(&fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys))
290 		return B_BAD_VALUE;
291 
292 	for (uint32 i = 0; i < sizeof(fKeys)/4; i++)
293 		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
294 
295 	if (file.Read(&fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32))
296 		return B_BAD_VALUE;
297 
298 	fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize);
299 
300 	delete[] fChars;
301 	fChars = new (nothrow) char[fCharsSize];
302 	if (fChars == NULL)
303 		return B_NO_MEMORY;
304 
305 	if (file.Read(fChars, fCharsSize) != (signed)fCharsSize)
306 		return B_BAD_VALUE;
307 
308 	return B_OK;
309 }
310 
311 
312 status_t
313 InputServer::_LoadSystemKeymap()
314 {
315 	delete[] fChars;
316 	fKeys = kSystemKeymap;
317 	fCharsSize = kSystemKeyCharsSize;
318 	fChars = new (nothrow) char[fCharsSize];
319 	if (fChars == NULL)
320 		return B_NO_MEMORY;
321 
322 	memcpy(fChars, kSystemKeyChars, fCharsSize);
323 
324 	// TODO: why are we doing this?
325 	// we save this keymap to file
326 	BPath path;
327 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
328 		return B_BAD_VALUE;
329 
330 	path.Append("Key_map");
331 
332 	BFile file;
333 	status_t err = file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
334 	if (err != B_OK) {
335 		PRINTERR(("error %s\n", strerror(err)));
336 		return err;
337 	}
338 
339 	for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) {
340 		((uint32*)&fKeys)[i] = B_HOST_TO_BENDIAN_INT32(((uint32*)&fKeys)[i]);
341 	}
342 
343 	if ((err = file.Write(&fKeys, sizeof(fKeys))) < (ssize_t)sizeof(fKeys))
344 		return err;
345 
346 	for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) {
347 		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
348 	}
349 
350 	uint32 size = B_HOST_TO_BENDIAN_INT32(fCharsSize);
351 
352 	if ((err = file.Write(&size, sizeof(uint32))) < (ssize_t)sizeof(uint32))
353 		return B_BAD_VALUE;
354 
355 	if ((err = file.Write(fChars, fCharsSize)) < (ssize_t)fCharsSize)
356 		return err;
357 
358 	return B_OK;
359 }
360 
361 
362 bool
363 InputServer::QuitRequested()
364 {
365 	CALLED();
366 	if (!BApplication::QuitRequested())
367 		return false;
368 
369 	PostMessage(SYSTEM_SHUTTING_DOWN);
370 
371 	bool shutdown = false;
372 	CurrentMessage()->FindBool("_shutdown_", &shutdown);
373 
374 	// Don't actually quit when the system is being shutdown
375 	if (shutdown) {
376 		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 B_SOME_APP_LAUNCHED:
589 		{
590 			const char *signature;
591 			// TODO: what's this for?
592 			if (message->FindString("be:signature", &signature)==B_OK) {
593 				PRINT(("input_server : %s\n", signature));
594 				if (strcmp(signature, "application/x-vnd.Be-TSKB")==0) {
595 
596 				}
597 			}
598 			return;
599 		}
600 
601 		default:
602 			return;
603 	}
604 
605 	reply.AddInt32("status", status);
606 	message->SendReply(&reply);
607 }
608 
609 
610 void
611 InputServer::HandleSetMethod(BMessage* message)
612 {
613 	CALLED();
614 	uint32 cookie;
615 	if (message->FindInt32("cookie", (int32*)&cookie) == B_OK) {
616 		BInputServerMethod *method = (BInputServerMethod*)cookie;
617 		PRINT(("%s cookie %p\n", __PRETTY_FUNCTION__, method));
618 		SetActiveMethod(method);
619 	}
620 }
621 
622 
623 status_t
624 InputServer::HandleGetSetMouseType(BMessage* message, BMessage* reply)
625 {
626 	int32 type;
627 	if (message->FindInt32("mouse_type", &type) == B_OK) {
628 		fMouseSettings.SetMouseType(type);
629 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
630 
631 		BMessage msg(IS_CONTROL_DEVICES);
632 		msg.AddInt32("type", B_POINTING_DEVICE);
633 		msg.AddInt32("code", B_MOUSE_TYPE_CHANGED);
634 		return fAddOnManager->PostMessage(&msg);
635 	}
636 
637 	return reply->AddInt32("mouse_type", fMouseSettings.MouseType());
638 }
639 
640 
641 status_t
642 InputServer::HandleGetSetMouseAcceleration(BMessage* message,
643 	BMessage* reply)
644 {
645 	int32 factor;
646 	if (message->FindInt32("speed", &factor) == B_OK) {
647 		fMouseSettings.SetAccelerationFactor(factor);
648 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
649 
650 		BMessage msg(IS_CONTROL_DEVICES);
651 		msg.AddInt32("type", B_POINTING_DEVICE);
652 		msg.AddInt32("code", B_MOUSE_ACCELERATION_CHANGED);
653 		return fAddOnManager->PostMessage(&msg);
654 	}
655 
656 	return reply->AddInt32("speed", fMouseSettings.AccelerationFactor());
657 }
658 
659 
660 status_t
661 InputServer::HandleGetSetKeyRepeatDelay(BMessage* message, BMessage* reply)
662 {
663 	bigtime_t delay;
664 	if (message->FindInt64("delay", &delay) == B_OK) {
665 		fKeyboardSettings.SetKeyboardRepeatDelay(delay);
666 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
667 
668 		BMessage msg(IS_CONTROL_DEVICES);
669 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
670 		msg.AddInt32("code", B_KEY_REPEAT_DELAY_CHANGED);
671 		return fAddOnManager->PostMessage(&msg);
672 	}
673 
674 	return reply->AddInt64("delay", fKeyboardSettings.KeyboardRepeatDelay());
675 }
676 
677 
678 status_t
679 InputServer::HandleGetKeyInfo(BMessage* message, BMessage* reply)
680 {
681 	return reply->AddData("key_info", B_ANY_TYPE, &fKeyInfo, sizeof(fKeyInfo));
682 }
683 
684 
685 status_t
686 InputServer::HandleGetModifiers(BMessage* message, BMessage* reply)
687 {
688 	return reply->AddInt32("modifiers", fKeyInfo.modifiers);
689 }
690 
691 
692 status_t
693 InputServer::HandleSetModifierKey(BMessage* message, BMessage* reply)
694 {
695 	int32 modifier, key;
696 	if (message->FindInt32("modifier", &modifier) == B_OK
697 		&& message->FindInt32("key", &key) == B_OK) {
698 		switch (modifier) {
699 			case B_CAPS_LOCK:
700 				fKeys.caps_key = key;
701 				break;
702 			case B_NUM_LOCK:
703 				fKeys.num_key = key;
704 				break;
705 			case B_SCROLL_LOCK:
706 				fKeys.num_key = key;
707 				break;
708 			case B_LEFT_SHIFT_KEY:
709 				fKeys.left_shift_key = key;
710 				break;
711 			case B_RIGHT_SHIFT_KEY:
712 				fKeys.right_shift_key = key;
713 				break;
714 			case B_LEFT_COMMAND_KEY:
715 				fKeys.left_command_key = key;
716 				break;
717 			case B_RIGHT_COMMAND_KEY:
718 				fKeys.right_command_key = key;
719 				break;
720 			case B_LEFT_CONTROL_KEY:
721 				fKeys.left_control_key = key;
722 				break;
723 			case B_RIGHT_CONTROL_KEY:
724 				fKeys.right_control_key = key;
725 				break;
726 			case B_LEFT_OPTION_KEY:
727 				fKeys.left_option_key = key;
728 				break;
729 			case B_RIGHT_OPTION_KEY:
730 				fKeys.right_option_key = key;
731 				break;
732 			case B_MENU_KEY:
733 				fKeys.menu_key = key;
734 				break;
735 			default:
736 				return B_ERROR;
737 		}
738 
739 		// TODO: unmap the key ?
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 		BMessage msg(IS_CONTROL_DEVICES);
756 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
757 		msg.AddInt32("code", B_KEY_LOCKS_CHANGED);
758 		return fAddOnManager->PostMessage(&msg);
759 	}
760 
761 	return B_ERROR;
762 }
763 
764 
765 status_t
766 InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply)
767 {
768 	int32 speed;
769 	if (message->FindInt32("speed", &speed) == B_OK) {
770 		fMouseSettings.SetMouseSpeed(speed);
771 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
772 
773 		BMessage msg(IS_CONTROL_DEVICES);
774 		msg.AddInt32("type", B_POINTING_DEVICE);
775 		msg.AddInt32("code", B_MOUSE_SPEED_CHANGED);
776 		return fAddOnManager->PostMessage(&msg);
777 	}
778 
779 	return reply->AddInt32("speed", fMouseSettings.MouseSpeed());
780 }
781 
782 
783 status_t
784 InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply)
785 {
786 	CALLED();
787 
788 	BPoint where;
789 	if (message->FindPoint("where", &where) != B_OK)
790 		return B_BAD_VALUE;
791 
792 	// create a new event for this and enqueue it to the event list just like any other
793 
794 	BMessage* event = new BMessage(B_MOUSE_MOVED);
795 	if (event == NULL)
796 		return B_NO_MEMORY;
797 
798 	event->AddPoint("where", where);
799 	event->AddBool("be:set_mouse", true);
800 	if (EnqueueDeviceMessage(event) != B_OK) {
801 		delete event;
802 		return B_NO_MEMORY;
803 	}
804 
805 	return B_OK;
806 }
807 
808 
809 status_t
810 InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply)
811 {
812 	mouse_map *map;
813 	ssize_t size;
814 	if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) {
815 		fMouseSettings.SetMapping(*map);
816 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
817 
818 		BMessage msg(IS_CONTROL_DEVICES);
819 		msg.AddInt32("type", B_POINTING_DEVICE);
820 		msg.AddInt32("code", B_MOUSE_MAP_CHANGED);
821 		return fAddOnManager->PostMessage(&msg);
822 	} else {
823 		mouse_map map;
824 		fMouseSettings.Mapping(map);
825 		return reply->AddData("mousemap", B_RAW_TYPE, &map, sizeof(mouse_map));
826 	}
827 }
828 
829 
830 status_t
831 InputServer::HandleGetKeyboardID(BMessage* message, BMessage* reply)
832 {
833 	return reply->AddInt16("id", fKeyboardID);
834 }
835 
836 
837 status_t
838 InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply)
839 {
840 	bigtime_t clickSpeed;
841 	if (message->FindInt64("speed", &clickSpeed) == B_OK) {
842 		fMouseSettings.SetClickSpeed(clickSpeed);
843 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
844 
845 		BMessage msg(IS_CONTROL_DEVICES);
846 		msg.AddInt32("type", B_POINTING_DEVICE);
847 		msg.AddInt32("code", B_CLICK_SPEED_CHANGED);
848 		return fAddOnManager->PostMessage(&msg);
849 	}
850 
851 	return reply->AddInt64("speed", fMouseSettings.ClickSpeed());
852 }
853 
854 
855 status_t
856 InputServer::HandleGetSetKeyRepeatRate(BMessage* message, BMessage* reply)
857 {
858 	int32 keyRepeatRate;
859 	if (message->FindInt32("rate", &keyRepeatRate) == B_OK) {
860 		fKeyboardSettings.SetKeyboardRepeatRate(keyRepeatRate);
861 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
862 
863 		BMessage msg(IS_CONTROL_DEVICES);
864 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
865 		msg.AddInt32("code", B_KEY_REPEAT_RATE_CHANGED);
866 		return fAddOnManager->PostMessage(&msg);
867 	}
868 
869 	return reply->AddInt32("rate", fKeyboardSettings.KeyboardRepeatRate());
870 }
871 
872 
873 status_t
874 InputServer::HandleGetSetKeyMap(BMessage* message, BMessage* reply)
875 {
876 	CALLED();
877 
878 	if (message->what == IS_GET_KEY_MAP) {
879 		status_t status = reply->AddData("keymap", B_ANY_TYPE, &fKeys, sizeof(fKeys));
880 		if (status == B_OK)
881 			status = reply->AddData("key_buffer", B_ANY_TYPE, fChars, fCharsSize);
882 
883 		return status;
884 	}
885 
886 	if (_LoadKeymap() != B_OK)
887 		_LoadSystemKeymap();
888 
889 	BMessage msg(IS_CONTROL_DEVICES);
890 	msg.AddInt32("type", B_KEYBOARD_DEVICE);
891 	msg.AddInt32("code", B_KEY_MAP_CHANGED);
892 	return fAddOnManager->PostMessage(&msg);
893 }
894 
895 
896 status_t
897 InputServer::HandleFocusUnfocusIMAwareView(BMessage* message,
898 	BMessage* reply)
899 {
900 	CALLED();
901 
902 	BMessenger messenger;
903 	status_t status = message->FindMessenger("view", &messenger);
904 	if (status != B_OK)
905 		return status;
906 
907 	// check if current view is ours
908 
909 	if (message->what == IS_FOCUS_IM_AWARE_VIEW) {
910 		PRINT(("HandleFocusUnfocusIMAwareView : entering\n"));
911 		fInputMethodAware = true;
912 	} else {
913 		PRINT(("HandleFocusUnfocusIMAwareView : leaving\n"));
914 		fInputMethodAware = false;
915 	}
916 
917 	return B_OK;
918 }
919 
920 
921 /**	Enqueues the message into the event queue.
922  *	The message must only be deleted in case this method returns an error.
923  */
924 
925 status_t
926 InputServer::EnqueueDeviceMessage(BMessage* message)
927 {
928 	CALLED();
929 
930 	BAutolock _(fEventQueueLock);
931 	if (!fEventQueue.AddItem(message))
932 		return B_NO_MEMORY;
933 
934 	if (fEventQueue.CountItems() == 1) {
935 		// notify event loop only if we haven't already done so
936 		write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0);
937 	}
938 	return B_OK;
939 }
940 
941 
942 /**	Enqueues the message into the method queue.
943  *	The message must only be deleted in case this method returns an error.
944  */
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 
1035 InputDeviceListItem*
1036 InputServer::_FindInputDeviceListItem(BInputServerDevice& device)
1037 {
1038 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1039 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1040 
1041 		if (item->ServerDevice() == &device)
1042 			return item;
1043 	}
1044 
1045 	return NULL;
1046 }
1047 
1048 
1049 status_t
1050 InputServer::GetDeviceInfo(const char* name, input_device_type *_type,
1051 	bool *_isRunning)
1052 {
1053     BAutolock lock(fInputDeviceListLocker);
1054 
1055 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1056 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1057 
1058 		if (item->HasName(name)) {
1059 			if (_type)
1060 				*_type = item->Type();
1061 			if (_isRunning)
1062 				*_isRunning = item->Running();
1063 
1064 			return B_OK;
1065 		}
1066 	}
1067 
1068 	return B_NAME_NOT_FOUND;
1069 }
1070 
1071 
1072 status_t
1073 InputServer::GetDeviceInfos(BMessage *msg)
1074 {
1075 	CALLED();
1076 	BAutolock lock(fInputDeviceListLocker);
1077 
1078 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1079 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1080 		msg->AddString("device", item->Name());
1081 		msg->AddInt32("type", item->Type());
1082 	}
1083 	return B_OK;
1084 }
1085 
1086 
1087 status_t
1088 InputServer::UnregisterDevices(BInputServerDevice& serverDevice,
1089 	input_device_ref **devices)
1090 {
1091     CALLED();
1092     BAutolock lock(fInputDeviceListLocker);
1093 
1094 	if (devices != NULL) {
1095 		// remove the devices as specified only
1096 		input_device_ref *device = NULL;
1097 		for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1098 			for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1099 				InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1100 
1101 				if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) {
1102 					item->Stop();
1103 					fInputDeviceList.RemoveItem(j);
1104 					delete item;
1105 					break;
1106 				}
1107 			}
1108 		}
1109 	} else {
1110 		// remove all devices from this BInputServerObject
1111 		for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1112 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1113 
1114 			if (item->ServerDevice() == &serverDevice) {
1115 				item->Stop();
1116 				fInputDeviceList.RemoveItem(i);
1117 				delete item;
1118 			}
1119 		}
1120 	}
1121 
1122     return B_OK;
1123 }
1124 
1125 
1126 status_t
1127 InputServer::RegisterDevices(BInputServerDevice& serverDevice,
1128 	input_device_ref** devices)
1129 {
1130 	if (devices == NULL)
1131 		return B_BAD_VALUE;
1132 
1133 	BAutolock lock(fInputDeviceListLocker);
1134 
1135 	input_device_ref *device = NULL;
1136 	for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1137 		if (device->type != B_POINTING_DEVICE
1138 			&& device->type != B_KEYBOARD_DEVICE
1139 			&& device->type != B_UNDEFINED_DEVICE)
1140 			continue;
1141 
1142 		// find existing input server device
1143 
1144 		bool found = false;
1145 		for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1146 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1147 
1148 			if (item->HasName(device->name)) {
1149 				PRINT(("RegisterDevices found %s\n", device->name));
1150 				found = true;
1151 				break;
1152 			}
1153 		}
1154 
1155 		if (!found) {
1156 			PRINT(("RegisterDevices not found %s\n", device->name));
1157 			InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice,
1158 				*device);
1159 			if (item != NULL && fInputDeviceList.AddItem(item)) {
1160 				item->Start();
1161 			} else {
1162 				delete item;
1163 				return B_NO_MEMORY;
1164 			}
1165 		}
1166 	}
1167 
1168 	return B_OK;
1169 }
1170 
1171 
1172 status_t
1173 InputServer::StartStopDevices(const char* name, input_device_type type, bool doStart)
1174 {
1175 	CALLED();
1176 	BAutolock lock(fInputDeviceListLocker);
1177 
1178 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1179 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1180 		if (!item)
1181 			continue;
1182 
1183 		if (item->Matches(name, type)) {
1184 			if (!doStart ^ item->Running())
1185 				return B_ERROR;
1186 
1187 			if (doStart)
1188 				item->Start();
1189 			else
1190 				item->Stop();
1191 
1192 			if (name)
1193 				return B_OK;
1194 		}
1195 	}
1196 
1197 	if (name)
1198 		return B_ERROR;
1199 
1200 	return B_OK;
1201 }
1202 
1203 
1204 
1205 status_t
1206 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart)
1207 {
1208 	CALLED();
1209 	BAutolock lock(fInputDeviceListLocker);
1210 
1211 	InputDeviceListItem* item = _FindInputDeviceListItem(serverDevice);
1212 	if (item != NULL) {
1213 		if (!doStart ^ item->Running())
1214 			return B_ERROR;
1215 
1216 		if (doStart)
1217 			item->Start();
1218 		else
1219 			item->Stop();
1220 	}
1221 	EXIT();
1222 
1223 	return B_OK;
1224 }
1225 
1226 
1227 status_t
1228 InputServer::ControlDevices(const char* name, input_device_type type,
1229 	uint32 code, BMessage* message)
1230 {
1231 	CALLED();
1232 	BAutolock lock(fInputDeviceListLocker);
1233 
1234 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1235 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1236 		if (!item)
1237 			continue;
1238 
1239 		if (item->Matches(name, type)) {
1240 			item->Control(code, message);
1241 
1242 			if (name)
1243 				return B_OK;
1244 		}
1245 	}
1246 
1247 	if (name)
1248 		return B_ERROR;
1249 
1250 	return B_OK;
1251 }
1252 
1253 
1254 bool
1255 InputServer::DoMouseAcceleration(int32* _x, int32* _y)
1256 {
1257 	CALLED();
1258 	int32 speed = fMouseSettings.MouseSpeed() >> 15;
1259 
1260 	// ToDo: implement mouse acceleration
1261 	(void)speed;
1262 	//*_y = *_x * speed;
1263 	PRINT(("DoMouse : %ld %ld %ld %ld\n", *_x, *_y, speed, fMouseSettings.MouseSpeed()));
1264 	return true;
1265 }
1266 
1267 
1268 bool
1269 InputServer::SetMousePos(long *, long *, long, long)
1270 {
1271 	CALLED();
1272 	return true;
1273 }
1274 
1275 
1276 bool
1277 InputServer::SetMousePos(long *, long *, BPoint)
1278 {
1279 	CALLED();
1280 	return true;
1281 }
1282 
1283 
1284 bool
1285 InputServer::SetMousePos(long *, long *, float, float)
1286 {
1287 	CALLED();
1288 	return true;
1289 }
1290 
1291 
1292 bool
1293 InputServer::SafeMode()
1294 {
1295 	return fSafeMode;
1296 }
1297 
1298 
1299 status_t
1300 InputServer::_StartEventLoop()
1301 {
1302 	CALLED();
1303 	fEventLooperPort = create_port(100, "input server events");
1304 	if (fEventLooperPort < 0) {
1305 		PRINTERR(("InputServer: create_port error: (0x%x) %s\n",
1306 			fEventLooperPort, strerror(fEventLooperPort)));
1307 		return fEventLooperPort;
1308 	}
1309 
1310 	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1311 		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1312 	if (thread < B_OK || resume_thread(thread) < B_OK) {
1313 		if (thread >= B_OK)
1314 			kill_thread(thread);
1315 		delete_port(fEventLooperPort);
1316 		fEventLooperPort = -1;
1317 		return thread < B_OK ? thread : B_ERROR;
1318 	}
1319 
1320 	return B_OK;
1321 }
1322 
1323 
1324 status_t
1325 InputServer::_EventLooper(void* arg)
1326 {
1327 	InputServer* self = (InputServer*)arg;
1328 	self->_EventLoop();
1329 
1330 	return B_OK;
1331 }
1332 
1333 
1334 void
1335 InputServer::_EventLoop()
1336 {
1337 	while (true) {
1338 		// Block until we find the size of the next message
1339 		ssize_t length = port_buffer_size(fEventLooperPort);
1340 		if (length < B_OK) {
1341 			PRINT(("[Event Looper] port gone, exiting.\n"));
1342 			return;
1343 		}
1344 
1345 		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1346 
1347 		char buffer[length];
1348 		int32 code;
1349 		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1350 		if (err != length) {
1351 			if (err >= 0) {
1352 				PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length));
1353 			} else {
1354 				PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err)));
1355 			}
1356 			continue;
1357 		}
1358 
1359 		EventList events;
1360 		if (fEventQueueLock.Lock()) {
1361 			// move the items to our own list to block the event queue as short as possible
1362 			events.AddList(&fEventQueue);
1363 			fEventQueue.MakeEmpty();
1364 			fEventQueueLock.Unlock();
1365 		}
1366 
1367 		if (length > 0) {
1368 			BMessage* event = new BMessage;
1369 
1370 			if ((err = event->Unflatten(buffer)) < 0) {
1371 				PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
1372 				delete event;
1373 			}
1374 
1375 			events.AddItem(event);
1376 		}
1377 
1378 		// This is where the message should be processed.
1379 
1380 		if (_SanitizeEvents(events)
1381 			&& _MethodizeEvents(events)
1382 			&& _FilterEvents(events))
1383 			_DispatchEvents(events);
1384 	}
1385 }
1386 
1387 
1388 /** Frees events from unwanted fields, adds missing fields, and removes
1389  *	unwanted events altogether.
1390  *	As a side effect, it will also update the internal mouse states.
1391  */
1392 
1393 bool
1394 InputServer::_SanitizeEvents(EventList& events)
1395 {
1396 	CALLED();
1397 	int32 index = 0;
1398 	BMessage *event;
1399 
1400 	while ((event = (BMessage*)events.ItemAt(index)) != NULL) {
1401 		switch (event->what) {
1402 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1403 	   		case IS_SCREEN_BOUNDS_UPDATED:
1404 	   		{
1405 				// This is what the R5 app_server sends us when the screen
1406 				// configuration changes
1407 				BRect frame;
1408 				if (event->FindRect("screen_bounds", &frame) != B_OK)
1409 					frame = fScreen.Frame();
1410 
1411 				if (frame != fFrame) {
1412 					fMousePos.x = fMousePos.x * frame.Width() / fFrame.Width();
1413 					fMousePos.y = fMousePos.y * frame.Height() / fFrame.Height();
1414 					fFrame = frame;
1415 				} else {
1416 					// TODO: discard event
1417 				}
1418 
1419 				event->what = B_MOUSE_MOVED;
1420 				event->AddPoint("where", fMousePos);
1421 				// supposed to fall through
1422 			}
1423 #endif
1424 	   		case B_MOUSE_MOVED:
1425 	   		case B_MOUSE_DOWN:
1426 	   		{
1427 	   			int32 buttons;
1428 	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1429 	   				event->AddInt32("buttons", 0);
1430 
1431 	   			// supposed to fall through
1432 	   		}
1433 	   		case B_MOUSE_UP:
1434 	   		{
1435 	   			BPoint where;
1436 				int32 x, y;
1437 				float absX, absY;
1438 
1439 	    		if (event->FindInt32("x", &x) == B_OK
1440 	    			&& event->FindInt32("y", &y) == B_OK) {
1441 					fMousePos.x += x;
1442 					fMousePos.y -= y;
1443 					fMousePos.ConstrainTo(fFrame);
1444 
1445 					event->RemoveName("x");
1446 					event->RemoveName("y");
1447 					event->AddPoint("where", fMousePos);
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 
1533 bool
1534 InputServer::_MethodizeEvents(EventList& events)
1535 {
1536 	CALLED();
1537 
1538 	if (fActiveMethod == NULL)
1539 		return true;
1540 
1541 	int32 count = events.CountItems();
1542 	for (int32 i = 0; i < count;) {
1543 		_FilterEvent(fActiveMethod, events, i, count);
1544 	}
1545 
1546 	{
1547 		// move the method events into the event queue - they are not
1548 		// "methodized" either
1549 		BAutolock _(fEventQueueLock);
1550 		events.AddList(&fMethodQueue);
1551 		fMethodQueue.MakeEmpty();
1552 	}
1553 
1554 	if (!fInputMethodAware) {
1555 		// special handling for non-input-method-aware views
1556 
1557 		int32 newCount = events.CountItems();
1558 			// we may add new events in this loop that don't need to be checked again
1559 
1560 		for (int32 i = 0; i < newCount; i++) {
1561 			BMessage* event = events.ItemAt(i);
1562 
1563 			if (event->what != B_INPUT_METHOD_EVENT)
1564 				continue;
1565 
1566 			SERIAL_PRINT(("IME received\n"));
1567 
1568 			bool removeEvent = true;
1569 
1570 			int32 opcode;
1571 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1572 				bool inlineOnly;
1573 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1574 					inlineOnly = false;
1575 
1576 				if (inlineOnly) {
1577 					BMessage translated;
1578 					bool confirmed;
1579 					if (opcode == B_INPUT_METHOD_CHANGED
1580 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1581 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1582 						// translate event for the non-aware view
1583 						*event = translated;
1584 						removeEvent = false;
1585 					}
1586 				} else {
1587 					if (fInputMethodWindow == NULL
1588 						&& opcode == B_INPUT_METHOD_STARTED)
1589 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1590 
1591 					if (fInputMethodWindow != NULL) {
1592 						EventList newEvents;
1593 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1594 
1595 						if (!newEvents.IsEmpty()) {
1596 							events.AddList(&newEvents);
1597 							opcode = B_INPUT_METHOD_STOPPED;
1598 						}
1599 
1600 						if (opcode == B_INPUT_METHOD_STOPPED) {
1601 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1602 							fInputMethodWindow = NULL;
1603 						}
1604 					}
1605 				}
1606 			}
1607 
1608 			if (removeEvent) {
1609 				// the inline/bottom window has eaten the event
1610 				events.RemoveItemAt(i--);
1611 				delete event;
1612 				newCount--;
1613 			}
1614 		}
1615 	}
1616 
1617 	return events.CountItems() > 0;
1618 }
1619 
1620 
1621 /**	This method applies all defined filters to each event in the
1622  *	supplied list.  The supplied list is modified to reflect the
1623  *	output of the filters.
1624  *	The method returns true if the filters were applied to all
1625  *	events without error and false otherwise.
1626  */
1627 
1628 bool
1629 InputServer::_FilterEvents(EventList& events)
1630 {
1631 	CALLED();
1632 	BAutolock _(gInputFilterListLocker);
1633 
1634 	int32 count = gInputFilterList.CountItems();
1635 	int32 eventCount = events.CountItems();
1636 
1637 	for (int32 i = 0; i < count; i++) {
1638 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1639 
1640 		// Apply the current filter to all available event messages.
1641 
1642 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1643 			_FilterEvent(filter, events, eventIndex, eventCount);
1644 		}
1645 	}
1646 
1647 	return eventCount != 0;
1648 }
1649 
1650 
1651 void
1652 InputServer::_DispatchEvents(EventList& events)
1653 {
1654 	CALLED();
1655 
1656 	int32 count = events.CountItems();
1657 
1658 	for (int32 i = 0; i < count; i++) {
1659 		BMessage* event = events.ItemAt(i);
1660 
1661 		// now we must send each event to the app_server
1662 		_DispatchEvent(event);
1663 		delete event;
1664 	}
1665 
1666 	events.MakeEmpty();
1667 }
1668 
1669 
1670 /**	Applies the given filter to the event list.
1671  *	For your convenience, it also alters the \a index and \a count arguments
1672  *	ready for the next call to this method.
1673  */
1674 
1675 void
1676 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1677 	int32& index, int32& count)
1678 {
1679 	BMessage* event = events.ItemAt(index);
1680 
1681 	BList newEvents;
1682 	filter_result result = filter->Filter(event, &newEvents);
1683 
1684 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1685 		// we no longer need the current event
1686 		events.RemoveItemAt(index);
1687 		delete event;
1688 
1689 		if (result == B_DISPATCH_MESSAGE) {
1690 			// add the new events - but don't methodize them again
1691 			events.AsBList()->AddList(&newEvents, index);
1692 			index += newEvents.CountItems();
1693 			count = events.CountItems();
1694 		} else
1695 			count--;
1696 	} else
1697 		index++;
1698 }
1699 
1700 
1701 status_t
1702 InputServer::_DispatchEvent(BMessage* event)
1703 {
1704 	CALLED();
1705 
1706    	switch (event->what) {
1707 		case B_MOUSE_MOVED:
1708 		case B_MOUSE_DOWN:
1709 		case B_MOUSE_UP:
1710 			if (fCursorBuffer) {
1711 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1712 				fCursorBuffer[0] = (0x3 << 30L)
1713                		| ((uint32)fMousePos.x & 0x7fff) << 15
1714                		| ((uint32)fMousePos.y & 0x7fff);
1715 
1716 				PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0]));
1717                 	release_sem(fCursorSem);
1718 #else
1719 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1720 					| ((uint32)fMousePos.y & 0xffff));
1721 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1722 					release_sem(fCursorSem);
1723 #endif
1724         	}
1725         	break;
1726 
1727 		case B_KEY_DOWN:
1728 		case B_KEY_UP:
1729 		case B_UNMAPPED_KEY_DOWN:
1730 		case B_UNMAPPED_KEY_UP:
1731 		case B_MODIFIERS_CHANGED:
1732 		{
1733 			// update or add modifiers
1734 			uint32 modifiers;
1735 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1736 				fKeyInfo.modifiers = modifiers;
1737 			else
1738 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1739 
1740 			// update or add key states
1741 			const uint8 *data;
1742 			ssize_t size;
1743 			if (event->FindData("states", B_UINT8_TYPE,
1744 					(const void**)&data, &size) == B_OK) {
1745 				PRINT(("updated keyinfo\n"));
1746 				if (size == sizeof(fKeyInfo.key_states))
1747 					memcpy(fKeyInfo.key_states, data, size);
1748 			} else {
1749 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1750 					sizeof(fKeyInfo.key_states));
1751 			}
1752 
1753 			break;
1754 		}
1755 
1756    		default:
1757 			break;
1758 	}
1759 
1760 #if defined(HAIKU_TARGET_PLATFORM_HAIKU)
1761 	BMessenger reply;
1762 	BMessage::Private messagePrivate(event);
1763 	return messagePrivate.SendMessage(fAppServerPort, -1, 0, true, 0, reply);
1764 #else
1765 	ssize_t length = event->FlattenedSize();
1766 	char buffer[length];
1767 	status_t err;
1768 	if ((err = event->Flatten(buffer,length)) < B_OK)
1769 		return err;
1770 
1771 	return write_port(fAppServerPort, 0, buffer, length);
1772 #endif
1773 }
1774 
1775 
1776 //	#pragma mark -
1777 
1778 
1779 extern "C" void
1780 RegisterDevices(input_device_ref** devices)
1781 {
1782 	CALLED();
1783 }
1784 
1785 
1786 BView *
1787 instantiate_deskbar_item()
1788 {
1789 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1790 }
1791 
1792 
1793 //	#pragma mark -
1794 
1795 
1796 int
1797 main(int /*argc*/, char** /*argv*/)
1798 {
1799 	InputServer	*inputServer = new InputServer;
1800 
1801 	inputServer->Run();
1802 	delete inputServer;
1803 
1804 	return 0;
1805 }
1806 
1807 
1808