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