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