xref: /haiku/src/servers/input/InputServer.cpp (revision 40e20c10768c3dcfc54074b8886e3e91455332e1)
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 	uint32 cookie;
629 	if (message->FindInt32("cookie", (int32*)&cookie) == B_OK) {
630 		BInputServerMethod *method = (BInputServerMethod*)cookie;
631 		PRINT(("%s cookie %p\n", __PRETTY_FUNCTION__, method));
632 		SetActiveMethod(method);
633 	}
634 }
635 
636 
637 status_t
638 InputServer::HandleGetSetMouseType(BMessage* message, BMessage* reply)
639 {
640 	int32 type;
641 	if (message->FindInt32("mouse_type", &type) == B_OK) {
642 		fMouseSettings.SetMouseType(type);
643 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
644 
645 		BMessage msg(IS_CONTROL_DEVICES);
646 		msg.AddInt32("type", B_POINTING_DEVICE);
647 		msg.AddInt32("code", B_MOUSE_TYPE_CHANGED);
648 		return fAddOnManager->PostMessage(&msg);
649 	}
650 
651 	return reply->AddInt32("mouse_type", fMouseSettings.MouseType());
652 }
653 
654 
655 status_t
656 InputServer::HandleGetSetMouseAcceleration(BMessage* message,
657 	BMessage* reply)
658 {
659 	int32 factor;
660 	if (message->FindInt32("speed", &factor) == B_OK) {
661 		fMouseSettings.SetAccelerationFactor(factor);
662 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
663 
664 		BMessage msg(IS_CONTROL_DEVICES);
665 		msg.AddInt32("type", B_POINTING_DEVICE);
666 		msg.AddInt32("code", B_MOUSE_ACCELERATION_CHANGED);
667 		return fAddOnManager->PostMessage(&msg);
668 	}
669 
670 	return reply->AddInt32("speed", fMouseSettings.AccelerationFactor());
671 }
672 
673 
674 status_t
675 InputServer::HandleGetSetKeyRepeatDelay(BMessage* message, BMessage* reply)
676 {
677 	bigtime_t delay;
678 	if (message->FindInt64("delay", &delay) == B_OK) {
679 		fKeyboardSettings.SetKeyboardRepeatDelay(delay);
680 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
681 
682 		BMessage msg(IS_CONTROL_DEVICES);
683 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
684 		msg.AddInt32("code", B_KEY_REPEAT_DELAY_CHANGED);
685 		return fAddOnManager->PostMessage(&msg);
686 	}
687 
688 	return reply->AddInt64("delay", fKeyboardSettings.KeyboardRepeatDelay());
689 }
690 
691 
692 status_t
693 InputServer::HandleGetKeyInfo(BMessage* message, BMessage* reply)
694 {
695 	return reply->AddData("key_info", B_ANY_TYPE, &fKeyInfo, sizeof(fKeyInfo));
696 }
697 
698 
699 status_t
700 InputServer::HandleGetModifiers(BMessage* message, BMessage* reply)
701 {
702 	return reply->AddInt32("modifiers", fKeyInfo.modifiers);
703 }
704 
705 
706 status_t
707 InputServer::HandleGetModifierKey(BMessage* message, BMessage* reply)
708 {
709 	int32 modifier;
710 
711 	if (message->FindInt32("modifier", &modifier) == B_OK) {
712 		switch (modifier) {
713 			case B_CAPS_LOCK:
714 				return reply->AddInt32("key", fKeys.caps_key);
715 			case B_NUM_LOCK:
716 				return reply->AddInt32("key", fKeys.num_key);
717 			case B_SCROLL_LOCK:
718 				return reply->AddInt32("key", fKeys.scroll_key);
719 			case B_LEFT_SHIFT_KEY:
720 				return reply->AddInt32("key", fKeys.left_shift_key);
721 			case B_RIGHT_SHIFT_KEY:
722 				return reply->AddInt32("key", fKeys.right_shift_key);
723 			case B_LEFT_COMMAND_KEY:
724 				return reply->AddInt32("key", fKeys.left_command_key);
725 			case B_RIGHT_COMMAND_KEY:
726 				return reply->AddInt32("key", fKeys.right_command_key);
727 			case B_LEFT_CONTROL_KEY:
728 				return reply->AddInt32("key", fKeys.left_control_key);
729 			case B_RIGHT_CONTROL_KEY:
730 				return reply->AddInt32("key", fKeys.right_control_key);
731 			case B_LEFT_OPTION_KEY:
732 				return reply->AddInt32("key", fKeys.left_option_key);
733 			case B_RIGHT_OPTION_KEY:
734 				return reply->AddInt32("key", fKeys.right_option_key);
735 			case B_MENU_KEY:
736 				return reply->AddInt32("key", fKeys.menu_key);
737 		}
738 	}
739 	return B_ERROR;
740 }
741 
742 
743 status_t
744 InputServer::HandleSetModifierKey(BMessage* message, BMessage* reply)
745 {
746 	int32 modifier, key;
747 	if (message->FindInt32("modifier", &modifier) == B_OK
748 		&& message->FindInt32("key", &key) == B_OK) {
749 		switch (modifier) {
750 			case B_CAPS_LOCK:
751 				fKeys.caps_key = key;
752 				break;
753 			case B_NUM_LOCK:
754 				fKeys.num_key = key;
755 				break;
756 			case B_SCROLL_LOCK:
757 				fKeys.scroll_key = key;
758 				break;
759 			case B_LEFT_SHIFT_KEY:
760 				fKeys.left_shift_key = key;
761 				break;
762 			case B_RIGHT_SHIFT_KEY:
763 				fKeys.right_shift_key = key;
764 				break;
765 			case B_LEFT_COMMAND_KEY:
766 				fKeys.left_command_key = key;
767 				break;
768 			case B_RIGHT_COMMAND_KEY:
769 				fKeys.right_command_key = key;
770 				break;
771 			case B_LEFT_CONTROL_KEY:
772 				fKeys.left_control_key = key;
773 				break;
774 			case B_RIGHT_CONTROL_KEY:
775 				fKeys.right_control_key = key;
776 				break;
777 			case B_LEFT_OPTION_KEY:
778 				fKeys.left_option_key = key;
779 				break;
780 			case B_RIGHT_OPTION_KEY:
781 				fKeys.right_option_key = key;
782 				break;
783 			case B_MENU_KEY:
784 				fKeys.menu_key = key;
785 				break;
786 			default:
787 				return B_ERROR;
788 		}
789 
790 		// TODO: unmap the key ?
791 
792 		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
793 
794 		BMessage msg(IS_CONTROL_DEVICES);
795 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
796 		msg.AddInt32("code", B_KEY_MAP_CHANGED);
797 		return fAddOnManager->PostMessage(&msg);
798 	}
799 
800 	return B_ERROR;
801 }
802 
803 
804 status_t
805 InputServer::HandleSetKeyboardLocks(BMessage* message, BMessage* reply)
806 {
807 	if (message->FindInt32("locks", (int32*)&fKeys.lock_settings) == B_OK) {
808 		be_app_messenger.SendMessage(IS_SAVE_KEYMAP);
809 
810 		BMessage msg(IS_CONTROL_DEVICES);
811 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
812 		msg.AddInt32("code", B_KEY_LOCKS_CHANGED);
813 		return fAddOnManager->PostMessage(&msg);
814 	}
815 
816 	return B_ERROR;
817 }
818 
819 
820 status_t
821 InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply)
822 {
823 	int32 speed;
824 	if (message->FindInt32("speed", &speed) == B_OK) {
825 		fMouseSettings.SetMouseSpeed(speed);
826 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
827 
828 		BMessage msg(IS_CONTROL_DEVICES);
829 		msg.AddInt32("type", B_POINTING_DEVICE);
830 		msg.AddInt32("code", B_MOUSE_SPEED_CHANGED);
831 		return fAddOnManager->PostMessage(&msg);
832 	}
833 
834 	return reply->AddInt32("speed", fMouseSettings.MouseSpeed());
835 }
836 
837 
838 status_t
839 InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply)
840 {
841 	CALLED();
842 
843 	BPoint where;
844 	if (message->FindPoint("where", &where) != B_OK)
845 		return B_BAD_VALUE;
846 
847 	// create a new event for this and enqueue it to the event list just like any other
848 
849 	BMessage* event = new BMessage(B_MOUSE_MOVED);
850 	if (event == NULL)
851 		return B_NO_MEMORY;
852 
853 	event->AddPoint("where", where);
854 	event->AddBool("be:set_mouse", true);
855 	if (EnqueueDeviceMessage(event) != B_OK) {
856 		delete event;
857 		return B_NO_MEMORY;
858 	}
859 
860 	return B_OK;
861 }
862 
863 
864 status_t
865 InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply)
866 {
867 	mouse_map *map;
868 	ssize_t size;
869 	if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) {
870 		fMouseSettings.SetMapping(*map);
871 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
872 
873 		BMessage msg(IS_CONTROL_DEVICES);
874 		msg.AddInt32("type", B_POINTING_DEVICE);
875 		msg.AddInt32("code", B_MOUSE_MAP_CHANGED);
876 		return fAddOnManager->PostMessage(&msg);
877 	} else {
878 		mouse_map map;
879 		fMouseSettings.Mapping(map);
880 		return reply->AddData("mousemap", B_RAW_TYPE, &map, sizeof(mouse_map));
881 	}
882 }
883 
884 
885 status_t
886 InputServer::HandleGetSetKeyboardID(BMessage* message, BMessage* reply)
887 {
888 	int16 id;
889 	if (message->FindInt16("id", &id) == B_OK) {
890 		fKeyboardID = (uint16)id;
891 		return B_OK;
892 	}
893 	return reply->AddInt16("id", fKeyboardID);
894 }
895 
896 
897 status_t
898 InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply)
899 {
900 	bigtime_t clickSpeed;
901 	if (message->FindInt64("speed", &clickSpeed) == B_OK) {
902 		fMouseSettings.SetClickSpeed(clickSpeed);
903 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
904 
905 		BMessage msg(IS_CONTROL_DEVICES);
906 		msg.AddInt32("type", B_POINTING_DEVICE);
907 		msg.AddInt32("code", B_CLICK_SPEED_CHANGED);
908 		return fAddOnManager->PostMessage(&msg);
909 	}
910 
911 	return reply->AddInt64("speed", fMouseSettings.ClickSpeed());
912 }
913 
914 
915 status_t
916 InputServer::HandleGetSetKeyRepeatRate(BMessage* message, BMessage* reply)
917 {
918 	int32 keyRepeatRate;
919 	if (message->FindInt32("rate", &keyRepeatRate) == B_OK) {
920 		fKeyboardSettings.SetKeyboardRepeatRate(keyRepeatRate);
921 		be_app_messenger.SendMessage(IS_SAVE_SETTINGS);
922 
923 		BMessage msg(IS_CONTROL_DEVICES);
924 		msg.AddInt32("type", B_KEYBOARD_DEVICE);
925 		msg.AddInt32("code", B_KEY_REPEAT_RATE_CHANGED);
926 		return fAddOnManager->PostMessage(&msg);
927 	}
928 
929 	return reply->AddInt32("rate", fKeyboardSettings.KeyboardRepeatRate());
930 }
931 
932 
933 status_t
934 InputServer::HandleGetSetKeyMap(BMessage* message, BMessage* reply)
935 {
936 	CALLED();
937 
938 	if (message->what == IS_GET_KEY_MAP) {
939 		status_t status = reply->AddData("keymap", B_ANY_TYPE, &fKeys, sizeof(fKeys));
940 		if (status == B_OK)
941 			status = reply->AddData("key_buffer", B_ANY_TYPE, fChars, fCharsSize);
942 
943 		return status;
944 	}
945 
946 	if (_LoadKeymap() != B_OK)
947 		_LoadSystemKeymap();
948 
949 	BMessage msg(IS_CONTROL_DEVICES);
950 	msg.AddInt32("type", B_KEYBOARD_DEVICE);
951 	msg.AddInt32("code", B_KEY_MAP_CHANGED);
952 	return fAddOnManager->PostMessage(&msg);
953 }
954 
955 
956 status_t
957 InputServer::HandleFocusUnfocusIMAwareView(BMessage* message,
958 	BMessage* reply)
959 {
960 	CALLED();
961 
962 	BMessenger messenger;
963 	status_t status = message->FindMessenger("view", &messenger);
964 	if (status != B_OK)
965 		return status;
966 
967 	// check if current view is ours
968 
969 	if (message->what == IS_FOCUS_IM_AWARE_VIEW) {
970 		PRINT(("HandleFocusUnfocusIMAwareView : entering\n"));
971 		fInputMethodAware = true;
972 	} else {
973 		PRINT(("HandleFocusUnfocusIMAwareView : leaving\n"));
974 		fInputMethodAware = false;
975 	}
976 
977 	return B_OK;
978 }
979 
980 
981 /*!	Enqueues the message into the event queue.
982 	The message must only be deleted in case this method returns an error.
983 */
984 status_t
985 InputServer::EnqueueDeviceMessage(BMessage* message)
986 {
987 	CALLED();
988 
989 	BAutolock _(fEventQueueLock);
990 	if (!fEventQueue.AddItem(message))
991 		return B_NO_MEMORY;
992 
993 	if (fEventQueue.CountItems() == 1) {
994 		// notify event loop only if we haven't already done so
995 		write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0);
996 	}
997 	return B_OK;
998 }
999 
1000 
1001 /*!	Enqueues the message into the method queue.
1002 	The message must only be deleted in case this method returns an error.
1003 */
1004 status_t
1005 InputServer::EnqueueMethodMessage(BMessage* message)
1006 {
1007 	CALLED();
1008 	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, (char)(message->what >> 24),
1009 		(char)(message->what >> 16), (char)(message->what >> 8), (char)message->what));
1010 
1011 #ifdef DEBUG
1012 	if (message->what == 'IMEV') {
1013 		int32 code;
1014 		message->FindInt32("be:opcode", &code);
1015 		PRINT(("%s be:opcode %li\n", __PRETTY_FUNCTION__, code));
1016 	}
1017 #endif
1018 
1019 	BAutolock _(fEventQueueLock);
1020 	if (!fMethodQueue.AddItem(message))
1021 		return B_NO_MEMORY;
1022 
1023 	if (fMethodQueue.CountItems() == 1) {
1024 		// notify event loop only if we haven't already done so
1025 		write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
1026 	}
1027 	return B_OK;
1028 }
1029 
1030 
1031 status_t
1032 InputServer::SetNextMethod(bool direction)
1033 {
1034 	gInputMethodListLocker.Lock();
1035 
1036 	int32 index = gInputMethodList.IndexOf(fActiveMethod);
1037 	int32 oldIndex = index;
1038 
1039 	index += (direction ? 1 : -1);
1040 
1041 	if (index < -1)
1042 		index = gInputMethodList.CountItems() - 1;
1043 	if (index >= gInputMethodList.CountItems())
1044 		index = -1;
1045 
1046 	if (index == oldIndex)
1047 		return B_BAD_INDEX;
1048 
1049 	BInputServerMethod *method = &gKeymapMethod;
1050 
1051 	if (index != -1)
1052 		method = (BInputServerMethod *)gInputMethodList.ItemAt(index);
1053 
1054 	SetActiveMethod(method);
1055 
1056 	gInputMethodListLocker.Unlock();
1057 	return B_OK;
1058 }
1059 
1060 
1061 void
1062 InputServer::SetActiveMethod(BInputServerMethod* method)
1063 {
1064 	CALLED();
1065 	if (fActiveMethod)
1066 		fActiveMethod->fOwner->MethodActivated(false);
1067 
1068 	fActiveMethod = method;
1069 
1070 	if (fActiveMethod)
1071 		fActiveMethod->fOwner->MethodActivated(true);
1072 }
1073 
1074 
1075 const BMessenger*
1076 InputServer::MethodReplicant()
1077 {
1078 	return fReplicantMessenger;
1079 }
1080 
1081 
1082 void
1083 InputServer::SetMethodReplicant(const BMessenger* messenger)
1084 {
1085 	fReplicantMessenger = messenger;
1086 }
1087 
1088 
1089 bool
1090 InputServer::EventLoopRunning()
1091 {
1092 	return fEventLooperPort >= B_OK;
1093 }
1094 
1095 
1096 status_t
1097 InputServer::GetDeviceInfo(const char* name, input_device_type *_type,
1098 	bool *_isRunning)
1099 {
1100     BAutolock lock(fInputDeviceListLocker);
1101 
1102 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1103 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1104 
1105 		if (item->HasName(name)) {
1106 			if (_type)
1107 				*_type = item->Type();
1108 			if (_isRunning)
1109 				*_isRunning = item->Running();
1110 
1111 			return B_OK;
1112 		}
1113 	}
1114 
1115 	return B_NAME_NOT_FOUND;
1116 }
1117 
1118 
1119 status_t
1120 InputServer::GetDeviceInfos(BMessage *msg)
1121 {
1122 	CALLED();
1123 	BAutolock lock(fInputDeviceListLocker);
1124 
1125 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1126 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1127 		msg->AddString("device", item->Name());
1128 		msg->AddInt32("type", item->Type());
1129 	}
1130 	return B_OK;
1131 }
1132 
1133 
1134 status_t
1135 InputServer::UnregisterDevices(BInputServerDevice& serverDevice,
1136 	input_device_ref **devices)
1137 {
1138     CALLED();
1139     BAutolock lock(fInputDeviceListLocker);
1140 
1141 	if (devices != NULL) {
1142 		// remove the devices as specified only
1143 		input_device_ref *device = NULL;
1144 		for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1145 			for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1146 				InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1147 
1148 				if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) {
1149 					item->Stop();
1150 					if (fInputDeviceList.RemoveItem(j))
1151 						delete item;
1152 					break;
1153 				}
1154 			}
1155 		}
1156 	} else {
1157 		// remove all devices from this BInputServerObject
1158 		for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1159 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1160 
1161 			if (item->ServerDevice() == &serverDevice) {
1162 				item->Stop();
1163 				if (fInputDeviceList.RemoveItem(i))
1164 					delete item;
1165 			}
1166 		}
1167 	}
1168 
1169     return B_OK;
1170 }
1171 
1172 
1173 status_t
1174 InputServer::RegisterDevices(BInputServerDevice& serverDevice,
1175 	input_device_ref** devices)
1176 {
1177 	if (devices == NULL)
1178 		return B_BAD_VALUE;
1179 
1180 	BAutolock lock(fInputDeviceListLocker);
1181 
1182 	input_device_ref *device = NULL;
1183 	for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1184 		if (device->type != B_POINTING_DEVICE
1185 			&& device->type != B_KEYBOARD_DEVICE
1186 			&& device->type != B_UNDEFINED_DEVICE)
1187 			continue;
1188 
1189 		// find existing input server device
1190 
1191 		bool found = false;
1192 		for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1193 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1194 
1195 			if (item->HasName(device->name)) {
1196 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name);
1197 				PRINT(("RegisterDevices found %s\n", device->name));
1198 				found = true;
1199 				break;
1200 			}
1201 		}
1202 
1203 		if (!found) {
1204 			PRINT(("RegisterDevices not found %s\n", device->name));
1205 			InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice,
1206 				*device);
1207 			if (item != NULL && fInputDeviceList.AddItem(item)) {
1208 				item->Start();
1209 			} else {
1210 				delete item;
1211 				return B_NO_MEMORY;
1212 			}
1213 		}
1214 	}
1215 
1216 	return B_OK;
1217 }
1218 
1219 
1220 status_t
1221 InputServer::StartStopDevices(const char* name, input_device_type type,
1222 	bool doStart)
1223 {
1224 	CALLED();
1225 	BAutolock lock(fInputDeviceListLocker);
1226 
1227 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1228 		InputDeviceListItem* item
1229 			= (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1230 		if (!item)
1231 			continue;
1232 
1233 		if (item->Matches(name, type)) {
1234 			if (doStart == item->Running()) {
1235 				if (name)
1236 					return B_OK;
1237 				else
1238 					continue;
1239 			}
1240 
1241 			if (doStart)
1242 				item->Start();
1243 			else
1244 				item->Stop();
1245 
1246 			if (name)
1247 				return B_OK;
1248 		}
1249 	}
1250 
1251 	if (name) {
1252 		// item not found
1253 		return B_ERROR;
1254 	}
1255 
1256 	return B_OK;
1257 }
1258 
1259 
1260 
1261 status_t
1262 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart)
1263 {
1264 	CALLED();
1265 	BAutolock lock(fInputDeviceListLocker);
1266 
1267 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1268 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1269 
1270 		if (item->ServerDevice() != &serverDevice)
1271 			continue;
1272 
1273 		if (doStart == item->Running())
1274 			continue;
1275 
1276 		if (doStart)
1277 			item->Start();
1278 		else
1279 			item->Stop();
1280 	}
1281 
1282 	return B_OK;
1283 }
1284 
1285 
1286 status_t
1287 InputServer::ControlDevices(const char* name, input_device_type type,
1288 	uint32 code, BMessage* message)
1289 {
1290 	CALLED();
1291 	BAutolock lock(fInputDeviceListLocker);
1292 
1293 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1294 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1295 		if (!item)
1296 			continue;
1297 
1298 		if (item->Matches(name, type)) {
1299 			item->Control(code, message);
1300 
1301 			if (name)
1302 				return B_OK;
1303 		}
1304 	}
1305 
1306 	if (name)
1307 		return B_ERROR;
1308 
1309 	return B_OK;
1310 }
1311 
1312 
1313 bool
1314 InputServer::DoMouseAcceleration(int32* _x, int32* _y)
1315 {
1316 	CALLED();
1317 	int32 speed = fMouseSettings.MouseSpeed() >> 15;
1318 
1319 	// ToDo: implement mouse acceleration
1320 	(void)speed;
1321 	//*_y = *_x * speed;
1322 	PRINT(("DoMouse : %ld %ld %ld %ld\n", *_x, *_y, speed, fMouseSettings.MouseSpeed()));
1323 	return true;
1324 }
1325 
1326 
1327 bool
1328 InputServer::SetMousePos(long *, long *, long, long)
1329 {
1330 	CALLED();
1331 	return true;
1332 }
1333 
1334 
1335 bool
1336 InputServer::SetMousePos(long *, long *, BPoint)
1337 {
1338 	CALLED();
1339 	return true;
1340 }
1341 
1342 
1343 bool
1344 InputServer::SetMousePos(long *, long *, float, float)
1345 {
1346 	CALLED();
1347 	return true;
1348 }
1349 
1350 
1351 bool
1352 InputServer::SafeMode()
1353 {
1354 	return fSafeMode;
1355 }
1356 
1357 
1358 status_t
1359 InputServer::_StartEventLoop()
1360 {
1361 	CALLED();
1362 	fEventLooperPort = create_port(100, "input server events");
1363 	if (fEventLooperPort < 0) {
1364 		PRINTERR(("InputServer: create_port error: (0x%lx) %s\n",
1365 			fEventLooperPort, strerror(fEventLooperPort)));
1366 		return fEventLooperPort;
1367 	}
1368 
1369 	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1370 		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1371 	if (thread < B_OK || resume_thread(thread) < B_OK) {
1372 		if (thread >= B_OK)
1373 			kill_thread(thread);
1374 		delete_port(fEventLooperPort);
1375 		fEventLooperPort = -1;
1376 		return thread < B_OK ? thread : B_ERROR;
1377 	}
1378 
1379 	return B_OK;
1380 }
1381 
1382 
1383 status_t
1384 InputServer::_EventLooper(void* arg)
1385 {
1386 	InputServer* self = (InputServer*)arg;
1387 	self->_EventLoop();
1388 
1389 	return B_OK;
1390 }
1391 
1392 
1393 void
1394 InputServer::_EventLoop()
1395 {
1396 	while (true) {
1397 		// Block until we find the size of the next message
1398 		ssize_t length = port_buffer_size(fEventLooperPort);
1399 		if (length < B_OK) {
1400 			PRINT(("[Event Looper] port gone, exiting.\n"));
1401 			return;
1402 		}
1403 
1404 		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1405 
1406 		char buffer[length];
1407 		int32 code;
1408 		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1409 		if (err != length) {
1410 			if (err >= 0) {
1411 				PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length));
1412 			} else {
1413 				PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err)));
1414 			}
1415 			continue;
1416 		}
1417 
1418 		EventList events;
1419 		if (fEventQueueLock.Lock()) {
1420 			// move the items to our own list to block the event queue as short as possible
1421 			events.AddList(&fEventQueue);
1422 			fEventQueue.MakeEmpty();
1423 			fEventQueueLock.Unlock();
1424 		}
1425 
1426 		if (length > 0) {
1427 			BMessage* event = new BMessage;
1428 
1429 			if ((err = event->Unflatten(buffer)) < 0) {
1430 				PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
1431 				delete event;
1432 				continue;
1433 			}
1434 
1435 			events.AddItem(event);
1436 		}
1437 
1438 		// This is where the message should be processed.
1439 
1440 		if (_SanitizeEvents(events)
1441 			&& _MethodizeEvents(events)
1442 			&& _FilterEvents(events)) {
1443 			_UpdateMouseAndKeys(events);
1444 			_DispatchEvents(events);
1445 		}
1446 	}
1447 }
1448 
1449 
1450 /*!	Updates the internal mouse position and keyboard info. */
1451 void
1452 InputServer::_UpdateMouseAndKeys(EventList& events)
1453 {
1454 	for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index);
1455 			index++) {
1456 		switch (event->what) {
1457 			case B_MOUSE_DOWN:
1458 			case B_MOUSE_UP:
1459 			case B_MOUSE_MOVED:
1460 				event->FindPoint("where", &fMousePos);
1461 				break;
1462 
1463 			case B_KEY_DOWN:
1464 			case B_UNMAPPED_KEY_DOWN:
1465 				// update modifiers
1466 				uint32 modifiers;
1467 				if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1468 					fKeyInfo.modifiers = modifiers;
1469 
1470 				// update key states
1471 				const uint8 *data;
1472 				ssize_t size;
1473 				if (event->FindData("states", B_UINT8_TYPE,
1474 						(const void**)&data, &size) == B_OK) {
1475 					PRINT(("updated keyinfo\n"));
1476 					if (size == sizeof(fKeyInfo.key_states))
1477 						memcpy(fKeyInfo.key_states, data, size);
1478 				}
1479 
1480 				if (fActiveMethod == NULL)
1481 					break;
1482 
1483 				// we scan for Alt+Space key down events which means we change
1484 				// to next input method
1485 				// (pressing "shift" will let us switch to the previous method)
1486 
1487 				// If there is only one input method, SetNextMethod will return
1488 				// B_BAD_INDEX and the event will be forwarded to the user.
1489 
1490 				PRINT(("SanitizeEvents: %lx, %x\n", fKeyInfo.modifiers,
1491 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1492 
1493 				uint8 byte;
1494 				if (event->FindInt8("byte", (int8*)&byte) < B_OK)
1495 					byte = 0;
1496 
1497 				if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ')
1498 						|| byte == B_HANKAKU_ZENKAKU)
1499 					&& SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0)
1500 							== B_OK) {
1501 					// this event isn't sent to the user
1502 					events.RemoveItemAt(index);
1503 					delete event;
1504 					continue;
1505 				}
1506 				break;
1507 		}
1508 	}
1509 }
1510 
1511 
1512 /*!	Frees events from unwanted fields, adds missing fields, and removes
1513 	unwanted events altogether.
1514 */
1515 bool
1516 InputServer::_SanitizeEvents(EventList& events)
1517 {
1518 	CALLED();
1519 
1520 	for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index);
1521 			index++) {
1522 		switch (event->what) {
1523 	   		case B_MOUSE_MOVED:
1524 	   		case B_MOUSE_DOWN:
1525 	   		{
1526 	   			int32 buttons;
1527 	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1528 	   				event->AddInt32("buttons", 0);
1529 
1530 	   			// supposed to fall through
1531 	   		}
1532 	   		case B_MOUSE_UP:
1533 	   		{
1534 	   			BPoint where;
1535 				int32 x, y;
1536 				float absX, absY;
1537 
1538 				if (event->FindInt32("x", &x) == B_OK
1539 					&& event->FindInt32("y", &y) == B_OK) {
1540 					where.x = fMousePos.x + x;
1541 					where.y = fMousePos.y - y;
1542 
1543 					event->RemoveName("x");
1544 					event->RemoveName("y");
1545 					event->AddInt32("be:delta_x", x);
1546 					event->AddInt32("be:delta_y", y);
1547 
1548 					PRINT(("new position: %f, %f, %ld, %ld\n",
1549 						where.x, where.y, x, y));
1550 				} else if (event->FindFloat("x", &absX) == B_OK
1551 					&& event->FindFloat("y", &absY) == B_OK) {
1552 					// The device gives us absolute screen coords in range 0..1;
1553 					// convert them to absolute screen position
1554 					// (the message is supposed to contain the original
1555 					// absolute coordinates as "be:tablet_x/y").
1556 					where.x = absX * fFrame.Width();
1557 					where.y = absY * fFrame.Height();
1558 
1559 					event->RemoveName("x");
1560 					event->RemoveName("y");
1561 					PRINT(("new position : %f, %f\n", where.x, where.y));
1562 				} else if (event->FindPoint("where", &where) == B_OK) {
1563 					PRINT(("new position : %f, %f\n", where.x, where.y));
1564 				}
1565 
1566 				// Constrain and filter the mouse coords and add the final
1567 				// point to the message.
1568 				where.x = roundf(where.x);
1569 				where.y = roundf(where.y);
1570 				where.ConstrainTo(fFrame);
1571 				if (event->ReplacePoint("where", where) != B_OK)
1572 					event->AddPoint("where", where);
1573 
1574 				if (!event->HasInt64("when"))
1575 					event->AddInt64("when", system_time());
1576 
1577 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1578 				break;
1579 	   		}
1580 			case B_KEY_DOWN:
1581 			case B_UNMAPPED_KEY_DOWN:
1582 				// add modifiers
1583 				if (!event->HasInt32("modifiers"))
1584 					event->AddInt32("modifiers", fKeyInfo.modifiers);
1585 
1586 				// add key states
1587 				if (!event->HasData("states", B_UINT8_TYPE)) {
1588 					event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1589 						sizeof(fKeyInfo.key_states));
1590 				}
1591 				break;
1592 		}
1593 	}
1594 
1595 	return true;
1596 }
1597 
1598 
1599 /*!	Applies the filters of the active input method to the
1600 	incoming events. It will also move the events in the method
1601 	queue to the event list.
1602 */
1603 bool
1604 InputServer::_MethodizeEvents(EventList& events)
1605 {
1606 	CALLED();
1607 
1608 	if (fActiveMethod == NULL)
1609 		return true;
1610 
1611 	int32 count = events.CountItems();
1612 	for (int32 i = 0; i < count;) {
1613 		_FilterEvent(fActiveMethod, events, i, count);
1614 	}
1615 
1616 	{
1617 		// move the method events into the event queue - they are not
1618 		// "methodized" either
1619 		BAutolock _(fEventQueueLock);
1620 		events.AddList(&fMethodQueue);
1621 		fMethodQueue.MakeEmpty();
1622 	}
1623 
1624 	if (!fInputMethodAware) {
1625 		// special handling for non-input-method-aware views
1626 
1627 		int32 newCount = events.CountItems();
1628 			// we may add new events in this loop that don't need to be checked again
1629 
1630 		for (int32 i = 0; i < newCount; i++) {
1631 			BMessage* event = events.ItemAt(i);
1632 
1633 			if (event->what != B_INPUT_METHOD_EVENT)
1634 				continue;
1635 
1636 			SERIAL_PRINT(("IME received\n"));
1637 
1638 			bool removeEvent = true;
1639 
1640 			int32 opcode;
1641 			if (event->FindInt32("be:opcode", &opcode) == B_OK) {
1642 				bool inlineOnly;
1643 				if (event->FindBool("be:inline_only", &inlineOnly) != B_OK)
1644 					inlineOnly = false;
1645 
1646 				if (inlineOnly) {
1647 					BMessage translated;
1648 					bool confirmed;
1649 					if (opcode == B_INPUT_METHOD_CHANGED
1650 						&& event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed
1651 						&& event->FindMessage("be:translated", &translated) == B_OK) {
1652 						// translate event for the non-aware view
1653 						*event = translated;
1654 						removeEvent = false;
1655 					}
1656 				} else {
1657 					if (fInputMethodWindow == NULL
1658 						&& opcode == B_INPUT_METHOD_STARTED)
1659 						fInputMethodWindow = new (nothrow) BottomlineWindow();
1660 
1661 					if (fInputMethodWindow != NULL) {
1662 						EventList newEvents;
1663 						fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1664 
1665 						if (!newEvents.IsEmpty()) {
1666 							events.AddList(&newEvents);
1667 							opcode = B_INPUT_METHOD_STOPPED;
1668 						}
1669 
1670 						if (opcode == B_INPUT_METHOD_STOPPED) {
1671 							fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1672 							fInputMethodWindow = NULL;
1673 						}
1674 					}
1675 				}
1676 			}
1677 
1678 			if (removeEvent) {
1679 				// the inline/bottom window has eaten the event
1680 				events.RemoveItemAt(i--);
1681 				delete event;
1682 				newCount--;
1683 			}
1684 		}
1685 	}
1686 
1687 	return events.CountItems() > 0;
1688 }
1689 
1690 
1691 /*!	This method applies all defined filters to each event in the
1692 	supplied list.  The supplied list is modified to reflect the
1693 	output of the filters.
1694 	The method returns true if the filters were applied to all
1695 	events without error and false otherwise.
1696 */
1697 bool
1698 InputServer::_FilterEvents(EventList& events)
1699 {
1700 	CALLED();
1701 	BAutolock _(gInputFilterListLocker);
1702 
1703 	int32 count = gInputFilterList.CountItems();
1704 	int32 eventCount = events.CountItems();
1705 
1706 	for (int32 i = 0; i < count; i++) {
1707 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1708 
1709 		// Apply the current filter to all available event messages.
1710 
1711 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1712 			_FilterEvent(filter, events, eventIndex, eventCount);
1713 		}
1714 	}
1715 
1716 	return eventCount != 0;
1717 }
1718 
1719 
1720 void
1721 InputServer::_DispatchEvents(EventList& events)
1722 {
1723 	CALLED();
1724 
1725 	int32 count = events.CountItems();
1726 
1727 	for (int32 i = 0; i < count; i++) {
1728 		BMessage* event = events.ItemAt(i);
1729 
1730 		// now we must send each event to the app_server
1731 		_DispatchEvent(event);
1732 		delete event;
1733 	}
1734 
1735 	events.MakeEmpty();
1736 }
1737 
1738 
1739 /*!	Applies the given filter to the event list.
1740 	For your convenience, it also alters the \a index and \a count arguments
1741 	ready for the next call to this method.
1742 */
1743 void
1744 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1745 	int32& index, int32& count)
1746 {
1747 	BMessage* event = events.ItemAt(index);
1748 
1749 	BList newEvents;
1750 	filter_result result = filter->Filter(event, &newEvents);
1751 
1752 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1753 		// we no longer need the current event
1754 		events.RemoveItemAt(index);
1755 		delete event;
1756 
1757 		if (result == B_DISPATCH_MESSAGE) {
1758 			EventList addedEvents;
1759 			EventList::Private(&addedEvents).AsBList()->AddList(&newEvents);
1760 			_SanitizeEvents(addedEvents);
1761 			// add the new events - but don't methodize them again
1762 			events.AddList(&addedEvents, index);
1763 			index += newEvents.CountItems();
1764 			count = events.CountItems();
1765 		} else
1766 			count--;
1767 	} else
1768 		index++;
1769 }
1770 
1771 
1772 status_t
1773 InputServer::_DispatchEvent(BMessage* event)
1774 {
1775 	CALLED();
1776 
1777    	switch (event->what) {
1778 		case B_MOUSE_MOVED:
1779 		case B_MOUSE_DOWN:
1780 		case B_MOUSE_UP:
1781 			if (fCursorBuffer) {
1782 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1783 					| ((uint32)fMousePos.y & 0xffff));
1784 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1785 					release_sem(fCursorSem);
1786         	}
1787         	break;
1788 
1789 		case B_KEY_DOWN:
1790 		case B_KEY_UP:
1791 		case B_UNMAPPED_KEY_DOWN:
1792 		case B_UNMAPPED_KEY_UP:
1793 		case B_MODIFIERS_CHANGED:
1794 		{
1795 			// update or add modifiers
1796 			uint32 modifiers;
1797 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1798 				fKeyInfo.modifiers = modifiers;
1799 			else
1800 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1801 
1802 			// update or add key states
1803 			const uint8 *data;
1804 			ssize_t size;
1805 			if (event->FindData("states", B_UINT8_TYPE,
1806 					(const void**)&data, &size) == B_OK) {
1807 				PRINT(("updated keyinfo\n"));
1808 				if (size == sizeof(fKeyInfo.key_states))
1809 					memcpy(fKeyInfo.key_states, data, size);
1810 			} else {
1811 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1812 					sizeof(fKeyInfo.key_states));
1813 			}
1814 
1815 			break;
1816 		}
1817 
1818    		default:
1819 			break;
1820 	}
1821 
1822 	BMessenger reply;
1823 	BMessage::Private messagePrivate(event);
1824 	return messagePrivate.SendMessage(fAppServerPort, -1, 0, 0, false, reply);
1825 }
1826 
1827 
1828 //	#pragma mark -
1829 
1830 
1831 extern "C" void
1832 RegisterDevices(input_device_ref** devices)
1833 {
1834 	CALLED();
1835 }
1836 
1837 
1838 BView *
1839 instantiate_deskbar_item()
1840 {
1841 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1842 }
1843 
1844 
1845 //	#pragma mark -
1846 
1847 
1848 int
1849 main(int /*argc*/, char** /*argv*/)
1850 {
1851 	InputServer	*inputServer = new InputServer;
1852 
1853 	inputServer->Run();
1854 	delete inputServer;
1855 
1856 	return 0;
1857 }
1858 
1859 
1860