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