xref: /haiku/src/servers/input/InputServer.cpp (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
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 #ifndef USE_R5_STYLE_COMM
36 #include <ServerProtocol.h>
37 #endif
38 
39 using std::nothrow;
40 
41 #define FAST_MOUSE_MOVED '_FMM'
42 	// received from app_server when screen res changed, but could be sent to too.
43 
44 
45 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
46 extern "C" status_t _kern_get_safemode_option(const char *parameter,
47 	char *buffer, size_t *_bufferSize);
48 #else
49 extern "C" status_t _kget_safemode_option_(const char *parameter,
50 	char *buffer, size_t *_bufferSize);
51 #endif
52 
53 
54 // Global InputServer member variables.
55 
56 InputServer* gInputServer;
57 
58 BList InputServer::gInputFilterList;
59 BLocker InputServer::gInputFilterListLocker("is_filter_queue_sem");
60 
61 BList InputServer::gInputMethodList;
62 BLocker InputServer::gInputMethodListLocker("is_method_queue_sem");
63 
64 DeviceManager InputServer::gDeviceManager;
65 
66 KeymapMethod InputServer::gKeymapMethod;
67 
68 #if DEBUG == 2
69 FILE *InputServer::sLogFile = NULL;
70 #endif
71 
72 
73 extern "C" _EXPORT BView* instantiate_deskbar_item();
74 
75 
76 InputDeviceListItem::InputDeviceListItem(BInputServerDevice& serverDevice,
77 	input_device_ref& device)
78 	:
79 	fServerDevice(&serverDevice),
80 	fDevice(device),
81 	fRunning(false)
82 {
83 }
84 
85 
86 void
87 InputDeviceListItem::Start()
88 {
89 	PRINT(("  Starting: %s\n", fDevice.name));
90 	fServerDevice->Start(fDevice.name, fDevice.cookie);
91 	fRunning = true;
92 }
93 
94 
95 void
96 InputDeviceListItem::Stop()
97 {
98 	PRINT(("  Stopping: %s\n", fDevice.name));
99 	fServerDevice->Stop(fDevice.name, fDevice.cookie);
100 	fRunning = false;
101 }
102 
103 
104 void
105 InputDeviceListItem::Control(uint32 code, BMessage* message)
106 {
107 	fServerDevice->Control(fDevice.name, fDevice.cookie, code, message);
108 }
109 
110 
111 bool
112 InputDeviceListItem::HasName(const char* name) const
113 {
114 	if (name == NULL)
115 		return false;
116 
117 	return !strcmp(name, fDevice.name);
118 }
119 
120 
121 bool
122 InputDeviceListItem::HasType(input_device_type type) const
123 {
124 	return type == fDevice.type;
125 }
126 
127 
128 bool
129 InputDeviceListItem::Matches(const char* name, input_device_type type) const
130 {
131 	if (name != NULL)
132 		return HasName(name);
133 
134 	return HasType(type);
135 }
136 
137 
138 //	#pragma mark -
139 
140 
141 InputServer::InputServer()
142 	: BApplication(INPUTSERVER_SIGNATURE),
143 	fSafeMode(false),
144 	fInputDeviceListLocker("input server device list"),
145 	fChars(NULL),
146 	fScreen(B_MAIN_SCREEN_ID),
147 	fInputMethodWindow(NULL),
148 	fInputMethodAware(false),
149 	fCursorSem(-1),
150 	fAppServerPort(-1),
151 	fCursorArea(-1)
152 {
153 #if DEBUG == 2
154 	if (sLogFile == NULL)
155 		sLogFile = fopen("/var/log/input_server.log", "a");
156 #endif
157 
158 	CALLED();
159 	gInputServer = this;
160 
161 	_StartEventLoop();
162 
163 	char parameter[32];
164 	size_t parameterLength = sizeof(parameter);
165 
166 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
167 	if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, &parameterLength) == B_OK)
168 #else
169 	if (_kget_safemode_option_(B_SAFEMODE_SAFE_MODE, parameter, &parameterLength) == B_OK)
170 #endif
171 	{
172 		if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
173 			|| !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
174 			|| !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
175 			fSafeMode = true;
176 	}
177 
178 	gDeviceManager.LoadState();
179 
180 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
181 	if (has_data(find_thread(NULL))) {
182 		PRINT(("HasData == YES\n"));
183 		int32 buffer[2];
184 		thread_id appThreadId;
185 		memset(buffer, 0, sizeof(buffer));
186 		int32 code = receive_data(&appThreadId, buffer, sizeof(buffer));
187 		(void)code;	// suppresses warning in non-debug build
188 		PRINT(("tid : %ld, code :%ld\n", appThreadId, code));
189 		for (int32 i = 0; i < 2; i++) {
190 			PRINT(("data : %lx\n", buffer[i]));
191 		}
192 		fCursorSem = buffer[0];
193 		area_id appArea = buffer[1];
194 
195 		fCursorArea = clone_area("isClone", (void**)&fCursorBuffer,
196 			B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, appArea);
197 		if (fCursorArea < B_OK) {
198 			PRINTERR(("clone_area error : %s\n", strerror(fCloneArea)));
199 		}
200 
201 		fAppServerPort = create_port(100, "is_as");
202 
203 		PRINT(("is_as port :%ld\n", fAppServerPort));
204 
205 		buffer[1] = fEventLooperPort;
206 		buffer[0] = fAppServerPort;
207 
208 		status_t err;
209 		if ((err = send_data(appThreadId, 0, buffer, sizeof(buffer)))!=B_OK)
210 			PRINTERR(("error when send_data %s\n", strerror(err)));
211 	}
212 #endif
213 
214 	_InitKeyboardMouseStates();
215 
216 	fAddOnManager = new AddOnManager(SafeMode());
217 	fAddOnManager->LoadState();
218 
219 	BMessenger messenger(this);
220 	BRoster().StartWatching(messenger, B_REQUEST_LAUNCHED);
221 }
222 
223 
224 InputServer::~InputServer()
225 {
226 	CALLED();
227 	fAddOnManager->Lock();
228 	fAddOnManager->Quit();
229 
230 	_ReleaseInput(NULL);
231 
232 #if DEBUG == 2
233 	fclose(sLogFile);
234 #endif
235 }
236 
237 
238 void
239 InputServer::ArgvReceived(int32 argc, char** argv)
240 {
241 	CALLED();
242 	if (2 == argc && (0 == strcmp("-q", argv[1]))) {
243 		PRINT(("InputServer::ArgvReceived - Restarting ...\n"));
244 		status_t quit_status = B_OK;
245 		BMessenger msgr = BMessenger(INPUTSERVER_SIGNATURE, -1, &quit_status);
246 		if (B_OK == quit_status) {
247 			msgr.SendMessage(B_QUIT_REQUESTED);
248 		} else {
249 			PRINTERR(("Unable to send Quit message to running InputServer.\n"));
250 		}
251 	}
252 }
253 
254 
255 void
256 InputServer::_InitKeyboardMouseStates()
257 {
258 	CALLED();
259 	// This is where we determine the screen resolution from the app_server and find the center of the screen
260 	// fMousePos is then set to the center of the screen.
261 
262 	fFrame = fScreen.Frame();
263 	if (fFrame == BRect(0, 0, 0, 0))
264 		fFrame = BRect(0, 0, 800, 600);
265 	fMousePos = BPoint(fFrame.right / 2, fFrame.bottom / 2);
266 
267 	if (_LoadKeymap() != B_OK)
268 		_LoadSystemKeymap();
269 
270 	BMessage *msg = new BMessage(B_MOUSE_MOVED);
271 	HandleSetMousePosition(msg, msg);
272 
273 	fActiveMethod = &gKeymapMethod;
274 }
275 
276 
277 status_t
278 InputServer::_LoadKeymap()
279 {
280 	BPath path;
281 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path)!=B_OK)
282 		return B_BAD_VALUE;
283 
284 	path.Append("Key_map");
285 
286 	entry_ref ref;
287 	get_ref_for_path(path.Path(), &ref);
288 
289 	status_t err;
290 
291 	BFile file(&ref, B_READ_ONLY);
292 	if ((err = file.InitCheck()) != B_OK)
293 		return err;
294 
295 	if (file.Read(&fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys))
296 		return B_BAD_VALUE;
297 
298 	for (uint32 i = 0; i < sizeof(fKeys)/4; i++)
299 		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
300 
301 	if (file.Read(&fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32))
302 		return B_BAD_VALUE;
303 
304 	fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize);
305 
306 	delete[] fChars;
307 	fChars = new (nothrow) char[fCharsSize];
308 	if (fChars == NULL)
309 		return B_NO_MEMORY;
310 
311 	if (file.Read(fChars, fCharsSize) != (signed)fCharsSize)
312 		return B_BAD_VALUE;
313 
314 	return B_OK;
315 }
316 
317 
318 status_t
319 InputServer::_LoadSystemKeymap()
320 {
321 	delete[] fChars;
322 	fKeys = sSystemKeymap;
323 	fCharsSize = sSystemKeyCharsSize;
324 	fChars = new (nothrow) char[fCharsSize];
325 	if (fChars == NULL)
326 		return B_NO_MEMORY;
327 
328 	memcpy(fChars, sSystemKeyChars, fCharsSize);
329 
330 	// we save this keymap to file
331 	BPath path;
332 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
333 		return B_BAD_VALUE;
334 
335 	path.Append("Key_map");
336 
337 	entry_ref ref;
338 	get_ref_for_path(path.Path(), &ref);
339 
340 	BFile file;
341 	status_t err = file.SetTo(&ref, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
342 	if (err != B_OK) {
343 		PRINTERR(("error %s\n", strerror(err)));
344 		return err;
345 	}
346 
347 	for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) {
348 		((uint32*)&fKeys)[i] = B_HOST_TO_BENDIAN_INT32(((uint32*)&fKeys)[i]);
349 	}
350 
351 	if ((err = file.Write(&fKeys, sizeof(fKeys))) < (ssize_t)sizeof(fKeys))
352 		return err;
353 
354 	for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) {
355 		((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]);
356 	}
357 
358 	fCharsSize = B_HOST_TO_BENDIAN_INT32(fCharsSize);
359 
360 	if ((err = file.Write(&fCharsSize, sizeof(uint32))) < (ssize_t)sizeof(uint32))
361 		return B_BAD_VALUE;
362 
363 	fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize);
364 
365 	if ((err = file.Write(fChars, fCharsSize)) < (ssize_t)fCharsSize)
366 		return err;
367 
368 	return B_OK;
369 }
370 
371 
372 bool
373 InputServer::QuitRequested()
374 {
375 	CALLED();
376 	if (!BApplication::QuitRequested())
377 		return false;
378 
379 	PostMessage(SYSTEM_SHUTTING_DOWN);
380 
381 	fAddOnManager->SaveState();
382 	gDeviceManager.SaveState();
383 
384 	delete_port(fEventLooperPort);
385 		// the event looper thread will exit after this
386 	fEventLooperPort = -1;
387 	return true;
388 }
389 
390 
391 void
392 InputServer::ReadyToRun()
393 {
394 	CALLED();
395 
396 	// say hello to the app_server
397 
398 	BPrivate::AppServerLink link;
399 	link.StartMessage(AS_REGISTER_INPUT_SERVER);
400 	link.Flush();
401 }
402 
403 
404 status_t
405 InputServer::_AcquireInput(BMessage& message, BMessage& reply)
406 {
407 	// TODO: it currently just gets everything we have
408 	area_id area;
409 	if (message.FindInt32("cursor_area", &area) == B_OK) {
410 		// try to clone the area
411 		fCursorBuffer = NULL;
412 
413 		fCursorSem = create_sem(0, "cursor semaphore");
414 		if (fCursorSem >= B_OK) {
415 			fCursorArea = clone_area("input server cursor", (void**)&fCursorBuffer,
416 				B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area);
417 		}
418 	}
419 
420 	fAppServerPort = create_port(200, "input server target");
421 	if (fAppServerPort < B_OK) {
422 		_ReleaseInput(&message);
423 		return fAppServerPort;
424 	}
425 
426 	// TODO: would be nice if we could just reply to this message...
427 #if 0
428 	reply.AddBool("has_keyboard", true);
429 	reply.AddBool("has_mouse", true);
430 	reply.AddInt32("event port", fAppServerPort);
431 
432 	if (fCursorBuffer != NULL) {
433 		// cursor shared buffer is supported
434 		reply.AddInt32("cursor semaphore", fCursorSem);
435 	}
436 #else
437 	BPrivate::AppServerLink link;
438 	link.StartMessage(AS_ACQUIRED_INPUT_STREAM);
439 	link.Attach<bool>(true);
440 	link.Attach<bool>(true);
441 	link.Attach<int32>(fAppServerPort);
442 	link.Attach<int32>(fCursorSem);
443 	link.Flush();
444 #endif
445 	return B_OK;
446 }
447 
448 
449 void
450 InputServer::_ReleaseInput(BMessage* /*message*/)
451 {
452 	if (fCursorBuffer != NULL) {
453 		fCursorBuffer = NULL;
454 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
455 		delete_sem(fCursorSem);
456 #endif
457 		delete_area(fCursorArea);
458 
459 		fCursorSem = -1;
460 		fCursorArea = -1;
461 	}
462 
463 	delete_port(fAppServerPort);
464 }
465 
466 
467 void
468 InputServer::MessageReceived(BMessage* message)
469 {
470 	CALLED();
471 
472 	BMessage reply;
473 	status_t status = B_OK;
474 
475 	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what >> 24,
476 		message->what >> 16, message->what >> 8, message->what));
477 
478 	switch (message->what) {
479 		case IS_SET_METHOD:
480 			HandleSetMethod(message);
481 			break;
482 		case IS_GET_MOUSE_TYPE:
483 			status = HandleGetSetMouseType(message, &reply);
484 			break;
485 		case IS_SET_MOUSE_TYPE:
486 			status = HandleGetSetMouseType(message, &reply);
487 			break;
488 		case IS_GET_MOUSE_ACCELERATION:
489 			status = HandleGetSetMouseAcceleration(message, &reply);
490 			break;
491 		case IS_SET_MOUSE_ACCELERATION:
492 			status = HandleGetSetMouseAcceleration(message, &reply);
493 			break;
494 		case IS_GET_KEY_REPEAT_DELAY:
495 			status = HandleGetSetKeyRepeatDelay(message, &reply);
496 			break;
497 		case IS_SET_KEY_REPEAT_DELAY:
498 			status = HandleGetSetKeyRepeatDelay(message, &reply);
499 			break;
500 		case IS_GET_KEY_INFO:
501 			status = HandleGetKeyInfo(message, &reply);
502 			break;
503 		case IS_GET_MODIFIERS:
504 			status = HandleGetModifiers(message, &reply);
505 			break;
506 		case IS_SET_MODIFIER_KEY:
507 			status = HandleSetModifierKey(message, &reply);
508 			break;
509 		case IS_SET_KEYBOARD_LOCKS:
510 			status = HandleSetKeyboardLocks(message, &reply);
511 			break;
512 		case IS_GET_MOUSE_SPEED:
513 			status = HandleGetSetMouseSpeed(message, &reply);
514 			break;
515 		case IS_SET_MOUSE_SPEED:
516 			status = HandleGetSetMouseSpeed(message, &reply);
517 			break;
518 		case IS_SET_MOUSE_POSITION:
519 			status = HandleSetMousePosition(message, &reply);
520 			break;
521 		case IS_GET_MOUSE_MAP:
522 			status = HandleGetSetMouseMap(message, &reply);
523 			break;
524 		case IS_SET_MOUSE_MAP:
525 			status = HandleGetSetMouseMap(message, &reply);
526 			break;
527 		case IS_GET_KEYBOARD_ID:
528 			status = HandleGetKeyboardID(message, &reply);
529 			break;
530 		case IS_GET_CLICK_SPEED:
531 			status = HandleGetSetClickSpeed(message, &reply);
532 			break;
533 		case IS_SET_CLICK_SPEED:
534 			status = HandleGetSetClickSpeed(message, &reply);
535 			break;
536 		case IS_GET_KEY_REPEAT_RATE:
537 			status = HandleGetSetKeyRepeatRate(message, &reply);
538 			break;
539 		case IS_SET_KEY_REPEAT_RATE:
540 			status = HandleGetSetKeyRepeatRate(message, &reply);
541 			break;
542 		case IS_GET_KEY_MAP:
543 			status = HandleGetSetKeyMap(message, &reply);
544 			break;
545 		case IS_RESTORE_KEY_MAP:
546 			status = HandleGetSetKeyMap(message, &reply);
547 			break;
548 		case IS_FOCUS_IM_AWARE_VIEW:
549 			status = HandleFocusUnfocusIMAwareView(message, &reply);
550 			break;
551 		case IS_UNFOCUS_IM_AWARE_VIEW:
552 			status = HandleFocusUnfocusIMAwareView(message, &reply);
553 			break;
554 
555 		// app_server communication
556 		case IS_ACQUIRE_INPUT:
557 			_AcquireInput(*message, reply);
558 			return;
559 		case IS_RELEASE_INPUT:
560 			_ReleaseInput(message);
561 			return;
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::UnregisterDevices(BInputServerDevice& serverDevice,
1054 	input_device_ref **devices)
1055 {
1056     CALLED();
1057     BAutolock lock(fInputDeviceListLocker);
1058 
1059 	if (devices != NULL) {
1060 		// remove the devices as specified only
1061 		input_device_ref *device = NULL;
1062 		for (int32 i = 0; NULL != (device = devices[i]); i++) {
1063 			for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1064 				InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1065 
1066 				if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) {
1067 					item->Stop();
1068 					fInputDeviceList.RemoveItem(j);
1069 					delete item;
1070 					break;
1071 				}
1072 			}
1073 		}
1074 	} else {
1075 		// remove all devices from this BInputServerObject
1076 		for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1077 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1078 
1079 			if (item->ServerDevice() == &serverDevice) {
1080 				item->Stop();
1081 				fInputDeviceList.RemoveItem(i);
1082 				delete item;
1083 			}
1084 		}
1085 	}
1086 
1087     return B_OK;
1088 }
1089 
1090 
1091 status_t
1092 InputServer::RegisterDevices(BInputServerDevice& serverDevice,
1093 	input_device_ref** devices)
1094 {
1095 	if (devices == NULL)
1096 		return B_BAD_VALUE;
1097 
1098 	BAutolock lock(fInputDeviceListLocker);
1099 
1100 	input_device_ref *device = NULL;
1101 	for (int32 i = 0; (device = devices[i]) != NULL; i++) {
1102 		if (device->type != B_POINTING_DEVICE
1103 			&& device->type != B_KEYBOARD_DEVICE
1104 			&& device->type != B_UNDEFINED_DEVICE)
1105 			continue;
1106 
1107 		// find existing input server device
1108 
1109 		bool found = false;
1110 		for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) {
1111 			InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j);
1112 
1113 			if (item->HasName(device->name)) {
1114 				PRINT(("RegisterDevices found %s\n", device->name));
1115 				found = true;
1116 				break;
1117 			}
1118 		}
1119 
1120 		if (!found) {
1121 			PRINT(("RegisterDevices not found %s\n", device->name));
1122 			InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice,
1123 				*device);
1124 			if (item != NULL && fInputDeviceList.AddItem(item)) {
1125 				item->Start();
1126 			} else {
1127 				delete item;
1128 				return B_NO_MEMORY;
1129 			}
1130 		}
1131 	}
1132 
1133 	return B_OK;
1134 }
1135 
1136 
1137 status_t
1138 InputServer::StartStopDevices(const char* name, input_device_type type, bool doStart)
1139 {
1140 	CALLED();
1141 	BAutolock lock(fInputDeviceListLocker);
1142 
1143 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1144 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1145 		if (!item)
1146 			continue;
1147 
1148 		if (item->Matches(name, type)) {
1149 			if (doStart)
1150 				item->Start();
1151 			else
1152 				item->Stop();
1153 
1154 			if (name)
1155 				return B_OK;
1156 		}
1157 	}
1158 
1159 	if (name)
1160 		return B_ERROR;
1161 
1162 	return B_OK;
1163 }
1164 
1165 
1166 
1167 status_t
1168 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart)
1169 {
1170 	CALLED();
1171 	BAutolock lock(fInputDeviceListLocker);
1172 
1173 	InputDeviceListItem* item = _FindInputDeviceListItem(serverDevice);
1174 	if (item != NULL) {
1175 		if (doStart)
1176 			item->Start();
1177 		else
1178 			item->Stop();
1179 	}
1180 	EXIT();
1181 
1182 	return B_OK;
1183 }
1184 
1185 
1186 status_t
1187 InputServer::ControlDevices(const char* name, input_device_type type,
1188 	uint32 code, BMessage* message)
1189 {
1190 	CALLED();
1191 	BAutolock lock(fInputDeviceListLocker);
1192 
1193 	for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) {
1194 		InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i);
1195 		if (!item)
1196 			continue;
1197 
1198 		if (item->Matches(name, type)) {
1199 			item->Control(code, message);
1200 
1201 			if (name)
1202 				return B_OK;
1203 		}
1204 	}
1205 
1206 	if (name)
1207 		return B_ERROR;
1208 
1209 	return B_OK;
1210 }
1211 
1212 
1213 bool
1214 InputServer::DoMouseAcceleration(int32* _x, int32* _y)
1215 {
1216 	CALLED();
1217 	int32 speed = fMouseSettings.MouseSpeed() >> 15;
1218 
1219 	// ToDo: implement mouse acceleration
1220 	(void)speed;
1221 	//*y = *x * speed;
1222 	PRINT(("DoMouse : %ld %ld %ld %ld\n", *x, *y, speed, fMouseSettings.MouseSpeed()));
1223 	return true;
1224 }
1225 
1226 
1227 bool
1228 InputServer::SetMousePos(long *, long *, long, long)
1229 {
1230 	CALLED();
1231 	return true;
1232 }
1233 
1234 
1235 bool
1236 InputServer::SetMousePos(long *, long *, BPoint)
1237 {
1238 	CALLED();
1239 	return true;
1240 }
1241 
1242 
1243 bool
1244 InputServer::SetMousePos(long *, long *, float, float)
1245 {
1246 	CALLED();
1247 	return true;
1248 }
1249 
1250 
1251 bool
1252 InputServer::SafeMode()
1253 {
1254 	return fSafeMode;
1255 }
1256 
1257 
1258 status_t
1259 InputServer::_StartEventLoop()
1260 {
1261 	CALLED();
1262 	fEventLooperPort = create_port(100, "input server events");
1263 	if (fEventLooperPort < 0) {
1264 		PRINTERR(("InputServer: create_port error: (0x%x) %s\n",
1265 			fEventLooperPort, strerror(fEventLooperPort)));
1266 		return fEventLooperPort;
1267 	}
1268 
1269 	thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
1270 		B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
1271 	if (thread < B_OK || resume_thread(thread) < B_OK) {
1272 		if (thread >= B_OK)
1273 			kill_thread(thread);
1274 		delete_port(fEventLooperPort);
1275 		fEventLooperPort = -1;
1276 		return thread < B_OK ? thread : B_ERROR;
1277 	}
1278 
1279 	return B_OK;
1280 }
1281 
1282 
1283 status_t
1284 InputServer::_EventLooper(void* arg)
1285 {
1286 	InputServer* self = (InputServer*)arg;
1287 	self->_EventLoop();
1288 
1289 	return B_OK;
1290 }
1291 
1292 
1293 void
1294 InputServer::_EventLoop()
1295 {
1296 	while (true) {
1297 		// Block until we find the size of the next message
1298 		ssize_t length = port_buffer_size(fEventLooperPort);
1299 		if (length < B_OK) {
1300 			PRINT("[Event Looper] port gone, exiting.\n");
1301 			return;
1302 		}
1303 
1304 		PRINT(("[Event Looper] BMessage Size = %lu\n", length));
1305 
1306 		char buffer[length];
1307 		int32 code;
1308 		status_t err = read_port(fEventLooperPort, &code, buffer, length);
1309 		if (err != length) {
1310 			if (err >= 0) {
1311 				PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length));
1312 			} else {
1313 				PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err)));
1314 			}
1315 			continue;
1316 		}
1317 
1318 		EventList events;
1319 		if (fEventQueueLock.Lock()) {
1320 			// move the items to our own list to block the event queue as short as possible
1321 			events.AddList(&fEventQueue);
1322 			fEventQueue.MakeEmpty();
1323 			fEventQueueLock.Unlock();
1324 		}
1325 
1326 		if (length > 0) {
1327 			BMessage* event = new BMessage;
1328 
1329 			if ((err = event->Unflatten(buffer)) < 0) {
1330 				PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
1331 				delete event;
1332 			}
1333 
1334 			events.AddItem(event);
1335 		}
1336 
1337 		// This is where the message should be processed.
1338 
1339 		if (_SanitizeEvents(events)
1340 			&& _MethodizeEvents(events)
1341 			&& _FilterEvents(events))
1342 			_DispatchEvents(events);
1343 	}
1344 }
1345 
1346 
1347 /** Frees events from unwanted fields, adds missing fields, and removes
1348  *	unwanted events altogether.
1349  *	As a side effect, it will also update the internal mouse states.
1350  */
1351 
1352 bool
1353 InputServer::_SanitizeEvents(EventList& events)
1354 {
1355 	CALLED();
1356 	int32 index = 0;
1357 	BMessage *event;
1358 
1359 	while ((event = (BMessage*)events.ItemAt(index)) != NULL) {
1360 		switch (event->what) {
1361 	   		case FAST_MOUSE_MOVED:
1362 	   		{
1363 				// here we test for a message coming from app_server,
1364 				// screen resolution change could have happened
1365 				BRect frame = fScreen.Frame();
1366 				if (frame != fFrame) {
1367 					fMousePos.x = fMousePos.x * frame.Width() / fFrame.Width();
1368 					fMousePos.y = fMousePos.y * frame.Height() / fFrame.Height();
1369 					fFrame = frame;
1370 				} else {
1371 					// TODO: discard event
1372 				}
1373 
1374 				event->what = B_MOUSE_MOVED;
1375 				event->AddPoint("where", fMousePos);
1376 				// supposed to fall through
1377 			}
1378 	   		case B_MOUSE_MOVED:
1379 	   		case B_MOUSE_DOWN:
1380 	   		{
1381 	   			int32 buttons;
1382 	   			if (event->FindInt32("buttons", &buttons) != B_OK)
1383 	   				event->AddInt32("buttons", 0);
1384 
1385 	   			// supposed to fall through
1386 	   		}
1387 	   		case B_MOUSE_UP:
1388 	   		{
1389 	   			BPoint where;
1390 				int32 x, y;
1391 
1392 	    		if (event->FindInt32("x", &x) == B_OK
1393 	    			&& event->FindInt32("y", &y) == B_OK) {
1394 					fMousePos.x += x;
1395 					fMousePos.y -= y;
1396 					fMousePos.ConstrainTo(fFrame);
1397 
1398 					event->RemoveName("x");
1399 					event->RemoveName("y");
1400 					event->AddPoint("where", fMousePos);
1401 
1402 					PRINT(("new position: %f, %f, %ld, %ld\n",
1403 						fMousePos.x, fMousePos.y, xValue, yValue));
1404 		   		} else if (event->FindPoint("where", &where) == B_OK) {
1405 		   			fMousePos = where;
1406 					fMousePos.ConstrainTo(fFrame);
1407 
1408 					event->ReplacePoint("where", fMousePos);
1409 					PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
1410 				}
1411 
1412 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1413 				break;
1414 	   		}
1415 			case B_KEY_DOWN:
1416 			case B_UNMAPPED_KEY_DOWN:
1417 				if (fActiveMethod == NULL)
1418 					break;
1419 
1420 				// we scan for Alt+Space key down events which means we change
1421 				// to next input method
1422 				// (pressing "shift" will let us switch to the previous method)
1423 
1424 				PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers,
1425 					fKeyInfo.key_states[KEY_Spacebar >> 3]));
1426 
1427 				if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0
1428 					&& (fKeyInfo.key_states[KEY_Spacebar >> 3]
1429 						& (1 << (7 - (KEY_Spacebar % 8))))) {
1430 					SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY);
1431 
1432 					// this event isn't sent to the user
1433 					events.RemoveItemAt(index);
1434 					delete event;
1435 					continue;
1436 				}
1437 				break;
1438 		}
1439 
1440 		index++;
1441 	}
1442 
1443 	return true;
1444 }
1445 
1446 
1447 /** Applies the filters of the active input method to the
1448  *	incoming events. It will also move the events in the method
1449  *	queue to the event list.
1450  */
1451 
1452 bool
1453 InputServer::_MethodizeEvents(EventList& events)
1454 {
1455 	CALLED();
1456 
1457 	if (fActiveMethod == NULL)
1458 		return true;
1459 
1460 	int32 count = events.CountItems();
1461 	for (int32 i = 0; i < count;) {
1462 		_FilterEvent(fActiveMethod, events, i, count);
1463 	}
1464 
1465 	if (!fInputMethodAware) {
1466 		// special handling for non-input-method-aware views
1467 		for (int32 i = 0; i < count; i++) {
1468 			BMessage* event = events.ItemAt(i);
1469 
1470 			if (event->what != B_INPUT_METHOD_EVENT)
1471 				continue;
1472 
1473 			SERIAL_PRINT(("IME received\n"));
1474 
1475 			int32 opcode;
1476 			if (fInputMethodWindow == NULL
1477 				&& event->FindInt32("be:opcode", &opcode) == B_OK
1478 				&& opcode == B_INPUT_METHOD_STARTED)
1479 				fInputMethodWindow = new (nothrow) BottomlineWindow();
1480 
1481 			if (fInputMethodWindow != NULL) {
1482 				EventList newEvents;
1483 				fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
1484 
1485 				if (!newEvents.IsEmpty()) {
1486 					fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
1487 					fInputMethodWindow = NULL;
1488 
1489 					// replace event with new events (but don't scan them again
1490 					// for input method messages)
1491 					events.RemoveItemAt(i);
1492 					delete event;
1493 
1494 					events.AddList(&newEvents, i);
1495 					i += newEvents.CountItems() - 1;
1496 					count = events.CountItems();
1497 				}
1498 			}
1499 		}
1500 	}
1501 
1502 	// move the method events into the event queue - they are not
1503 	// "methodized" either
1504 	BAutolock _(fEventQueueLock);
1505 	events.AddList(&fMethodQueue);
1506 	fMethodQueue.MakeEmpty();
1507 
1508 	return events.CountItems() > 0;
1509 }
1510 
1511 
1512 /**	This method applies all defined filters to each event in the
1513  *	supplied list.  The supplied list is modified to reflect the
1514  *	output of the filters.
1515  *	The method returns true if the filters were applied to all
1516  *	events without error and false otherwise.
1517  */
1518 
1519 bool
1520 InputServer::_FilterEvents(EventList& events)
1521 {
1522 	CALLED();
1523 	BAutolock _(gInputFilterListLocker);
1524 
1525 	int32 count = gInputFilterList.CountItems();
1526 	int32 eventCount = events.CountItems();
1527 
1528 	for (int32 i = 0; i < count; i++) {
1529 		BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
1530 
1531 		// Apply the current filter to all available event messages.
1532 
1533 		for (int32 eventIndex = 0; eventIndex < eventCount;) {
1534 			_FilterEvent(filter, events, eventIndex, eventCount);
1535 		}
1536 	}
1537 
1538 	return eventCount != 0;
1539 }
1540 
1541 
1542 void
1543 InputServer::_DispatchEvents(EventList& events)
1544 {
1545 	CALLED();
1546 
1547 	int32 count = events.CountItems();
1548 
1549 	for (int32 i = 0; i < count; i++) {
1550 		BMessage* event = events.ItemAt(i);
1551 
1552 		// now we must send each event to the app_server
1553 		_DispatchEvent(event);
1554 		delete event;
1555 	}
1556 
1557 	events.MakeEmpty();
1558 }
1559 
1560 
1561 /**	Applies the given filter to the event list.
1562  *	For your convenience, it also alters the \a index and \a count arguments
1563  *	ready for the next call to this method.
1564  */
1565 
1566 void
1567 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
1568 	int32& index, int32& count)
1569 {
1570 	BMessage* event = events.ItemAt(index);
1571 
1572 	BList newEvents;
1573 	filter_result result = filter->Filter(event, &newEvents);
1574 
1575 	if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
1576 		// we no longer need the current event
1577 		events.RemoveItemAt(index);
1578 		delete event;
1579 
1580 		if (result == B_DISPATCH_MESSAGE) {
1581 			// add the new events - but don't methodize them again
1582 			events.AsBList()->AddList(&newEvents, index);
1583 			index += newEvents.CountItems();
1584 			count = events.CountItems();
1585 		} else
1586 			count--;
1587 	} else
1588 		index++;
1589 }
1590 
1591 
1592 status_t
1593 InputServer::_DispatchEvent(BMessage* event)
1594 {
1595 	CALLED();
1596 
1597    	switch (event->what) {
1598 		case B_MOUSE_MOVED:
1599 		case B_MOUSE_DOWN:
1600 		case B_MOUSE_UP:
1601 			if (fCursorBuffer) {
1602 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
1603 				fCursorBuffer[0] = (0x3 << 30L)
1604                		| ((uint32)fMousePos.x & 0x7fff) << 15
1605                		| ((uint32)fMousePos.y & 0x7fff);
1606 
1607 				PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0]));
1608                 	release_sem(fCursorSem);
1609 #else
1610 				atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
1611 					| ((uint32)fMousePos.y & 0xffff));
1612 				if (atomic_or(&fCursorBuffer->read, 1) == 0)
1613 					release_sem_etc(fCursorSem, 0, B_RELEASE_ALL);
1614 #endif
1615         	}
1616         	break;
1617 
1618 		case B_KEY_DOWN:
1619 		case B_KEY_UP:
1620 		case B_UNMAPPED_KEY_DOWN:
1621 		case B_UNMAPPED_KEY_UP:
1622 		case B_MODIFIERS_CHANGED:
1623 		{
1624 			// update or add modifiers
1625 			uint32 modifiers;
1626 			if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
1627 				fKeyInfo.modifiers = modifiers;
1628 			else
1629 				event->AddInt32("modifiers", fKeyInfo.modifiers);
1630 
1631 			// update or add key states
1632 			const uint8 *data;
1633 			ssize_t size;
1634 			if (event->FindData("states", B_UINT8_TYPE,
1635 					(const void**)&data, &size) == B_OK) {
1636 				PRINT(("updated keyinfo\n"));
1637 				if (size == sizeof(fKeyInfo.key_states))
1638 					memcpy(fKeyInfo.key_states, data, size);
1639 			} else {
1640 				event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
1641 					sizeof(fKeyInfo.key_states));
1642 			}
1643 
1644 			PRINT(("keyinfo %ld %ld\n", size, (ssize_t)sizeof(fKeyInfo.key_states)));
1645 			break;
1646 		}
1647 
1648    		default:
1649 			break;
1650 	}
1651 
1652 #if defined(HAIKU_TARGET_PLATFORM_HAIKU) && defined(USING_MESSAGE4)
1653 	BMessenger reply;
1654 	BMessage::Private messagePrivate(event);
1655 	return messagePrivate.SendMessage(fAppServerPort, 0, true, 0, false, reply);
1656 #else
1657 	ssize_t length = event->FlattenedSize();
1658 	char buffer[length];
1659 	status_t err;
1660 	if ((err = event->Flatten(buffer,length)) < B_OK)
1661 		return err;
1662 
1663 	return write_port(fAppServerPort, 0, buffer, length);
1664 #endif
1665 }
1666 
1667 
1668 //	#pragma mark -
1669 
1670 
1671 extern "C" void
1672 RegisterDevices(input_device_ref** devices)
1673 {
1674 	CALLED();
1675 };
1676 
1677 
1678 BView *
1679 instantiate_deskbar_item()
1680 {
1681 	return new MethodReplicant(INPUTSERVER_SIGNATURE);
1682 }
1683 
1684 
1685 int
1686 main()
1687 {
1688 	InputServer	*inputServer = new InputServer;
1689 
1690 	inputServer->Run();
1691 	delete inputServer;
1692 
1693 	return 0;
1694 }
1695 
1696 
1697