xref: /haiku/src/servers/input/InputServer.cpp (revision 4a850ca730d8282b5b924e49e09b4ba4d6db7f54)
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", item->Name());
1254 						message.AddInt32("type", item->Type());
1255 						fAddOnManager->PostMessage(&message);
1256 						delete item;
1257 					}
1258 					break;
1259 				}
1260 			}
1261 		}
1262 	} else {
1263 		// remove all devices from this BInputServerObject
1264 		for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1265 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1266 
1267 			if (item->ServerDevice() == &serverDevice) {
1268 				item->Stop();
1269 				if (fInputDeviceList.RemoveItem(i))
1270 					delete item;
1271 			}
1272 		}
1273 	}
1274 
1275     return B_OK;
1276 }
1277 
1278 
1279 status_t
1280 InputServer::RegisterDevices(BInputServerDevice& serverDevice,
1281 	input_device_ref** devices)
1282 {
1283 	if (devices == NULL)
1284 		return B_BAD_VALUE;
1285 
1286 	BAutolock lock(fInputDeviceListLocker);
1287 
1288 	input_device_ref *device = NULL;
1289 	for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1290 		if (device->type != B_POINTING_DEVICE
1291 			&& device->type != B_KEYBOARD_DEVICE
1292 			&& device->type != B_UNDEFINED_DEVICE)
1293 			continue;
1294 
1295 		// find existing input server device
1296 
1297 		bool found = false;
1298 		for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1299 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1300 
1301 			if (item->HasName(device->name)) {
1302 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name);
1303 				PRINT(("RegisterDevices found %s\n", device->name));
1304 				found = true;
1305 				break;
1306 			}
1307 		}
1308 
1309 		if (!found) {
1310 			PRINT(("RegisterDevices not found %s\n", device->name));
1311 			InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice,
1312 				*device);
1313 			if (item != NULL && fInputDeviceList.AddItem(item)) {
1314 				item->Start();
1315 				BMessage message(IS_NOTIFY_DEVICE);
1316 				message.AddBool("added", true);
1317 				message.AddString("name", item->Name());
1318 				message.AddInt32("type", item->Type());
1319 				fAddOnManager->PostMessage(&message);
1320 			} else {
1321 				delete item;
1322 				return B_NO_MEMORY;
1323 			}
1324 		}
1325 	}
1326 
1327 	return B_OK;
1328 }
1329 
1330 
1331 status_t
1332 InputServer::StartStopDevices(const char* name, input_device_type type,
1333 	bool doStart)
1334 {
1335 	CALLED();
1336 	BAutolock lock(fInputDeviceListLocker);
1337 
1338 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1339 		InputDeviceListItem* item
1340 			= (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1341 		if (!item)
1342 			continue;
1343 
1344 		if (item->Matches(name, type)) {
1345 			if (doStart == item->Running()) {
1346 				if (name)
1347 					return B_OK;
1348 				else
1349 					continue;
1350 			}
1351 
1352 			if (doStart)
1353 				item->Start();
1354 			else
1355 				item->Stop();
1356 
1357 			BMessage message(IS_NOTIFY_DEVICE);
1358 			message.AddBool("started", doStart);
1359 			message.AddString("name", item->Name());
1360 			message.AddInt32("type", item->Type());
1361 			fAddOnManager->PostMessage(&message);
1362 
1363 			if (name)
1364 				return B_OK;
1365 		}
1366 	}
1367 
1368 	if (name) {
1369 		// item not found
1370 		return B_ERROR;
1371 	}
1372 
1373 	return B_OK;
1374 }
1375 
1376 
1377 
1378 status_t
1379 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart)
1380 {
1381 	CALLED();
1382 	BAutolock lock(fInputDeviceListLocker);
1383 
1384 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1385 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1386 
1387 		if (item->ServerDevice() != &serverDevice)
1388 			continue;
1389 
1390 		if (doStart == item->Running())
1391 			continue;
1392 
1393 		if (doStart)
1394 			item->Start();
1395 		else
1396 			item->Stop();
1397 
1398 		BMessage message(IS_NOTIFY_DEVICE);
1399 		message.AddBool("started", doStart);
1400 		message.AddString("name", item->Name());
1401 		message.AddInt32("type", item->Type());
1402 		fAddOnManager->PostMessage(&message);
1403 	}
1404 
1405 	return B_OK;
1406 }
1407 
1408 
1409 status_t
1410 InputServer::ControlDevices(const char* name, input_device_type type,
1411 	uint32 code, BMessage* message)
1412 {
1413 	CALLED();
1414 	BAutolock lock(fInputDeviceListLocker);
1415 
1416 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1417 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1418 		if (!item)
1419 			continue;
1420 
1421 		if (item->Matches(name, type)) {
1422 			item->Control(code, message);
1423 
1424 			if (name)
1425 				return B_OK;
1426 		}
1427 	}
1428 
1429 	if (name)
1430 		return B_ERROR;
1431 
1432 	return B_OK;
1433 }
1434 
1435 
1436 bool
1437 InputServer::SafeMode()
1438 {
1439 	char parameter[32];
1440 	size_t parameterLength = sizeof(parameter);
1441 
1442 	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter,
1443 			&parameterLength) == B_OK) {
1444 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
1445 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
1446 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) {
1447 			return true;
1448 		}
1449 	}
1450 
1451 	if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter,
1452 			&parameterLength) == B_OK) {
1453 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
1454 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
1455 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) {
1456 			return true;
1457 		}
1458 	}
1459 
1460 	return false;
1461 }
1462 
1463 
1464 status_t
1465 InputServer::_StartEventLoop()
1466 {
1467 	CALLED();
1468 	fEventLooperPort = create_port(100, "input server events");
1469 	if (fEventLooperPort < 0) {
1470 		PRINTERR(("InputServer: create_port error: (0x%" B_PRIx32 ") %s\n",
1471 			fEventLooperPort, strerror(fEventLooperPort)));
1472 		return fEventLooperPort;
1473 	}
1474 
1475 	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1476 		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1477 	if (thread < B_OK || resume_thread(thread) < B_OK) {
1478 		if (thread >= B_OK)
1479 			kill_thread(thread);
1480 		delete_port(fEventLooperPort);
1481 		fEventLooperPort = -1;
1482 		return thread < B_OK ? thread : B_ERROR;
1483 	}
1484 
1485 	return B_OK;
1486 }
1487 
1488 
1489 status_t
1490 InputServer::_EventLooper(void* arg)
1491 {
1492 	InputServer* self = (InputServer*)arg;
1493 	self->_EventLoop();
1494 
1495 	return B_OK;
1496 }
1497 
1498 
1499 void
1500 InputServer::_EventLoop()
1501 {
1502 	while (true) {
1503 		// Block until we find the size of the next message
1504 		ssize_t length = port_buffer_size(fEventLooperPort);
1505 		if (length < B_OK) {
1506 			PRINT(("[Event Looper] port gone, exiting.\n"));
1507 			return;
1508 		}
1509 
1510 		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1511 
1512 		char buffer[length];
1513 		int32 code;
1514 		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1515 		if (err != length) {
1516 			if (err >= 0) {
1517 				PRINTERR(("InputServer: failed to read full packet "
1518 					"(read %" B_PRIu32 " of %lu)\n", err, length));
1519 			} else {
1520 				PRINTERR(("InputServer: read_port error: (0x%" B_PRIx32
1521 					") %s\n", err, strerror(err)));
1522 			}
1523 			continue;
1524 		}
1525 
1526 		EventList events;
1527 		if (fEventQueueLock.Lock()) {
1528 			// move the items to our own list to block the event queue as short
1529 			// as possible
1530 			events.AddList(&fEventQueue);
1531 			fEventQueue.MakeEmpty();
1532 			fEventQueueLock.Unlock();
1533 		}
1534 
1535 		if (length > 0) {
1536 			BMessage* event = new BMessage;
1537 
1538 			if ((err = event->Unflatten(buffer)) < 0) {
1539 				PRINTERR(("[InputServer] Unflatten() error: (0x%" B_PRIx32
1540 					") %s\n", err, strerror(err)));
1541 				delete event;
1542 				continue;
1543 			}
1544 
1545 			events.AddItem(event);
1546 		}
1547 
1548 		// This is where the message should be processed.
1549 
1550 		if (_SanitizeEvents(events)
1551 			&& _MethodizeEvents(events)
1552 			&& _FilterEvents(events)) {
1553 			_UpdateMouseAndKeys(events);
1554 			_DispatchEvents(events);
1555 		}
1556 	}
1557 }
1558 
1559 
1560 /*!	Updates the internal mouse position and keyboard info. */
1561 void
1562 InputServer::_UpdateMouseAndKeys(EventList& events)
1563 {
1564 	for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index);
1565 			index++) {
1566 		switch (event->what) {
1567 			case B_MOUSE_DOWN:
1568 			case B_MOUSE_UP:
1569 			case B_MOUSE_MOVED:
1570 				event->FindPoint("where", &fMousePos);
1571 				break;
1572 
1573 			case B_KEY_DOWN:
1574 			case B_UNMAPPED_KEY_DOWN:
1575 				// update modifiers
1576 				uint32 modifiers;
1577 				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1578 					fKeyInfo.modifiers = modifiers;
1579 
1580 				// update key states
1581 				const uint8 *data;
1582 				ssize_t size;
1583 				if (event->FindData("states", B_UINT8_TYPE,
1584 						(const void**)&data, &size) == B_OK) {
1585 					PRINT(("updated keyinfo\n"));
1586 					if (size == sizeof(fKeyInfo.key_states))
1587 						memcpy(fKeyInfo.key_states, data, size);
1588 				}
1589 
1590 				if (fActiveMethod == NULL)
1591 					break;
1592 
1593 				// we scan for Alt+Space key down events which means we change
1594 				// to next input method
1595 				// (pressing "shift" will let us switch to the previous method)
1596 
1597 				// If there is only one input method, SetNextMethod will return
1598 				// B_BAD_INDEX and the event will be forwarded to the user.
1599 
1600 				PRINT(("SanitizeEvents: %" B_PRIx32 ", %x\n", fKeyInfo.modifiers,
1601 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1602 
1603 				uint8 byte;
1604 				if (event->FindInt8("byte", (int8*)&byte) < B_OK)
1605 					byte = 0;
1606 
1607 				if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ')
1608 						|| byte == B_HANKAKU_ZENKAKU)
1609 					&& SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0)
1610 							== B_OK) {
1611 					// this event isn't sent to the user
1612 					events.RemoveItemAt(index);
1613 					delete event;
1614 					continue;
1615 				}
1616 				break;
1617 		}
1618 	}
1619 }
1620 
1621 
1622 /*!	Frees events from unwanted fields, adds missing fields, and removes
1623 	unwanted events altogether.
1624 */
1625 bool
1626 InputServer::_SanitizeEvents(EventList& events)
1627 {
1628 	CALLED();
1629 
1630 	for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index);
1631 			index++) {
1632 		switch (event->what) {
1633 	   		case B_MOUSE_MOVED:
1634 	   		case B_MOUSE_DOWN:
1635 	   		{
1636 	   			int32 buttons;
1637 	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1638 	   				event->AddInt32("buttons", 0);
1639 
1640 	   			// supposed to fall through
1641 	   		}
1642 	   		case B_MOUSE_UP:
1643 	   		{
1644 	   			BPoint where;
1645 				int32 x, y;
1646 				float absX, absY;
1647 
1648 				if (event->FindInt32("x", &x) == B_OK
1649 					&& event->FindInt32("y", &y) == B_OK) {
1650 					where.x = fMousePos.x + x;
1651 					where.y = fMousePos.y - y;
1652 
1653 					event->RemoveName("x");
1654 					event->RemoveName("y");
1655 					event->AddInt32("be:delta_x", x);
1656 					event->AddInt32("be:delta_y", y);
1657 
1658 					PRINT(("new position: %f, %f, %" B_PRId32 ", %" B_PRId32
1659 						"\n", where.x, where.y, x, y));
1660 				} else if (event->FindFloat("x", &absX) == B_OK
1661 					&& event->FindFloat("y", &absY) == B_OK) {
1662 					// The device gives us absolute screen coords in range 0..1;
1663 					// convert them to absolute screen position
1664 					// (the message is supposed to contain the original
1665 					// absolute coordinates as "be:tablet_x/y").
1666 					where.x = absX * fFrame.Width();
1667 					where.y = absY * fFrame.Height();
1668 
1669 					event->RemoveName("x");
1670 					event->RemoveName("y");
1671 					PRINT(("new position : %f, %f\n", where.x, where.y));
1672 				} else if (event->FindPoint("where", &where) == B_OK) {
1673 					PRINT(("new position : %f, %f\n", where.x, where.y));
1674 				}
1675 
1676 				// Constrain and filter the mouse coords and add the final
1677 				// point to the message.
1678 				where.x = roundf(where.x);
1679 				where.y = roundf(where.y);
1680 				where.ConstrainTo(fFrame);
1681 				if (event->ReplacePoint("where", where) != B_OK)
1682 					event->AddPoint("where", where);
1683 
1684 				if (!event->HasInt64("when"))
1685 					event->AddInt64("when", system_time());
1686 
1687 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1688 				break;
1689 	   		}
1690 			case B_KEY_DOWN:
1691 			case B_UNMAPPED_KEY_DOWN:
1692 				// add modifiers
1693 				if (!event->HasInt32("modifiers"))
1694 					event->AddInt32("modifiers", fKeyInfo.modifiers);
1695 
1696 				// add key states
1697 				if (!event->HasData("states", B_UINT8_TYPE)) {
1698 					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1699 						sizeof(fKeyInfo.key_states));
1700 				}
1701 				break;
1702 		}
1703 	}
1704 
1705 	return true;
1706 }
1707 
1708 
1709 /*!	Applies the filters of the active input method to the
1710 	incoming events. It will also move the events in the method
1711 	queue to the event list.
1712 */
1713 bool
1714 InputServer::_MethodizeEvents(EventList& events)
1715 {
1716 	CALLED();
1717 
1718 	if (fActiveMethod == NULL)
1719 		return true;
1720 
1721 	int32 count = events.CountItems();
1722 	for (int32 i = 0; i < count;) {
1723 		_FilterEvent(fActiveMethod, events, i, count);
1724 	}
1725 
1726 	{
1727 		// move the method events into the event queue - they are not
1728 		// "methodized" either
1729 		BAutolock _(fEventQueueLock);
1730 		events.AddList(&fMethodQueue);
1731 		fMethodQueue.MakeEmpty();
1732 	}
1733 
1734 	if (!fInputMethodAware) {
1735 		// special handling for non-input-method-aware views
1736 
1737 		int32 newCount = events.CountItems();
1738 			// we may add new events in this loop that don't need to be checked again
1739 
1740 		for (int32 i = 0; i < newCount; i++) {
1741 			BMessage* event = events.ItemAt(i);
1742 
1743 			if (event->what != B_INPUT_METHOD_EVENT)
1744 				continue;
1745 
1746 			SERIAL_PRINT(("IME received\n"));
1747 
1748 			bool removeEvent = true;
1749 
1750 			int32 opcode;
1751 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1752 				bool inlineOnly;
1753 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1754 					inlineOnly = false;
1755 
1756 				if (inlineOnly) {
1757 					BMessage translated;
1758 					bool confirmed;
1759 					if (opcode == B_INPUT_METHOD_CHANGED
1760 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1761 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1762 						// translate event for the non-aware view
1763 						*event = translated;
1764 						removeEvent = false;
1765 					}
1766 				} else {
1767 					if (fInputMethodWindow == NULL
1768 						&& opcode == B_INPUT_METHOD_STARTED)
1769 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1770 
1771 					if (fInputMethodWindow != NULL) {
1772 						EventList newEvents;
1773 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1774 
1775 						if (!newEvents.IsEmpty()) {
1776 							events.AddList(&newEvents);
1777 							opcode = B_INPUT_METHOD_STOPPED;
1778 						}
1779 
1780 						if (opcode == B_INPUT_METHOD_STOPPED) {
1781 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1782 							fInputMethodWindow = NULL;
1783 						}
1784 					}
1785 				}
1786 			}
1787 
1788 			if (removeEvent) {
1789 				// the inline/bottom window has eaten the event
1790 				events.RemoveItemAt(i--);
1791 				delete event;
1792 				newCount--;
1793 			}
1794 		}
1795 	}
1796 
1797 	return events.CountItems() > 0;
1798 }
1799 
1800 
1801 /*!	This method applies all defined filters to each event in the
1802 	supplied list.  The supplied list is modified to reflect the
1803 	output of the filters.
1804 	The method returns true if the filters were applied to all
1805 	events without error and false otherwise.
1806 */
1807 bool
1808 InputServer::_FilterEvents(EventList& events)
1809 {
1810 	CALLED();
1811 	BAutolock _(gInputFilterListLocker);
1812 
1813 	int32 count = gInputFilterList.CountItems();
1814 	int32 eventCount = events.CountItems();
1815 
1816 	for (int32 i = 0; i < count; i++) {
1817 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1818 
1819 		// Apply the current filter to all available event messages.
1820 
1821 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1822 			_FilterEvent(filter, events, eventIndex, eventCount);
1823 		}
1824 	}
1825 
1826 	return eventCount != 0;
1827 }
1828 
1829 
1830 void
1831 InputServer::_DispatchEvents(EventList& events)
1832 {
1833 	CALLED();
1834 
1835 	int32 count = events.CountItems();
1836 
1837 	for (int32 i = 0; i < count; i++) {
1838 		BMessage* event = events.ItemAt(i);
1839 
1840 		// now we must send each event to the app_server
1841 		_DispatchEvent(event);
1842 		delete event;
1843 	}
1844 
1845 	events.MakeEmpty();
1846 }
1847 
1848 
1849 /*!	Applies the given filter to the event list.
1850 	For your convenience, it also alters the \a index and \a count arguments
1851 	ready for the next call to this method.
1852 */
1853 void
1854 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1855 	int32& index, int32& count)
1856 {
1857 	BMessage* event = events.ItemAt(index);
1858 
1859 	BList newEvents;
1860 	filter_result result = filter->Filter(event, &newEvents);
1861 
1862 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1863 		// we no longer need the current event
1864 		events.RemoveItemAt(index);
1865 		delete event;
1866 
1867 		if (result == B_DISPATCH_MESSAGE) {
1868 			EventList addedEvents;
1869 			EventList::Private(&addedEvents).AsBList()->AddList(&newEvents);
1870 			_SanitizeEvents(addedEvents);
1871 			// add the new events - but don't methodize them again
1872 			events.AddList(&addedEvents, index);
1873 			index += newEvents.CountItems();
1874 			count = events.CountItems();
1875 		} else
1876 			count--;
1877 	} else
1878 		index++;
1879 }
1880 
1881 
1882 status_t
1883 InputServer::_DispatchEvent(BMessage* event)
1884 {
1885 	CALLED();
1886 
1887    	switch (event->what) {
1888 		case B_MOUSE_MOVED:
1889 		case B_MOUSE_DOWN:
1890 		case B_MOUSE_UP:
1891 			if (fCursorBuffer) {
1892 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1893 					| ((uint32)fMousePos.y & 0xffff));
1894 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1895 					release_sem(fCursorSem);
1896         	}
1897         	break;
1898 
1899 		case B_KEY_DOWN:
1900 		case B_KEY_UP:
1901 		case B_UNMAPPED_KEY_DOWN:
1902 		case B_UNMAPPED_KEY_UP:
1903 		case B_MODIFIERS_CHANGED:
1904 		{
1905 			// update or add modifiers
1906 			uint32 modifiers;
1907 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1908 				fKeyInfo.modifiers = modifiers;
1909 			else
1910 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1911 
1912 			// update or add key states
1913 			const uint8 *data;
1914 			ssize_t size;
1915 			if (event->FindData("states", B_UINT8_TYPE,
1916 					(const void**)&data, &size) == B_OK) {
1917 				PRINT(("updated keyinfo\n"));
1918 				if (size == sizeof(fKeyInfo.key_states))
1919 					memcpy(fKeyInfo.key_states, data, size);
1920 			} else {
1921 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1922 					sizeof(fKeyInfo.key_states));
1923 			}
1924 
1925 			break;
1926 		}
1927 
1928    		default:
1929 			break;
1930 	}
1931 
1932 	BMessenger reply;
1933 	BMessage::Private messagePrivate(event);
1934 	return messagePrivate.SendMessage(fAppServerPort, fAppServerTeam, 0, 0,
1935 		false, reply);
1936 }
1937 
1938 
1939 //	#pragma mark -
1940 
1941 
1942 extern "C" void
1943 RegisterDevices(input_device_ref** devices)
1944 {
1945 	CALLED();
1946 }
1947 
1948 
1949 BView *
1950 instantiate_deskbar_item()
1951 {
1952 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1953 }
1954 
1955 
1956 //	#pragma mark -
1957 
1958 
1959 int
1960 main(int /*argc*/, char** /*argv*/)
1961 {
1962 	InputServer	*inputServer = new InputServer;
1963 
1964 	inputServer->Run();
1965 	delete inputServer;
1966 
1967 	return 0;
1968 }
1969