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