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