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", device->name); 1254 fAddOnManager->PostMessage(&message); 1255 delete item; 1256 } 1257 break; 1258 } 1259 } 1260 } 1261 } else { 1262 // remove all devices from this BInputServerObject 1263 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1264 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1265 1266 if (item->ServerDevice() == &serverDevice) { 1267 item->Stop(); 1268 if (fInputDeviceList.RemoveItem(i)) 1269 delete item; 1270 } 1271 } 1272 } 1273 1274 return B_OK; 1275 } 1276 1277 1278 status_t 1279 InputServer::RegisterDevices(BInputServerDevice& serverDevice, 1280 input_device_ref** devices) 1281 { 1282 if (devices == NULL) 1283 return B_BAD_VALUE; 1284 1285 BAutolock lock(fInputDeviceListLocker); 1286 1287 input_device_ref *device = NULL; 1288 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1289 if (device->type != B_POINTING_DEVICE 1290 && device->type != B_KEYBOARD_DEVICE 1291 && device->type != B_UNDEFINED_DEVICE) 1292 continue; 1293 1294 // find existing input server device 1295 1296 bool found = false; 1297 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1298 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1299 1300 if (item->HasName(device->name)) { 1301 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name); 1302 PRINT(("RegisterDevices found %s\n", device->name)); 1303 found = true; 1304 break; 1305 } 1306 } 1307 1308 if (!found) { 1309 PRINT(("RegisterDevices not found %s\n", device->name)); 1310 InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice, 1311 *device); 1312 if (item != NULL && fInputDeviceList.AddItem(item)) { 1313 item->Start(); 1314 BMessage message(IS_NOTIFY_DEVICE); 1315 message.AddBool("added", true); 1316 message.AddString("name", device->name); 1317 fAddOnManager->PostMessage(&message); 1318 } else { 1319 delete item; 1320 return B_NO_MEMORY; 1321 } 1322 } 1323 } 1324 1325 return B_OK; 1326 } 1327 1328 1329 status_t 1330 InputServer::StartStopDevices(const char* name, input_device_type type, 1331 bool doStart) 1332 { 1333 CALLED(); 1334 BAutolock lock(fInputDeviceListLocker); 1335 1336 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1337 InputDeviceListItem* item 1338 = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1339 if (!item) 1340 continue; 1341 1342 if (item->Matches(name, type)) { 1343 if (doStart == item->Running()) { 1344 if (name) 1345 return B_OK; 1346 else 1347 continue; 1348 } 1349 1350 if (doStart) 1351 item->Start(); 1352 else 1353 item->Stop(); 1354 1355 if (name) 1356 return B_OK; 1357 } 1358 } 1359 1360 if (name) { 1361 // item not found 1362 return B_ERROR; 1363 } 1364 1365 return B_OK; 1366 } 1367 1368 1369 1370 status_t 1371 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart) 1372 { 1373 CALLED(); 1374 BAutolock lock(fInputDeviceListLocker); 1375 1376 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1377 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1378 1379 if (item->ServerDevice() != &serverDevice) 1380 continue; 1381 1382 if (doStart == item->Running()) 1383 continue; 1384 1385 if (doStart) 1386 item->Start(); 1387 else 1388 item->Stop(); 1389 } 1390 1391 return B_OK; 1392 } 1393 1394 1395 status_t 1396 InputServer::ControlDevices(const char* name, input_device_type type, 1397 uint32 code, BMessage* message) 1398 { 1399 CALLED(); 1400 BAutolock lock(fInputDeviceListLocker); 1401 1402 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1403 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1404 if (!item) 1405 continue; 1406 1407 if (item->Matches(name, type)) { 1408 item->Control(code, message); 1409 1410 if (name) 1411 return B_OK; 1412 } 1413 } 1414 1415 if (name) 1416 return B_ERROR; 1417 1418 return B_OK; 1419 } 1420 1421 1422 bool 1423 InputServer::SafeMode() 1424 { 1425 char parameter[32]; 1426 size_t parameterLength = sizeof(parameter); 1427 1428 if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, 1429 ¶meterLength) == B_OK) { 1430 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1431 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1432 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1433 return true; 1434 } 1435 } 1436 1437 if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter, 1438 ¶meterLength) == B_OK) { 1439 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1440 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1441 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1442 return true; 1443 } 1444 } 1445 1446 return false; 1447 } 1448 1449 1450 status_t 1451 InputServer::_StartEventLoop() 1452 { 1453 CALLED(); 1454 fEventLooperPort = create_port(100, "input server events"); 1455 if (fEventLooperPort < 0) { 1456 PRINTERR(("InputServer: create_port error: (0x%" B_PRIx32 ") %s\n", 1457 fEventLooperPort, strerror(fEventLooperPort))); 1458 return fEventLooperPort; 1459 } 1460 1461 thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_", 1462 B_REAL_TIME_DISPLAY_PRIORITY + 3, this); 1463 if (thread < B_OK || resume_thread(thread) < B_OK) { 1464 if (thread >= B_OK) 1465 kill_thread(thread); 1466 delete_port(fEventLooperPort); 1467 fEventLooperPort = -1; 1468 return thread < B_OK ? thread : B_ERROR; 1469 } 1470 1471 return B_OK; 1472 } 1473 1474 1475 status_t 1476 InputServer::_EventLooper(void* arg) 1477 { 1478 InputServer* self = (InputServer*)arg; 1479 self->_EventLoop(); 1480 1481 return B_OK; 1482 } 1483 1484 1485 void 1486 InputServer::_EventLoop() 1487 { 1488 while (true) { 1489 // Block until we find the size of the next message 1490 ssize_t length = port_buffer_size(fEventLooperPort); 1491 if (length < B_OK) { 1492 PRINT(("[Event Looper] port gone, exiting.\n")); 1493 return; 1494 } 1495 1496 PRINT(("[Event Looper] BMessage Size = %lu\n", length)); 1497 1498 char buffer[length]; 1499 int32 code; 1500 status_t err = read_port(fEventLooperPort, &code, buffer, length); 1501 if (err != length) { 1502 if (err >= 0) { 1503 PRINTERR(("InputServer: failed to read full packet " 1504 "(read %" B_PRIu32 " of %lu)\n", err, length)); 1505 } else { 1506 PRINTERR(("InputServer: read_port error: (0x%" B_PRIx32 1507 ") %s\n", err, strerror(err))); 1508 } 1509 continue; 1510 } 1511 1512 EventList events; 1513 if (fEventQueueLock.Lock()) { 1514 // move the items to our own list to block the event queue as short 1515 // as possible 1516 events.AddList(&fEventQueue); 1517 fEventQueue.MakeEmpty(); 1518 fEventQueueLock.Unlock(); 1519 } 1520 1521 if (length > 0) { 1522 BMessage* event = new BMessage; 1523 1524 if ((err = event->Unflatten(buffer)) < 0) { 1525 PRINTERR(("[InputServer] Unflatten() error: (0x%" B_PRIx32 1526 ") %s\n", err, strerror(err))); 1527 delete event; 1528 continue; 1529 } 1530 1531 events.AddItem(event); 1532 } 1533 1534 // This is where the message should be processed. 1535 1536 if (_SanitizeEvents(events) 1537 && _MethodizeEvents(events) 1538 && _FilterEvents(events)) { 1539 _UpdateMouseAndKeys(events); 1540 _DispatchEvents(events); 1541 } 1542 } 1543 } 1544 1545 1546 /*! Updates the internal mouse position and keyboard info. */ 1547 void 1548 InputServer::_UpdateMouseAndKeys(EventList& events) 1549 { 1550 for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index); 1551 index++) { 1552 switch (event->what) { 1553 case B_MOUSE_DOWN: 1554 case B_MOUSE_UP: 1555 case B_MOUSE_MOVED: 1556 event->FindPoint("where", &fMousePos); 1557 break; 1558 1559 case B_KEY_DOWN: 1560 case B_UNMAPPED_KEY_DOWN: 1561 // update modifiers 1562 uint32 modifiers; 1563 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1564 fKeyInfo.modifiers = modifiers; 1565 1566 // update key states 1567 const uint8 *data; 1568 ssize_t size; 1569 if (event->FindData("states", B_UINT8_TYPE, 1570 (const void**)&data, &size) == B_OK) { 1571 PRINT(("updated keyinfo\n")); 1572 if (size == sizeof(fKeyInfo.key_states)) 1573 memcpy(fKeyInfo.key_states, data, size); 1574 } 1575 1576 if (fActiveMethod == NULL) 1577 break; 1578 1579 // we scan for Alt+Space key down events which means we change 1580 // to next input method 1581 // (pressing "shift" will let us switch to the previous method) 1582 1583 // If there is only one input method, SetNextMethod will return 1584 // B_BAD_INDEX and the event will be forwarded to the user. 1585 1586 PRINT(("SanitizeEvents: %" B_PRIx32 ", %x\n", fKeyInfo.modifiers, 1587 fKeyInfo.key_states[KEY_Spacebar >> 3])); 1588 1589 uint8 byte; 1590 if (event->FindInt8("byte", (int8*)&byte) < B_OK) 1591 byte = 0; 1592 1593 if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ') 1594 || byte == B_HANKAKU_ZENKAKU) 1595 && SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0) 1596 == B_OK) { 1597 // this event isn't sent to the user 1598 events.RemoveItemAt(index); 1599 delete event; 1600 continue; 1601 } 1602 break; 1603 } 1604 } 1605 } 1606 1607 1608 /*! Frees events from unwanted fields, adds missing fields, and removes 1609 unwanted events altogether. 1610 */ 1611 bool 1612 InputServer::_SanitizeEvents(EventList& events) 1613 { 1614 CALLED(); 1615 1616 for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index); 1617 index++) { 1618 switch (event->what) { 1619 case B_MOUSE_MOVED: 1620 case B_MOUSE_DOWN: 1621 { 1622 int32 buttons; 1623 if (event->FindInt32("buttons", &buttons) != B_OK) 1624 event->AddInt32("buttons", 0); 1625 1626 // supposed to fall through 1627 } 1628 case B_MOUSE_UP: 1629 { 1630 BPoint where; 1631 int32 x, y; 1632 float absX, absY; 1633 1634 if (event->FindInt32("x", &x) == B_OK 1635 && event->FindInt32("y", &y) == B_OK) { 1636 where.x = fMousePos.x + x; 1637 where.y = fMousePos.y - y; 1638 1639 event->RemoveName("x"); 1640 event->RemoveName("y"); 1641 event->AddInt32("be:delta_x", x); 1642 event->AddInt32("be:delta_y", y); 1643 1644 PRINT(("new position: %f, %f, %" B_PRId32 ", %" B_PRId32 1645 "\n", where.x, where.y, x, y)); 1646 } else if (event->FindFloat("x", &absX) == B_OK 1647 && event->FindFloat("y", &absY) == B_OK) { 1648 // The device gives us absolute screen coords in range 0..1; 1649 // convert them to absolute screen position 1650 // (the message is supposed to contain the original 1651 // absolute coordinates as "be:tablet_x/y"). 1652 where.x = absX * fFrame.Width(); 1653 where.y = absY * fFrame.Height(); 1654 1655 event->RemoveName("x"); 1656 event->RemoveName("y"); 1657 PRINT(("new position : %f, %f\n", where.x, where.y)); 1658 } else if (event->FindPoint("where", &where) == B_OK) { 1659 PRINT(("new position : %f, %f\n", where.x, where.y)); 1660 } 1661 1662 // Constrain and filter the mouse coords and add the final 1663 // point to the message. 1664 where.x = roundf(where.x); 1665 where.y = roundf(where.y); 1666 where.ConstrainTo(fFrame); 1667 if (event->ReplacePoint("where", where) != B_OK) 1668 event->AddPoint("where", where); 1669 1670 if (!event->HasInt64("when")) 1671 event->AddInt64("when", system_time()); 1672 1673 event->AddInt32("modifiers", fKeyInfo.modifiers); 1674 break; 1675 } 1676 case B_KEY_DOWN: 1677 case B_UNMAPPED_KEY_DOWN: 1678 // add modifiers 1679 if (!event->HasInt32("modifiers")) 1680 event->AddInt32("modifiers", fKeyInfo.modifiers); 1681 1682 // add key states 1683 if (!event->HasData("states", B_UINT8_TYPE)) { 1684 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1685 sizeof(fKeyInfo.key_states)); 1686 } 1687 break; 1688 } 1689 } 1690 1691 return true; 1692 } 1693 1694 1695 /*! Applies the filters of the active input method to the 1696 incoming events. It will also move the events in the method 1697 queue to the event list. 1698 */ 1699 bool 1700 InputServer::_MethodizeEvents(EventList& events) 1701 { 1702 CALLED(); 1703 1704 if (fActiveMethod == NULL) 1705 return true; 1706 1707 int32 count = events.CountItems(); 1708 for (int32 i = 0; i < count;) { 1709 _FilterEvent(fActiveMethod, events, i, count); 1710 } 1711 1712 { 1713 // move the method events into the event queue - they are not 1714 // "methodized" either 1715 BAutolock _(fEventQueueLock); 1716 events.AddList(&fMethodQueue); 1717 fMethodQueue.MakeEmpty(); 1718 } 1719 1720 if (!fInputMethodAware) { 1721 // special handling for non-input-method-aware views 1722 1723 int32 newCount = events.CountItems(); 1724 // we may add new events in this loop that don't need to be checked again 1725 1726 for (int32 i = 0; i < newCount; i++) { 1727 BMessage* event = events.ItemAt(i); 1728 1729 if (event->what != B_INPUT_METHOD_EVENT) 1730 continue; 1731 1732 SERIAL_PRINT(("IME received\n")); 1733 1734 bool removeEvent = true; 1735 1736 int32 opcode; 1737 if (event->FindInt32("be:opcode", &opcode) == B_OK) { 1738 bool inlineOnly; 1739 if (event->FindBool("be:inline_only", &inlineOnly) != B_OK) 1740 inlineOnly = false; 1741 1742 if (inlineOnly) { 1743 BMessage translated; 1744 bool confirmed; 1745 if (opcode == B_INPUT_METHOD_CHANGED 1746 && event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed 1747 && event->FindMessage("be:translated", &translated) == B_OK) { 1748 // translate event for the non-aware view 1749 *event = translated; 1750 removeEvent = false; 1751 } 1752 } else { 1753 if (fInputMethodWindow == NULL 1754 && opcode == B_INPUT_METHOD_STARTED) 1755 fInputMethodWindow = new (nothrow) BottomlineWindow(); 1756 1757 if (fInputMethodWindow != NULL) { 1758 EventList newEvents; 1759 fInputMethodWindow->HandleInputMethodEvent(event, newEvents); 1760 1761 if (!newEvents.IsEmpty()) { 1762 events.AddList(&newEvents); 1763 opcode = B_INPUT_METHOD_STOPPED; 1764 } 1765 1766 if (opcode == B_INPUT_METHOD_STOPPED) { 1767 fInputMethodWindow->PostMessage(B_QUIT_REQUESTED); 1768 fInputMethodWindow = NULL; 1769 } 1770 } 1771 } 1772 } 1773 1774 if (removeEvent) { 1775 // the inline/bottom window has eaten the event 1776 events.RemoveItemAt(i--); 1777 delete event; 1778 newCount--; 1779 } 1780 } 1781 } 1782 1783 return events.CountItems() > 0; 1784 } 1785 1786 1787 /*! This method applies all defined filters to each event in the 1788 supplied list. The supplied list is modified to reflect the 1789 output of the filters. 1790 The method returns true if the filters were applied to all 1791 events without error and false otherwise. 1792 */ 1793 bool 1794 InputServer::_FilterEvents(EventList& events) 1795 { 1796 CALLED(); 1797 BAutolock _(gInputFilterListLocker); 1798 1799 int32 count = gInputFilterList.CountItems(); 1800 int32 eventCount = events.CountItems(); 1801 1802 for (int32 i = 0; i < count; i++) { 1803 BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i); 1804 1805 // Apply the current filter to all available event messages. 1806 1807 for (int32 eventIndex = 0; eventIndex < eventCount;) { 1808 _FilterEvent(filter, events, eventIndex, eventCount); 1809 } 1810 } 1811 1812 return eventCount != 0; 1813 } 1814 1815 1816 void 1817 InputServer::_DispatchEvents(EventList& events) 1818 { 1819 CALLED(); 1820 1821 int32 count = events.CountItems(); 1822 1823 for (int32 i = 0; i < count; i++) { 1824 BMessage* event = events.ItemAt(i); 1825 1826 // now we must send each event to the app_server 1827 _DispatchEvent(event); 1828 delete event; 1829 } 1830 1831 events.MakeEmpty(); 1832 } 1833 1834 1835 /*! Applies the given filter to the event list. 1836 For your convenience, it also alters the \a index and \a count arguments 1837 ready for the next call to this method. 1838 */ 1839 void 1840 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events, 1841 int32& index, int32& count) 1842 { 1843 BMessage* event = events.ItemAt(index); 1844 1845 BList newEvents; 1846 filter_result result = filter->Filter(event, &newEvents); 1847 1848 if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) { 1849 // we no longer need the current event 1850 events.RemoveItemAt(index); 1851 delete event; 1852 1853 if (result == B_DISPATCH_MESSAGE) { 1854 EventList addedEvents; 1855 EventList::Private(&addedEvents).AsBList()->AddList(&newEvents); 1856 _SanitizeEvents(addedEvents); 1857 // add the new events - but don't methodize them again 1858 events.AddList(&addedEvents, index); 1859 index += newEvents.CountItems(); 1860 count = events.CountItems(); 1861 } else 1862 count--; 1863 } else 1864 index++; 1865 } 1866 1867 1868 status_t 1869 InputServer::_DispatchEvent(BMessage* event) 1870 { 1871 CALLED(); 1872 1873 switch (event->what) { 1874 case B_MOUSE_MOVED: 1875 case B_MOUSE_DOWN: 1876 case B_MOUSE_UP: 1877 if (fCursorBuffer) { 1878 atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL 1879 | ((uint32)fMousePos.y & 0xffff)); 1880 if (atomic_or(&fCursorBuffer->read, 1) == 0) 1881 release_sem(fCursorSem); 1882 } 1883 break; 1884 1885 case B_KEY_DOWN: 1886 case B_KEY_UP: 1887 case B_UNMAPPED_KEY_DOWN: 1888 case B_UNMAPPED_KEY_UP: 1889 case B_MODIFIERS_CHANGED: 1890 { 1891 // update or add modifiers 1892 uint32 modifiers; 1893 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1894 fKeyInfo.modifiers = modifiers; 1895 else 1896 event->AddInt32("modifiers", fKeyInfo.modifiers); 1897 1898 // update or add key states 1899 const uint8 *data; 1900 ssize_t size; 1901 if (event->FindData("states", B_UINT8_TYPE, 1902 (const void**)&data, &size) == B_OK) { 1903 PRINT(("updated keyinfo\n")); 1904 if (size == sizeof(fKeyInfo.key_states)) 1905 memcpy(fKeyInfo.key_states, data, size); 1906 } else { 1907 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1908 sizeof(fKeyInfo.key_states)); 1909 } 1910 1911 break; 1912 } 1913 1914 default: 1915 break; 1916 } 1917 1918 BMessenger reply; 1919 BMessage::Private messagePrivate(event); 1920 return messagePrivate.SendMessage(fAppServerPort, fAppServerTeam, 0, 0, 1921 false, reply); 1922 } 1923 1924 1925 // #pragma mark - 1926 1927 1928 extern "C" void 1929 RegisterDevices(input_device_ref** devices) 1930 { 1931 CALLED(); 1932 } 1933 1934 1935 BView * 1936 instantiate_deskbar_item() 1937 { 1938 return new MethodReplicant(INPUTSERVER_SIGNATURE); 1939 } 1940 1941 1942 // #pragma mark - 1943 1944 1945 int 1946 main(int /*argc*/, char** /*argv*/) 1947 { 1948 InputServer *inputServer = new InputServer; 1949 1950 inputServer->Run(); 1951 delete inputServer; 1952 1953 return 0; 1954 } 1955