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