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