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