1 /* 2 * Copyright 2002-2013 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "InputServer.h" 8 #include "InputServerTypes.h" 9 #include "BottomlineWindow.h" 10 #include "MethodReplicant.h" 11 12 #include <driver_settings.h> 13 #include <keyboard_mouse_driver.h> 14 #include <safemode_defs.h> 15 #include <syscalls.h> 16 17 #include <AppServerLink.h> 18 #include <MessagePrivate.h> 19 #include <ObjectListPrivate.h> 20 #include <RosterPrivate.h> 21 22 #include <Autolock.h> 23 #include <Deskbar.h> 24 #include <Directory.h> 25 #include <Entry.h> 26 #include <File.h> 27 #include <FindDirectory.h> 28 #include <Locker.h> 29 #include <Message.h> 30 #include <OS.h> 31 #include <Path.h> 32 #include <Roster.h> 33 #include <String.h> 34 35 #include <stdio.h> 36 #include <strings.h> 37 38 #include "SystemKeymap.h" 39 // this is an automatically generated file 40 41 #include <ServerProtocol.h> 42 43 using std::nothrow; 44 45 46 // Global InputServer member variables. 47 48 InputServer* gInputServer; 49 50 BList InputServer::gInputFilterList; 51 BLocker InputServer::gInputFilterListLocker("is_filter_queue_sem"); 52 53 BList InputServer::gInputMethodList; 54 BLocker InputServer::gInputMethodListLocker("is_method_queue_sem"); 55 56 KeymapMethod InputServer::gKeymapMethod; 57 58 59 extern "C" _EXPORT BView* instantiate_deskbar_item(); 60 61 62 // #pragma mark - InputDeviceListItem 63 64 65 InputDeviceListItem::InputDeviceListItem(BInputServerDevice& serverDevice, 66 const input_device_ref& device) 67 : 68 fServerDevice(&serverDevice), 69 fDevice(), 70 fRunning(false) 71 { 72 fDevice.name = strdup(device.name); 73 fDevice.type = device.type; 74 fDevice.cookie = device.cookie; 75 } 76 77 78 InputDeviceListItem::~InputDeviceListItem() 79 { 80 free(fDevice.name); 81 } 82 83 84 void 85 InputDeviceListItem::Start() 86 { 87 PRINT((" Starting: %s\n", fDevice.name)); 88 status_t err = fServerDevice->Start(fDevice.name, fDevice.cookie); 89 if (err != B_OK) { 90 PRINTERR((" error: %s (%" B_PRIx32 ")\n", strerror(err), err)); 91 } 92 fRunning = err == B_OK; 93 } 94 95 96 void 97 InputDeviceListItem::Stop() 98 { 99 PRINT((" Stopping: %s\n", fDevice.name)); 100 fServerDevice->Stop(fDevice.name, fDevice.cookie); 101 fRunning = false; 102 } 103 104 105 void 106 InputDeviceListItem::Control(uint32 code, BMessage* message) 107 { 108 fServerDevice->Control(fDevice.name, fDevice.cookie, code, message); 109 } 110 111 112 bool 113 InputDeviceListItem::HasName(const char* name) const 114 { 115 if (name == NULL) 116 return false; 117 118 return !strcmp(name, fDevice.name); 119 } 120 121 122 bool 123 InputDeviceListItem::HasType(input_device_type type) const 124 { 125 return type == fDevice.type; 126 } 127 128 129 bool 130 InputDeviceListItem::Matches(const char* name, input_device_type type) const 131 { 132 if (name != NULL) 133 return HasName(name); 134 135 return HasType(type); 136 } 137 138 139 // #pragma mark - 140 141 142 InputServer::InputServer() 143 : 144 BApplication(INPUTSERVER_SIGNATURE), 145 fKeyboardID(0), 146 fInputDeviceListLocker("input server device list"), 147 fKeyboardSettings(), 148 fMouseSettings(), 149 fChars(NULL), 150 fScreen(B_MAIN_SCREEN_ID), 151 fEventQueueLock("input server event queue"), 152 fReplicantMessenger(NULL), 153 fInputMethodWindow(NULL), 154 fInputMethodAware(false), 155 fCursorSem(-1), 156 fAppServerPort(-1), 157 fAppServerTeam(-1), 158 fCursorArea(-1) 159 { 160 CALLED(); 161 gInputServer = this; 162 163 set_thread_priority(find_thread(NULL), B_URGENT_DISPLAY_PRIORITY); 164 // elevate priority for client interaction 165 166 _StartEventLoop(); 167 168 _InitKeyboardMouseStates(); 169 170 fAddOnManager = new(std::nothrow) ::AddOnManager(); 171 if (fAddOnManager != NULL) { 172 // We need to Run() the AddOnManager looper after having loaded 173 // the initial add-ons, otherwise we may deadlock when the looper 174 // thread for some reason already receives node monitor notifications 175 // while we are still locked ourselves and are executing LoadState() 176 // at the same time (which may lock the add-on looper thread). 177 // NOTE: At first sight this may look like we may loose node monitor 178 // notifications while the thread is not yet running, but in fact those 179 // message should just pile up and be processed later. 180 fAddOnManager->LoadState(); 181 fAddOnManager->Run(); 182 } 183 184 BMessenger messenger(this); 185 BRoster().StartWatching(messenger, B_REQUEST_LAUNCHED); 186 } 187 188 189 InputServer::~InputServer() 190 { 191 CALLED(); 192 if (fAddOnManager->Lock()) 193 fAddOnManager->Quit(); 194 195 _ReleaseInput(NULL); 196 } 197 198 199 void 200 InputServer::ArgvReceived(int32 argc, char** argv) 201 { 202 CALLED(); 203 204 if (argc == 2 && strcmp(argv[1], "-q") == 0) { 205 PRINT(("InputServer::ArgvReceived - Restarting ...\n")); 206 PostMessage(B_QUIT_REQUESTED); 207 } 208 } 209 210 211 void 212 InputServer::_InitKeyboardMouseStates() 213 { 214 CALLED(); 215 // This is where we determine the screen resolution from the app_server and 216 // find the center of the screen 217 // fMousePos is then set to the center of the screen. 218 219 fFrame = fScreen.Frame(); 220 if (fFrame == BRect(0, 0, 0, 0)) 221 fFrame = BRect(0, 0, 799, 599); 222 fMousePos = BPoint((int32)((fFrame.right + 1) / 2), 223 (int32)((fFrame.bottom + 1) / 2)); 224 225 memset(&fKeyInfo, 0, sizeof(fKeyInfo)); 226 227 if (_LoadKeymap() != B_OK) 228 _LoadSystemKeymap(); 229 230 BMessage msg(B_MOUSE_MOVED); 231 HandleSetMousePosition(&msg, &msg); 232 233 fActiveMethod = &gKeymapMethod; 234 } 235 236 237 status_t 238 InputServer::_LoadKeymap() 239 { 240 BPath path; 241 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 242 return B_BAD_VALUE; 243 244 path.Append("Key_map"); 245 246 status_t err; 247 248 BFile file(path.Path(), B_READ_ONLY); 249 if ((err = file.InitCheck()) != B_OK) 250 return err; 251 252 if (file.Read(&fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys)) 253 return B_BAD_VALUE; 254 255 for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) 256 ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); 257 258 if (file.Read(&fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32)) 259 return B_BAD_VALUE; 260 261 fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); 262 if (fCharsSize <= 0) 263 return B_BAD_VALUE; 264 265 delete[] fChars; 266 fChars = new (nothrow) char[fCharsSize]; 267 if (fChars == NULL) 268 return B_NO_MEMORY; 269 270 if (file.Read(fChars, fCharsSize) != (signed)fCharsSize) 271 return B_BAD_VALUE; 272 273 return B_OK; 274 } 275 276 277 status_t 278 InputServer::_LoadSystemKeymap() 279 { 280 delete[] fChars; 281 fKeys = kSystemKeymap; 282 fCharsSize = kSystemKeyCharsSize; 283 fChars = new (nothrow) char[fCharsSize]; 284 if (fChars == NULL) 285 return B_NO_MEMORY; 286 287 memcpy(fChars, kSystemKeyChars, fCharsSize); 288 289 // TODO: why are we doing this? 290 return _SaveKeymap(true); 291 } 292 293 294 status_t 295 InputServer::_SaveKeymap(bool isDefault) 296 { 297 // we save this keymap to file 298 BPath path; 299 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 300 return B_BAD_VALUE; 301 302 path.Append("Key_map"); 303 304 BFile file; 305 status_t err = file.SetTo(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 306 if (err != B_OK) { 307 PRINTERR(("error %s\n", strerror(err))); 308 return err; 309 } 310 311 for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) { 312 ((uint32*)&fKeys)[i] = B_HOST_TO_BENDIAN_INT32(((uint32*)&fKeys)[i]); 313 } 314 315 if ((err = file.Write(&fKeys, sizeof(fKeys))) < (ssize_t)sizeof(fKeys)) 316 return err; 317 318 for (uint32 i = 0; i < sizeof(fKeys) / sizeof(uint32); i++) { 319 ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); 320 } 321 322 uint32 size = B_HOST_TO_BENDIAN_INT32(fCharsSize); 323 324 if ((err = file.Write(&size, sizeof(uint32))) < (ssize_t)sizeof(uint32)) 325 return B_BAD_VALUE; 326 327 if ((err = file.Write(fChars, fCharsSize)) < (ssize_t)fCharsSize) 328 return err; 329 330 // don't bother reporting an error if this fails, since this isn't fatal 331 // the keymap will still be functional, and will just be identified as (Current) in prefs instead of its 332 // actual name 333 if (isDefault) { 334 const BString systemKeymapName(kSystemKeymapName); 335 file.WriteAttrString("keymap:name", &systemKeymapName); 336 } 337 338 return B_OK; 339 } 340 341 342 bool 343 InputServer::QuitRequested() 344 { 345 CALLED(); 346 if (!BApplication::QuitRequested()) 347 return false; 348 349 PostMessage(SYSTEM_SHUTTING_DOWN); 350 351 bool shutdown = false; 352 CurrentMessage()->FindBool("_shutdown_", &shutdown); 353 354 // Don't actually quit when the system is being shutdown 355 if (shutdown) { 356 return false; 357 } else { 358 fAddOnManager->SaveState(); 359 360 delete_port(fEventLooperPort); 361 // the event looper thread will exit after this 362 fEventLooperPort = -1; 363 return true; 364 } 365 } 366 367 368 void 369 InputServer::ReadyToRun() 370 { 371 CALLED(); 372 373 // say hello to the app_server 374 375 BPrivate::AppServerLink link; 376 link.StartMessage(AS_REGISTER_INPUT_SERVER); 377 link.Flush(); 378 } 379 380 381 status_t 382 InputServer::_AcquireInput(BMessage& message, BMessage& reply) 383 { 384 // TODO: it currently just gets everything we have 385 area_id area; 386 if (message.FindInt32("cursor area", &area) == B_OK) { 387 // try to clone the area 388 fCursorBuffer = NULL; 389 390 fCursorSem = create_sem(0, "cursor semaphore"); 391 if (fCursorSem >= B_OK) { 392 fCursorArea = clone_area("input server cursor", (void**)&fCursorBuffer, 393 B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area); 394 } 395 } 396 397 if (message.FindInt32("remote team", &fAppServerTeam) != B_OK) 398 fAppServerTeam = -1; 399 400 fAppServerPort = create_port(200, "input server target"); 401 if (fAppServerPort < B_OK) { 402 _ReleaseInput(&message); 403 return fAppServerPort; 404 } 405 406 reply.AddBool("has keyboard", true); 407 reply.AddBool("has mouse", true); 408 reply.AddInt32("event port", fAppServerPort); 409 410 if (fCursorBuffer != NULL) { 411 // cursor shared buffer is supported 412 reply.AddInt32("cursor semaphore", fCursorSem); 413 } 414 415 return B_OK; 416 } 417 418 419 void 420 InputServer::_ReleaseInput(BMessage* /*message*/) 421 { 422 if (fCursorBuffer != NULL) { 423 fCursorBuffer = NULL; 424 delete_sem(fCursorSem); 425 delete_area(fCursorArea); 426 427 fCursorSem = -1; 428 fCursorArea = -1; 429 } 430 431 delete_port(fAppServerPort); 432 } 433 434 435 void 436 InputServer::MessageReceived(BMessage* message) 437 { 438 CALLED(); 439 440 BMessage reply; 441 status_t status = B_OK; 442 443 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, (char)(message->what >> 24), 444 (char)(message->what >> 16), (char)(message->what >> 8), (char)message->what)); 445 446 switch (message->what) { 447 case IS_SET_METHOD: 448 HandleSetMethod(message); 449 break; 450 case IS_GET_MOUSE_TYPE: 451 status = HandleGetSetMouseType(message, &reply); 452 break; 453 case IS_SET_MOUSE_TYPE: 454 status = HandleGetSetMouseType(message, &reply); 455 break; 456 case IS_GET_MOUSE_ACCELERATION: 457 status = HandleGetSetMouseAcceleration(message, &reply); 458 break; 459 case IS_SET_MOUSE_ACCELERATION: 460 status = HandleGetSetMouseAcceleration(message, &reply); 461 break; 462 case IS_GET_KEY_REPEAT_DELAY: 463 status = HandleGetSetKeyRepeatDelay(message, &reply); 464 break; 465 case IS_SET_KEY_REPEAT_DELAY: 466 status = HandleGetSetKeyRepeatDelay(message, &reply); 467 break; 468 case IS_GET_KEY_INFO: 469 status = HandleGetKeyInfo(message, &reply); 470 break; 471 case IS_GET_MODIFIERS: 472 status = HandleGetModifiers(message, &reply); 473 break; 474 case IS_GET_MODIFIER_KEY: 475 status = HandleGetModifierKey(message, &reply); 476 break; 477 case IS_SET_MODIFIER_KEY: 478 status = HandleSetModifierKey(message, &reply); 479 break; 480 case IS_SET_KEYBOARD_LOCKS: 481 status = HandleSetKeyboardLocks(message, &reply); 482 break; 483 case IS_GET_MOUSE_SPEED: 484 status = HandleGetSetMouseSpeed(message, &reply); 485 break; 486 case IS_SET_MOUSE_SPEED: 487 status = HandleGetSetMouseSpeed(message, &reply); 488 break; 489 case IS_SET_MOUSE_POSITION: 490 status = HandleSetMousePosition(message, &reply); 491 break; 492 case IS_GET_MOUSE_MAP: 493 status = HandleGetSetMouseMap(message, &reply); 494 break; 495 case IS_SET_MOUSE_MAP: 496 status = HandleGetSetMouseMap(message, &reply); 497 break; 498 case IS_GET_KEYBOARD_ID: 499 status = HandleGetSetKeyboardID(message, &reply); 500 break; 501 case IS_SET_KEYBOARD_ID: 502 status = HandleGetSetKeyboardID(message, &reply); 503 break; 504 case IS_GET_CLICK_SPEED: 505 status = HandleGetSetClickSpeed(message, &reply); 506 break; 507 case IS_SET_CLICK_SPEED: 508 status = HandleGetSetClickSpeed(message, &reply); 509 break; 510 case IS_GET_KEY_REPEAT_RATE: 511 status = HandleGetSetKeyRepeatRate(message, &reply); 512 break; 513 case IS_SET_KEY_REPEAT_RATE: 514 status = HandleGetSetKeyRepeatRate(message, &reply); 515 break; 516 case IS_GET_KEY_MAP: 517 status = HandleGetSetKeyMap(message, &reply); 518 break; 519 case IS_RESTORE_KEY_MAP: 520 status = HandleGetSetKeyMap(message, &reply); 521 break; 522 case IS_FOCUS_IM_AWARE_VIEW: 523 status = HandleFocusUnfocusIMAwareView(message, &reply); 524 break; 525 case IS_UNFOCUS_IM_AWARE_VIEW: 526 status = HandleFocusUnfocusIMAwareView(message, &reply); 527 break; 528 529 // app_server communication 530 case IS_ACQUIRE_INPUT: 531 status = _AcquireInput(*message, reply); 532 break; 533 case IS_RELEASE_INPUT: 534 _ReleaseInput(message); 535 return; 536 case IS_SCREEN_BOUNDS_UPDATED: 537 { 538 // This is what the R5 app_server sends us when the screen 539 // configuration changes 540 BRect frame; 541 if (message->FindRect("screen_bounds", &frame) != B_OK) 542 frame = fScreen.Frame(); 543 544 if (frame == fFrame) 545 break; 546 547 BPoint pos(fMousePos.x * frame.Width() / fFrame.Width(), 548 fMousePos.y * frame.Height() / fFrame.Height()); 549 fFrame = frame; 550 551 BMessage set; 552 set.AddPoint("where", pos); 553 HandleSetMousePosition(&set, NULL); 554 break; 555 } 556 557 // device looper related 558 case IS_FIND_DEVICES: 559 case IS_WATCH_DEVICES: 560 case IS_IS_DEVICE_RUNNING: 561 case IS_START_DEVICE: 562 case IS_STOP_DEVICE: 563 case IS_CONTROL_DEVICES: 564 case SYSTEM_SHUTTING_DOWN: 565 case IS_METHOD_REGISTER: 566 fAddOnManager->PostMessage(message); 567 return; 568 569 case IS_SAVE_SETTINGS: 570 fKeyboardSettings.Save(); 571 fMouseSettings.SaveSettings(); 572 return; 573 574 case IS_SAVE_KEYMAP: 575 _SaveKeymap(); 576 return; 577 578 case B_SOME_APP_LAUNCHED: 579 { 580 // The message contains a be:signature with the app signature 581 // TODO: what's this for? 582 return; 583 } 584 585 case kMsgAppServerRestarted: 586 { 587 BApplication::MessageReceived(message); 588 BPrivate::AppServerLink link; 589 link.StartMessage(AS_REGISTER_INPUT_SERVER); 590 link.Flush(); 591 return; 592 } 593 594 default: 595 return; 596 } 597 598 reply.AddInt32("status", status); 599 message->SendReply(&reply); 600 } 601 602 603 void 604 InputServer::HandleSetMethod(BMessage* message) 605 { 606 CALLED(); 607 int32 cookie; 608 if (message->FindInt32("cookie", &cookie) != B_OK) 609 return; 610 if (cookie == gKeymapMethod.fOwner->Cookie()) { 611 SetActiveMethod(&gKeymapMethod); 612 } else { 613 BAutolock lock(InputServer::gInputMethodListLocker); 614 for (int32 i = 0; i < gInputMethodList.CountItems(); i++) { 615 BInputServerMethod* method 616 = (BInputServerMethod*)InputServer::gInputMethodList.ItemAt(i); 617 if (method->fOwner->Cookie() == cookie) { 618 PRINT(("%s cookie %" B_PRId32 "\n", __PRETTY_FUNCTION__, 619 cookie)); 620 SetActiveMethod(method); 621 break; 622 } 623 } 624 } 625 } 626 627 628 status_t 629 InputServer::HandleGetSetKeyRepeatDelay(BMessage* message, BMessage* reply) 630 { 631 bigtime_t delay; 632 if (message->FindInt64("delay", &delay) == B_OK) { 633 fKeyboardSettings.SetKeyboardRepeatDelay(delay); 634 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 635 636 BMessage msg(IS_CONTROL_DEVICES); 637 msg.AddInt32("type", B_KEYBOARD_DEVICE); 638 msg.AddInt32("code", B_KEY_REPEAT_DELAY_CHANGED); 639 return fAddOnManager->PostMessage(&msg); 640 } 641 642 return reply->AddInt64("delay", fKeyboardSettings.KeyboardRepeatDelay()); 643 } 644 645 646 status_t 647 InputServer::HandleGetKeyInfo(BMessage* message, BMessage* reply) 648 { 649 return reply->AddData("key_info", B_ANY_TYPE, &fKeyInfo, sizeof(fKeyInfo)); 650 } 651 652 653 status_t 654 InputServer::HandleGetModifiers(BMessage* message, BMessage* reply) 655 { 656 return reply->AddInt32("modifiers", fKeyInfo.modifiers); 657 } 658 659 660 status_t 661 InputServer::HandleGetModifierKey(BMessage* message, BMessage* reply) 662 { 663 int32 modifier; 664 665 if (message->FindInt32("modifier", &modifier) == B_OK) { 666 switch (modifier) { 667 case B_CAPS_LOCK: 668 return reply->AddInt32("key", fKeys.caps_key); 669 case B_NUM_LOCK: 670 return reply->AddInt32("key", fKeys.num_key); 671 case B_SCROLL_LOCK: 672 return reply->AddInt32("key", fKeys.scroll_key); 673 case B_LEFT_SHIFT_KEY: 674 return reply->AddInt32("key", fKeys.left_shift_key); 675 case B_RIGHT_SHIFT_KEY: 676 return reply->AddInt32("key", fKeys.right_shift_key); 677 case B_LEFT_COMMAND_KEY: 678 return reply->AddInt32("key", fKeys.left_command_key); 679 case B_RIGHT_COMMAND_KEY: 680 return reply->AddInt32("key", fKeys.right_command_key); 681 case B_LEFT_CONTROL_KEY: 682 return reply->AddInt32("key", fKeys.left_control_key); 683 case B_RIGHT_CONTROL_KEY: 684 return reply->AddInt32("key", fKeys.right_control_key); 685 case B_LEFT_OPTION_KEY: 686 return reply->AddInt32("key", fKeys.left_option_key); 687 case B_RIGHT_OPTION_KEY: 688 return reply->AddInt32("key", fKeys.right_option_key); 689 case B_MENU_KEY: 690 return reply->AddInt32("key", fKeys.menu_key); 691 } 692 } 693 return B_ERROR; 694 } 695 696 697 status_t 698 InputServer::HandleSetModifierKey(BMessage* message, BMessage* reply) 699 { 700 int32 modifier, key; 701 if (message->FindInt32("modifier", &modifier) == B_OK 702 && message->FindInt32("key", &key) == B_OK) { 703 switch (modifier) { 704 case B_CAPS_LOCK: 705 fKeys.caps_key = key; 706 break; 707 case B_NUM_LOCK: 708 fKeys.num_key = key; 709 break; 710 case B_SCROLL_LOCK: 711 fKeys.scroll_key = key; 712 break; 713 case B_LEFT_SHIFT_KEY: 714 fKeys.left_shift_key = key; 715 break; 716 case B_RIGHT_SHIFT_KEY: 717 fKeys.right_shift_key = key; 718 break; 719 case B_LEFT_COMMAND_KEY: 720 fKeys.left_command_key = key; 721 break; 722 case B_RIGHT_COMMAND_KEY: 723 fKeys.right_command_key = key; 724 break; 725 case B_LEFT_CONTROL_KEY: 726 fKeys.left_control_key = key; 727 break; 728 case B_RIGHT_CONTROL_KEY: 729 fKeys.right_control_key = key; 730 break; 731 case B_LEFT_OPTION_KEY: 732 fKeys.left_option_key = key; 733 break; 734 case B_RIGHT_OPTION_KEY: 735 fKeys.right_option_key = key; 736 break; 737 case B_MENU_KEY: 738 fKeys.menu_key = key; 739 break; 740 default: 741 return B_ERROR; 742 } 743 744 // TODO: unmap the key ? 745 746 be_app_messenger.SendMessage(IS_SAVE_KEYMAP); 747 748 BMessage msg(IS_CONTROL_DEVICES); 749 msg.AddInt32("type", B_KEYBOARD_DEVICE); 750 msg.AddInt32("code", B_KEY_MAP_CHANGED); 751 return fAddOnManager->PostMessage(&msg); 752 } 753 754 return B_ERROR; 755 } 756 757 758 status_t 759 InputServer::HandleSetKeyboardLocks(BMessage* message, BMessage* reply) 760 { 761 if (message->FindInt32("locks", (int32*)&fKeys.lock_settings) == B_OK) { 762 be_app_messenger.SendMessage(IS_SAVE_KEYMAP); 763 764 BMessage msg(IS_CONTROL_DEVICES); 765 msg.AddInt32("type", B_KEYBOARD_DEVICE); 766 msg.AddInt32("code", B_KEY_LOCKS_CHANGED); 767 return fAddOnManager->PostMessage(&msg); 768 } 769 770 return B_ERROR; 771 } 772 773 774 // #pragma mark - Mouse settings 775 776 777 status_t 778 InputServer::_PostMouseControlMessage(int32 code, const BString& mouseName) 779 { 780 BMessage message(IS_CONTROL_DEVICES); 781 message.AddInt32("code", code); 782 if (mouseName.IsEmpty()) 783 message.AddInt32("type", B_POINTING_DEVICE); 784 else 785 message.AddString("device", mouseName); 786 787 return fAddOnManager->PostMessage(&message); 788 } 789 790 791 void 792 InputServer::_DeviceStarted(InputDeviceListItem& item) 793 { 794 if (item.Type() == B_POINTING_DEVICE && item.Running() && fRunningMouseListLocker.Lock()) { 795 fRunningMouseList.Add(item.Name()); 796 fRunningMouseListLocker.Unlock(); 797 } 798 } 799 800 801 void 802 InputServer::_DeviceStopping(InputDeviceListItem& item) 803 { 804 if (item.Type() == B_POINTING_DEVICE && fRunningMouseListLocker.Lock()) { 805 fRunningMouseList.Remove(item.Name()); 806 fRunningMouseListLocker.Unlock(); 807 } 808 } 809 810 811 MouseSettings* 812 InputServer::_RunningMouseSettings() 813 { 814 BAutolock lock(fRunningMouseListLocker); 815 816 if (fRunningMouseList.IsEmpty()) 817 return &fDefaultMouseSettings; 818 return _GetSettingsForMouse(fRunningMouseList.First()); 819 } 820 821 822 void 823 InputServer::_RunningMiceSettings(BList& settings) 824 { 825 BAutolock lock(fRunningMouseListLocker); 826 827 int32 count = fRunningMouseList.CountStrings(); 828 for (int32 i = 0; i < count; i++) 829 settings.AddItem(_GetSettingsForMouse(fRunningMouseList.StringAt(i))); 830 } 831 832 833 MouseSettings* 834 InputServer::_GetSettingsForMouse(BString mouseName) 835 { 836 // We need something different for get and set requests when no mouse name 837 // is specified, so leave that to the caller. 838 if (mouseName.IsEmpty()) 839 return NULL; 840 841 return fMouseSettings.AddMouseSettings(mouseName); 842 } 843 844 845 status_t 846 InputServer::HandleGetSetMouseType(BMessage* message, BMessage* reply) 847 { 848 BString mouseName; 849 message->FindString("mouse_name", &mouseName); 850 851 MouseSettings* settings = _GetSettingsForMouse(mouseName); 852 853 int32 type; 854 if (message->FindInt32("mouse_type", &type) == B_OK) { 855 if (settings == NULL) { 856 BList allSettings; 857 _RunningMiceSettings(allSettings); 858 int count = allSettings.CountItems(); 859 for (int i = 0; i < count; i++) 860 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetMouseType(type); 861 } else { 862 settings->SetMouseType(type); 863 } 864 865 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 866 867 return _PostMouseControlMessage(B_MOUSE_TYPE_CHANGED, mouseName); 868 } 869 870 if (settings == NULL) 871 settings = _RunningMouseSettings(); 872 return reply->AddInt32("mouse_type", settings->MouseType()); 873 } 874 875 876 status_t 877 InputServer::HandleGetSetMouseAcceleration(BMessage* message, BMessage* reply) 878 { 879 BString mouseName; 880 message->FindString("mouse_name", &mouseName); 881 882 MouseSettings* settings = _GetSettingsForMouse(mouseName); 883 884 int32 factor; 885 if (message->FindInt32("speed", &factor) == B_OK) { 886 if (settings == NULL) { 887 BList allSettings; 888 _RunningMiceSettings(allSettings); 889 int count = allSettings.CountItems(); 890 for (int i = 0; i < count; i++) 891 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetAccelerationFactor(factor); 892 } else { 893 settings->SetAccelerationFactor(factor); 894 } 895 896 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 897 898 return _PostMouseControlMessage(B_MOUSE_ACCELERATION_CHANGED, mouseName); 899 } 900 901 if (settings == NULL) 902 settings = _RunningMouseSettings(); 903 return reply->AddInt32("speed", settings->AccelerationFactor()); 904 } 905 906 907 status_t 908 InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply) 909 { 910 BString mouseName; 911 message->FindString("mouse_name", &mouseName); 912 913 MouseSettings* settings = _GetSettingsForMouse(mouseName); 914 915 int32 speed; 916 if (message->FindInt32("speed", &speed) == B_OK) { 917 if (settings == NULL) { 918 BList allSettings; 919 _RunningMiceSettings(allSettings); 920 int count = allSettings.CountItems(); 921 for (int i = 0; i < count; i++) 922 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetMouseSpeed(speed); 923 } else { 924 settings->SetMouseSpeed(speed); 925 } 926 927 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 928 929 return _PostMouseControlMessage(B_MOUSE_SPEED_CHANGED, mouseName); 930 } 931 932 if (settings == NULL) 933 settings = _RunningMouseSettings(); 934 return reply->AddInt32("speed", settings->MouseSpeed()); 935 } 936 937 938 status_t 939 InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply) 940 { 941 BString mouseName; 942 message->FindString("mouse_name", &mouseName); 943 944 MouseSettings* settings = _GetSettingsForMouse(mouseName); 945 946 mouse_map *map; 947 ssize_t size; 948 if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) { 949 if (settings == NULL) { 950 BList allSettings; 951 _RunningMiceSettings(allSettings); 952 int count = allSettings.CountItems(); 953 for (int i = 0; i < count; i++) 954 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetMapping(*map); 955 } else { 956 settings->SetMapping(*map); 957 } 958 959 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 960 961 return _PostMouseControlMessage(B_MOUSE_MAP_CHANGED, mouseName); 962 } 963 964 if (settings == NULL) 965 settings = _RunningMouseSettings(); 966 mouse_map getmap; 967 settings->Mapping(getmap); 968 return reply->AddData("mousemap", B_RAW_TYPE, &getmap, sizeof(mouse_map)); 969 } 970 971 972 status_t 973 InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply) 974 { 975 BString mouseName; 976 message->FindString("mouse_name", &mouseName); 977 978 MouseSettings* settings = _GetSettingsForMouse(mouseName); 979 980 bigtime_t clickSpeed; 981 if (message->FindInt64("speed", &clickSpeed) == B_OK) { 982 if (settings == NULL) { 983 BList allSettings; 984 _RunningMiceSettings(allSettings); 985 int count = allSettings.CountItems(); 986 for (int i = 0; i < count; i++) 987 static_cast<MouseSettings*>(allSettings.ItemAt(i))->SetClickSpeed(clickSpeed); 988 } else { 989 settings->SetClickSpeed(clickSpeed); 990 } 991 992 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 993 994 return _PostMouseControlMessage(B_CLICK_SPEED_CHANGED, mouseName); 995 } 996 997 if (settings == NULL) 998 settings = _RunningMouseSettings(); 999 return reply->AddInt64("speed", settings->ClickSpeed()); 1000 } 1001 1002 1003 status_t 1004 InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply) 1005 { 1006 CALLED(); 1007 1008 BPoint where; 1009 if (message->FindPoint("where", &where) != B_OK) 1010 return B_BAD_VALUE; 1011 1012 // create a new event for this and enqueue it to the event list just like any other 1013 1014 BMessage* event = new BMessage(B_MOUSE_MOVED); 1015 if (event == NULL) 1016 return B_NO_MEMORY; 1017 1018 event->AddPoint("where", where); 1019 event->AddBool("be:set_mouse", true); 1020 if (EnqueueDeviceMessage(event) != B_OK) { 1021 delete event; 1022 return B_NO_MEMORY; 1023 } 1024 1025 return B_OK; 1026 } 1027 1028 1029 // #pragma mark - Keyboard settings 1030 1031 1032 status_t 1033 InputServer::HandleGetSetKeyboardID(BMessage* message, BMessage* reply) 1034 { 1035 int16 id; 1036 if (message->FindInt16("id", &id) == B_OK) { 1037 fKeyboardID = (uint16)id; 1038 return B_OK; 1039 } 1040 return reply->AddInt16("id", fKeyboardID); 1041 } 1042 1043 1044 status_t 1045 InputServer::HandleGetSetKeyRepeatRate(BMessage* message, BMessage* reply) 1046 { 1047 int32 keyRepeatRate; 1048 if (message->FindInt32("rate", &keyRepeatRate) == B_OK) { 1049 fKeyboardSettings.SetKeyboardRepeatRate(keyRepeatRate); 1050 be_app_messenger.SendMessage(IS_SAVE_SETTINGS); 1051 1052 BMessage msg(IS_CONTROL_DEVICES); 1053 msg.AddInt32("type", B_KEYBOARD_DEVICE); 1054 msg.AddInt32("code", B_KEY_REPEAT_RATE_CHANGED); 1055 return fAddOnManager->PostMessage(&msg); 1056 } 1057 1058 return reply->AddInt32("rate", fKeyboardSettings.KeyboardRepeatRate()); 1059 } 1060 1061 1062 status_t 1063 InputServer::HandleGetSetKeyMap(BMessage* message, BMessage* reply) 1064 { 1065 CALLED(); 1066 1067 status_t status; 1068 if (message->what == IS_GET_KEY_MAP) { 1069 status = reply->AddData("keymap", B_ANY_TYPE, &fKeys, sizeof(fKeys)); 1070 if (status == B_OK) 1071 status = reply->AddData("key_buffer", B_ANY_TYPE, fChars, fCharsSize); 1072 1073 return status; 1074 } 1075 1076 status = _LoadKeymap(); 1077 if (status != B_OK) { 1078 status = _LoadSystemKeymap(); 1079 if (status != B_OK) 1080 return status; 1081 } 1082 1083 BMessage msg(IS_CONTROL_DEVICES); 1084 msg.AddInt32("type", B_KEYBOARD_DEVICE); 1085 msg.AddInt32("code", B_KEY_MAP_CHANGED); 1086 status = fAddOnManager->PostMessage(&msg); 1087 1088 if (status == B_OK) { 1089 BMessage appMsg(B_KEY_MAP_LOADED); 1090 be_roster->Broadcast(&appMsg); 1091 } 1092 1093 return status; 1094 } 1095 1096 1097 status_t 1098 InputServer::HandleFocusUnfocusIMAwareView(BMessage* message, 1099 BMessage* reply) 1100 { 1101 CALLED(); 1102 1103 BMessenger messenger; 1104 status_t status = message->FindMessenger("view", &messenger); 1105 if (status != B_OK) 1106 return status; 1107 1108 // check if current view is ours 1109 1110 if (message->what == IS_FOCUS_IM_AWARE_VIEW) { 1111 PRINT(("HandleFocusUnfocusIMAwareView : entering\n")); 1112 fInputMethodAware = true; 1113 } else { 1114 PRINT(("HandleFocusUnfocusIMAwareView : leaving\n")); 1115 fInputMethodAware = false; 1116 } 1117 1118 return B_OK; 1119 } 1120 1121 1122 /*! Enqueues the message into the event queue. 1123 The message must only be deleted in case this method returns an error. 1124 */ 1125 status_t 1126 InputServer::EnqueueDeviceMessage(BMessage* message) 1127 { 1128 CALLED(); 1129 1130 BAutolock _(fEventQueueLock); 1131 if (!fEventQueue.AddItem(message)) 1132 return B_NO_MEMORY; 1133 1134 if (fEventQueue.CountItems() == 1) { 1135 // notify event loop only if we haven't already done so 1136 write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0); 1137 } 1138 return B_OK; 1139 } 1140 1141 1142 /*! Enqueues the message into the method queue. 1143 The message must only be deleted in case this method returns an error. 1144 */ 1145 status_t 1146 InputServer::EnqueueMethodMessage(BMessage* message) 1147 { 1148 CALLED(); 1149 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, 1150 (char)(message->what >> 24), (char)(message->what >> 16), 1151 (char)(message->what >> 8), (char)message->what)); 1152 1153 #ifdef DEBUG 1154 if (message->what == 'IMEV') { 1155 int32 code; 1156 message->FindInt32("be:opcode", &code); 1157 PRINT(("%s be:opcode %" B_PRId32 "\n", __PRETTY_FUNCTION__, code)); 1158 } 1159 #endif 1160 1161 BAutolock _(fEventQueueLock); 1162 if (!fMethodQueue.AddItem(message)) 1163 return B_NO_MEMORY; 1164 1165 if (fMethodQueue.CountItems() == 1) { 1166 // notify event loop only if we haven't already done so 1167 write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0); 1168 } 1169 return B_OK; 1170 } 1171 1172 1173 status_t 1174 InputServer::SetNextMethod(bool direction) 1175 { 1176 gInputMethodListLocker.Lock(); 1177 1178 int32 index = gInputMethodList.IndexOf(fActiveMethod); 1179 int32 oldIndex = index; 1180 1181 index += (direction ? 1 : -1); 1182 1183 if (index < -1) 1184 index = gInputMethodList.CountItems() - 1; 1185 if (index >= gInputMethodList.CountItems()) 1186 index = -1; 1187 1188 if (index == oldIndex) 1189 return B_BAD_INDEX; 1190 1191 BInputServerMethod *method = &gKeymapMethod; 1192 1193 if (index != -1) 1194 method = (BInputServerMethod *)gInputMethodList.ItemAt(index); 1195 1196 SetActiveMethod(method); 1197 1198 gInputMethodListLocker.Unlock(); 1199 return B_OK; 1200 } 1201 1202 1203 void 1204 InputServer::SetActiveMethod(BInputServerMethod* method) 1205 { 1206 CALLED(); 1207 if (fActiveMethod) 1208 fActiveMethod->fOwner->MethodActivated(false); 1209 1210 fActiveMethod = method; 1211 1212 if (fActiveMethod) 1213 fActiveMethod->fOwner->MethodActivated(true); 1214 } 1215 1216 1217 const BMessenger* 1218 InputServer::MethodReplicant() 1219 { 1220 return fReplicantMessenger; 1221 } 1222 1223 1224 void 1225 InputServer::SetMethodReplicant(const BMessenger* messenger) 1226 { 1227 fReplicantMessenger = messenger; 1228 } 1229 1230 1231 bool 1232 InputServer::EventLoopRunning() 1233 { 1234 return fEventLooperPort >= B_OK; 1235 } 1236 1237 1238 status_t 1239 InputServer::GetDeviceInfo(const char* name, input_device_type *_type, 1240 bool *_isRunning) 1241 { 1242 BAutolock lock(fInputDeviceListLocker); 1243 1244 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1245 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1246 1247 if (item->HasName(name)) { 1248 if (_type) 1249 *_type = item->Type(); 1250 if (_isRunning) 1251 *_isRunning = item->Running(); 1252 1253 return B_OK; 1254 } 1255 } 1256 1257 return B_NAME_NOT_FOUND; 1258 } 1259 1260 1261 status_t 1262 InputServer::GetDeviceInfos(BMessage *msg) 1263 { 1264 CALLED(); 1265 BAutolock lock(fInputDeviceListLocker); 1266 1267 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1268 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1269 msg->AddString("device", item->Name()); 1270 msg->AddInt32("type", item->Type()); 1271 } 1272 return B_OK; 1273 } 1274 1275 1276 status_t 1277 InputServer::UnregisterDevices(BInputServerDevice& serverDevice, 1278 input_device_ref **devices) 1279 { 1280 CALLED(); 1281 BAutolock lock(fInputDeviceListLocker); 1282 1283 if (devices != NULL) { 1284 // remove the devices as specified only 1285 input_device_ref *device = NULL; 1286 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1287 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1288 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1289 1290 if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) { 1291 _DeviceStopping(*item); 1292 item->Stop(); 1293 if (fInputDeviceList.RemoveItem(j)) { 1294 BMessage message(IS_NOTIFY_DEVICE); 1295 message.AddBool("added", false); 1296 message.AddString("name", item->Name()); 1297 message.AddInt32("type", item->Type()); 1298 fAddOnManager->PostMessage(&message); 1299 delete item; 1300 } 1301 break; 1302 } 1303 } 1304 } 1305 } else { 1306 // remove all devices from this BInputServerObject 1307 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1308 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1309 1310 if (item->ServerDevice() == &serverDevice) { 1311 _DeviceStopping(*item); 1312 item->Stop(); 1313 if (fInputDeviceList.RemoveItem(i)) 1314 delete item; 1315 } 1316 } 1317 } 1318 1319 return B_OK; 1320 } 1321 1322 1323 status_t 1324 InputServer::RegisterDevices(BInputServerDevice& serverDevice, 1325 input_device_ref** devices) 1326 { 1327 if (devices == NULL) 1328 return B_BAD_VALUE; 1329 1330 BAutolock lock(fInputDeviceListLocker); 1331 1332 input_device_ref *device = NULL; 1333 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1334 if (device->type != B_POINTING_DEVICE 1335 && device->type != B_KEYBOARD_DEVICE 1336 && device->type != B_UNDEFINED_DEVICE) 1337 continue; 1338 1339 // find existing input server device 1340 1341 bool found = false; 1342 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1343 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1344 1345 if (item->HasName(device->name)) { 1346 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name); 1347 PRINT(("RegisterDevices found %s\n", device->name)); 1348 found = true; 1349 break; 1350 } 1351 } 1352 1353 if (!found) { 1354 PRINT(("RegisterDevices not found %s\n", device->name)); 1355 InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice, 1356 *device); 1357 if (item != NULL && fInputDeviceList.AddItem(item)) { 1358 item->Start(); 1359 _DeviceStarted(*item); 1360 BMessage message(IS_NOTIFY_DEVICE); 1361 message.AddBool("added", true); 1362 message.AddString("name", item->Name()); 1363 message.AddInt32("type", item->Type()); 1364 fAddOnManager->PostMessage(&message); 1365 } else { 1366 delete item; 1367 return B_NO_MEMORY; 1368 } 1369 } 1370 } 1371 1372 return B_OK; 1373 } 1374 1375 1376 status_t 1377 InputServer::StartStopDevices(const char* name, input_device_type type, 1378 bool doStart) 1379 { 1380 CALLED(); 1381 BAutolock lock(fInputDeviceListLocker); 1382 1383 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1384 InputDeviceListItem* item 1385 = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1386 if (!item) 1387 continue; 1388 1389 if (item->Matches(name, type)) { 1390 if (doStart == item->Running()) { 1391 if (name) 1392 return B_OK; 1393 else 1394 continue; 1395 } 1396 1397 if (doStart) { 1398 item->Start(); 1399 _DeviceStarted(*item); 1400 } else { 1401 _DeviceStopping(*item); 1402 item->Stop(); 1403 } 1404 1405 BMessage message(IS_NOTIFY_DEVICE); 1406 message.AddBool("started", doStart); 1407 message.AddString("name", item->Name()); 1408 message.AddInt32("type", item->Type()); 1409 fAddOnManager->PostMessage(&message); 1410 1411 if (name) 1412 return B_OK; 1413 } 1414 } 1415 1416 if (name) { 1417 // item not found 1418 return B_ERROR; 1419 } 1420 1421 return B_OK; 1422 } 1423 1424 1425 1426 status_t 1427 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart) 1428 { 1429 CALLED(); 1430 BAutolock lock(fInputDeviceListLocker); 1431 1432 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1433 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1434 1435 if (item->ServerDevice() != &serverDevice) 1436 continue; 1437 1438 if (doStart == item->Running()) 1439 continue; 1440 1441 if (doStart) { 1442 item->Start(); 1443 _DeviceStarted(*item); 1444 } else { 1445 _DeviceStopping(*item); 1446 item->Stop(); 1447 } 1448 1449 BMessage message(IS_NOTIFY_DEVICE); 1450 message.AddBool("started", doStart); 1451 message.AddString("name", item->Name()); 1452 message.AddInt32("type", item->Type()); 1453 fAddOnManager->PostMessage(&message); 1454 } 1455 1456 return B_OK; 1457 } 1458 1459 1460 status_t 1461 InputServer::ControlDevices(const char* name, input_device_type type, 1462 uint32 code, BMessage* message) 1463 { 1464 CALLED(); 1465 BAutolock lock(fInputDeviceListLocker); 1466 1467 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1468 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1469 if (!item) 1470 continue; 1471 1472 if (item->Matches(name, type)) { 1473 item->Control(code, message); 1474 1475 if (name) 1476 return B_OK; 1477 } 1478 } 1479 1480 if (name) 1481 return B_ERROR; 1482 1483 return B_OK; 1484 } 1485 1486 1487 bool 1488 InputServer::SafeMode() 1489 { 1490 char parameter[32]; 1491 size_t parameterLength = sizeof(parameter); 1492 1493 if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, 1494 ¶meterLength) == B_OK) { 1495 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1496 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1497 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1498 return true; 1499 } 1500 } 1501 1502 if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter, 1503 ¶meterLength) == B_OK) { 1504 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1505 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1506 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1507 return true; 1508 } 1509 } 1510 1511 return false; 1512 } 1513 1514 1515 status_t 1516 InputServer::_StartEventLoop() 1517 { 1518 CALLED(); 1519 fEventLooperPort = create_port(100, "input server events"); 1520 if (fEventLooperPort < 0) { 1521 PRINTERR(("InputServer: create_port error: (0x%" B_PRIx32 ") %s\n", 1522 fEventLooperPort, strerror(fEventLooperPort))); 1523 return fEventLooperPort; 1524 } 1525 1526 thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_", 1527 B_REAL_TIME_DISPLAY_PRIORITY + 3, this); 1528 if (thread < B_OK || resume_thread(thread) < B_OK) { 1529 if (thread >= B_OK) 1530 kill_thread(thread); 1531 delete_port(fEventLooperPort); 1532 fEventLooperPort = -1; 1533 return thread < B_OK ? thread : B_ERROR; 1534 } 1535 1536 return B_OK; 1537 } 1538 1539 1540 status_t 1541 InputServer::_EventLooper(void* arg) 1542 { 1543 InputServer* self = (InputServer*)arg; 1544 self->_EventLoop(); 1545 1546 return B_OK; 1547 } 1548 1549 1550 void 1551 InputServer::_EventLoop() 1552 { 1553 while (true) { 1554 // Block until we find the size of the next message 1555 ssize_t length = port_buffer_size(fEventLooperPort); 1556 if (length < B_OK) { 1557 PRINT(("[Event Looper] port gone, exiting.\n")); 1558 return; 1559 } 1560 1561 PRINT(("[Event Looper] BMessage Size = %lu\n", length)); 1562 1563 char buffer[length]; 1564 int32 code; 1565 status_t err = read_port(fEventLooperPort, &code, buffer, length); 1566 if (err != length) { 1567 if (err >= 0) { 1568 PRINTERR(("InputServer: failed to read full packet " 1569 "(read %" B_PRIu32 " of %lu)\n", err, length)); 1570 } else { 1571 PRINTERR(("InputServer: read_port error: (0x%" B_PRIx32 1572 ") %s\n", err, strerror(err))); 1573 } 1574 continue; 1575 } 1576 1577 EventList events; 1578 if (fEventQueueLock.Lock()) { 1579 // move the items to our own list to block the event queue as short 1580 // as possible 1581 events.AddList(&fEventQueue); 1582 fEventQueue.MakeEmpty(); 1583 fEventQueueLock.Unlock(); 1584 } 1585 1586 if (length > 0) { 1587 BMessage* event = new BMessage; 1588 1589 if ((err = event->Unflatten(buffer)) < 0) { 1590 PRINTERR(("[InputServer] Unflatten() error: (0x%" B_PRIx32 1591 ") %s\n", err, strerror(err))); 1592 delete event; 1593 continue; 1594 } 1595 1596 events.AddItem(event); 1597 } 1598 1599 // This is where the message should be processed. 1600 1601 if (_SanitizeEvents(events) 1602 && _MethodizeEvents(events) 1603 && _FilterEvents(events)) { 1604 _UpdateMouseAndKeys(events); 1605 _DispatchEvents(events); 1606 } 1607 } 1608 } 1609 1610 1611 /*! Updates the internal mouse position and keyboard info. */ 1612 void 1613 InputServer::_UpdateMouseAndKeys(EventList& events) 1614 { 1615 for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index); 1616 index++) { 1617 switch (event->what) { 1618 case B_MOUSE_DOWN: 1619 case B_MOUSE_UP: 1620 case B_MOUSE_MOVED: 1621 event->FindPoint("where", &fMousePos); 1622 break; 1623 1624 case B_KEY_DOWN: 1625 case B_UNMAPPED_KEY_DOWN: 1626 // update modifiers 1627 uint32 modifiers; 1628 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1629 fKeyInfo.modifiers = modifiers; 1630 1631 // update key states 1632 const uint8 *data; 1633 ssize_t size; 1634 if (event->FindData("states", B_UINT8_TYPE, 1635 (const void**)&data, &size) == B_OK) { 1636 PRINT(("updated keyinfo\n")); 1637 if (size == sizeof(fKeyInfo.key_states)) 1638 memcpy(fKeyInfo.key_states, data, size); 1639 } 1640 1641 if (fActiveMethod == NULL) 1642 break; 1643 1644 // we scan for Alt+Space key down events which means we change 1645 // to next input method 1646 // (pressing "shift" will let us switch to the previous method) 1647 1648 // If there is only one input method, SetNextMethod will return 1649 // B_BAD_INDEX and the event will be forwarded to the user. 1650 1651 PRINT(("SanitizeEvents: %" B_PRIx32 ", %x\n", fKeyInfo.modifiers, 1652 fKeyInfo.key_states[KEY_Spacebar >> 3])); 1653 1654 uint8 byte; 1655 if (event->FindInt8("byte", (int8*)&byte) < B_OK) 1656 byte = 0; 1657 1658 if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ') 1659 || byte == B_HANKAKU_ZENKAKU) 1660 && SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0) 1661 == B_OK) { 1662 // this event isn't sent to the user 1663 events.RemoveItemAt(index); 1664 delete event; 1665 continue; 1666 } 1667 break; 1668 } 1669 } 1670 } 1671 1672 1673 /*! Frees events from unwanted fields, adds missing fields, and removes 1674 unwanted events altogether. 1675 */ 1676 bool 1677 InputServer::_SanitizeEvents(EventList& events) 1678 { 1679 CALLED(); 1680 1681 for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index); 1682 index++) { 1683 switch (event->what) { 1684 case B_MOUSE_MOVED: 1685 case B_MOUSE_DOWN: 1686 { 1687 int32 buttons; 1688 if (event->FindInt32("buttons", &buttons) != B_OK) 1689 event->AddInt32("buttons", 0); 1690 1691 // supposed to fall through 1692 } 1693 case B_MOUSE_UP: 1694 { 1695 BPoint where; 1696 int32 x, y; 1697 float absX, absY; 1698 1699 if (event->FindInt32("x", &x) == B_OK 1700 && event->FindInt32("y", &y) == B_OK) { 1701 where.x = fMousePos.x + x; 1702 where.y = fMousePos.y - y; 1703 1704 event->RemoveName("x"); 1705 event->RemoveName("y"); 1706 event->AddInt32("be:delta_x", x); 1707 event->AddInt32("be:delta_y", y); 1708 1709 PRINT(("new position: %f, %f, %" B_PRId32 ", %" B_PRId32 1710 "\n", where.x, where.y, x, y)); 1711 } else if (event->FindFloat("x", &absX) == B_OK 1712 && event->FindFloat("y", &absY) == B_OK) { 1713 // The device gives us absolute screen coords in range 0..1; 1714 // convert them to absolute screen position 1715 // (the message is supposed to contain the original 1716 // absolute coordinates as "be:tablet_x/y"). 1717 where.x = absX * fFrame.Width(); 1718 where.y = absY * fFrame.Height(); 1719 1720 event->RemoveName("x"); 1721 event->RemoveName("y"); 1722 PRINT(("new position : %f, %f\n", where.x, where.y)); 1723 } else if (event->FindPoint("where", &where) == B_OK) { 1724 PRINT(("new position : %f, %f\n", where.x, where.y)); 1725 } 1726 1727 // Constrain and filter the mouse coords and add the final 1728 // point to the message. 1729 where.x = roundf(where.x); 1730 where.y = roundf(where.y); 1731 where.ConstrainTo(fFrame); 1732 if (event->ReplacePoint("where", where) != B_OK) 1733 event->AddPoint("where", where); 1734 1735 if (!event->HasInt64("when")) 1736 event->AddInt64("when", system_time()); 1737 1738 event->AddInt32("modifiers", fKeyInfo.modifiers); 1739 break; 1740 } 1741 case B_KEY_DOWN: 1742 case B_UNMAPPED_KEY_DOWN: 1743 // add modifiers 1744 if (!event->HasInt32("modifiers")) 1745 event->AddInt32("modifiers", fKeyInfo.modifiers); 1746 1747 // add key states 1748 if (!event->HasData("states", B_UINT8_TYPE)) { 1749 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1750 sizeof(fKeyInfo.key_states)); 1751 } 1752 break; 1753 } 1754 } 1755 1756 return true; 1757 } 1758 1759 1760 /*! Applies the filters of the active input method to the 1761 incoming events. It will also move the events in the method 1762 queue to the event list. 1763 */ 1764 bool 1765 InputServer::_MethodizeEvents(EventList& events) 1766 { 1767 CALLED(); 1768 1769 if (fActiveMethod == NULL) 1770 return true; 1771 1772 int32 count = events.CountItems(); 1773 for (int32 i = 0; i < count;) { 1774 _FilterEvent(fActiveMethod, events, i, count); 1775 } 1776 1777 { 1778 // move the method events into the event queue - they are not 1779 // "methodized" either 1780 BAutolock _(fEventQueueLock); 1781 events.AddList(&fMethodQueue); 1782 fMethodQueue.MakeEmpty(); 1783 } 1784 1785 if (!fInputMethodAware) { 1786 // special handling for non-input-method-aware views 1787 1788 int32 newCount = events.CountItems(); 1789 // we may add new events in this loop that don't need to be checked again 1790 1791 for (int32 i = 0; i < newCount; i++) { 1792 BMessage* event = events.ItemAt(i); 1793 1794 if (event->what != B_INPUT_METHOD_EVENT) 1795 continue; 1796 1797 SERIAL_PRINT(("IME received\n")); 1798 1799 bool removeEvent = true; 1800 1801 int32 opcode; 1802 if (event->FindInt32("be:opcode", &opcode) == B_OK) { 1803 bool inlineOnly; 1804 if (event->FindBool("be:inline_only", &inlineOnly) != B_OK) 1805 inlineOnly = false; 1806 1807 if (inlineOnly) { 1808 BMessage translated; 1809 bool confirmed; 1810 if (opcode == B_INPUT_METHOD_CHANGED 1811 && event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed 1812 && event->FindMessage("be:translated", &translated) == B_OK) { 1813 // translate event for the non-aware view 1814 *event = translated; 1815 removeEvent = false; 1816 } 1817 } else { 1818 if (fInputMethodWindow == NULL 1819 && opcode == B_INPUT_METHOD_STARTED) 1820 fInputMethodWindow = new (nothrow) BottomlineWindow(); 1821 1822 if (fInputMethodWindow != NULL) { 1823 EventList newEvents; 1824 fInputMethodWindow->HandleInputMethodEvent(event, newEvents); 1825 1826 if (!newEvents.IsEmpty()) { 1827 events.AddList(&newEvents); 1828 opcode = B_INPUT_METHOD_STOPPED; 1829 } 1830 1831 if (opcode == B_INPUT_METHOD_STOPPED) { 1832 fInputMethodWindow->PostMessage(B_QUIT_REQUESTED); 1833 fInputMethodWindow = NULL; 1834 } 1835 } 1836 } 1837 } 1838 1839 if (removeEvent) { 1840 // the inline/bottom window has eaten the event 1841 events.RemoveItemAt(i--); 1842 delete event; 1843 newCount--; 1844 } 1845 } 1846 } 1847 1848 return events.CountItems() > 0; 1849 } 1850 1851 1852 /*! This method applies all defined filters to each event in the 1853 supplied list. The supplied list is modified to reflect the 1854 output of the filters. 1855 The method returns true if the filters were applied to all 1856 events without error and false otherwise. 1857 */ 1858 bool 1859 InputServer::_FilterEvents(EventList& events) 1860 { 1861 CALLED(); 1862 BAutolock _(gInputFilterListLocker); 1863 1864 int32 count = gInputFilterList.CountItems(); 1865 int32 eventCount = events.CountItems(); 1866 1867 for (int32 i = 0; i < count; i++) { 1868 BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i); 1869 1870 // Apply the current filter to all available event messages. 1871 1872 for (int32 eventIndex = 0; eventIndex < eventCount;) { 1873 _FilterEvent(filter, events, eventIndex, eventCount); 1874 } 1875 } 1876 1877 return eventCount != 0; 1878 } 1879 1880 1881 void 1882 InputServer::_DispatchEvents(EventList& events) 1883 { 1884 CALLED(); 1885 1886 int32 count = events.CountItems(); 1887 1888 for (int32 i = 0; i < count; i++) { 1889 BMessage* event = events.ItemAt(i); 1890 1891 // now we must send each event to the app_server 1892 _DispatchEvent(event); 1893 delete event; 1894 } 1895 1896 events.MakeEmpty(); 1897 } 1898 1899 1900 /*! Applies the given filter to the event list. 1901 For your convenience, it also alters the \a index and \a count arguments 1902 ready for the next call to this method. 1903 */ 1904 void 1905 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events, 1906 int32& index, int32& count) 1907 { 1908 BMessage* event = events.ItemAt(index); 1909 1910 BList newEvents; 1911 filter_result result = filter->Filter(event, &newEvents); 1912 1913 if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) { 1914 // we no longer need the current event 1915 events.RemoveItemAt(index); 1916 delete event; 1917 1918 if (result == B_DISPATCH_MESSAGE) { 1919 EventList addedEvents; 1920 EventList::Private(&addedEvents).AsBList()->AddList(&newEvents); 1921 _SanitizeEvents(addedEvents); 1922 // add the new events - but don't methodize them again 1923 events.AddList(&addedEvents, index); 1924 index += newEvents.CountItems(); 1925 count = events.CountItems(); 1926 } else 1927 count--; 1928 } else 1929 index++; 1930 } 1931 1932 1933 status_t 1934 InputServer::_DispatchEvent(BMessage* event) 1935 { 1936 CALLED(); 1937 1938 switch (event->what) { 1939 case B_MOUSE_MOVED: 1940 case B_MOUSE_DOWN: 1941 case B_MOUSE_UP: 1942 if (fCursorBuffer) { 1943 atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL 1944 | ((uint32)fMousePos.y & 0xffff)); 1945 if (atomic_or(&fCursorBuffer->read, 1) == 0) 1946 release_sem(fCursorSem); 1947 } 1948 break; 1949 1950 case B_KEY_DOWN: 1951 case B_KEY_UP: 1952 case B_UNMAPPED_KEY_DOWN: 1953 case B_UNMAPPED_KEY_UP: 1954 case B_MODIFIERS_CHANGED: 1955 { 1956 // update or add modifiers 1957 uint32 modifiers; 1958 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1959 fKeyInfo.modifiers = modifiers; 1960 else 1961 event->AddInt32("modifiers", fKeyInfo.modifiers); 1962 1963 // update or add key states 1964 const uint8 *data; 1965 ssize_t size; 1966 if (event->FindData("states", B_UINT8_TYPE, 1967 (const void**)&data, &size) == B_OK) { 1968 PRINT(("updated keyinfo\n")); 1969 if (size == sizeof(fKeyInfo.key_states)) 1970 memcpy(fKeyInfo.key_states, data, size); 1971 } else { 1972 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1973 sizeof(fKeyInfo.key_states)); 1974 } 1975 1976 break; 1977 } 1978 1979 default: 1980 break; 1981 } 1982 1983 BMessenger reply; 1984 BMessage::Private messagePrivate(event); 1985 return messagePrivate.SendMessage(fAppServerPort, fAppServerTeam, 0, 0, 1986 false, reply); 1987 } 1988 1989 1990 // #pragma mark - 1991 1992 1993 extern "C" void 1994 RegisterDevices(input_device_ref** devices) 1995 { 1996 CALLED(); 1997 } 1998 1999 2000 BView * 2001 instantiate_deskbar_item() 2002 { 2003 return new MethodReplicant(INPUTSERVER_SIGNATURE); 2004 } 2005 2006 2007 // #pragma mark - 2008 2009 2010 int 2011 main(int /*argc*/, char** /*argv*/) 2012 { 2013 InputServer *inputServer = new InputServer; 2014 2015 inputServer->Run(); 2016 delete inputServer; 2017 2018 return 0; 2019 } 2020