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