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 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 78 InputDeviceListItem::~InputDeviceListItem() 79 { 80 free(fDevice.name); 81 } 82 83 84 void 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 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 106 InputDeviceListItem::Control(uint32 code, BMessage* message) 107 { 108 fServerDevice->Control(fDevice.name, fDevice.cookie, code, message); 109 } 110 111 112 bool 113 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 123 InputDeviceListItem::HasType(input_device_type type) const 124 { 125 return type == fDevice.type; 126 } 127 128 129 bool 130 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 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 189 InputServer::~InputServer() 190 { 191 CALLED(); 192 if (fAddOnManager->Lock()) 193 fAddOnManager->Quit(); 194 195 _ReleaseInput(NULL); 196 } 197 198 199 void 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 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 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 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 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 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 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 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 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 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 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 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 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 654 InputServer::HandleGetModifiers(BMessage* message, BMessage* reply) 655 { 656 return reply->AddInt32("modifiers", fKeyInfo.modifiers); 657 } 658 659 660 status_t 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 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 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 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 MouseSettings* 792 InputServer::_RunningMouseSettings() 793 { 794 BAutolock lock(fInputDeviceListLocker); 795 796 int32 count = fInputDeviceList.CountItems(); 797 for (int32 i = 0; i < count; i++) { 798 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 799 if (item == NULL) 800 continue; 801 802 if (item->Type() == B_POINTING_DEVICE && item->Running()) 803 return _GetSettingsForMouse(item->Name()); 804 } 805 806 return &fDefaultMouseSettings; 807 } 808 809 810 void 811 InputServer::_RunningMiceSettings(BList& settings) 812 { 813 BAutolock lock(fInputDeviceListLocker); 814 815 int32 count = fInputDeviceList.CountItems(); 816 for (int32 i = 0; i < count; i++) { 817 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 818 if (item == NULL) 819 continue; 820 821 if (item->Type() == B_POINTING_DEVICE && item->Running()) 822 settings.AddItem(_GetSettingsForMouse(item->Name())); 823 } 824 } 825 826 827 MouseSettings* 828 InputServer::_GetSettingsForMouse(BString mouseName) 829 { 830 // We need something different for get and set requests when no mouse name 831 // is specified, so leave that to the caller. 832 if (mouseName.IsEmpty()) 833 return NULL; 834 835 return fMouseSettings.AddMouseSettings(mouseName); 836 } 837 838 839 status_t 840 InputServer::HandleGetSetMouseType(BMessage* message, BMessage* reply) 841 { 842 BString mouseName; 843 message->FindString("mouse_name", &mouseName); 844 845 MouseSettings* settings = _GetSettingsForMouse(mouseName); 846 847 int32 type; 848 if (message->FindInt32("mouse_type", &type) == B_OK) { 849 if (settings == NULL) { 850 BList allSettings; 851 _RunningMiceSettings(allSettings); 852 int count = allSettings.CountItems(); 853 for (int i = 0; i < count; i++) 854 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetMouseType(type); 855 } else { 856 settings->SetMouseType(type); 857 } 858 859 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 860 861 return _PostMouseControlMessage(B_MOUSE_TYPE_CHANGED, mouseName); 862 } 863 864 if (settings == NULL) 865 settings = _RunningMouseSettings(); 866 return reply->AddInt32("mouse_type", settings->MouseType()); 867 } 868 869 870 status_t 871 InputServer::HandleGetSetMouseAcceleration(BMessage* message, BMessage* reply) 872 { 873 BString mouseName; 874 message->FindString("mouse_name", &mouseName); 875 876 MouseSettings* settings = _GetSettingsForMouse(mouseName); 877 878 int32 factor; 879 if (message->FindInt32("speed", &factor) == B_OK) { 880 if (settings == NULL) { 881 BList allSettings; 882 _RunningMiceSettings(allSettings); 883 int count = allSettings.CountItems(); 884 for (int i = 0; i < count; i++) 885 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetAccelerationFactor(factor); 886 } else { 887 settings->SetAccelerationFactor(factor); 888 } 889 890 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 891 892 return _PostMouseControlMessage(B_MOUSE_ACCELERATION_CHANGED, mouseName); 893 } 894 895 if (settings == NULL) 896 settings = _RunningMouseSettings(); 897 return reply->AddInt32("speed", settings->AccelerationFactor()); 898 } 899 900 901 status_t 902 InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply) 903 { 904 BString mouseName; 905 message->FindString("mouse_name", &mouseName); 906 907 MouseSettings* settings = _GetSettingsForMouse(mouseName); 908 909 int32 speed; 910 if (message->FindInt32("speed", &speed) == B_OK) { 911 if (settings == NULL) { 912 BList allSettings; 913 _RunningMiceSettings(allSettings); 914 int count = allSettings.CountItems(); 915 for (int i = 0; i < count; i++) 916 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetMouseSpeed(speed); 917 } else { 918 settings->SetMouseSpeed(speed); 919 } 920 921 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 922 923 return _PostMouseControlMessage(B_MOUSE_SPEED_CHANGED, mouseName); 924 } 925 926 if (settings == NULL) 927 settings = _RunningMouseSettings(); 928 return reply->AddInt32("speed", settings->MouseSpeed()); 929 } 930 931 932 status_t 933 InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply) 934 { 935 BString mouseName; 936 message->FindString("mouse_name", &mouseName); 937 938 MouseSettings* settings = _GetSettingsForMouse(mouseName); 939 940 mouse_map *map; 941 ssize_t size; 942 if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) { 943 if (settings == NULL) { 944 BList allSettings; 945 _RunningMiceSettings(allSettings); 946 int count = allSettings.CountItems(); 947 for (int i = 0; i < count; i++) 948 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetMapping(*map); 949 } else { 950 settings->SetMapping(*map); 951 } 952 953 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 954 955 return _PostMouseControlMessage(B_MOUSE_MAP_CHANGED, mouseName); 956 } 957 958 if (settings == NULL) 959 settings = _RunningMouseSettings(); 960 mouse_map getmap; 961 settings->Mapping(getmap); 962 return reply->AddData("mousemap", B_RAW_TYPE, &getmap, sizeof(mouse_map)); 963 } 964 965 966 status_t 967 InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply) 968 { 969 BString mouseName; 970 message->FindString("mouse_name", &mouseName); 971 972 MouseSettings* settings = _GetSettingsForMouse(mouseName); 973 974 bigtime_t clickSpeed; 975 if (message->FindInt64("speed", &clickSpeed) == B_OK) { 976 if (settings == NULL) { 977 BList allSettings; 978 _RunningMiceSettings(allSettings); 979 int count = allSettings.CountItems(); 980 for (int i = 0; i < count; i++) 981 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetClickSpeed(clickSpeed); 982 } else { 983 settings->SetClickSpeed(clickSpeed); 984 } 985 986 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 987 988 return _PostMouseControlMessage(B_CLICK_SPEED_CHANGED, mouseName); 989 } 990 991 if (settings == NULL) 992 settings = _RunningMouseSettings(); 993 return reply->AddInt64("speed", settings->ClickSpeed()); 994 } 995 996 997 status_t 998 InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply) 999 { 1000 CALLED(); 1001 1002 BPoint where; 1003 if (message->FindPoint("where", &where) != B_OK) 1004 return B_BAD_VALUE; 1005 1006 // create a new event for this and enqueue it to the event list just like any other 1007 1008 BMessage* event = new BMessage(B_MOUSE_MOVED); 1009 if (event == NULL) 1010 return B_NO_MEMORY; 1011 1012 event->AddPoint("where", where); 1013 event->AddBool("be:set_mouse", true); 1014 if (EnqueueDeviceMessage(event) != B_OK) { 1015 delete event; 1016 return B_NO_MEMORY; 1017 } 1018 1019 return B_OK; 1020 } 1021 1022 1023 // #pragma mark - Keyboard settings 1024 1025 1026 status_t 1027 InputServer::HandleGetSetKeyboardID(BMessage* message, BMessage* reply) 1028 { 1029 int16 id; 1030 if (message->FindInt16("id", &id) == B_OK) { 1031 fKeyboardID = (uint16)id; 1032 return B_OK; 1033 } 1034 return reply->AddInt16("id", fKeyboardID); 1035 } 1036 1037 1038 status_t 1039 InputServer::HandleGetSetKeyRepeatRate(BMessage* message, BMessage* reply) 1040 { 1041 int32 keyRepeatRate; 1042 if (message->FindInt32("rate", &keyRepeatRate) == B_OK) { 1043 fKeyboardSettings.SetKeyboardRepeatRate(keyRepeatRate); 1044 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 1045 1046 BMessage msg(IS_CONTROL_DEVICES); 1047 msg.AddInt32("type", B_KEYBOARD_DEVICE); 1048 msg.AddInt32("code", B_KEY_REPEAT_RATE_CHANGED); 1049 return fAddOnManager->PostMessage(&msg); 1050 } 1051 1052 return reply->AddInt32("rate", fKeyboardSettings.KeyboardRepeatRate()); 1053 } 1054 1055 1056 status_t 1057 InputServer::HandleGetSetKeyMap(BMessage* message, BMessage* reply) 1058 { 1059 CALLED(); 1060 1061 status_t status; 1062 if (message->what == IS_GET_KEY_MAP) { 1063 status = reply->AddData("keymap", B_ANY_TYPE, &fKeys, sizeof(fKeys)); 1064 if (status == B_OK) 1065 status = reply->AddData("key_buffer", B_ANY_TYPE, fChars, fCharsSize); 1066 1067 return status; 1068 } 1069 1070 status = _LoadKeymap(); 1071 if (status != B_OK) { 1072 status = _LoadSystemKeymap(); 1073 if (status != B_OK) 1074 return status; 1075 } 1076 1077 BMessage msg(IS_CONTROL_DEVICES); 1078 msg.AddInt32("type", B_KEYBOARD_DEVICE); 1079 msg.AddInt32("code", B_KEY_MAP_CHANGED); 1080 status = fAddOnManager->PostMessage(&msg); 1081 1082 if (status == B_OK) { 1083 BMessage appMsg(B_KEY_MAP_LOADED); 1084 be_roster->Broadcast(&appMsg); 1085 } 1086 1087 return status; 1088 } 1089 1090 1091 status_t 1092 InputServer::HandleFocusUnfocusIMAwareView(BMessage* message, 1093 BMessage* reply) 1094 { 1095 CALLED(); 1096 1097 BMessenger messenger; 1098 status_t status = message->FindMessenger("view", &messenger); 1099 if (status != B_OK) 1100 return status; 1101 1102 // check if current view is ours 1103 1104 if (message->what == IS_FOCUS_IM_AWARE_VIEW) { 1105 PRINT(("HandleFocusUnfocusIMAwareView : entering\n")); 1106 fInputMethodAware = true; 1107 } else { 1108 PRINT(("HandleFocusUnfocusIMAwareView : leaving\n")); 1109 fInputMethodAware = false; 1110 } 1111 1112 return B_OK; 1113 } 1114 1115 1116 /*! Enqueues the message into the event queue. 1117 The message must only be deleted in case this method returns an error. 1118 */ 1119 status_t 1120 InputServer::EnqueueDeviceMessage(BMessage* message) 1121 { 1122 CALLED(); 1123 1124 BAutolock _(fEventQueueLock); 1125 if (!fEventQueue.AddItem(message)) 1126 return B_NO_MEMORY; 1127 1128 if (fEventQueue.CountItems() == 1) { 1129 // notify event loop only if we haven't already done so 1130 write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0); 1131 } 1132 return B_OK; 1133 } 1134 1135 1136 /*! Enqueues the message into the method queue. 1137 The message must only be deleted in case this method returns an error. 1138 */ 1139 status_t 1140 InputServer::EnqueueMethodMessage(BMessage* message) 1141 { 1142 CALLED(); 1143 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, 1144 (char)(message->what >> 24), (char)(message->what >> 16), 1145 (char)(message->what >> 8), (char)message->what)); 1146 1147 #ifdef DEBUG 1148 if (message->what == 'IMEV') { 1149 int32 code; 1150 message->FindInt32("be:opcode", &code); 1151 PRINT(("%s be:opcode %" B_PRId32 "\n", __PRETTY_FUNCTION__, code)); 1152 } 1153 #endif 1154 1155 BAutolock _(fEventQueueLock); 1156 if (!fMethodQueue.AddItem(message)) 1157 return B_NO_MEMORY; 1158 1159 if (fMethodQueue.CountItems() == 1) { 1160 // notify event loop only if we haven't already done so 1161 write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0); 1162 } 1163 return B_OK; 1164 } 1165 1166 1167 status_t 1168 InputServer::SetNextMethod(bool direction) 1169 { 1170 gInputMethodListLocker.Lock(); 1171 1172 int32 index = gInputMethodList.IndexOf(fActiveMethod); 1173 int32 oldIndex = index; 1174 1175 index += (direction ? 1 : -1); 1176 1177 if (index < -1) 1178 index = gInputMethodList.CountItems() - 1; 1179 if (index >= gInputMethodList.CountItems()) 1180 index = -1; 1181 1182 if (index == oldIndex) 1183 return B_BAD_INDEX; 1184 1185 BInputServerMethod *method = &gKeymapMethod; 1186 1187 if (index != -1) 1188 method = (BInputServerMethod *)gInputMethodList.ItemAt(index); 1189 1190 SetActiveMethod(method); 1191 1192 gInputMethodListLocker.Unlock(); 1193 return B_OK; 1194 } 1195 1196 1197 void 1198 InputServer::SetActiveMethod(BInputServerMethod* method) 1199 { 1200 CALLED(); 1201 if (fActiveMethod) 1202 fActiveMethod->fOwner->MethodActivated(false); 1203 1204 fActiveMethod = method; 1205 1206 if (fActiveMethod) 1207 fActiveMethod->fOwner->MethodActivated(true); 1208 } 1209 1210 1211 const BMessenger* 1212 InputServer::MethodReplicant() 1213 { 1214 return fReplicantMessenger; 1215 } 1216 1217 1218 void 1219 InputServer::SetMethodReplicant(const BMessenger* messenger) 1220 { 1221 fReplicantMessenger = messenger; 1222 } 1223 1224 1225 bool 1226 InputServer::EventLoopRunning() 1227 { 1228 return fEventLooperPort >= B_OK; 1229 } 1230 1231 1232 status_t 1233 InputServer::GetDeviceInfo(const char* name, input_device_type *_type, 1234 bool *_isRunning) 1235 { 1236 BAutolock lock(fInputDeviceListLocker); 1237 1238 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1239 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1240 1241 if (item->HasName(name)) { 1242 if (_type) 1243 *_type = item->Type(); 1244 if (_isRunning) 1245 *_isRunning = item->Running(); 1246 1247 return B_OK; 1248 } 1249 } 1250 1251 return B_NAME_NOT_FOUND; 1252 } 1253 1254 1255 status_t 1256 InputServer::GetDeviceInfos(BMessage *msg) 1257 { 1258 CALLED(); 1259 BAutolock lock(fInputDeviceListLocker); 1260 1261 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1262 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1263 msg->AddString("device", item->Name()); 1264 msg->AddInt32("type", item->Type()); 1265 } 1266 return B_OK; 1267 } 1268 1269 1270 status_t 1271 InputServer::UnregisterDevices(BInputServerDevice& serverDevice, 1272 input_device_ref **devices) 1273 { 1274 CALLED(); 1275 BAutolock lock(fInputDeviceListLocker); 1276 1277 if (devices != NULL) { 1278 // remove the devices as specified only 1279 input_device_ref *device = NULL; 1280 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1281 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1282 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1283 1284 if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) { 1285 item->Stop(); 1286 if (fInputDeviceList.RemoveItem(j)) { 1287 BMessage message(IS_NOTIFY_DEVICE); 1288 message.AddBool("added", false); 1289 message.AddString("name", item->Name()); 1290 message.AddInt32("type", item->Type()); 1291 fAddOnManager->PostMessage(&message); 1292 delete item; 1293 } 1294 break; 1295 } 1296 } 1297 } 1298 } else { 1299 // remove all devices from this BInputServerObject 1300 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1301 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1302 1303 if (item->ServerDevice() == &serverDevice) { 1304 item->Stop(); 1305 if (fInputDeviceList.RemoveItem(i)) 1306 delete item; 1307 } 1308 } 1309 } 1310 1311 return B_OK; 1312 } 1313 1314 1315 status_t 1316 InputServer::RegisterDevices(BInputServerDevice& serverDevice, 1317 input_device_ref** devices) 1318 { 1319 if (devices == NULL) 1320 return B_BAD_VALUE; 1321 1322 BAutolock lock(fInputDeviceListLocker); 1323 1324 input_device_ref *device = NULL; 1325 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1326 if (device->type != B_POINTING_DEVICE 1327 && device->type != B_KEYBOARD_DEVICE 1328 && device->type != B_UNDEFINED_DEVICE) 1329 continue; 1330 1331 // find existing input server device 1332 1333 bool found = false; 1334 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1335 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1336 1337 if (item->HasName(device->name)) { 1338 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name); 1339 PRINT(("RegisterDevices found %s\n", device->name)); 1340 found = true; 1341 break; 1342 } 1343 } 1344 1345 if (!found) { 1346 PRINT(("RegisterDevices not found %s\n", device->name)); 1347 InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice, 1348 *device); 1349 if (item != NULL && fInputDeviceList.AddItem(item)) { 1350 item->Start(); 1351 BMessage message(IS_NOTIFY_DEVICE); 1352 message.AddBool("added", true); 1353 message.AddString("name", item->Name()); 1354 message.AddInt32("type", item->Type()); 1355 fAddOnManager->PostMessage(&message); 1356 } else { 1357 delete item; 1358 return B_NO_MEMORY; 1359 } 1360 } 1361 } 1362 1363 return B_OK; 1364 } 1365 1366 1367 status_t 1368 InputServer::StartStopDevices(const char* name, input_device_type type, 1369 bool doStart) 1370 { 1371 CALLED(); 1372 BAutolock lock(fInputDeviceListLocker); 1373 1374 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1375 InputDeviceListItem* item 1376 = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1377 if (!item) 1378 continue; 1379 1380 if (item->Matches(name, type)) { 1381 if (doStart == item->Running()) { 1382 if (name) 1383 return B_OK; 1384 else 1385 continue; 1386 } 1387 1388 if (doStart) 1389 item->Start(); 1390 else 1391 item->Stop(); 1392 1393 BMessage message(IS_NOTIFY_DEVICE); 1394 message.AddBool("started", doStart); 1395 message.AddString("name", item->Name()); 1396 message.AddInt32("type", item->Type()); 1397 fAddOnManager->PostMessage(&message); 1398 1399 if (name) 1400 return B_OK; 1401 } 1402 } 1403 1404 if (name) { 1405 // item not found 1406 return B_ERROR; 1407 } 1408 1409 return B_OK; 1410 } 1411 1412 1413 1414 status_t 1415 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart) 1416 { 1417 CALLED(); 1418 BAutolock lock(fInputDeviceListLocker); 1419 1420 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1421 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1422 1423 if (item->ServerDevice() != &serverDevice) 1424 continue; 1425 1426 if (doStart == item->Running()) 1427 continue; 1428 1429 if (doStart) 1430 item->Start(); 1431 else 1432 item->Stop(); 1433 1434 BMessage message(IS_NOTIFY_DEVICE); 1435 message.AddBool("started", doStart); 1436 message.AddString("name", item->Name()); 1437 message.AddInt32("type", item->Type()); 1438 fAddOnManager->PostMessage(&message); 1439 } 1440 1441 return B_OK; 1442 } 1443 1444 1445 status_t 1446 InputServer::ControlDevices(const char* name, input_device_type type, 1447 uint32 code, BMessage* message) 1448 { 1449 CALLED(); 1450 BAutolock lock(fInputDeviceListLocker); 1451 1452 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1453 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1454 if (!item) 1455 continue; 1456 1457 if (item->Matches(name, type)) { 1458 item->Control(code, message); 1459 1460 if (name) 1461 return B_OK; 1462 } 1463 } 1464 1465 if (name) 1466 return B_ERROR; 1467 1468 return B_OK; 1469 } 1470 1471 1472 bool 1473 InputServer::SafeMode() 1474 { 1475 char parameter[32]; 1476 size_t parameterLength = sizeof(parameter); 1477 1478 if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, 1479 ¶meterLength) == B_OK) { 1480 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1481 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1482 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1483 return true; 1484 } 1485 } 1486 1487 if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter, 1488 ¶meterLength) == B_OK) { 1489 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1490 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1491 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1492 return true; 1493 } 1494 } 1495 1496 return false; 1497 } 1498 1499 1500 status_t 1501 InputServer::_StartEventLoop() 1502 { 1503 CALLED(); 1504 fEventLooperPort = create_port(100, "input server events"); 1505 if (fEventLooperPort < 0) { 1506 PRINTERR(("InputServer: create_port error: (0x%" B_PRIx32 ") %s\n", 1507 fEventLooperPort, strerror(fEventLooperPort))); 1508 return fEventLooperPort; 1509 } 1510 1511 thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_", 1512 B_REAL_TIME_DISPLAY_PRIORITY + 3, this); 1513 if (thread < B_OK || resume_thread(thread) < B_OK) { 1514 if (thread >= B_OK) 1515 kill_thread(thread); 1516 delete_port(fEventLooperPort); 1517 fEventLooperPort = -1; 1518 return thread < B_OK ? thread : B_ERROR; 1519 } 1520 1521 return B_OK; 1522 } 1523 1524 1525 status_t 1526 InputServer::_EventLooper(void* arg) 1527 { 1528 InputServer* self = (InputServer*)arg; 1529 self->_EventLoop(); 1530 1531 return B_OK; 1532 } 1533 1534 1535 void 1536 InputServer::_EventLoop() 1537 { 1538 while (true) { 1539 // Block until we find the size of the next message 1540 ssize_t length = port_buffer_size(fEventLooperPort); 1541 if (length < B_OK) { 1542 PRINT(("[Event Looper] port gone, exiting.\n")); 1543 return; 1544 } 1545 1546 PRINT(("[Event Looper] BMessage Size = %lu\n", length)); 1547 1548 char buffer[length]; 1549 int32 code; 1550 status_t err = read_port(fEventLooperPort, &code, buffer, length); 1551 if (err != length) { 1552 if (err >= 0) { 1553 PRINTERR(("InputServer: failed to read full packet " 1554 "(read %" B_PRIu32 " of %lu)\n", err, length)); 1555 } else { 1556 PRINTERR(("InputServer: read_port error: (0x%" B_PRIx32 1557 ") %s\n", err, strerror(err))); 1558 } 1559 continue; 1560 } 1561 1562 EventList events; 1563 if (fEventQueueLock.Lock()) { 1564 // move the items to our own list to block the event queue as short 1565 // as possible 1566 events.AddList(&fEventQueue); 1567 fEventQueue.MakeEmpty(); 1568 fEventQueueLock.Unlock(); 1569 } 1570 1571 if (length > 0) { 1572 BMessage* event = new BMessage; 1573 1574 if ((err = event->Unflatten(buffer)) < 0) { 1575 PRINTERR(("[InputServer] Unflatten() error: (0x%" B_PRIx32 1576 ") %s\n", err, strerror(err))); 1577 delete event; 1578 continue; 1579 } 1580 1581 events.AddItem(event); 1582 } 1583 1584 // This is where the message should be processed. 1585 1586 if (_SanitizeEvents(events) 1587 && _MethodizeEvents(events) 1588 && _FilterEvents(events)) { 1589 _UpdateMouseAndKeys(events); 1590 _DispatchEvents(events); 1591 } 1592 } 1593 } 1594 1595 1596 /*! Updates the internal mouse position and keyboard info. */ 1597 void 1598 InputServer::_UpdateMouseAndKeys(EventList& events) 1599 { 1600 for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index); 1601 index++) { 1602 switch (event->what) { 1603 case B_MOUSE_DOWN: 1604 case B_MOUSE_UP: 1605 case B_MOUSE_MOVED: 1606 event->FindPoint("where", &fMousePos); 1607 break; 1608 1609 case B_KEY_DOWN: 1610 case B_UNMAPPED_KEY_DOWN: 1611 // update modifiers 1612 uint32 modifiers; 1613 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1614 fKeyInfo.modifiers = modifiers; 1615 1616 // update key states 1617 const uint8 *data; 1618 ssize_t size; 1619 if (event->FindData("states", B_UINT8_TYPE, 1620 (const void**)&data, &size) == B_OK) { 1621 PRINT(("updated keyinfo\n")); 1622 if (size == sizeof(fKeyInfo.key_states)) 1623 memcpy(fKeyInfo.key_states, data, size); 1624 } 1625 1626 if (fActiveMethod == NULL) 1627 break; 1628 1629 // we scan for Alt+Space key down events which means we change 1630 // to next input method 1631 // (pressing "shift" will let us switch to the previous method) 1632 1633 // If there is only one input method, SetNextMethod will return 1634 // B_BAD_INDEX and the event will be forwarded to the user. 1635 1636 PRINT(("SanitizeEvents: %" B_PRIx32 ", %x\n", fKeyInfo.modifiers, 1637 fKeyInfo.key_states[KEY_Spacebar >> 3])); 1638 1639 uint8 byte; 1640 if (event->FindInt8("byte", (int8*)&byte) < B_OK) 1641 byte = 0; 1642 1643 if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ') 1644 || byte == B_HANKAKU_ZENKAKU) 1645 && SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0) 1646 == B_OK) { 1647 // this event isn't sent to the user 1648 events.RemoveItemAt(index); 1649 delete event; 1650 continue; 1651 } 1652 break; 1653 } 1654 } 1655 } 1656 1657 1658 /*! Frees events from unwanted fields, adds missing fields, and removes 1659 unwanted events altogether. 1660 */ 1661 bool 1662 InputServer::_SanitizeEvents(EventList& events) 1663 { 1664 CALLED(); 1665 1666 for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index); 1667 index++) { 1668 switch (event->what) { 1669 case B_MOUSE_MOVED: 1670 case B_MOUSE_DOWN: 1671 { 1672 int32 buttons; 1673 if (event->FindInt32("buttons", &buttons) != B_OK) 1674 event->AddInt32("buttons", 0); 1675 1676 // supposed to fall through 1677 } 1678 case B_MOUSE_UP: 1679 { 1680 BPoint where; 1681 int32 x, y; 1682 float absX, absY; 1683 1684 if (event->FindInt32("x", &x) == B_OK 1685 && event->FindInt32("y", &y) == B_OK) { 1686 where.x = fMousePos.x + x; 1687 where.y = fMousePos.y - y; 1688 1689 event->RemoveName("x"); 1690 event->RemoveName("y"); 1691 event->AddInt32("be:delta_x", x); 1692 event->AddInt32("be:delta_y", y); 1693 1694 PRINT(("new position: %f, %f, %" B_PRId32 ", %" B_PRId32 1695 "\n", where.x, where.y, x, y)); 1696 } else if (event->FindFloat("x", &absX) == B_OK 1697 && event->FindFloat("y", &absY) == B_OK) { 1698 // The device gives us absolute screen coords in range 0..1; 1699 // convert them to absolute screen position 1700 // (the message is supposed to contain the original 1701 // absolute coordinates as "be:tablet_x/y"). 1702 where.x = absX * fFrame.Width(); 1703 where.y = absY * fFrame.Height(); 1704 1705 event->RemoveName("x"); 1706 event->RemoveName("y"); 1707 PRINT(("new position : %f, %f\n", where.x, where.y)); 1708 } else if (event->FindPoint("where", &where) == B_OK) { 1709 PRINT(("new position : %f, %f\n", where.x, where.y)); 1710 } 1711 1712 // Constrain and filter the mouse coords and add the final 1713 // point to the message. 1714 where.x = roundf(where.x); 1715 where.y = roundf(where.y); 1716 where.ConstrainTo(fFrame); 1717 if (event->ReplacePoint("where", where) != B_OK) 1718 event->AddPoint("where", where); 1719 1720 if (!event->HasInt64("when")) 1721 event->AddInt64("when", system_time()); 1722 1723 event->AddInt32("modifiers", fKeyInfo.modifiers); 1724 break; 1725 } 1726 case B_KEY_DOWN: 1727 case B_UNMAPPED_KEY_DOWN: 1728 // add modifiers 1729 if (!event->HasInt32("modifiers")) 1730 event->AddInt32("modifiers", fKeyInfo.modifiers); 1731 1732 // add key states 1733 if (!event->HasData("states", B_UINT8_TYPE)) { 1734 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1735 sizeof(fKeyInfo.key_states)); 1736 } 1737 break; 1738 } 1739 } 1740 1741 return true; 1742 } 1743 1744 1745 /*! Applies the filters of the active input method to the 1746 incoming events. It will also move the events in the method 1747 queue to the event list. 1748 */ 1749 bool 1750 InputServer::_MethodizeEvents(EventList& events) 1751 { 1752 CALLED(); 1753 1754 if (fActiveMethod == NULL) 1755 return true; 1756 1757 int32 count = events.CountItems(); 1758 for (int32 i = 0; i < count;) { 1759 _FilterEvent(fActiveMethod, events, i, count); 1760 } 1761 1762 { 1763 // move the method events into the event queue - they are not 1764 // "methodized" either 1765 BAutolock _(fEventQueueLock); 1766 events.AddList(&fMethodQueue); 1767 fMethodQueue.MakeEmpty(); 1768 } 1769 1770 if (!fInputMethodAware) { 1771 // special handling for non-input-method-aware views 1772 1773 int32 newCount = events.CountItems(); 1774 // we may add new events in this loop that don't need to be checked again 1775 1776 for (int32 i = 0; i < newCount; i++) { 1777 BMessage* event = events.ItemAt(i); 1778 1779 if (event->what != B_INPUT_METHOD_EVENT) 1780 continue; 1781 1782 SERIAL_PRINT(("IME received\n")); 1783 1784 bool removeEvent = true; 1785 1786 int32 opcode; 1787 if (event->FindInt32("be:opcode", &opcode) == B_OK) { 1788 bool inlineOnly; 1789 if (event->FindBool("be:inline_only", &inlineOnly) != B_OK) 1790 inlineOnly = false; 1791 1792 if (inlineOnly) { 1793 BMessage translated; 1794 bool confirmed; 1795 if (opcode == B_INPUT_METHOD_CHANGED 1796 && event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed 1797 && event->FindMessage("be:translated", &translated) == B_OK) { 1798 // translate event for the non-aware view 1799 *event = translated; 1800 removeEvent = false; 1801 } 1802 } else { 1803 if (fInputMethodWindow == NULL 1804 && opcode == B_INPUT_METHOD_STARTED) 1805 fInputMethodWindow = new (nothrow) BottomlineWindow(); 1806 1807 if (fInputMethodWindow != NULL) { 1808 EventList newEvents; 1809 fInputMethodWindow->HandleInputMethodEvent(event, newEvents); 1810 1811 if (!newEvents.IsEmpty()) { 1812 events.AddList(&newEvents); 1813 opcode = B_INPUT_METHOD_STOPPED; 1814 } 1815 1816 if (opcode == B_INPUT_METHOD_STOPPED) { 1817 fInputMethodWindow->PostMessage(B_QUIT_REQUESTED); 1818 fInputMethodWindow = NULL; 1819 } 1820 } 1821 } 1822 } 1823 1824 if (removeEvent) { 1825 // the inline/bottom window has eaten the event 1826 events.RemoveItemAt(i--); 1827 delete event; 1828 newCount--; 1829 } 1830 } 1831 } 1832 1833 return events.CountItems() > 0; 1834 } 1835 1836 1837 /*! This method applies all defined filters to each event in the 1838 supplied list. The supplied list is modified to reflect the 1839 output of the filters. 1840 The method returns true if the filters were applied to all 1841 events without error and false otherwise. 1842 */ 1843 bool 1844 InputServer::_FilterEvents(EventList& events) 1845 { 1846 CALLED(); 1847 BAutolock _(gInputFilterListLocker); 1848 1849 int32 count = gInputFilterList.CountItems(); 1850 int32 eventCount = events.CountItems(); 1851 1852 for (int32 i = 0; i < count; i++) { 1853 BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i); 1854 1855 // Apply the current filter to all available event messages. 1856 1857 for (int32 eventIndex = 0; eventIndex < eventCount;) { 1858 _FilterEvent(filter, events, eventIndex, eventCount); 1859 } 1860 } 1861 1862 return eventCount != 0; 1863 } 1864 1865 1866 void 1867 InputServer::_DispatchEvents(EventList& events) 1868 { 1869 CALLED(); 1870 1871 int32 count = events.CountItems(); 1872 1873 for (int32 i = 0; i < count; i++) { 1874 BMessage* event = events.ItemAt(i); 1875 1876 // now we must send each event to the app_server 1877 _DispatchEvent(event); 1878 delete event; 1879 } 1880 1881 events.MakeEmpty(); 1882 } 1883 1884 1885 /*! Applies the given filter to the event list. 1886 For your convenience, it also alters the \a index and \a count arguments 1887 ready for the next call to this method. 1888 */ 1889 void 1890 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events, 1891 int32& index, int32& count) 1892 { 1893 BMessage* event = events.ItemAt(index); 1894 1895 BList newEvents; 1896 filter_result result = filter->Filter(event, &newEvents); 1897 1898 if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) { 1899 // we no longer need the current event 1900 events.RemoveItemAt(index); 1901 delete event; 1902 1903 if (result == B_DISPATCH_MESSAGE) { 1904 EventList addedEvents; 1905 EventList::Private(&addedEvents).AsBList()->AddList(&newEvents); 1906 _SanitizeEvents(addedEvents); 1907 // add the new events - but don't methodize them again 1908 events.AddList(&addedEvents, index); 1909 index += newEvents.CountItems(); 1910 count = events.CountItems(); 1911 } else 1912 count--; 1913 } else 1914 index++; 1915 } 1916 1917 1918 status_t 1919 InputServer::_DispatchEvent(BMessage* event) 1920 { 1921 CALLED(); 1922 1923 switch (event->what) { 1924 case B_MOUSE_MOVED: 1925 case B_MOUSE_DOWN: 1926 case B_MOUSE_UP: 1927 if (fCursorBuffer) { 1928 atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL 1929 | ((uint32)fMousePos.y & 0xffff)); 1930 if (atomic_or(&fCursorBuffer->read, 1) == 0) 1931 release_sem(fCursorSem); 1932 } 1933 break; 1934 1935 case B_KEY_DOWN: 1936 case B_KEY_UP: 1937 case B_UNMAPPED_KEY_DOWN: 1938 case B_UNMAPPED_KEY_UP: 1939 case B_MODIFIERS_CHANGED: 1940 { 1941 // update or add modifiers 1942 uint32 modifiers; 1943 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1944 fKeyInfo.modifiers = modifiers; 1945 else 1946 event->AddInt32("modifiers", fKeyInfo.modifiers); 1947 1948 // update or add key states 1949 const uint8 *data; 1950 ssize_t size; 1951 if (event->FindData("states", B_UINT8_TYPE, 1952 (const void**)&data, &size) == B_OK) { 1953 PRINT(("updated keyinfo\n")); 1954 if (size == sizeof(fKeyInfo.key_states)) 1955 memcpy(fKeyInfo.key_states, data, size); 1956 } else { 1957 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1958 sizeof(fKeyInfo.key_states)); 1959 } 1960 1961 break; 1962 } 1963 1964 default: 1965 break; 1966 } 1967 1968 BMessenger reply; 1969 BMessage::Private messagePrivate(event); 1970 return messagePrivate.SendMessage(fAppServerPort, fAppServerTeam, 0, 0, 1971 false, reply); 1972 } 1973 1974 1975 // #pragma mark - 1976 1977 1978 extern "C" void 1979 RegisterDevices(input_device_ref** devices) 1980 { 1981 CALLED(); 1982 } 1983 1984 1985 BView * 1986 instantiate_deskbar_item() 1987 { 1988 return new MethodReplicant(INPUTSERVER_SIGNATURE); 1989 } 1990 1991 1992 // #pragma mark - 1993 1994 1995 int 1996 main(int /*argc*/, char** /*argv*/) 1997 { 1998 InputServer *inputServer = new InputServer; 1999 2000 inputServer->Run(); 2001 delete inputServer; 2002 2003 return 0; 2004 } 2005