xref: /haiku/src/servers/input/InputServer.cpp (revision 0c93c0a807b27096abbfad677436afb7d1712d4a)
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 
1438 	    		if (event->FindInt32("x", &x) == B_OK
1439 	    			&& event->FindInt32("y", &y) == B_OK) {
1440 					fMousePos.x += x;
1441 					fMousePos.y -= y;
1442 					fMousePos.ConstrainTo(fFrame);
1443 
1444 					event->RemoveName("x");
1445 					event->RemoveName("y");
1446 					event->AddPoint("where", fMousePos);
1447 
1448 					PRINT(("new position: %f, %f, %ld, %ld\n",
1449 						fMousePos.x, fMousePos.y, x, y));
1450 		   		} else if (event->FindPoint("where", &where) == B_OK) {
1451 		   			fMousePos = where;
1452 					fMousePos.ConstrainTo(fFrame);
1453 
1454 					event->ReplacePoint("where", fMousePos);
1455 					PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
1456 				}
1457 
1458 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1459 				break;
1460 	   		}
1461 			case B_KEY_DOWN:
1462 			case B_UNMAPPED_KEY_DOWN:
1463 				// update or add modifiers
1464 				uint32 modifiers;
1465 				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1466 					fKeyInfo.modifiers = modifiers;
1467 				else
1468 					event->AddInt32("modifiers", fKeyInfo.modifiers);
1469 
1470 				// update or add key states
1471 				const uint8 *data;
1472 				ssize_t size;
1473 				if (event->FindData("states", B_UINT8_TYPE,
1474 						(const void**)&data, &size) == B_OK) {
1475 					PRINT(("updated keyinfo\n"));
1476 					if (size == sizeof(fKeyInfo.key_states))
1477 						memcpy(fKeyInfo.key_states, data, size);
1478 				} else {
1479 					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1480 						sizeof(fKeyInfo.key_states));
1481 				}
1482 				if (fActiveMethod == NULL)
1483 					break;
1484 
1485 				// we scan for Alt+Space key down events which means we change
1486 				// to next input method
1487 				// (pressing "shift" will let us switch to the previous method)
1488 
1489 				PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers,
1490 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1491 
1492 				int8 byte;
1493 				if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0
1494 					&& event->FindInt8("byte", &byte) == B_OK && byte == ' ') {
1495 					SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY);
1496 
1497 					// this event isn't sent to the user
1498 					events.RemoveItemAt(index);
1499 					delete event;
1500 					continue;
1501 				}
1502 				break;
1503 		}
1504 
1505 		index++;
1506 	}
1507 
1508 	return true;
1509 }
1510 
1511 
1512 /** Applies the filters of the active input method to the
1513  *	incoming events. It will also move the events in the method
1514  *	queue to the event list.
1515  */
1516 
1517 bool
1518 InputServer::_MethodizeEvents(EventList& events)
1519 {
1520 	CALLED();
1521 
1522 	if (fActiveMethod == NULL)
1523 		return true;
1524 
1525 	int32 count = events.CountItems();
1526 	for (int32 i = 0; i < count;) {
1527 		_FilterEvent(fActiveMethod, events, i, count);
1528 	}
1529 
1530 	{
1531 		// move the method events into the event queue - they are not
1532 		// "methodized" either
1533 		BAutolock _(fEventQueueLock);
1534 		events.AddList(&fMethodQueue);
1535 		fMethodQueue.MakeEmpty();
1536 	}
1537 
1538 	if (!fInputMethodAware) {
1539 		// special handling for non-input-method-aware views
1540 
1541 		int32 newCount = events.CountItems();
1542 			// we may add new events in this loop that don't need to be checked again
1543 
1544 		for (int32 i = 0; i < newCount; i++) {
1545 			BMessage* event = events.ItemAt(i);
1546 
1547 			if (event->what != B_INPUT_METHOD_EVENT)
1548 				continue;
1549 
1550 			SERIAL_PRINT(("IME received\n"));
1551 
1552 			bool removeEvent = true;
1553 
1554 			int32 opcode;
1555 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1556 				bool inlineOnly;
1557 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1558 					inlineOnly = false;
1559 
1560 				if (inlineOnly) {
1561 					BMessage translated;
1562 					bool confirmed;
1563 					if (opcode == B_INPUT_METHOD_CHANGED
1564 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1565 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1566 						// translate event for the non-aware view
1567 						*event = translated;
1568 						removeEvent = false;
1569 					}
1570 				} else {
1571 					if (fInputMethodWindow == NULL
1572 						&& opcode == B_INPUT_METHOD_STARTED)
1573 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1574 
1575 					if (fInputMethodWindow != NULL) {
1576 						EventList newEvents;
1577 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1578 
1579 						if (!newEvents.IsEmpty()) {
1580 							events.AddList(&newEvents);
1581 							opcode = B_INPUT_METHOD_STOPPED;
1582 						}
1583 
1584 						if (opcode == B_INPUT_METHOD_STOPPED) {
1585 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1586 							fInputMethodWindow = NULL;
1587 						}
1588 					}
1589 				}
1590 			}
1591 
1592 			if (removeEvent) {
1593 				// the inline/bottom window has eaten the event
1594 				events.RemoveItemAt(i--);
1595 				delete event;
1596 				newCount--;
1597 			}
1598 		}
1599 	}
1600 
1601 	return events.CountItems() > 0;
1602 }
1603 
1604 
1605 /**	This method applies all defined filters to each event in the
1606  *	supplied list.  The supplied list is modified to reflect the
1607  *	output of the filters.
1608  *	The method returns true if the filters were applied to all
1609  *	events without error and false otherwise.
1610  */
1611 
1612 bool
1613 InputServer::_FilterEvents(EventList& events)
1614 {
1615 	CALLED();
1616 	BAutolock _(gInputFilterListLocker);
1617 
1618 	int32 count = gInputFilterList.CountItems();
1619 	int32 eventCount = events.CountItems();
1620 
1621 	for (int32 i = 0; i < count; i++) {
1622 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1623 
1624 		// Apply the current filter to all available event messages.
1625 
1626 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1627 			_FilterEvent(filter, events, eventIndex, eventCount);
1628 		}
1629 	}
1630 
1631 	return eventCount != 0;
1632 }
1633 
1634 
1635 void
1636 InputServer::_DispatchEvents(EventList& events)
1637 {
1638 	CALLED();
1639 
1640 	int32 count = events.CountItems();
1641 
1642 	for (int32 i = 0; i < count; i++) {
1643 		BMessage* event = events.ItemAt(i);
1644 
1645 		// now we must send each event to the app_server
1646 		_DispatchEvent(event);
1647 		delete event;
1648 	}
1649 
1650 	events.MakeEmpty();
1651 }
1652 
1653 
1654 /**	Applies the given filter to the event list.
1655  *	For your convenience, it also alters the \a index and \a count arguments
1656  *	ready for the next call to this method.
1657  */
1658 
1659 void
1660 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1661 	int32& index, int32& count)
1662 {
1663 	BMessage* event = events.ItemAt(index);
1664 
1665 	BList newEvents;
1666 	filter_result result = filter->Filter(event, &newEvents);
1667 
1668 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1669 		// we no longer need the current event
1670 		events.RemoveItemAt(index);
1671 		delete event;
1672 
1673 		if (result == B_DISPATCH_MESSAGE) {
1674 			// add the new events - but don't methodize them again
1675 			events.AsBList()->AddList(&newEvents, index);
1676 			index += newEvents.CountItems();
1677 			count = events.CountItems();
1678 		} else
1679 			count--;
1680 	} else
1681 		index++;
1682 }
1683 
1684 
1685 status_t
1686 InputServer::_DispatchEvent(BMessage* event)
1687 {
1688 	CALLED();
1689 
1690    	switch (event->what) {
1691 		case B_MOUSE_MOVED:
1692 		case B_MOUSE_DOWN:
1693 		case B_MOUSE_UP:
1694 			if (fCursorBuffer) {
1695 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1696 				fCursorBuffer[0] = (0x3 << 30L)
1697                		| ((uint32)fMousePos.x & 0x7fff) << 15
1698                		| ((uint32)fMousePos.y & 0x7fff);
1699 
1700 				PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0]));
1701                 	release_sem(fCursorSem);
1702 #else
1703 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1704 					| ((uint32)fMousePos.y & 0xffff));
1705 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1706 					release_sem(fCursorSem);
1707 #endif
1708         	}
1709         	break;
1710 
1711 		case B_KEY_DOWN:
1712 		case B_KEY_UP:
1713 		case B_UNMAPPED_KEY_DOWN:
1714 		case B_UNMAPPED_KEY_UP:
1715 		case B_MODIFIERS_CHANGED:
1716 		{
1717 			// update or add modifiers
1718 			uint32 modifiers;
1719 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1720 				fKeyInfo.modifiers = modifiers;
1721 			else
1722 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1723 
1724 			// update or add key states
1725 			const uint8 *data;
1726 			ssize_t size;
1727 			if (event->FindData("states", B_UINT8_TYPE,
1728 					(const void**)&data, &size) == B_OK) {
1729 				PRINT(("updated keyinfo\n"));
1730 				if (size == sizeof(fKeyInfo.key_states))
1731 					memcpy(fKeyInfo.key_states, data, size);
1732 			} else {
1733 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1734 					sizeof(fKeyInfo.key_states));
1735 			}
1736 
1737 			break;
1738 		}
1739 
1740    		default:
1741 			break;
1742 	}
1743 
1744 #if defined(HAIKU_TARGET_PLATFORM_HAIKU)
1745 	BMessenger reply;
1746 	BMessage::Private messagePrivate(event);
1747 	return messagePrivate.SendMessage(fAppServerPort, -1, 0, true, 0, reply);
1748 #else
1749 	ssize_t length = event->FlattenedSize();
1750 	char buffer[length];
1751 	status_t err;
1752 	if ((err = event->Flatten(buffer,length)) < B_OK)
1753 		return err;
1754 
1755 	return write_port(fAppServerPort, 0, buffer, length);
1756 #endif
1757 }
1758 
1759 
1760 //	#pragma mark -
1761 
1762 
1763 extern "C" void
1764 RegisterDevices(input_device_ref** devices)
1765 {
1766 	CALLED();
1767 }
1768 
1769 
1770 BView *
1771 instantiate_deskbar_item()
1772 {
1773 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1774 }
1775 
1776 
1777 //	#pragma mark -
1778 
1779 
1780 int
1781 main(int /*argc*/, char** /*argv*/)
1782 {
1783 	InputServer	*inputServer = new InputServer;
1784 
1785 	inputServer->Run();
1786 	delete inputServer;
1787 
1788 	return 0;
1789 }
1790 
1791 
1792