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