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