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