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