2 * Copyright 2002-2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
7 #include "InputServer.h"
8 #include "InputServerTypes.h"
9 #include "BottomlineWindow.h"
10 #include "MethodReplicant.h"
12 #include <driver_settings.h>
13 #include <keyboard_mouse_driver.h>
14 #include <safemode_defs.h>
17 #include <AppServerLink.h>
18 #include <MessagePrivate.h>
19 #include <ObjectListPrivate.h>
20 #include <RosterPrivate.h>
24 #include <Directory.h>
27 #include <FindDirectory.h>
38 #include "SystemKeymap.h"
39 // this is an automatically generated file
41 #include <ServerProtocol.h>
46 // Global InputServer member variables.
48 InputServer
* gInputServer
;
50 BList
InputServer::gInputFilterList
;
51 BLocker
InputServer::gInputFilterListLocker("is_filter_queue_sem");
53 BList
InputServer::gInputMethodList
;
54 BLocker
InputServer::gInputMethodListLocker("is_method_queue_sem");
56 KeymapMethod
InputServer::gKeymapMethod
;
59 extern "C" _EXPORT BView
* instantiate_deskbar_item();
62 // #pragma mark - InputDeviceListItem
65 InputDeviceListItem::InputDeviceListItem(BInputServerDevice
& serverDevice
,
66 const input_device_ref
& device
)
68 fServerDevice(&serverDevice
),
72 fDevice
.name
= strdup(device
.name
);
73 fDevice
.type
= device
.type
;
74 fDevice
.cookie
= device
.cookie
;
78 InputDeviceListItem::~InputDeviceListItem()
85 InputDeviceListItem::Start()
87 PRINT((" Starting: %s\n", fDevice
.name
));
88 status_t err
= fServerDevice
->Start(fDevice
.name
, fDevice
.cookie
);
90 PRINTERR((" error: %s (%lx)\n", strerror(err
), err
));
92 fRunning
= err
== B_OK
;
97 InputDeviceListItem::Stop()
99 PRINT((" Stopping: %s\n", fDevice
.name
));
100 fServerDevice
->Stop(fDevice
.name
, fDevice
.cookie
);
106 InputDeviceListItem::Control(uint32 code
, BMessage
* message
)
108 fServerDevice
->Control(fDevice
.name
, fDevice
.cookie
, code
, message
);
113 InputDeviceListItem::HasName(const char* name
) const
118 return !strcmp(name
, fDevice
.name
);
123 InputDeviceListItem::HasType(input_device_type type
) const
125 return type
== fDevice
.type
;
130 InputDeviceListItem::Matches(const char* name
, input_device_type type
) const
133 return HasName(name
);
135 return HasType(type
);
142 InputServer::InputServer()
144 BApplication(INPUTSERVER_SIGNATURE
),
146 fInputDeviceListLocker("input server device list"),
150 fScreen(B_MAIN_SCREEN_ID
),
151 fEventQueueLock("input server event queue"),
152 fReplicantMessenger(NULL
),
153 fInputMethodWindow(NULL
),
154 fInputMethodAware(false),
163 set_thread_priority(find_thread(NULL
), B_URGENT_DISPLAY_PRIORITY
);
164 // elevate priority for client interaction
168 _InitKeyboardMouseStates();
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();
184 BMessenger
messenger(this);
185 BRoster().StartWatching(messenger
, B_REQUEST_LAUNCHED
);
189 InputServer::~InputServer()
192 if (fAddOnManager
->Lock())
193 fAddOnManager
->Quit();
200 InputServer::ArgvReceived(int32 argc
, char** argv
)
204 if (argc
== 2 && strcmp(argv
[1], "-q") == 0) {
205 PRINT(("InputServer::ArgvReceived - Restarting ...\n"));
206 PostMessage(B_QUIT_REQUESTED
);
212 InputServer::_InitKeyboardMouseStates()
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.
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));
225 memset(&fKeyInfo
, 0, sizeof(fKeyInfo
));
227 if (_LoadKeymap() != B_OK
)
230 BMessage
msg(B_MOUSE_MOVED
);
231 HandleSetMousePosition(&msg
, &msg
);
233 fActiveMethod
= &gKeymapMethod
;
238 InputServer::_LoadKeymap()
241 if (find_directory(B_USER_SETTINGS_DIRECTORY
, &path
) != B_OK
)
244 path
.Append("Key_map");
248 BFile
file(path
.Path(), B_READ_ONLY
);
249 if ((err
= file
.InitCheck()) != B_OK
)
252 if (file
.Read(&fKeys
, sizeof(fKeys
)) < (ssize_t
)sizeof(fKeys
))
255 for (uint32 i
= 0; i
< sizeof(fKeys
) / 4; i
++)
256 ((uint32
*)&fKeys
)[i
] = B_BENDIAN_TO_HOST_INT32(((uint32
*)&fKeys
)[i
]);
258 if (file
.Read(&fCharsSize
, sizeof(uint32
)) < (ssize_t
)sizeof(uint32
))
261 fCharsSize
= B_BENDIAN_TO_HOST_INT32(fCharsSize
);
266 fChars
= new (nothrow
) char[fCharsSize
];
270 if (file
.Read(fChars
, fCharsSize
) != (signed)fCharsSize
)
278 InputServer::_LoadSystemKeymap()
281 fKeys
= kSystemKeymap
;
282 fCharsSize
= kSystemKeyCharsSize
;
283 fChars
= new (nothrow
) char[fCharsSize
];
287 memcpy(fChars
, kSystemKeyChars
, fCharsSize
);
289 // TODO: why are we doing this?
290 return _SaveKeymap(true);
295 InputServer::_SaveKeymap(bool isDefault
)
297 // we save this keymap to file
299 if (find_directory(B_USER_SETTINGS_DIRECTORY
, &path
) != B_OK
)
302 path
.Append("Key_map");
305 status_t err
= file
.SetTo(path
.Path(), B_WRITE_ONLY
| B_CREATE_FILE
| B_ERASE_FILE
);
307 PRINTERR(("error %s\n", strerror(err
)));
311 for (uint32 i
= 0; i
< sizeof(fKeys
) / sizeof(uint32
); i
++) {
312 ((uint32
*)&fKeys
)[i
] = B_HOST_TO_BENDIAN_INT32(((uint32
*)&fKeys
)[i
]);
315 if ((err
= file
.Write(&fKeys
, sizeof(fKeys
))) < (ssize_t
)sizeof(fKeys
))
318 for (uint32 i
= 0; i
< sizeof(fKeys
) / sizeof(uint32
); i
++) {
319 ((uint32
*)&fKeys
)[i
] = B_BENDIAN_TO_HOST_INT32(((uint32
*)&fKeys
)[i
]);
322 uint32 size
= B_HOST_TO_BENDIAN_INT32(fCharsSize
);
324 if ((err
= file
.Write(&size
, sizeof(uint32
))) < (ssize_t
)sizeof(uint32
))
327 if ((err
= file
.Write(fChars
, fCharsSize
)) < (ssize_t
)fCharsSize
)
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
334 file
.WriteAttr("keymap:name", B_STRING_TYPE
, 0, kSystemKeymapName
, strlen(kSystemKeymapName
));
341 InputServer::QuitRequested()
344 if (!BApplication::QuitRequested())
347 PostMessage(SYSTEM_SHUTTING_DOWN
);
349 bool shutdown
= false;
350 CurrentMessage()->FindBool("_shutdown_", &shutdown
);
352 // Don't actually quit when the system is being shutdown
356 fAddOnManager
->SaveState();
358 delete_port(fEventLooperPort
);
359 // the event looper thread will exit after this
360 fEventLooperPort
= -1;
367 InputServer::ReadyToRun()
371 // say hello to the app_server
373 BPrivate::AppServerLink link
;
374 link
.StartMessage(AS_REGISTER_INPUT_SERVER
);
380 InputServer::_AcquireInput(BMessage
& message
, BMessage
& reply
)
382 // TODO: it currently just gets everything we have
384 if (message
.FindInt32("cursor area", &area
) == B_OK
) {
385 // try to clone the area
386 fCursorBuffer
= NULL
;
388 fCursorSem
= create_sem(0, "cursor semaphore");
389 if (fCursorSem
>= B_OK
) {
390 fCursorArea
= clone_area("input server cursor", (void**)&fCursorBuffer
,
391 B_ANY_ADDRESS
, B_READ_AREA
| B_WRITE_AREA
, area
);
395 if (message
.FindInt32("remote team", &fAppServerTeam
) != B_OK
)
398 fAppServerPort
= create_port(200, "input server target");
399 if (fAppServerPort
< B_OK
) {
400 _ReleaseInput(&message
);
401 return fAppServerPort
;
404 reply
.AddBool("has keyboard", true);
405 reply
.AddBool("has mouse", true);
406 reply
.AddInt32("event port", fAppServerPort
);
408 if (fCursorBuffer
!= NULL
) {
409 // cursor shared buffer is supported
410 reply
.AddInt32("cursor semaphore", fCursorSem
);
418 InputServer::_ReleaseInput(BMessage
* /*message*/)
420 if (fCursorBuffer
!= NULL
) {
421 fCursorBuffer
= NULL
;
422 delete_sem(fCursorSem
);
423 delete_area(fCursorArea
);
429 delete_port(fAppServerPort
);
434 InputServer::MessageReceived(BMessage
* message
)
439 status_t status
= B_OK
;
441 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__
, (char)(message
->what
>> 24),
442 (char)(message
->what
>> 16), (char)(message
->what
>> 8), (char)message
->what
));
444 switch (message
->what
) {
446 HandleSetMethod(message
);
448 case IS_GET_MOUSE_TYPE
:
449 status
= HandleGetSetMouseType(message
, &reply
);
451 case IS_SET_MOUSE_TYPE
:
452 status
= HandleGetSetMouseType(message
, &reply
);
454 case IS_GET_MOUSE_ACCELERATION
:
455 status
= HandleGetSetMouseAcceleration(message
, &reply
);
457 case IS_SET_MOUSE_ACCELERATION
:
458 status
= HandleGetSetMouseAcceleration(message
, &reply
);
460 case IS_GET_KEY_REPEAT_DELAY
:
461 status
= HandleGetSetKeyRepeatDelay(message
, &reply
);
463 case IS_SET_KEY_REPEAT_DELAY
:
464 status
= HandleGetSetKeyRepeatDelay(message
, &reply
);
466 case IS_GET_KEY_INFO
:
467 status
= HandleGetKeyInfo(message
, &reply
);
469 case IS_GET_MODIFIERS
:
470 status
= HandleGetModifiers(message
, &reply
);
472 case IS_GET_MODIFIER_KEY
:
473 status
= HandleGetModifierKey(message
, &reply
);
475 case IS_SET_MODIFIER_KEY
:
476 status
= HandleSetModifierKey(message
, &reply
);
478 case IS_SET_KEYBOARD_LOCKS
:
479 status
= HandleSetKeyboardLocks(message
, &reply
);
481 case IS_GET_MOUSE_SPEED
:
482 status
= HandleGetSetMouseSpeed(message
, &reply
);
484 case IS_SET_MOUSE_SPEED
:
485 status
= HandleGetSetMouseSpeed(message
, &reply
);
487 case IS_SET_MOUSE_POSITION
:
488 status
= HandleSetMousePosition(message
, &reply
);
490 case IS_GET_MOUSE_MAP
:
491 status
= HandleGetSetMouseMap(message
, &reply
);
493 case IS_SET_MOUSE_MAP
:
494 status
= HandleGetSetMouseMap(message
, &reply
);
496 case IS_GET_KEYBOARD_ID
:
497 status
= HandleGetSetKeyboardID(message
, &reply
);
499 case IS_SET_KEYBOARD_ID
:
500 status
= HandleGetSetKeyboardID(message
, &reply
);
502 case IS_GET_CLICK_SPEED
:
503 status
= HandleGetSetClickSpeed(message
, &reply
);
505 case IS_SET_CLICK_SPEED
:
506 status
= HandleGetSetClickSpeed(message
, &reply
);
508 case IS_GET_KEY_REPEAT_RATE
:
509 status
= HandleGetSetKeyRepeatRate(message
, &reply
);
511 case IS_SET_KEY_REPEAT_RATE
:
512 status
= HandleGetSetKeyRepeatRate(message
, &reply
);
515 status
= HandleGetSetKeyMap(message
, &reply
);
517 case IS_RESTORE_KEY_MAP
:
518 status
= HandleGetSetKeyMap(message
, &reply
);
520 case IS_FOCUS_IM_AWARE_VIEW
:
521 status
= HandleFocusUnfocusIMAwareView(message
, &reply
);
523 case IS_UNFOCUS_IM_AWARE_VIEW
:
524 status
= HandleFocusUnfocusIMAwareView(message
, &reply
);
527 // app_server communication
528 case IS_ACQUIRE_INPUT
:
529 status
= _AcquireInput(*message
, reply
);
531 case IS_RELEASE_INPUT
:
532 _ReleaseInput(message
);
534 case IS_SCREEN_BOUNDS_UPDATED
:
536 // This is what the R5 app_server sends us when the screen
537 // configuration changes
539 if (message
->FindRect("screen_bounds", &frame
) != B_OK
)
540 frame
= fScreen
.Frame();
545 BPoint
pos(fMousePos
.x
* frame
.Width() / fFrame
.Width(),
546 fMousePos
.y
* frame
.Height() / fFrame
.Height());
550 set
.AddPoint("where", pos
);
551 HandleSetMousePosition(&set
, NULL
);
555 // device looper related
556 case IS_FIND_DEVICES
:
557 case IS_WATCH_DEVICES
:
558 case IS_IS_DEVICE_RUNNING
:
559 case IS_START_DEVICE
:
561 case IS_CONTROL_DEVICES
:
562 case SYSTEM_SHUTTING_DOWN
:
563 case IS_METHOD_REGISTER
:
564 fAddOnManager
->PostMessage(message
);
567 case IS_SAVE_SETTINGS
:
568 fKeyboardSettings
.Save();
569 fMouseSettings
.SaveSettings();
576 case B_SOME_APP_LAUNCHED
:
578 const char *signature
;
579 // TODO: what's this for?
580 if (message
->FindString("be:signature", &signature
)==B_OK
) {
581 PRINT(("input_server : %s\n", signature
));
582 if (strcmp(signature
, "application/x-vnd.Be-TSKB")==0) {
589 case kMsgAppServerRestarted
:
591 BApplication::MessageReceived(message
);
592 BPrivate::AppServerLink link
;
593 link
.StartMessage(AS_REGISTER_INPUT_SERVER
);
602 reply
.AddInt32("status", status
);
603 message
->SendReply(&reply
);
608 InputServer::HandleSetMethod(BMessage
* message
)
612 if (message
->FindInt32("cookie", &cookie
) != B_OK
)
614 if (cookie
== gKeymapMethod
.fOwner
->Cookie()) {
615 SetActiveMethod(&gKeymapMethod
);
617 BAutolock
lock(InputServer::gInputMethodListLocker
);
618 for (int32 i
= 0; i
< gInputMethodList
.CountItems(); i
++) {
619 BInputServerMethod
* method
620 = (BInputServerMethod
*)InputServer::gInputMethodList
.ItemAt(i
);
621 if (method
->fOwner
->Cookie() == cookie
) {
622 PRINT(("%s cookie %" B_PRId32
"\n", __PRETTY_FUNCTION__
,
624 SetActiveMethod(method
);
633 InputServer::HandleGetSetMouseType(BMessage
* message
, BMessage
* reply
)
636 if (message
->FindInt32("mouse_type", &type
) == B_OK
) {
637 fMouseSettings
.SetMouseType(type
);
638 be_app_messenger
.SendMessage(IS_SAVE_SETTINGS
);
640 BMessage
msg(IS_CONTROL_DEVICES
);
641 msg
.AddInt32("type", B_POINTING_DEVICE
);
642 msg
.AddInt32("code", B_MOUSE_TYPE_CHANGED
);
643 return fAddOnManager
->PostMessage(&msg
);
646 return reply
->AddInt32("mouse_type", fMouseSettings
.MouseType());
651 InputServer::HandleGetSetMouseAcceleration(BMessage
* message
,
655 if (message
->FindInt32("speed", &factor
) == B_OK
) {
656 fMouseSettings
.SetAccelerationFactor(factor
);
657 be_app_messenger
.SendMessage(IS_SAVE_SETTINGS
);
659 BMessage
msg(IS_CONTROL_DEVICES
);
660 msg
.AddInt32("type", B_POINTING_DEVICE
);
661 msg
.AddInt32("code", B_MOUSE_ACCELERATION_CHANGED
);
662 return fAddOnManager
->PostMessage(&msg
);
665 return reply
->AddInt32("speed", fMouseSettings
.AccelerationFactor());
670 InputServer::HandleGetSetKeyRepeatDelay(BMessage
* message
, BMessage
* reply
)
673 if (message
->FindInt64("delay", &delay
) == B_OK
) {
674 fKeyboardSettings
.SetKeyboardRepeatDelay(delay
);
675 be_app_messenger
.SendMessage(IS_SAVE_SETTINGS
);
677 BMessage
msg(IS_CONTROL_DEVICES
);
678 msg
.AddInt32("type", B_KEYBOARD_DEVICE
);
679 msg
.AddInt32("code", B_KEY_REPEAT_DELAY_CHANGED
);
680 return fAddOnManager
->PostMessage(&msg
);
683 return reply
->AddInt64("delay", fKeyboardSettings
.KeyboardRepeatDelay());
688 InputServer::HandleGetKeyInfo(BMessage
* message
, BMessage
* reply
)
690 return reply
->AddData("key_info", B_ANY_TYPE
, &fKeyInfo
, sizeof(fKeyInfo
));
695 InputServer::HandleGetModifiers(BMessage
* message
, BMessage
* reply
)
697 return reply
->AddInt32("modifiers", fKeyInfo
.modifiers
);
702 InputServer::HandleGetModifierKey(BMessage
* message
, BMessage
* reply
)
706 if (message
->FindInt32("modifier", &modifier
) == B_OK
) {
709 return reply
->AddInt32("key", fKeys
.caps_key
);
711 return reply
->AddInt32("key", fKeys
.num_key
);
713 return reply
->AddInt32("key", fKeys
.scroll_key
);
714 case B_LEFT_SHIFT_KEY
:
715 return reply
->AddInt32("key", fKeys
.left_shift_key
);
716 case B_RIGHT_SHIFT_KEY
:
717 return reply
->AddInt32("key", fKeys
.right_shift_key
);
718 case B_LEFT_COMMAND_KEY
:
719 return reply
->AddInt32("key", fKeys
.left_command_key
);
720 case B_RIGHT_COMMAND_KEY
:
721 return reply
->AddInt32("key", fKeys
.right_command_key
);
722 case B_LEFT_CONTROL_KEY
:
723 return reply
->AddInt32("key", fKeys
.left_control_key
);
724 case B_RIGHT_CONTROL_KEY
:
725 return reply
->AddInt32("key", fKeys
.right_control_key
);
726 case B_LEFT_OPTION_KEY
:
727 return reply
->AddInt32("key", fKeys
.left_option_key
);
728 case B_RIGHT_OPTION_KEY
:
729 return reply
->AddInt32("key", fKeys
.right_option_key
);
731 return reply
->AddInt32("key", fKeys
.menu_key
);
739 InputServer::HandleSetModifierKey(BMessage
* message
, BMessage
* reply
)
742 if (message
->FindInt32("modifier", &modifier
) == B_OK
743 && message
->FindInt32("key", &key
) == B_OK
) {
746 fKeys
.caps_key
= key
;
752 fKeys
.scroll_key
= key
;
754 case B_LEFT_SHIFT_KEY
:
755 fKeys
.left_shift_key
= key
;
757 case B_RIGHT_SHIFT_KEY
:
758 fKeys
.right_shift_key
= key
;
760 case B_LEFT_COMMAND_KEY
:
761 fKeys
.left_command_key
= key
;
763 case B_RIGHT_COMMAND_KEY
:
764 fKeys
.right_command_key
= key
;
766 case B_LEFT_CONTROL_KEY
:
767 fKeys
.left_control_key
= key
;
769 case B_RIGHT_CONTROL_KEY
:
770 fKeys
.right_control_key
= key
;
772 case B_LEFT_OPTION_KEY
:
773 fKeys
.left_option_key
= key
;
775 case B_RIGHT_OPTION_KEY
:
776 fKeys
.right_option_key
= key
;
779 fKeys
.menu_key
= key
;
785 // TODO: unmap the key ?
787 be_app_messenger
.SendMessage(IS_SAVE_KEYMAP
);
789 BMessage
msg(IS_CONTROL_DEVICES
);
790 msg
.AddInt32("type", B_KEYBOARD_DEVICE
);
791 msg
.AddInt32("code", B_KEY_MAP_CHANGED
);
792 return fAddOnManager
->PostMessage(&msg
);
800 InputServer::HandleSetKeyboardLocks(BMessage
* message
, BMessage
* reply
)
802 if (message
->FindInt32("locks", (int32
*)&fKeys
.lock_settings
) == B_OK
) {
803 be_app_messenger
.SendMessage(IS_SAVE_KEYMAP
);
805 BMessage
msg(IS_CONTROL_DEVICES
);
806 msg
.AddInt32("type", B_KEYBOARD_DEVICE
);
807 msg
.AddInt32("code", B_KEY_LOCKS_CHANGED
);
808 return fAddOnManager
->PostMessage(&msg
);
816 InputServer::HandleGetSetMouseSpeed(BMessage
* message
, BMessage
* reply
)
819 if (message
->FindInt32("speed", &speed
) == B_OK
) {
820 fMouseSettings
.SetMouseSpeed(speed
);
821 be_app_messenger
.SendMessage(IS_SAVE_SETTINGS
);
823 BMessage
msg(IS_CONTROL_DEVICES
);
824 msg
.AddInt32("type", B_POINTING_DEVICE
);
825 msg
.AddInt32("code", B_MOUSE_SPEED_CHANGED
);
826 return fAddOnManager
->PostMessage(&msg
);
829 return reply
->AddInt32("speed", fMouseSettings
.MouseSpeed());
834 InputServer::HandleSetMousePosition(BMessage
* message
, BMessage
* reply
)
839 if (message
->FindPoint("where", &where
) != B_OK
)
842 // create a new event for this and enqueue it to the event list just like any other
844 BMessage
* event
= new BMessage(B_MOUSE_MOVED
);
848 event
->AddPoint("where", where
);
849 event
->AddBool("be:set_mouse", true);
850 if (EnqueueDeviceMessage(event
) != B_OK
) {
860 InputServer::HandleGetSetMouseMap(BMessage
* message
, BMessage
* reply
)
864 if (message
->FindData("mousemap", B_RAW_TYPE
, (const void**)&map
, &size
) == B_OK
) {
865 fMouseSettings
.SetMapping(*map
);
866 be_app_messenger
.SendMessage(IS_SAVE_SETTINGS
);
868 BMessage
msg(IS_CONTROL_DEVICES
);
869 msg
.AddInt32("type", B_POINTING_DEVICE
);
870 msg
.AddInt32("code", B_MOUSE_MAP_CHANGED
);
871 return fAddOnManager
->PostMessage(&msg
);
874 fMouseSettings
.Mapping(map
);
875 return reply
->AddData("mousemap", B_RAW_TYPE
, &map
, sizeof(mouse_map
));
881 InputServer::HandleGetSetKeyboardID(BMessage
* message
, BMessage
* reply
)
884 if (message
->FindInt16("id", &id
) == B_OK
) {
885 fKeyboardID
= (uint16
)id
;
888 return reply
->AddInt16("id", fKeyboardID
);
893 InputServer::HandleGetSetClickSpeed(BMessage
* message
, BMessage
* reply
)
895 bigtime_t clickSpeed
;
896 if (message
->FindInt64("speed", &clickSpeed
) == B_OK
) {
897 fMouseSettings
.SetClickSpeed(clickSpeed
);
898 be_app_messenger
.SendMessage(IS_SAVE_SETTINGS
);
900 BMessage
msg(IS_CONTROL_DEVICES
);
901 msg
.AddInt32("type", B_POINTING_DEVICE
);
902 msg
.AddInt32("code", B_CLICK_SPEED_CHANGED
);
903 return fAddOnManager
->PostMessage(&msg
);
906 return reply
->AddInt64("speed", fMouseSettings
.ClickSpeed());
911 InputServer::HandleGetSetKeyRepeatRate(BMessage
* message
, BMessage
* reply
)
914 if (message
->FindInt32("rate", &keyRepeatRate
) == B_OK
) {
915 fKeyboardSettings
.SetKeyboardRepeatRate(keyRepeatRate
);
916 be_app_messenger
.SendMessage(IS_SAVE_SETTINGS
);
918 BMessage
msg(IS_CONTROL_DEVICES
);
919 msg
.AddInt32("type", B_KEYBOARD_DEVICE
);
920 msg
.AddInt32("code", B_KEY_REPEAT_RATE_CHANGED
);
921 return fAddOnManager
->PostMessage(&msg
);
924 return reply
->AddInt32("rate", fKeyboardSettings
.KeyboardRepeatRate());
929 InputServer::HandleGetSetKeyMap(BMessage
* message
, BMessage
* reply
)
933 if (message
->what
== IS_GET_KEY_MAP
) {
934 status_t status
= reply
->AddData("keymap", B_ANY_TYPE
, &fKeys
, sizeof(fKeys
));
936 status
= reply
->AddData("key_buffer", B_ANY_TYPE
, fChars
, fCharsSize
);
941 if (_LoadKeymap() != B_OK
)
944 BMessage
msg(IS_CONTROL_DEVICES
);
945 msg
.AddInt32("type", B_KEYBOARD_DEVICE
);
946 msg
.AddInt32("code", B_KEY_MAP_CHANGED
);
947 return fAddOnManager
->PostMessage(&msg
);
952 InputServer::HandleFocusUnfocusIMAwareView(BMessage
* message
,
957 BMessenger messenger
;
958 status_t status
= message
->FindMessenger("view", &messenger
);
962 // check if current view is ours
964 if (message
->what
== IS_FOCUS_IM_AWARE_VIEW
) {
965 PRINT(("HandleFocusUnfocusIMAwareView : entering\n"));
966 fInputMethodAware
= true;
968 PRINT(("HandleFocusUnfocusIMAwareView : leaving\n"));
969 fInputMethodAware
= false;
976 /*! Enqueues the message into the event queue.
977 The message must only be deleted in case this method returns an error.
980 InputServer::EnqueueDeviceMessage(BMessage
* message
)
984 BAutolock
_(fEventQueueLock
);
985 if (!fEventQueue
.AddItem(message
))
988 if (fEventQueue
.CountItems() == 1) {
989 // notify event loop only if we haven't already done so
990 write_port_etc(fEventLooperPort
, 1, NULL
, 0, B_RELATIVE_TIMEOUT
, 0);
996 /*! Enqueues the message into the method queue.
997 The message must only be deleted in case this method returns an error.
1000 InputServer::EnqueueMethodMessage(BMessage
* message
)
1003 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__
, (char)(message
->what
>> 24),
1004 (char)(message
->what
>> 16), (char)(message
->what
>> 8), (char)message
->what
));
1007 if (message
->what
== 'IMEV') {
1009 message
->FindInt32("be:opcode", &code
);
1010 PRINT(("%s be:opcode %li\n", __PRETTY_FUNCTION__
, code
));
1014 BAutolock
_(fEventQueueLock
);
1015 if (!fMethodQueue
.AddItem(message
))
1018 if (fMethodQueue
.CountItems() == 1) {
1019 // notify event loop only if we haven't already done so
1020 write_port_etc(fEventLooperPort
, 0, NULL
, 0, B_RELATIVE_TIMEOUT
, 0);
1027 InputServer::SetNextMethod(bool direction
)
1029 gInputMethodListLocker
.Lock();
1031 int32 index
= gInputMethodList
.IndexOf(fActiveMethod
);
1032 int32 oldIndex
= index
;
1034 index
+= (direction
? 1 : -1);
1037 index
= gInputMethodList
.CountItems() - 1;
1038 if (index
>= gInputMethodList
.CountItems())
1041 if (index
== oldIndex
)
1044 BInputServerMethod
*method
= &gKeymapMethod
;
1047 method
= (BInputServerMethod
*)gInputMethodList
.ItemAt(index
);
1049 SetActiveMethod(method
);
1051 gInputMethodListLocker
.Unlock();
1057 InputServer::SetActiveMethod(BInputServerMethod
* method
)
1061 fActiveMethod
->fOwner
->MethodActivated(false);
1063 fActiveMethod
= method
;
1066 fActiveMethod
->fOwner
->MethodActivated(true);
1071 InputServer::MethodReplicant()
1073 return fReplicantMessenger
;
1078 InputServer::SetMethodReplicant(const BMessenger
* messenger
)
1080 fReplicantMessenger
= messenger
;
1085 InputServer::EventLoopRunning()
1087 return fEventLooperPort
>= B_OK
;
1092 InputServer::GetDeviceInfo(const char* name
, input_device_type
*_type
,
1095 BAutolock
lock(fInputDeviceListLocker
);
1097 for (int32 i
= fInputDeviceList
.CountItems() - 1; i
>= 0; i
--) {
1098 InputDeviceListItem
* item
= (InputDeviceListItem
*)fInputDeviceList
.ItemAt(i
);
1100 if (item
->HasName(name
)) {
1102 *_type
= item
->Type();
1104 *_isRunning
= item
->Running();
1110 return B_NAME_NOT_FOUND
;
1115 InputServer::GetDeviceInfos(BMessage
*msg
)
1118 BAutolock
lock(fInputDeviceListLocker
);
1120 for (int32 i
= fInputDeviceList
.CountItems() - 1; i
>= 0; i
--) {
1121 InputDeviceListItem
* item
= (InputDeviceListItem
*)fInputDeviceList
.ItemAt(i
);
1122 msg
->AddString("device", item
->Name());
1123 msg
->AddInt32("type", item
->Type());
1130 InputServer::UnregisterDevices(BInputServerDevice
& serverDevice
,
1131 input_device_ref
**devices
)
1134 BAutolock
lock(fInputDeviceListLocker
);
1136 if (devices
!= NULL
) {
1137 // remove the devices as specified only
1138 input_device_ref
*device
= NULL
;
1139 for (int32 i
= 0; (device
= devices
[i
]) != NULL
; i
++) {
1140 for (int32 j
= fInputDeviceList
.CountItems() - 1; j
>= 0; j
--) {
1141 InputDeviceListItem
* item
= (InputDeviceListItem
*)fInputDeviceList
.ItemAt(j
);
1143 if (item
->ServerDevice() == &serverDevice
&& item
->HasName(device
->name
)) {
1145 if (fInputDeviceList
.RemoveItem(j
))
1152 // remove all devices from this BInputServerObject
1153 for (int32 i
= fInputDeviceList
.CountItems() - 1; i
>= 0; i
--) {
1154 InputDeviceListItem
* item
= (InputDeviceListItem
*)fInputDeviceList
.ItemAt(i
);
1156 if (item
->ServerDevice() == &serverDevice
) {
1158 if (fInputDeviceList
.RemoveItem(i
))
1169 InputServer::RegisterDevices(BInputServerDevice
& serverDevice
,
1170 input_device_ref
** devices
)
1172 if (devices
== NULL
)
1175 BAutolock
lock(fInputDeviceListLocker
);
1177 input_device_ref
*device
= NULL
;
1178 for (int32 i
= 0; (device
= devices
[i
]) != NULL
; i
++) {
1179 if (device
->type
!= B_POINTING_DEVICE
1180 && device
->type
!= B_KEYBOARD_DEVICE
1181 && device
->type
!= B_UNDEFINED_DEVICE
)
1184 // find existing input server device
1187 for (int32 j
= fInputDeviceList
.CountItems() - 1; j
>= 0; j
--) {
1188 InputDeviceListItem
* item
= (InputDeviceListItem
*)fInputDeviceList
.ItemAt(j
);
1190 if (item
->HasName(device
->name
)) {
1191 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device
->name
);
1192 PRINT(("RegisterDevices found %s\n", device
->name
));
1199 PRINT(("RegisterDevices not found %s\n", device
->name
));
1200 InputDeviceListItem
* item
= new (nothrow
) InputDeviceListItem(serverDevice
,
1202 if (item
!= NULL
&& fInputDeviceList
.AddItem(item
)) {
1216 InputServer::StartStopDevices(const char* name
, input_device_type type
,
1220 BAutolock
lock(fInputDeviceListLocker
);
1222 for (int32 i
= fInputDeviceList
.CountItems() - 1; i
>= 0; i
--) {
1223 InputDeviceListItem
* item
1224 = (InputDeviceListItem
*)fInputDeviceList
.ItemAt(i
);
1228 if (item
->Matches(name
, type
)) {
1229 if (doStart
== item
->Running()) {
1257 InputServer::StartStopDevices(BInputServerDevice
& serverDevice
, bool doStart
)
1260 BAutolock
lock(fInputDeviceListLocker
);
1262 for (int32 i
= fInputDeviceList
.CountItems() - 1; i
>= 0; i
--) {
1263 InputDeviceListItem
* item
= (InputDeviceListItem
*)fInputDeviceList
.ItemAt(i
);
1265 if (item
->ServerDevice() != &serverDevice
)
1268 if (doStart
== item
->Running())
1282 InputServer::ControlDevices(const char* name
, input_device_type type
,
1283 uint32 code
, BMessage
* message
)
1286 BAutolock
lock(fInputDeviceListLocker
);
1288 for (int32 i
= fInputDeviceList
.CountItems() - 1; i
>= 0; i
--) {
1289 InputDeviceListItem
* item
= (InputDeviceListItem
*)fInputDeviceList
.ItemAt(i
);
1293 if (item
->Matches(name
, type
)) {
1294 item
->Control(code
, message
);
1309 InputServer::SafeMode()
1312 size_t parameterLength
= sizeof(parameter
);
1314 if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE
, parameter
,
1315 ¶meterLength
) == B_OK
) {
1316 if (!strcasecmp(parameter
, "enabled") || !strcasecmp(parameter
, "on")
1317 || !strcasecmp(parameter
, "true") || !strcasecmp(parameter
, "yes")
1318 || !strcasecmp(parameter
, "enable") || !strcmp(parameter
, "1")) {
1323 if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS
, parameter
,
1324 ¶meterLength
) == B_OK
) {
1325 if (!strcasecmp(parameter
, "enabled") || !strcasecmp(parameter
, "on")
1326 || !strcasecmp(parameter
, "true") || !strcasecmp(parameter
, "yes")
1327 || !strcasecmp(parameter
, "enable") || !strcmp(parameter
, "1")) {
1337 InputServer::_StartEventLoop()
1340 fEventLooperPort
= create_port(100, "input server events");
1341 if (fEventLooperPort
< 0) {
1342 PRINTERR(("InputServer: create_port error: (0x%lx) %s\n",
1343 fEventLooperPort
, strerror(fEventLooperPort
)));
1344 return fEventLooperPort
;
1347 thread_id thread
= spawn_thread(_EventLooper
, "_input_server_event_loop_",
1348 B_REAL_TIME_DISPLAY_PRIORITY
+ 3, this);
1349 if (thread
< B_OK
|| resume_thread(thread
) < B_OK
) {
1351 kill_thread(thread
);
1352 delete_port(fEventLooperPort
);
1353 fEventLooperPort
= -1;
1354 return thread
< B_OK
? thread
: B_ERROR
;
1362 InputServer::_EventLooper(void* arg
)
1364 InputServer
* self
= (InputServer
*)arg
;
1372 InputServer::_EventLoop()
1375 // Block until we find the size of the next message
1376 ssize_t length
= port_buffer_size(fEventLooperPort
);
1377 if (length
< B_OK
) {
1378 PRINT(("[Event Looper] port gone, exiting.\n"));
1382 PRINT(("[Event Looper] BMessage Size = %lu\n", length
));
1384 char buffer
[length
];
1386 status_t err
= read_port(fEventLooperPort
, &code
, buffer
, length
);
1387 if (err
!= length
) {
1389 PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err
, length
));
1391 PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err
, strerror(err
)));
1397 if (fEventQueueLock
.Lock()) {
1398 // move the items to our own list to block the event queue as short as possible
1399 events
.AddList(&fEventQueue
);
1400 fEventQueue
.MakeEmpty();
1401 fEventQueueLock
.Unlock();
1405 BMessage
* event
= new BMessage
;
1407 if ((err
= event
->Unflatten(buffer
)) < 0) {
1408 PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err
, strerror(err
)));
1413 events
.AddItem(event
);
1416 // This is where the message should be processed.
1418 if (_SanitizeEvents(events
)
1419 && _MethodizeEvents(events
)
1420 && _FilterEvents(events
)) {
1421 _UpdateMouseAndKeys(events
);
1422 _DispatchEvents(events
);
1428 /*! Updates the internal mouse position and keyboard info. */
1430 InputServer::_UpdateMouseAndKeys(EventList
& events
)
1432 for (int32 index
= 0;BMessage
* event
= (BMessage
*)events
.ItemAt(index
);
1434 switch (event
->what
) {
1438 event
->FindPoint("where", &fMousePos
);
1442 case B_UNMAPPED_KEY_DOWN
:
1445 if (event
->FindInt32("modifiers", (int32
*)&modifiers
) == B_OK
)
1446 fKeyInfo
.modifiers
= modifiers
;
1448 // update key states
1451 if (event
->FindData("states", B_UINT8_TYPE
,
1452 (const void**)&data
, &size
) == B_OK
) {
1453 PRINT(("updated keyinfo\n"));
1454 if (size
== sizeof(fKeyInfo
.key_states
))
1455 memcpy(fKeyInfo
.key_states
, data
, size
);
1458 if (fActiveMethod
== NULL
)
1461 // we scan for Alt+Space key down events which means we change
1462 // to next input method
1463 // (pressing "shift" will let us switch to the previous method)
1465 // If there is only one input method, SetNextMethod will return
1466 // B_BAD_INDEX and the event will be forwarded to the user.
1468 PRINT(("SanitizeEvents: %lx, %x\n", fKeyInfo
.modifiers
,
1469 fKeyInfo
.key_states
[KEY_Spacebar
>> 3]));
1472 if (event
->FindInt8("byte", (int8
*)&byte
) < B_OK
)
1475 if ((((fKeyInfo
.modifiers
& B_COMMAND_KEY
) != 0 && byte
== ' ')
1476 || byte
== B_HANKAKU_ZENKAKU
)
1477 && SetNextMethod((fKeyInfo
.modifiers
& B_SHIFT_KEY
) == 0)
1479 // this event isn't sent to the user
1480 events
.RemoveItemAt(index
);
1490 /*! Frees events from unwanted fields, adds missing fields, and removes
1491 unwanted events altogether.
1494 InputServer::_SanitizeEvents(EventList
& events
)
1498 for (int32 index
= 0; BMessage
* event
= (BMessage
*)events
.ItemAt(index
);
1500 switch (event
->what
) {
1505 if (event
->FindInt32("buttons", &buttons
) != B_OK
)
1506 event
->AddInt32("buttons", 0);
1508 // supposed to fall through
1516 if (event
->FindInt32("x", &x
) == B_OK
1517 && event
->FindInt32("y", &y
) == B_OK
) {
1518 where
.x
= fMousePos
.x
+ x
;
1519 where
.y
= fMousePos
.y
- y
;
1521 event
->RemoveName("x");
1522 event
->RemoveName("y");
1523 event
->AddInt32("be:delta_x", x
);
1524 event
->AddInt32("be:delta_y", y
);
1526 PRINT(("new position: %f, %f, %ld, %ld\n",
1527 where
.x
, where
.y
, x
, y
));
1528 } else if (event
->FindFloat("x", &absX
) == B_OK
1529 && event
->FindFloat("y", &absY
) == B_OK
) {
1530 // The device gives us absolute screen coords in range 0..1;
1531 // convert them to absolute screen position
1532 // (the message is supposed to contain the original
1533 // absolute coordinates as "be:tablet_x/y").
1534 where
.x
= absX
* fFrame
.Width();
1535 where
.y
= absY
* fFrame
.Height();
1537 event
->RemoveName("x");
1538 event
->RemoveName("y");
1539 PRINT(("new position : %f, %f\n", where
.x
, where
.y
));
1540 } else if (event
->FindPoint("where", &where
) == B_OK
) {
1541 PRINT(("new position : %f, %f\n", where
.x
, where
.y
));
1544 // Constrain and filter the mouse coords and add the final
1545 // point to the message.
1546 where
.x
= roundf(where
.x
);
1547 where
.y
= roundf(where
.y
);
1548 where
.ConstrainTo(fFrame
);
1549 if (event
->ReplacePoint("where", where
) != B_OK
)
1550 event
->AddPoint("where", where
);
1552 if (!event
->HasInt64("when"))
1553 event
->AddInt64("when", system_time());
1555 event
->AddInt32("modifiers", fKeyInfo
.modifiers
);
1559 case B_UNMAPPED_KEY_DOWN
:
1561 if (!event
->HasInt32("modifiers"))
1562 event
->AddInt32("modifiers", fKeyInfo
.modifiers
);
1565 if (!event
->HasData("states", B_UINT8_TYPE
)) {
1566 event
->AddData("states", B_UINT8_TYPE
, fKeyInfo
.key_states
,
1567 sizeof(fKeyInfo
.key_states
));
1577 /*! Applies the filters of the active input method to the
1578 incoming events. It will also move the events in the method
1579 queue to the event list.
1582 InputServer::_MethodizeEvents(EventList
& events
)
1586 if (fActiveMethod
== NULL
)
1589 int32 count
= events
.CountItems();
1590 for (int32 i
= 0; i
< count
;) {
1591 _FilterEvent(fActiveMethod
, events
, i
, count
);
1595 // move the method events into the event queue - they are not
1596 // "methodized" either
1597 BAutolock
_(fEventQueueLock
);
1598 events
.AddList(&fMethodQueue
);
1599 fMethodQueue
.MakeEmpty();
1602 if (!fInputMethodAware
) {
1603 // special handling for non-input-method-aware views
1605 int32 newCount
= events
.CountItems();
1606 // we may add new events in this loop that don't need to be checked again
1608 for (int32 i
= 0; i
< newCount
; i
++) {
1609 BMessage
* event
= events
.ItemAt(i
);
1611 if (event
->what
!= B_INPUT_METHOD_EVENT
)
1614 SERIAL_PRINT(("IME received\n"));
1616 bool removeEvent
= true;
1619 if (event
->FindInt32("be:opcode", &opcode
) == B_OK
) {
1621 if (event
->FindBool("be:inline_only", &inlineOnly
) != B_OK
)
1625 BMessage translated
;
1627 if (opcode
== B_INPUT_METHOD_CHANGED
1628 && event
->FindBool("be:confirmed", &confirmed
) == B_OK
&& confirmed
1629 && event
->FindMessage("be:translated", &translated
) == B_OK
) {
1630 // translate event for the non-aware view
1631 *event
= translated
;
1632 removeEvent
= false;
1635 if (fInputMethodWindow
== NULL
1636 && opcode
== B_INPUT_METHOD_STARTED
)
1637 fInputMethodWindow
= new (nothrow
) BottomlineWindow();
1639 if (fInputMethodWindow
!= NULL
) {
1640 EventList newEvents
;
1641 fInputMethodWindow
->HandleInputMethodEvent(event
, newEvents
);
1643 if (!newEvents
.IsEmpty()) {
1644 events
.AddList(&newEvents
);
1645 opcode
= B_INPUT_METHOD_STOPPED
;
1648 if (opcode
== B_INPUT_METHOD_STOPPED
) {
1649 fInputMethodWindow
->PostMessage(B_QUIT_REQUESTED
);
1650 fInputMethodWindow
= NULL
;
1657 // the inline/bottom window has eaten the event
1658 events
.RemoveItemAt(i
--);
1665 return events
.CountItems() > 0;
1669 /*! This method applies all defined filters to each event in the
1670 supplied list. The supplied list is modified to reflect the
1671 output of the filters.
1672 The method returns true if the filters were applied to all
1673 events without error and false otherwise.
1676 InputServer::_FilterEvents(EventList
& events
)
1679 BAutolock
_(gInputFilterListLocker
);
1681 int32 count
= gInputFilterList
.CountItems();
1682 int32 eventCount
= events
.CountItems();
1684 for (int32 i
= 0; i
< count
; i
++) {
1685 BInputServerFilter
* filter
= (BInputServerFilter
*)gInputFilterList
.ItemAt(i
);
1687 // Apply the current filter to all available event messages.
1689 for (int32 eventIndex
= 0; eventIndex
< eventCount
;) {
1690 _FilterEvent(filter
, events
, eventIndex
, eventCount
);
1694 return eventCount
!= 0;
1699 InputServer::_DispatchEvents(EventList
& events
)
1703 int32 count
= events
.CountItems();
1705 for (int32 i
= 0; i
< count
; i
++) {
1706 BMessage
* event
= events
.ItemAt(i
);
1708 // now we must send each event to the app_server
1709 _DispatchEvent(event
);
1717 /*! Applies the given filter to the event list.
1718 For your convenience, it also alters the \a index and \a count arguments
1719 ready for the next call to this method.
1722 InputServer::_FilterEvent(BInputServerFilter
* filter
, EventList
& events
,
1723 int32
& index
, int32
& count
)
1725 BMessage
* event
= events
.ItemAt(index
);
1728 filter_result result
= filter
->Filter(event
, &newEvents
);
1730 if (result
== B_SKIP_MESSAGE
|| newEvents
.CountItems() > 0) {
1731 // we no longer need the current event
1732 events
.RemoveItemAt(index
);
1735 if (result
== B_DISPATCH_MESSAGE
) {
1736 EventList addedEvents
;
1737 EventList::Private(&addedEvents
).AsBList()->AddList(&newEvents
);
1738 _SanitizeEvents(addedEvents
);
1739 // add the new events - but don't methodize them again
1740 events
.AddList(&addedEvents
, index
);
1741 index
+= newEvents
.CountItems();
1742 count
= events
.CountItems();
1751 InputServer::_DispatchEvent(BMessage
* event
)
1755 switch (event
->what
) {
1759 if (fCursorBuffer
) {
1760 atomic_set((int32
*)&fCursorBuffer
->pos
, (uint32
)fMousePos
.x
<< 16UL
1761 | ((uint32
)fMousePos
.y
& 0xffff));
1762 if (atomic_or(&fCursorBuffer
->read
, 1) == 0)
1763 release_sem(fCursorSem
);
1769 case B_UNMAPPED_KEY_DOWN
:
1770 case B_UNMAPPED_KEY_UP
:
1771 case B_MODIFIERS_CHANGED
:
1773 // update or add modifiers
1775 if (event
->FindInt32("modifiers", (int32
*)&modifiers
) == B_OK
)
1776 fKeyInfo
.modifiers
= modifiers
;
1778 event
->AddInt32("modifiers", fKeyInfo
.modifiers
);
1780 // update or add key states
1783 if (event
->FindData("states", B_UINT8_TYPE
,
1784 (const void**)&data
, &size
) == B_OK
) {
1785 PRINT(("updated keyinfo\n"));
1786 if (size
== sizeof(fKeyInfo
.key_states
))
1787 memcpy(fKeyInfo
.key_states
, data
, size
);
1789 event
->AddData("states", B_UINT8_TYPE
, fKeyInfo
.key_states
,
1790 sizeof(fKeyInfo
.key_states
));
1801 BMessage::Private
messagePrivate(event
);
1802 return messagePrivate
.SendMessage(fAppServerPort
, fAppServerTeam
, 0, 0,
1811 RegisterDevices(input_device_ref
** devices
)
1818 instantiate_deskbar_item()
1820 return new MethodReplicant(INPUTSERVER_SIGNATURE
);
1828 main(int /*argc*/, char** /*argv*/)
1830 InputServer
*inputServer
= new InputServer
;