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