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