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