xref: /haiku/src/servers/input/InputServer.cpp (revision 19a1dd49cff7ec6a6467cbe2f7006b88931c37d8)
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 			const char *signature;
581 			// TODO: what's this for?
582 			if (message->FindString("be:signature", &signature)==B_OK) {
583 				PRINT(("input_server : %s\n", signature));
584 				if (strcmp(signature, "application/x-vnd.Be-TSKB")==0) {
585 
586 				}
587 			}
588 			return;
589 		}
590 
591 		case kMsgAppServerRestarted:
592 		{
593 			BApplication::MessageReceived(message);
594 			BPrivate::AppServerLink link;
595 			link.StartMessage(AS_REGISTER_INPUT_SERVER);
596 			link.Flush();
597 			return;
598 		}
599 
600 		default:
601 			return;
602 	}
603 
604 	reply.AddInt32("status", status);
605 	message->SendReply(&reply);
606 }
607 
608 
609 void
610 InputServer::HandleSetMethod(BMessage* message)
611 {
612 	CALLED();
613 	int32 cookie;
614 	if (message->FindInt32("cookie", &cookie) != B_OK)
615 		return;
616 	if (cookie == gKeymapMethod.fOwner->Cookie()) {
617 		SetActiveMethod(&gKeymapMethod);
618 	} else {
619 		BAutolock lock(InputServer::gInputMethodListLocker);
620 		for (int32 i = 0; i < gInputMethodList.CountItems(); i++) {
621 			BInputServerMethod* method
622 				= (BInputServerMethod*)InputServer::gInputMethodList.ItemAt(i);
623 			if (method->fOwner->Cookie() == cookie) {
624 				PRINT(("%s cookie %" B_PRId32 "\n", __PRETTY_FUNCTION__,
625 					cookie));
626 				SetActiveMethod(method);
627 				break;
628 			}
629 		}
630 	}
631 }
632 
633 
634 status_t
635 InputServer::HandleGetSetMouseType(BMessage* message, BMessage* reply)
636 {
637 	BString mouseName;
638 	MouseSettings* settings = NULL;
639 	if (message->FindString("mouse_name", &mouseName) == B_OK) {
640 		settings = fMouseSettings.GetMouseSettings(mouseName);
641 		if (settings == NULL)
642 			return B_NAME_NOT_FOUND;
643 	}
644 
645 	int32 type;
646 	if (message->FindInt32("mouse_type", &type) == B_OK) {
647 		if (settings != NULL)
648 			settings->SetMouseType(type);
649 		else {
650 			// TODO if no mouse_name was specified, apply the setting to
651 			// all mouses
652 			return B_NOT_SUPPORTED;
653 		}
654 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
655 
656 		BMessage msg(IS_CONTROL_DEVICES);
657 		msg.AddInt32("type", B_POINTING_DEVICE);
658 		msg.AddInt32("code", B_MOUSE_TYPE_CHANGED);
659 		return fAddOnManager->PostMessage(&msg);
660 	}
661 
662 	if (settings != NULL) {
663 		return reply->AddInt32("mouse_type",
664 			settings->MouseType());
665 	} else {
666 		// TODO return type of the "first" mouse?
667 		return B_NOT_SUPPORTED;
668 	}
669 }
670 
671 
672 status_t
673 InputServer::HandleGetSetMouseAcceleration(BMessage* message,
674 	BMessage* reply)
675 {
676 	BString mouseName;
677 	MouseSettings* settings = NULL;
678 	if (message->FindString("mouse_name", &mouseName) == B_OK) {
679 		settings = fMouseSettings.GetMouseSettings(mouseName);
680 		if (settings == NULL)
681 			return B_NAME_NOT_FOUND;
682 	}
683 
684 	int32 factor;
685 	if (message->FindInt32("speed", &factor) == B_OK) {
686 		if (settings != NULL)
687 			settings->SetAccelerationFactor(factor);
688 		else {
689 			// TODO if no mouse_name was specified, apply the setting to
690 			// all mouses
691 			return B_NOT_SUPPORTED;
692 		}
693 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
694 
695 		BMessage msg(IS_CONTROL_DEVICES);
696 		msg.AddInt32("type", B_POINTING_DEVICE);
697 		msg.AddInt32("code", B_MOUSE_ACCELERATION_CHANGED);
698 		return fAddOnManager->PostMessage(&msg);
699 	}
700 
701 	if (settings != NULL)
702 		return reply->AddInt32("speed", settings->AccelerationFactor());
703 	else {
704 		// TODO return type of the "first" mouse?
705 		return B_NOT_SUPPORTED;
706 	}
707 }
708 
709 
710 status_t
711 InputServer::HandleGetSetKeyRepeatDelay(BMessage* message, BMessage* reply)
712 {
713 	bigtime_t delay;
714 	if (message->FindInt64("delay", &delay) == B_OK) {
715 		fKeyboardSettings.SetKeyboardRepeatDelay(delay);
716 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
717 
718 		BMessage msg(IS_CONTROL_DEVICES);
719 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
720 		msg.AddInt32("code", B_KEY_REPEAT_DELAY_CHANGED);
721 		return fAddOnManager->PostMessage(&msg);
722 	}
723 
724 	return reply->AddInt64("delay", fKeyboardSettings.KeyboardRepeatDelay());
725 }
726 
727 
728 status_t
729 InputServer::HandleGetKeyInfo(BMessage* message, BMessage* reply)
730 {
731 	return reply->AddData("key_info", B_ANY_TYPE, &fKeyInfo, sizeof(fKeyInfo));
732 }
733 
734 
735 status_t
736 InputServer::HandleGetModifiers(BMessage* message, BMessage* reply)
737 {
738 	return reply->AddInt32("modifiers", fKeyInfo.modifiers);
739 }
740 
741 
742 status_t
743 InputServer::HandleGetModifierKey(BMessage* message, BMessage* reply)
744 {
745 	int32 modifier;
746 
747 	if (message->FindInt32("modifier", &modifier) == B_OK) {
748 		switch (modifier) {
749 			case B_CAPS_LOCK:
750 				return reply->AddInt32("key", fKeys.caps_key);
751 			case B_NUM_LOCK:
752 				return reply->AddInt32("key", fKeys.num_key);
753 			case B_SCROLL_LOCK:
754 				return reply->AddInt32("key", fKeys.scroll_key);
755 			case B_LEFT_SHIFT_KEY:
756 				return reply->AddInt32("key", fKeys.left_shift_key);
757 			case B_RIGHT_SHIFT_KEY:
758 				return reply->AddInt32("key", fKeys.right_shift_key);
759 			case B_LEFT_COMMAND_KEY:
760 				return reply->AddInt32("key", fKeys.left_command_key);
761 			case B_RIGHT_COMMAND_KEY:
762 				return reply->AddInt32("key", fKeys.right_command_key);
763 			case B_LEFT_CONTROL_KEY:
764 				return reply->AddInt32("key", fKeys.left_control_key);
765 			case B_RIGHT_CONTROL_KEY:
766 				return reply->AddInt32("key", fKeys.right_control_key);
767 			case B_LEFT_OPTION_KEY:
768 				return reply->AddInt32("key", fKeys.left_option_key);
769 			case B_RIGHT_OPTION_KEY:
770 				return reply->AddInt32("key", fKeys.right_option_key);
771 			case B_MENU_KEY:
772 				return reply->AddInt32("key", fKeys.menu_key);
773 		}
774 	}
775 	return B_ERROR;
776 }
777 
778 
779 status_t
780 InputServer::HandleSetModifierKey(BMessage* message, BMessage* reply)
781 {
782 	int32 modifier, key;
783 	if (message->FindInt32("modifier", &modifier) == B_OK
784 		&& message->FindInt32("key", &key) == B_OK) {
785 		switch (modifier) {
786 			case B_CAPS_LOCK:
787 				fKeys.caps_key = key;
788 				break;
789 			case B_NUM_LOCK:
790 				fKeys.num_key = key;
791 				break;
792 			case B_SCROLL_LOCK:
793 				fKeys.scroll_key = key;
794 				break;
795 			case B_LEFT_SHIFT_KEY:
796 				fKeys.left_shift_key = key;
797 				break;
798 			case B_RIGHT_SHIFT_KEY:
799 				fKeys.right_shift_key = key;
800 				break;
801 			case B_LEFT_COMMAND_KEY:
802 				fKeys.left_command_key = key;
803 				break;
804 			case B_RIGHT_COMMAND_KEY:
805 				fKeys.right_command_key = key;
806 				break;
807 			case B_LEFT_CONTROL_KEY:
808 				fKeys.left_control_key = key;
809 				break;
810 			case B_RIGHT_CONTROL_KEY:
811 				fKeys.right_control_key = key;
812 				break;
813 			case B_LEFT_OPTION_KEY:
814 				fKeys.left_option_key = key;
815 				break;
816 			case B_RIGHT_OPTION_KEY:
817 				fKeys.right_option_key = key;
818 				break;
819 			case B_MENU_KEY:
820 				fKeys.menu_key = key;
821 				break;
822 			default:
823 				return B_ERROR;
824 		}
825 
826 		// TODO: unmap the key ?
827 
828 		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
829 
830 		BMessage msg(IS_CONTROL_DEVICES);
831 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
832 		msg.AddInt32("code", B_KEY_MAP_CHANGED);
833 		return fAddOnManager->PostMessage(&msg);
834 	}
835 
836 	return B_ERROR;
837 }
838 
839 
840 status_t
841 InputServer::HandleSetKeyboardLocks(BMessage* message, BMessage* reply)
842 {
843 	if (message->FindInt32("locks", (int32*)&fKeys.lock_settings) == B_OK) {
844 		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
845 
846 		BMessage msg(IS_CONTROL_DEVICES);
847 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
848 		msg.AddInt32("code", B_KEY_LOCKS_CHANGED);
849 		return fAddOnManager->PostMessage(&msg);
850 	}
851 
852 	return B_ERROR;
853 }
854 
855 
856 // #pragma mark - Mouse settings
857 
858 
859 /** This method does all possible efforts to return some settings.
860  *
861  * The settings will be created if they do not exist. If a mouse name is
862  * specified, the settings for that mouse are created and used. Otherwise,
863  * default settings are returned.
864  */
865 MouseSettings*
866 InputServer::_GetSettingsForMouse(BString mouseName)
867 {
868 	// If no mouse name is specified, use the first one found in settings
869 	if (mouseName == "") {
870 		std::map<BString, MouseSettings*>::iterator itr
871 			= fMouseSettingsObject.begin();
872 		if (itr != fMouseSettingsObject.end())
873 			return itr->second;
874 	}
875 
876 	// If a mouse name is specified or there are no settings yet, get or create
877 	// some
878 	return fMouseSettings.AddMouseSettings(mouseName);
879 }
880 
881 
882 status_t
883 InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply)
884 {
885 	BString mouseName;
886 	message->FindString("mouse_name", &mouseName);
887 
888 	MouseSettings* settings = _GetSettingsForMouse(mouseName);
889 
890 	if (settings == NULL)
891 		return B_NO_MEMORY;
892 
893 	int32 speed;
894 	if (message->FindInt32("speed", &speed) == B_OK) {
895 		settings->SetMouseSpeed(speed);
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_MOUSE_SPEED_CHANGED);
901 		return fAddOnManager->PostMessage(&msg);
902 	}
903 
904 	return reply->AddInt32("speed", settings->MouseSpeed());
905 }
906 
907 
908 status_t
909 InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply)
910 {
911 	BString mouseName;
912 	message->FindString("mouse_name", &mouseName);
913 
914 	MouseSettings* settings = _GetSettingsForMouse(mouseName);
915 	if (settings == NULL)
916 		return B_NO_MEMORY;
917 
918 	mouse_map *map;
919 	ssize_t size;
920 	if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) {
921 		settings->SetMapping(*map);
922 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
923 
924 		BMessage msg(IS_CONTROL_DEVICES);
925 		msg.AddInt32("type", B_POINTING_DEVICE);
926 		msg.AddInt32("code", B_MOUSE_MAP_CHANGED);
927 		return fAddOnManager->PostMessage(&msg);
928 	}
929 
930 	mouse_map getmap;
931 	settings->Mapping(getmap);
932 	return reply->AddData("mousemap", B_RAW_TYPE, &getmap, sizeof(mouse_map));
933 }
934 
935 
936 status_t
937 InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply)
938 {
939 	BString mouseName;
940 	message->FindString("mouse_name", &mouseName);
941 
942 	MouseSettings* settings = _GetSettingsForMouse(mouseName);
943 	if (settings == NULL)
944 		return B_NO_MEMORY;
945 
946 	bigtime_t clickSpeed;
947 	if (message->FindInt64("speed", &clickSpeed) == B_OK) {
948 		settings->SetClickSpeed(clickSpeed);
949 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
950 
951 		BMessage msg(IS_CONTROL_DEVICES);
952 		msg.AddInt32("type", B_POINTING_DEVICE);
953 		msg.AddInt32("code", B_CLICK_SPEED_CHANGED);
954 		return fAddOnManager->PostMessage(&msg);
955 	}
956 
957 	return reply->AddInt64("speed", settings->ClickSpeed());
958 }
959 
960 
961 status_t
962 InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply)
963 {
964 	CALLED();
965 
966 	BPoint where;
967 	if (message->FindPoint("where", &where) != B_OK)
968 		return B_BAD_VALUE;
969 
970 	// create a new event for this and enqueue it to the event list just like any other
971 
972 	BMessage* event = new BMessage(B_MOUSE_MOVED);
973 	if (event == NULL)
974 		return B_NO_MEMORY;
975 
976 	event->AddPoint("where", where);
977 	event->AddBool("be:set_mouse", true);
978 	if (EnqueueDeviceMessage(event) != B_OK) {
979 		delete event;
980 		return B_NO_MEMORY;
981 	}
982 
983 	return B_OK;
984 }
985 
986 
987 // #pragma mark - Keyboard settings
988 
989 
990 status_t
991 InputServer::HandleGetSetKeyboardID(BMessage* message, BMessage* reply)
992 {
993 	int16 id;
994 	if (message->FindInt16("id", &id) == B_OK) {
995 		fKeyboardID = (uint16)id;
996 		return B_OK;
997 	}
998 	return reply->AddInt16("id", fKeyboardID);
999 }
1000 
1001 
1002 status_t
1003 InputServer::HandleGetSetKeyRepeatRate(BMessage* message, BMessage* reply)
1004 {
1005 	int32 keyRepeatRate;
1006 	if (message->FindInt32("rate", &keyRepeatRate) == B_OK) {
1007 		fKeyboardSettings.SetKeyboardRepeatRate(keyRepeatRate);
1008 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
1009 
1010 		BMessage msg(IS_CONTROL_DEVICES);
1011 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
1012 		msg.AddInt32("code", B_KEY_REPEAT_RATE_CHANGED);
1013 		return fAddOnManager->PostMessage(&msg);
1014 	}
1015 
1016 	return reply->AddInt32("rate", fKeyboardSettings.KeyboardRepeatRate());
1017 }
1018 
1019 
1020 status_t
1021 InputServer::HandleGetSetKeyMap(BMessage* message, BMessage* reply)
1022 {
1023 	CALLED();
1024 
1025 	status_t status;
1026 	if (message->what == IS_GET_KEY_MAP) {
1027 		status = reply->AddData("keymap", B_ANY_TYPE, &fKeys, sizeof(fKeys));
1028 		if (status == B_OK)
1029 			status = reply->AddData("key_buffer", B_ANY_TYPE, fChars, fCharsSize);
1030 
1031 		return status;
1032 	}
1033 
1034 	status = _LoadKeymap();
1035 	if (status != B_OK) {
1036 		status = _LoadSystemKeymap();
1037 		if (status != B_OK)
1038 			return status;
1039 	}
1040 
1041 	BMessage msg(IS_CONTROL_DEVICES);
1042 	msg.AddInt32("type", B_KEYBOARD_DEVICE);
1043 	msg.AddInt32("code", B_KEY_MAP_CHANGED);
1044 	status = fAddOnManager->PostMessage(&msg);
1045 
1046 	if (status == B_OK) {
1047 		BMessage appMsg(B_KEY_MAP_LOADED);
1048 		be_roster->Broadcast(&appMsg);
1049 	}
1050 
1051 	return status;
1052 }
1053 
1054 
1055 status_t
1056 InputServer::HandleFocusUnfocusIMAwareView(BMessage* message,
1057 	BMessage* reply)
1058 {
1059 	CALLED();
1060 
1061 	BMessenger messenger;
1062 	status_t status = message->FindMessenger("view", &messenger);
1063 	if (status != B_OK)
1064 		return status;
1065 
1066 	// check if current view is ours
1067 
1068 	if (message->what == IS_FOCUS_IM_AWARE_VIEW) {
1069 		PRINT(("HandleFocusUnfocusIMAwareView : entering\n"));
1070 		fInputMethodAware = true;
1071 	} else {
1072 		PRINT(("HandleFocusUnfocusIMAwareView : leaving\n"));
1073 		fInputMethodAware = false;
1074 	}
1075 
1076 	return B_OK;
1077 }
1078 
1079 
1080 /*!	Enqueues the message into the event queue.
1081 	The message must only be deleted in case this method returns an error.
1082 */
1083 status_t
1084 InputServer::EnqueueDeviceMessage(BMessage* message)
1085 {
1086 	CALLED();
1087 
1088 	BAutolock _(fEventQueueLock);
1089 	if (!fEventQueue.AddItem(message))
1090 		return B_NO_MEMORY;
1091 
1092 	if (fEventQueue.CountItems() == 1) {
1093 		// notify event loop only if we haven't already done so
1094 		write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0);
1095 	}
1096 	return B_OK;
1097 }
1098 
1099 
1100 /*!	Enqueues the message into the method queue.
1101 	The message must only be deleted in case this method returns an error.
1102 */
1103 status_t
1104 InputServer::EnqueueMethodMessage(BMessage* message)
1105 {
1106 	CALLED();
1107 	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__,
1108 		(char)(message->what >> 24), (char)(message->what >> 16),
1109 		(char)(message->what >> 8), (char)message->what));
1110 
1111 #ifdef DEBUG
1112 	if (message->what == 'IMEV') {
1113 		int32 code;
1114 		message->FindInt32("be:opcode", &code);
1115 		PRINT(("%s be:opcode %" B_PRId32 "\n", __PRETTY_FUNCTION__, code));
1116 	}
1117 #endif
1118 
1119 	BAutolock _(fEventQueueLock);
1120 	if (!fMethodQueue.AddItem(message))
1121 		return B_NO_MEMORY;
1122 
1123 	if (fMethodQueue.CountItems() == 1) {
1124 		// notify event loop only if we haven't already done so
1125 		write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
1126 	}
1127 	return B_OK;
1128 }
1129 
1130 
1131 status_t
1132 InputServer::SetNextMethod(bool direction)
1133 {
1134 	gInputMethodListLocker.Lock();
1135 
1136 	int32 index = gInputMethodList.IndexOf(fActiveMethod);
1137 	int32 oldIndex = index;
1138 
1139 	index += (direction ? 1 : -1);
1140 
1141 	if (index < -1)
1142 		index = gInputMethodList.CountItems() - 1;
1143 	if (index >= gInputMethodList.CountItems())
1144 		index = -1;
1145 
1146 	if (index == oldIndex)
1147 		return B_BAD_INDEX;
1148 
1149 	BInputServerMethod *method = &gKeymapMethod;
1150 
1151 	if (index != -1)
1152 		method = (BInputServerMethod *)gInputMethodList.ItemAt(index);
1153 
1154 	SetActiveMethod(method);
1155 
1156 	gInputMethodListLocker.Unlock();
1157 	return B_OK;
1158 }
1159 
1160 
1161 void
1162 InputServer::SetActiveMethod(BInputServerMethod* method)
1163 {
1164 	CALLED();
1165 	if (fActiveMethod)
1166 		fActiveMethod->fOwner->MethodActivated(false);
1167 
1168 	fActiveMethod = method;
1169 
1170 	if (fActiveMethod)
1171 		fActiveMethod->fOwner->MethodActivated(true);
1172 }
1173 
1174 
1175 const BMessenger*
1176 InputServer::MethodReplicant()
1177 {
1178 	return fReplicantMessenger;
1179 }
1180 
1181 
1182 void
1183 InputServer::SetMethodReplicant(const BMessenger* messenger)
1184 {
1185 	fReplicantMessenger = messenger;
1186 }
1187 
1188 
1189 bool
1190 InputServer::EventLoopRunning()
1191 {
1192 	return fEventLooperPort >= B_OK;
1193 }
1194 
1195 
1196 status_t
1197 InputServer::GetDeviceInfo(const char* name, input_device_type *_type,
1198 	bool *_isRunning)
1199 {
1200     BAutolock lock(fInputDeviceListLocker);
1201 
1202 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1203 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1204 
1205 		if (item->HasName(name)) {
1206 			if (_type)
1207 				*_type = item->Type();
1208 			if (_isRunning)
1209 				*_isRunning = item->Running();
1210 
1211 			return B_OK;
1212 		}
1213 	}
1214 
1215 	return B_NAME_NOT_FOUND;
1216 }
1217 
1218 
1219 status_t
1220 InputServer::GetDeviceInfos(BMessage *msg)
1221 {
1222 	CALLED();
1223 	BAutolock lock(fInputDeviceListLocker);
1224 
1225 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1226 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1227 		msg->AddString("device", item->Name());
1228 		msg->AddInt32("type", item->Type());
1229 	}
1230 	return B_OK;
1231 }
1232 
1233 
1234 status_t
1235 InputServer::UnregisterDevices(BInputServerDevice& serverDevice,
1236 	input_device_ref **devices)
1237 {
1238     CALLED();
1239     BAutolock lock(fInputDeviceListLocker);
1240 
1241 	if (devices != NULL) {
1242 		// remove the devices as specified only
1243 		input_device_ref *device = NULL;
1244 		for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1245 			for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1246 				InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1247 
1248 				if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) {
1249 					item->Stop();
1250 					if (fInputDeviceList.RemoveItem(j)) {
1251 						BMessage message(IS_NOTIFY_DEVICE);
1252 						message.AddBool("added", false);
1253 						message.AddString("name", device->name);
1254 						fAddOnManager->PostMessage(&message);
1255 						delete item;
1256 					}
1257 					break;
1258 				}
1259 			}
1260 		}
1261 	} else {
1262 		// remove all devices from this BInputServerObject
1263 		for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1264 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1265 
1266 			if (item->ServerDevice() == &serverDevice) {
1267 				item->Stop();
1268 				if (fInputDeviceList.RemoveItem(i))
1269 					delete item;
1270 			}
1271 		}
1272 	}
1273 
1274     return B_OK;
1275 }
1276 
1277 
1278 status_t
1279 InputServer::RegisterDevices(BInputServerDevice& serverDevice,
1280 	input_device_ref** devices)
1281 {
1282 	if (devices == NULL)
1283 		return B_BAD_VALUE;
1284 
1285 	BAutolock lock(fInputDeviceListLocker);
1286 
1287 	input_device_ref *device = NULL;
1288 	for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1289 		if (device->type != B_POINTING_DEVICE
1290 			&& device->type != B_KEYBOARD_DEVICE
1291 			&& device->type != B_UNDEFINED_DEVICE)
1292 			continue;
1293 
1294 		// find existing input server device
1295 
1296 		bool found = false;
1297 		for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1298 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1299 
1300 			if (item->HasName(device->name)) {
1301 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name);
1302 				PRINT(("RegisterDevices found %s\n", device->name));
1303 				found = true;
1304 				break;
1305 			}
1306 		}
1307 
1308 		if (!found) {
1309 			PRINT(("RegisterDevices not found %s\n", device->name));
1310 			InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice,
1311 				*device);
1312 			if (item != NULL && fInputDeviceList.AddItem(item)) {
1313 				item->Start();
1314 				BMessage message(IS_NOTIFY_DEVICE);
1315 				message.AddBool("added", true);
1316 				message.AddString("name", device->name);
1317 				fAddOnManager->PostMessage(&message);
1318 			} else {
1319 				delete item;
1320 				return B_NO_MEMORY;
1321 			}
1322 		}
1323 	}
1324 
1325 	return B_OK;
1326 }
1327 
1328 
1329 status_t
1330 InputServer::StartStopDevices(const char* name, input_device_type type,
1331 	bool doStart)
1332 {
1333 	CALLED();
1334 	BAutolock lock(fInputDeviceListLocker);
1335 
1336 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1337 		InputDeviceListItem* item
1338 			= (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1339 		if (!item)
1340 			continue;
1341 
1342 		if (item->Matches(name, type)) {
1343 			if (doStart == item->Running()) {
1344 				if (name)
1345 					return B_OK;
1346 				else
1347 					continue;
1348 			}
1349 
1350 			if (doStart)
1351 				item->Start();
1352 			else
1353 				item->Stop();
1354 
1355 			if (name)
1356 				return B_OK;
1357 		}
1358 	}
1359 
1360 	if (name) {
1361 		// item not found
1362 		return B_ERROR;
1363 	}
1364 
1365 	return B_OK;
1366 }
1367 
1368 
1369 
1370 status_t
1371 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart)
1372 {
1373 	CALLED();
1374 	BAutolock lock(fInputDeviceListLocker);
1375 
1376 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1377 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1378 
1379 		if (item->ServerDevice() != &serverDevice)
1380 			continue;
1381 
1382 		if (doStart == item->Running())
1383 			continue;
1384 
1385 		if (doStart)
1386 			item->Start();
1387 		else
1388 			item->Stop();
1389 	}
1390 
1391 	return B_OK;
1392 }
1393 
1394 
1395 status_t
1396 InputServer::ControlDevices(const char* name, input_device_type type,
1397 	uint32 code, BMessage* message)
1398 {
1399 	CALLED();
1400 	BAutolock lock(fInputDeviceListLocker);
1401 
1402 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1403 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1404 		if (!item)
1405 			continue;
1406 
1407 		if (item->Matches(name, type)) {
1408 			item->Control(code, message);
1409 
1410 			if (name)
1411 				return B_OK;
1412 		}
1413 	}
1414 
1415 	if (name)
1416 		return B_ERROR;
1417 
1418 	return B_OK;
1419 }
1420 
1421 
1422 bool
1423 InputServer::SafeMode()
1424 {
1425 	char parameter[32];
1426 	size_t parameterLength = sizeof(parameter);
1427 
1428 	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter,
1429 			&parameterLength) == B_OK) {
1430 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
1431 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
1432 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) {
1433 			return true;
1434 		}
1435 	}
1436 
1437 	if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter,
1438 			&parameterLength) == B_OK) {
1439 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
1440 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
1441 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) {
1442 			return true;
1443 		}
1444 	}
1445 
1446 	return false;
1447 }
1448 
1449 
1450 status_t
1451 InputServer::_StartEventLoop()
1452 {
1453 	CALLED();
1454 	fEventLooperPort = create_port(100, "input server events");
1455 	if (fEventLooperPort < 0) {
1456 		PRINTERR(("InputServer: create_port error: (0x%" B_PRIx32 ") %s\n",
1457 			fEventLooperPort, strerror(fEventLooperPort)));
1458 		return fEventLooperPort;
1459 	}
1460 
1461 	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1462 		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1463 	if (thread < B_OK || resume_thread(thread) < B_OK) {
1464 		if (thread >= B_OK)
1465 			kill_thread(thread);
1466 		delete_port(fEventLooperPort);
1467 		fEventLooperPort = -1;
1468 		return thread < B_OK ? thread : B_ERROR;
1469 	}
1470 
1471 	return B_OK;
1472 }
1473 
1474 
1475 status_t
1476 InputServer::_EventLooper(void* arg)
1477 {
1478 	InputServer* self = (InputServer*)arg;
1479 	self->_EventLoop();
1480 
1481 	return B_OK;
1482 }
1483 
1484 
1485 void
1486 InputServer::_EventLoop()
1487 {
1488 	while (true) {
1489 		// Block until we find the size of the next message
1490 		ssize_t length = port_buffer_size(fEventLooperPort);
1491 		if (length < B_OK) {
1492 			PRINT(("[Event Looper] port gone, exiting.\n"));
1493 			return;
1494 		}
1495 
1496 		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1497 
1498 		char buffer[length];
1499 		int32 code;
1500 		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1501 		if (err != length) {
1502 			if (err >= 0) {
1503 				PRINTERR(("InputServer: failed to read full packet "
1504 					"(read %" B_PRIu32 " of %lu)\n", err, length));
1505 			} else {
1506 				PRINTERR(("InputServer: read_port error: (0x%" B_PRIx32
1507 					") %s\n", err, strerror(err)));
1508 			}
1509 			continue;
1510 		}
1511 
1512 		EventList events;
1513 		if (fEventQueueLock.Lock()) {
1514 			// move the items to our own list to block the event queue as short
1515 			// as possible
1516 			events.AddList(&fEventQueue);
1517 			fEventQueue.MakeEmpty();
1518 			fEventQueueLock.Unlock();
1519 		}
1520 
1521 		if (length > 0) {
1522 			BMessage* event = new BMessage;
1523 
1524 			if ((err = event->Unflatten(buffer)) < 0) {
1525 				PRINTERR(("[InputServer] Unflatten() error: (0x%" B_PRIx32
1526 					") %s\n", err, strerror(err)));
1527 				delete event;
1528 				continue;
1529 			}
1530 
1531 			events.AddItem(event);
1532 		}
1533 
1534 		// This is where the message should be processed.
1535 
1536 		if (_SanitizeEvents(events)
1537 			&& _MethodizeEvents(events)
1538 			&& _FilterEvents(events)) {
1539 			_UpdateMouseAndKeys(events);
1540 			_DispatchEvents(events);
1541 		}
1542 	}
1543 }
1544 
1545 
1546 /*!	Updates the internal mouse position and keyboard info. */
1547 void
1548 InputServer::_UpdateMouseAndKeys(EventList& events)
1549 {
1550 	for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index);
1551 			index++) {
1552 		switch (event->what) {
1553 			case B_MOUSE_DOWN:
1554 			case B_MOUSE_UP:
1555 			case B_MOUSE_MOVED:
1556 				event->FindPoint("where", &fMousePos);
1557 				break;
1558 
1559 			case B_KEY_DOWN:
1560 			case B_UNMAPPED_KEY_DOWN:
1561 				// update modifiers
1562 				uint32 modifiers;
1563 				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1564 					fKeyInfo.modifiers = modifiers;
1565 
1566 				// update key states
1567 				const uint8 *data;
1568 				ssize_t size;
1569 				if (event->FindData("states", B_UINT8_TYPE,
1570 						(const void**)&data, &size) == B_OK) {
1571 					PRINT(("updated keyinfo\n"));
1572 					if (size == sizeof(fKeyInfo.key_states))
1573 						memcpy(fKeyInfo.key_states, data, size);
1574 				}
1575 
1576 				if (fActiveMethod == NULL)
1577 					break;
1578 
1579 				// we scan for Alt+Space key down events which means we change
1580 				// to next input method
1581 				// (pressing "shift" will let us switch to the previous method)
1582 
1583 				// If there is only one input method, SetNextMethod will return
1584 				// B_BAD_INDEX and the event will be forwarded to the user.
1585 
1586 				PRINT(("SanitizeEvents: %" B_PRIx32 ", %x\n", fKeyInfo.modifiers,
1587 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1588 
1589 				uint8 byte;
1590 				if (event->FindInt8("byte", (int8*)&byte) < B_OK)
1591 					byte = 0;
1592 
1593 				if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ')
1594 						|| byte == B_HANKAKU_ZENKAKU)
1595 					&& SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0)
1596 							== B_OK) {
1597 					// this event isn't sent to the user
1598 					events.RemoveItemAt(index);
1599 					delete event;
1600 					continue;
1601 				}
1602 				break;
1603 		}
1604 	}
1605 }
1606 
1607 
1608 /*!	Frees events from unwanted fields, adds missing fields, and removes
1609 	unwanted events altogether.
1610 */
1611 bool
1612 InputServer::_SanitizeEvents(EventList& events)
1613 {
1614 	CALLED();
1615 
1616 	for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index);
1617 			index++) {
1618 		switch (event->what) {
1619 	   		case B_MOUSE_MOVED:
1620 	   		case B_MOUSE_DOWN:
1621 	   		{
1622 	   			int32 buttons;
1623 	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1624 	   				event->AddInt32("buttons", 0);
1625 
1626 	   			// supposed to fall through
1627 	   		}
1628 	   		case B_MOUSE_UP:
1629 	   		{
1630 	   			BPoint where;
1631 				int32 x, y;
1632 				float absX, absY;
1633 
1634 				if (event->FindInt32("x", &x) == B_OK
1635 					&& event->FindInt32("y", &y) == B_OK) {
1636 					where.x = fMousePos.x + x;
1637 					where.y = fMousePos.y - y;
1638 
1639 					event->RemoveName("x");
1640 					event->RemoveName("y");
1641 					event->AddInt32("be:delta_x", x);
1642 					event->AddInt32("be:delta_y", y);
1643 
1644 					PRINT(("new position: %f, %f, %" B_PRId32 ", %" B_PRId32
1645 						"\n", where.x, where.y, x, y));
1646 				} else if (event->FindFloat("x", &absX) == B_OK
1647 					&& event->FindFloat("y", &absY) == B_OK) {
1648 					// The device gives us absolute screen coords in range 0..1;
1649 					// convert them to absolute screen position
1650 					// (the message is supposed to contain the original
1651 					// absolute coordinates as "be:tablet_x/y").
1652 					where.x = absX * fFrame.Width();
1653 					where.y = absY * fFrame.Height();
1654 
1655 					event->RemoveName("x");
1656 					event->RemoveName("y");
1657 					PRINT(("new position : %f, %f\n", where.x, where.y));
1658 				} else if (event->FindPoint("where", &where) == B_OK) {
1659 					PRINT(("new position : %f, %f\n", where.x, where.y));
1660 				}
1661 
1662 				// Constrain and filter the mouse coords and add the final
1663 				// point to the message.
1664 				where.x = roundf(where.x);
1665 				where.y = roundf(where.y);
1666 				where.ConstrainTo(fFrame);
1667 				if (event->ReplacePoint("where", where) != B_OK)
1668 					event->AddPoint("where", where);
1669 
1670 				if (!event->HasInt64("when"))
1671 					event->AddInt64("when", system_time());
1672 
1673 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1674 				break;
1675 	   		}
1676 			case B_KEY_DOWN:
1677 			case B_UNMAPPED_KEY_DOWN:
1678 				// add modifiers
1679 				if (!event->HasInt32("modifiers"))
1680 					event->AddInt32("modifiers", fKeyInfo.modifiers);
1681 
1682 				// add key states
1683 				if (!event->HasData("states", B_UINT8_TYPE)) {
1684 					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1685 						sizeof(fKeyInfo.key_states));
1686 				}
1687 				break;
1688 		}
1689 	}
1690 
1691 	return true;
1692 }
1693 
1694 
1695 /*!	Applies the filters of the active input method to the
1696 	incoming events. It will also move the events in the method
1697 	queue to the event list.
1698 */
1699 bool
1700 InputServer::_MethodizeEvents(EventList& events)
1701 {
1702 	CALLED();
1703 
1704 	if (fActiveMethod == NULL)
1705 		return true;
1706 
1707 	int32 count = events.CountItems();
1708 	for (int32 i = 0; i < count;) {
1709 		_FilterEvent(fActiveMethod, events, i, count);
1710 	}
1711 
1712 	{
1713 		// move the method events into the event queue - they are not
1714 		// "methodized" either
1715 		BAutolock _(fEventQueueLock);
1716 		events.AddList(&fMethodQueue);
1717 		fMethodQueue.MakeEmpty();
1718 	}
1719 
1720 	if (!fInputMethodAware) {
1721 		// special handling for non-input-method-aware views
1722 
1723 		int32 newCount = events.CountItems();
1724 			// we may add new events in this loop that don't need to be checked again
1725 
1726 		for (int32 i = 0; i < newCount; i++) {
1727 			BMessage* event = events.ItemAt(i);
1728 
1729 			if (event->what != B_INPUT_METHOD_EVENT)
1730 				continue;
1731 
1732 			SERIAL_PRINT(("IME received\n"));
1733 
1734 			bool removeEvent = true;
1735 
1736 			int32 opcode;
1737 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1738 				bool inlineOnly;
1739 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1740 					inlineOnly = false;
1741 
1742 				if (inlineOnly) {
1743 					BMessage translated;
1744 					bool confirmed;
1745 					if (opcode == B_INPUT_METHOD_CHANGED
1746 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1747 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1748 						// translate event for the non-aware view
1749 						*event = translated;
1750 						removeEvent = false;
1751 					}
1752 				} else {
1753 					if (fInputMethodWindow == NULL
1754 						&& opcode == B_INPUT_METHOD_STARTED)
1755 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1756 
1757 					if (fInputMethodWindow != NULL) {
1758 						EventList newEvents;
1759 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1760 
1761 						if (!newEvents.IsEmpty()) {
1762 							events.AddList(&newEvents);
1763 							opcode = B_INPUT_METHOD_STOPPED;
1764 						}
1765 
1766 						if (opcode == B_INPUT_METHOD_STOPPED) {
1767 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1768 							fInputMethodWindow = NULL;
1769 						}
1770 					}
1771 				}
1772 			}
1773 
1774 			if (removeEvent) {
1775 				// the inline/bottom window has eaten the event
1776 				events.RemoveItemAt(i--);
1777 				delete event;
1778 				newCount--;
1779 			}
1780 		}
1781 	}
1782 
1783 	return events.CountItems() > 0;
1784 }
1785 
1786 
1787 /*!	This method applies all defined filters to each event in the
1788 	supplied list.  The supplied list is modified to reflect the
1789 	output of the filters.
1790 	The method returns true if the filters were applied to all
1791 	events without error and false otherwise.
1792 */
1793 bool
1794 InputServer::_FilterEvents(EventList& events)
1795 {
1796 	CALLED();
1797 	BAutolock _(gInputFilterListLocker);
1798 
1799 	int32 count = gInputFilterList.CountItems();
1800 	int32 eventCount = events.CountItems();
1801 
1802 	for (int32 i = 0; i < count; i++) {
1803 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1804 
1805 		// Apply the current filter to all available event messages.
1806 
1807 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1808 			_FilterEvent(filter, events, eventIndex, eventCount);
1809 		}
1810 	}
1811 
1812 	return eventCount != 0;
1813 }
1814 
1815 
1816 void
1817 InputServer::_DispatchEvents(EventList& events)
1818 {
1819 	CALLED();
1820 
1821 	int32 count = events.CountItems();
1822 
1823 	for (int32 i = 0; i < count; i++) {
1824 		BMessage* event = events.ItemAt(i);
1825 
1826 		// now we must send each event to the app_server
1827 		_DispatchEvent(event);
1828 		delete event;
1829 	}
1830 
1831 	events.MakeEmpty();
1832 }
1833 
1834 
1835 /*!	Applies the given filter to the event list.
1836 	For your convenience, it also alters the \a index and \a count arguments
1837 	ready for the next call to this method.
1838 */
1839 void
1840 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1841 	int32& index, int32& count)
1842 {
1843 	BMessage* event = events.ItemAt(index);
1844 
1845 	BList newEvents;
1846 	filter_result result = filter->Filter(event, &newEvents);
1847 
1848 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1849 		// we no longer need the current event
1850 		events.RemoveItemAt(index);
1851 		delete event;
1852 
1853 		if (result == B_DISPATCH_MESSAGE) {
1854 			EventList addedEvents;
1855 			EventList::Private(&addedEvents).AsBList()->AddList(&newEvents);
1856 			_SanitizeEvents(addedEvents);
1857 			// add the new events - but don't methodize them again
1858 			events.AddList(&addedEvents, index);
1859 			index += newEvents.CountItems();
1860 			count = events.CountItems();
1861 		} else
1862 			count--;
1863 	} else
1864 		index++;
1865 }
1866 
1867 
1868 status_t
1869 InputServer::_DispatchEvent(BMessage* event)
1870 {
1871 	CALLED();
1872 
1873    	switch (event->what) {
1874 		case B_MOUSE_MOVED:
1875 		case B_MOUSE_DOWN:
1876 		case B_MOUSE_UP:
1877 			if (fCursorBuffer) {
1878 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1879 					| ((uint32)fMousePos.y & 0xffff));
1880 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1881 					release_sem(fCursorSem);
1882         	}
1883         	break;
1884 
1885 		case B_KEY_DOWN:
1886 		case B_KEY_UP:
1887 		case B_UNMAPPED_KEY_DOWN:
1888 		case B_UNMAPPED_KEY_UP:
1889 		case B_MODIFIERS_CHANGED:
1890 		{
1891 			// update or add modifiers
1892 			uint32 modifiers;
1893 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1894 				fKeyInfo.modifiers = modifiers;
1895 			else
1896 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1897 
1898 			// update or add key states
1899 			const uint8 *data;
1900 			ssize_t size;
1901 			if (event->FindData("states", B_UINT8_TYPE,
1902 					(const void**)&data, &size) == B_OK) {
1903 				PRINT(("updated keyinfo\n"));
1904 				if (size == sizeof(fKeyInfo.key_states))
1905 					memcpy(fKeyInfo.key_states, data, size);
1906 			} else {
1907 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1908 					sizeof(fKeyInfo.key_states));
1909 			}
1910 
1911 			break;
1912 		}
1913 
1914    		default:
1915 			break;
1916 	}
1917 
1918 	BMessenger reply;
1919 	BMessage::Private messagePrivate(event);
1920 	return messagePrivate.SendMessage(fAppServerPort, fAppServerTeam, 0, 0,
1921 		false, reply);
1922 }
1923 
1924 
1925 //	#pragma mark -
1926 
1927 
1928 extern "C" void
1929 RegisterDevices(input_device_ref** devices)
1930 {
1931 	CALLED();
1932 }
1933 
1934 
1935 BView *
1936 instantiate_deskbar_item()
1937 {
1938 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1939 }
1940 
1941 
1942 //	#pragma mark -
1943 
1944 
1945 int
1946 main(int /*argc*/, char** /*argv*/)
1947 {
1948 	InputServer	*inputServer = new InputServer;
1949 
1950 	inputServer->Run();
1951 	delete inputServer;
1952 
1953 	return 0;
1954 }
1955