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