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