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