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