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