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