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