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 if (message->what == IS_GET_KEY_MAP) { 936 status_t status = reply->AddData("keymap", B_ANY_TYPE, &fKeys, sizeof(fKeys)); 937 if (status == B_OK) 938 status = reply->AddData("key_buffer", B_ANY_TYPE, fChars, fCharsSize); 939 940 return status; 941 } 942 943 if (_LoadKeymap() != B_OK) 944 _LoadSystemKeymap(); 945 946 BMessage msg(IS_CONTROL_DEVICES); 947 msg.AddInt32("type", B_KEYBOARD_DEVICE); 948 msg.AddInt32("code", B_KEY_MAP_CHANGED); 949 return fAddOnManager->PostMessage(&msg); 950 } 951 952 953 status_t 954 InputServer::HandleFocusUnfocusIMAwareView(BMessage* message, 955 BMessage* reply) 956 { 957 CALLED(); 958 959 BMessenger messenger; 960 status_t status = message->FindMessenger("view", &messenger); 961 if (status != B_OK) 962 return status; 963 964 // check if current view is ours 965 966 if (message->what == IS_FOCUS_IM_AWARE_VIEW) { 967 PRINT(("HandleFocusUnfocusIMAwareView : entering\n")); 968 fInputMethodAware = true; 969 } else { 970 PRINT(("HandleFocusUnfocusIMAwareView : leaving\n")); 971 fInputMethodAware = false; 972 } 973 974 return B_OK; 975 } 976 977 978 /*! Enqueues the message into the event queue. 979 The message must only be deleted in case this method returns an error. 980 */ 981 status_t 982 InputServer::EnqueueDeviceMessage(BMessage* message) 983 { 984 CALLED(); 985 986 BAutolock _(fEventQueueLock); 987 if (!fEventQueue.AddItem(message)) 988 return B_NO_MEMORY; 989 990 if (fEventQueue.CountItems() == 1) { 991 // notify event loop only if we haven't already done so 992 write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0); 993 } 994 return B_OK; 995 } 996 997 998 /*! Enqueues the message into the method queue. 999 The message must only be deleted in case this method returns an error. 1000 */ 1001 status_t 1002 InputServer::EnqueueMethodMessage(BMessage* message) 1003 { 1004 CALLED(); 1005 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, (char)(message->what >> 24), 1006 (char)(message->what >> 16), (char)(message->what >> 8), (char)message->what)); 1007 1008 #ifdef DEBUG 1009 if (message->what == 'IMEV') { 1010 int32 code; 1011 message->FindInt32("be:opcode", &code); 1012 PRINT(("%s be:opcode %li\n", __PRETTY_FUNCTION__, code)); 1013 } 1014 #endif 1015 1016 BAutolock _(fEventQueueLock); 1017 if (!fMethodQueue.AddItem(message)) 1018 return B_NO_MEMORY; 1019 1020 if (fMethodQueue.CountItems() == 1) { 1021 // notify event loop only if we haven't already done so 1022 write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0); 1023 } 1024 return B_OK; 1025 } 1026 1027 1028 status_t 1029 InputServer::SetNextMethod(bool direction) 1030 { 1031 gInputMethodListLocker.Lock(); 1032 1033 int32 index = gInputMethodList.IndexOf(fActiveMethod); 1034 int32 oldIndex = index; 1035 1036 index += (direction ? 1 : -1); 1037 1038 if (index < -1) 1039 index = gInputMethodList.CountItems() - 1; 1040 if (index >= gInputMethodList.CountItems()) 1041 index = -1; 1042 1043 if (index == oldIndex) 1044 return B_BAD_INDEX; 1045 1046 BInputServerMethod *method = &gKeymapMethod; 1047 1048 if (index != -1) 1049 method = (BInputServerMethod *)gInputMethodList.ItemAt(index); 1050 1051 SetActiveMethod(method); 1052 1053 gInputMethodListLocker.Unlock(); 1054 return B_OK; 1055 } 1056 1057 1058 void 1059 InputServer::SetActiveMethod(BInputServerMethod* method) 1060 { 1061 CALLED(); 1062 if (fActiveMethod) 1063 fActiveMethod->fOwner->MethodActivated(false); 1064 1065 fActiveMethod = method; 1066 1067 if (fActiveMethod) 1068 fActiveMethod->fOwner->MethodActivated(true); 1069 } 1070 1071 1072 const BMessenger* 1073 InputServer::MethodReplicant() 1074 { 1075 return fReplicantMessenger; 1076 } 1077 1078 1079 void 1080 InputServer::SetMethodReplicant(const BMessenger* messenger) 1081 { 1082 fReplicantMessenger = messenger; 1083 } 1084 1085 1086 bool 1087 InputServer::EventLoopRunning() 1088 { 1089 return fEventLooperPort >= B_OK; 1090 } 1091 1092 1093 status_t 1094 InputServer::GetDeviceInfo(const char* name, input_device_type *_type, 1095 bool *_isRunning) 1096 { 1097 BAutolock lock(fInputDeviceListLocker); 1098 1099 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1100 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1101 1102 if (item->HasName(name)) { 1103 if (_type) 1104 *_type = item->Type(); 1105 if (_isRunning) 1106 *_isRunning = item->Running(); 1107 1108 return B_OK; 1109 } 1110 } 1111 1112 return B_NAME_NOT_FOUND; 1113 } 1114 1115 1116 status_t 1117 InputServer::GetDeviceInfos(BMessage *msg) 1118 { 1119 CALLED(); 1120 BAutolock lock(fInputDeviceListLocker); 1121 1122 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1123 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1124 msg->AddString("device", item->Name()); 1125 msg->AddInt32("type", item->Type()); 1126 } 1127 return B_OK; 1128 } 1129 1130 1131 status_t 1132 InputServer::UnregisterDevices(BInputServerDevice& serverDevice, 1133 input_device_ref **devices) 1134 { 1135 CALLED(); 1136 BAutolock lock(fInputDeviceListLocker); 1137 1138 if (devices != NULL) { 1139 // remove the devices as specified only 1140 input_device_ref *device = NULL; 1141 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1142 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1143 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1144 1145 if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) { 1146 item->Stop(); 1147 if (fInputDeviceList.RemoveItem(j)) 1148 delete item; 1149 break; 1150 } 1151 } 1152 } 1153 } else { 1154 // remove all devices from this BInputServerObject 1155 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1156 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1157 1158 if (item->ServerDevice() == &serverDevice) { 1159 item->Stop(); 1160 if (fInputDeviceList.RemoveItem(i)) 1161 delete item; 1162 } 1163 } 1164 } 1165 1166 return B_OK; 1167 } 1168 1169 1170 status_t 1171 InputServer::RegisterDevices(BInputServerDevice& serverDevice, 1172 input_device_ref** devices) 1173 { 1174 if (devices == NULL) 1175 return B_BAD_VALUE; 1176 1177 BAutolock lock(fInputDeviceListLocker); 1178 1179 input_device_ref *device = NULL; 1180 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1181 if (device->type != B_POINTING_DEVICE 1182 && device->type != B_KEYBOARD_DEVICE 1183 && device->type != B_UNDEFINED_DEVICE) 1184 continue; 1185 1186 // find existing input server device 1187 1188 bool found = false; 1189 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1190 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1191 1192 if (item->HasName(device->name)) { 1193 debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", device->name); 1194 PRINT(("RegisterDevices found %s\n", device->name)); 1195 found = true; 1196 break; 1197 } 1198 } 1199 1200 if (!found) { 1201 PRINT(("RegisterDevices not found %s\n", device->name)); 1202 InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice, 1203 *device); 1204 if (item != NULL && fInputDeviceList.AddItem(item)) { 1205 item->Start(); 1206 } else { 1207 delete item; 1208 return B_NO_MEMORY; 1209 } 1210 } 1211 } 1212 1213 return B_OK; 1214 } 1215 1216 1217 status_t 1218 InputServer::StartStopDevices(const char* name, input_device_type type, 1219 bool doStart) 1220 { 1221 CALLED(); 1222 BAutolock lock(fInputDeviceListLocker); 1223 1224 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1225 InputDeviceListItem* item 1226 = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1227 if (!item) 1228 continue; 1229 1230 if (item->Matches(name, type)) { 1231 if (doStart == item->Running()) { 1232 if (name) 1233 return B_OK; 1234 else 1235 continue; 1236 } 1237 1238 if (doStart) 1239 item->Start(); 1240 else 1241 item->Stop(); 1242 1243 if (name) 1244 return B_OK; 1245 } 1246 } 1247 1248 if (name) { 1249 // item not found 1250 return B_ERROR; 1251 } 1252 1253 return B_OK; 1254 } 1255 1256 1257 1258 status_t 1259 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart) 1260 { 1261 CALLED(); 1262 BAutolock lock(fInputDeviceListLocker); 1263 1264 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1265 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1266 1267 if (item->ServerDevice() != &serverDevice) 1268 continue; 1269 1270 if (doStart == item->Running()) 1271 continue; 1272 1273 if (doStart) 1274 item->Start(); 1275 else 1276 item->Stop(); 1277 } 1278 1279 return B_OK; 1280 } 1281 1282 1283 status_t 1284 InputServer::ControlDevices(const char* name, input_device_type type, 1285 uint32 code, BMessage* message) 1286 { 1287 CALLED(); 1288 BAutolock lock(fInputDeviceListLocker); 1289 1290 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1291 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1292 if (!item) 1293 continue; 1294 1295 if (item->Matches(name, type)) { 1296 item->Control(code, message); 1297 1298 if (name) 1299 return B_OK; 1300 } 1301 } 1302 1303 if (name) 1304 return B_ERROR; 1305 1306 return B_OK; 1307 } 1308 1309 1310 bool 1311 InputServer::SafeMode() 1312 { 1313 char parameter[32]; 1314 size_t parameterLength = sizeof(parameter); 1315 1316 if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, 1317 ¶meterLength) == B_OK) { 1318 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1319 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1320 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1321 return true; 1322 } 1323 } 1324 1325 if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS, parameter, 1326 ¶meterLength) == B_OK) { 1327 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on") 1328 || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes") 1329 || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1")) { 1330 return true; 1331 } 1332 } 1333 1334 return false; 1335 } 1336 1337 1338 status_t 1339 InputServer::_StartEventLoop() 1340 { 1341 CALLED(); 1342 fEventLooperPort = create_port(100, "input server events"); 1343 if (fEventLooperPort < 0) { 1344 PRINTERR(("InputServer: create_port error: (0x%lx) %s\n", 1345 fEventLooperPort, strerror(fEventLooperPort))); 1346 return fEventLooperPort; 1347 } 1348 1349 thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_", 1350 B_REAL_TIME_DISPLAY_PRIORITY + 3, this); 1351 if (thread < B_OK || resume_thread(thread) < B_OK) { 1352 if (thread >= B_OK) 1353 kill_thread(thread); 1354 delete_port(fEventLooperPort); 1355 fEventLooperPort = -1; 1356 return thread < B_OK ? thread : B_ERROR; 1357 } 1358 1359 return B_OK; 1360 } 1361 1362 1363 status_t 1364 InputServer::_EventLooper(void* arg) 1365 { 1366 InputServer* self = (InputServer*)arg; 1367 self->_EventLoop(); 1368 1369 return B_OK; 1370 } 1371 1372 1373 void 1374 InputServer::_EventLoop() 1375 { 1376 while (true) { 1377 // Block until we find the size of the next message 1378 ssize_t length = port_buffer_size(fEventLooperPort); 1379 if (length < B_OK) { 1380 PRINT(("[Event Looper] port gone, exiting.\n")); 1381 return; 1382 } 1383 1384 PRINT(("[Event Looper] BMessage Size = %lu\n", length)); 1385 1386 char buffer[length]; 1387 int32 code; 1388 status_t err = read_port(fEventLooperPort, &code, buffer, length); 1389 if (err != length) { 1390 if (err >= 0) { 1391 PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length)); 1392 } else { 1393 PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err))); 1394 } 1395 continue; 1396 } 1397 1398 EventList events; 1399 if (fEventQueueLock.Lock()) { 1400 // move the items to our own list to block the event queue as short as possible 1401 events.AddList(&fEventQueue); 1402 fEventQueue.MakeEmpty(); 1403 fEventQueueLock.Unlock(); 1404 } 1405 1406 if (length > 0) { 1407 BMessage* event = new BMessage; 1408 1409 if ((err = event->Unflatten(buffer)) < 0) { 1410 PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err))); 1411 delete event; 1412 continue; 1413 } 1414 1415 events.AddItem(event); 1416 } 1417 1418 // This is where the message should be processed. 1419 1420 if (_SanitizeEvents(events) 1421 && _MethodizeEvents(events) 1422 && _FilterEvents(events)) { 1423 _UpdateMouseAndKeys(events); 1424 _DispatchEvents(events); 1425 } 1426 } 1427 } 1428 1429 1430 /*! Updates the internal mouse position and keyboard info. */ 1431 void 1432 InputServer::_UpdateMouseAndKeys(EventList& events) 1433 { 1434 for (int32 index = 0;BMessage* event = (BMessage*)events.ItemAt(index); 1435 index++) { 1436 switch (event->what) { 1437 case B_MOUSE_DOWN: 1438 case B_MOUSE_UP: 1439 case B_MOUSE_MOVED: 1440 event->FindPoint("where", &fMousePos); 1441 break; 1442 1443 case B_KEY_DOWN: 1444 case B_UNMAPPED_KEY_DOWN: 1445 // update modifiers 1446 uint32 modifiers; 1447 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1448 fKeyInfo.modifiers = modifiers; 1449 1450 // update key states 1451 const uint8 *data; 1452 ssize_t size; 1453 if (event->FindData("states", B_UINT8_TYPE, 1454 (const void**)&data, &size) == B_OK) { 1455 PRINT(("updated keyinfo\n")); 1456 if (size == sizeof(fKeyInfo.key_states)) 1457 memcpy(fKeyInfo.key_states, data, size); 1458 } 1459 1460 if (fActiveMethod == NULL) 1461 break; 1462 1463 // we scan for Alt+Space key down events which means we change 1464 // to next input method 1465 // (pressing "shift" will let us switch to the previous method) 1466 1467 // If there is only one input method, SetNextMethod will return 1468 // B_BAD_INDEX and the event will be forwarded to the user. 1469 1470 PRINT(("SanitizeEvents: %lx, %x\n", fKeyInfo.modifiers, 1471 fKeyInfo.key_states[KEY_Spacebar >> 3])); 1472 1473 uint8 byte; 1474 if (event->FindInt8("byte", (int8*)&byte) < B_OK) 1475 byte = 0; 1476 1477 if ((((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 && byte == ' ') 1478 || byte == B_HANKAKU_ZENKAKU) 1479 && SetNextMethod((fKeyInfo.modifiers & B_SHIFT_KEY) == 0) 1480 == B_OK) { 1481 // this event isn't sent to the user 1482 events.RemoveItemAt(index); 1483 delete event; 1484 continue; 1485 } 1486 break; 1487 } 1488 } 1489 } 1490 1491 1492 /*! Frees events from unwanted fields, adds missing fields, and removes 1493 unwanted events altogether. 1494 */ 1495 bool 1496 InputServer::_SanitizeEvents(EventList& events) 1497 { 1498 CALLED(); 1499 1500 for (int32 index = 0; BMessage* event = (BMessage*)events.ItemAt(index); 1501 index++) { 1502 switch (event->what) { 1503 case B_MOUSE_MOVED: 1504 case B_MOUSE_DOWN: 1505 { 1506 int32 buttons; 1507 if (event->FindInt32("buttons", &buttons) != B_OK) 1508 event->AddInt32("buttons", 0); 1509 1510 // supposed to fall through 1511 } 1512 case B_MOUSE_UP: 1513 { 1514 BPoint where; 1515 int32 x, y; 1516 float absX, absY; 1517 1518 if (event->FindInt32("x", &x) == B_OK 1519 && event->FindInt32("y", &y) == B_OK) { 1520 where.x = fMousePos.x + x; 1521 where.y = fMousePos.y - y; 1522 1523 event->RemoveName("x"); 1524 event->RemoveName("y"); 1525 event->AddInt32("be:delta_x", x); 1526 event->AddInt32("be:delta_y", y); 1527 1528 PRINT(("new position: %f, %f, %ld, %ld\n", 1529 where.x, where.y, x, y)); 1530 } else if (event->FindFloat("x", &absX) == B_OK 1531 && event->FindFloat("y", &absY) == B_OK) { 1532 // The device gives us absolute screen coords in range 0..1; 1533 // convert them to absolute screen position 1534 // (the message is supposed to contain the original 1535 // absolute coordinates as "be:tablet_x/y"). 1536 where.x = absX * fFrame.Width(); 1537 where.y = absY * fFrame.Height(); 1538 1539 event->RemoveName("x"); 1540 event->RemoveName("y"); 1541 PRINT(("new position : %f, %f\n", where.x, where.y)); 1542 } else if (event->FindPoint("where", &where) == B_OK) { 1543 PRINT(("new position : %f, %f\n", where.x, where.y)); 1544 } 1545 1546 // Constrain and filter the mouse coords and add the final 1547 // point to the message. 1548 where.x = roundf(where.x); 1549 where.y = roundf(where.y); 1550 where.ConstrainTo(fFrame); 1551 if (event->ReplacePoint("where", where) != B_OK) 1552 event->AddPoint("where", where); 1553 1554 if (!event->HasInt64("when")) 1555 event->AddInt64("when", system_time()); 1556 1557 event->AddInt32("modifiers", fKeyInfo.modifiers); 1558 break; 1559 } 1560 case B_KEY_DOWN: 1561 case B_UNMAPPED_KEY_DOWN: 1562 // add modifiers 1563 if (!event->HasInt32("modifiers")) 1564 event->AddInt32("modifiers", fKeyInfo.modifiers); 1565 1566 // add key states 1567 if (!event->HasData("states", B_UINT8_TYPE)) { 1568 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1569 sizeof(fKeyInfo.key_states)); 1570 } 1571 break; 1572 } 1573 } 1574 1575 return true; 1576 } 1577 1578 1579 /*! Applies the filters of the active input method to the 1580 incoming events. It will also move the events in the method 1581 queue to the event list. 1582 */ 1583 bool 1584 InputServer::_MethodizeEvents(EventList& events) 1585 { 1586 CALLED(); 1587 1588 if (fActiveMethod == NULL) 1589 return true; 1590 1591 int32 count = events.CountItems(); 1592 for (int32 i = 0; i < count;) { 1593 _FilterEvent(fActiveMethod, events, i, count); 1594 } 1595 1596 { 1597 // move the method events into the event queue - they are not 1598 // "methodized" either 1599 BAutolock _(fEventQueueLock); 1600 events.AddList(&fMethodQueue); 1601 fMethodQueue.MakeEmpty(); 1602 } 1603 1604 if (!fInputMethodAware) { 1605 // special handling for non-input-method-aware views 1606 1607 int32 newCount = events.CountItems(); 1608 // we may add new events in this loop that don't need to be checked again 1609 1610 for (int32 i = 0; i < newCount; i++) { 1611 BMessage* event = events.ItemAt(i); 1612 1613 if (event->what != B_INPUT_METHOD_EVENT) 1614 continue; 1615 1616 SERIAL_PRINT(("IME received\n")); 1617 1618 bool removeEvent = true; 1619 1620 int32 opcode; 1621 if (event->FindInt32("be:opcode", &opcode) == B_OK) { 1622 bool inlineOnly; 1623 if (event->FindBool("be:inline_only", &inlineOnly) != B_OK) 1624 inlineOnly = false; 1625 1626 if (inlineOnly) { 1627 BMessage translated; 1628 bool confirmed; 1629 if (opcode == B_INPUT_METHOD_CHANGED 1630 && event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed 1631 && event->FindMessage("be:translated", &translated) == B_OK) { 1632 // translate event for the non-aware view 1633 *event = translated; 1634 removeEvent = false; 1635 } 1636 } else { 1637 if (fInputMethodWindow == NULL 1638 && opcode == B_INPUT_METHOD_STARTED) 1639 fInputMethodWindow = new (nothrow) BottomlineWindow(); 1640 1641 if (fInputMethodWindow != NULL) { 1642 EventList newEvents; 1643 fInputMethodWindow->HandleInputMethodEvent(event, newEvents); 1644 1645 if (!newEvents.IsEmpty()) { 1646 events.AddList(&newEvents); 1647 opcode = B_INPUT_METHOD_STOPPED; 1648 } 1649 1650 if (opcode == B_INPUT_METHOD_STOPPED) { 1651 fInputMethodWindow->PostMessage(B_QUIT_REQUESTED); 1652 fInputMethodWindow = NULL; 1653 } 1654 } 1655 } 1656 } 1657 1658 if (removeEvent) { 1659 // the inline/bottom window has eaten the event 1660 events.RemoveItemAt(i--); 1661 delete event; 1662 newCount--; 1663 } 1664 } 1665 } 1666 1667 return events.CountItems() > 0; 1668 } 1669 1670 1671 /*! This method applies all defined filters to each event in the 1672 supplied list. The supplied list is modified to reflect the 1673 output of the filters. 1674 The method returns true if the filters were applied to all 1675 events without error and false otherwise. 1676 */ 1677 bool 1678 InputServer::_FilterEvents(EventList& events) 1679 { 1680 CALLED(); 1681 BAutolock _(gInputFilterListLocker); 1682 1683 int32 count = gInputFilterList.CountItems(); 1684 int32 eventCount = events.CountItems(); 1685 1686 for (int32 i = 0; i < count; i++) { 1687 BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i); 1688 1689 // Apply the current filter to all available event messages. 1690 1691 for (int32 eventIndex = 0; eventIndex < eventCount;) { 1692 _FilterEvent(filter, events, eventIndex, eventCount); 1693 } 1694 } 1695 1696 return eventCount != 0; 1697 } 1698 1699 1700 void 1701 InputServer::_DispatchEvents(EventList& events) 1702 { 1703 CALLED(); 1704 1705 int32 count = events.CountItems(); 1706 1707 for (int32 i = 0; i < count; i++) { 1708 BMessage* event = events.ItemAt(i); 1709 1710 // now we must send each event to the app_server 1711 _DispatchEvent(event); 1712 delete event; 1713 } 1714 1715 events.MakeEmpty(); 1716 } 1717 1718 1719 /*! Applies the given filter to the event list. 1720 For your convenience, it also alters the \a index and \a count arguments 1721 ready for the next call to this method. 1722 */ 1723 void 1724 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events, 1725 int32& index, int32& count) 1726 { 1727 BMessage* event = events.ItemAt(index); 1728 1729 BList newEvents; 1730 filter_result result = filter->Filter(event, &newEvents); 1731 1732 if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) { 1733 // we no longer need the current event 1734 events.RemoveItemAt(index); 1735 delete event; 1736 1737 if (result == B_DISPATCH_MESSAGE) { 1738 EventList addedEvents; 1739 EventList::Private(&addedEvents).AsBList()->AddList(&newEvents); 1740 _SanitizeEvents(addedEvents); 1741 // add the new events - but don't methodize them again 1742 events.AddList(&addedEvents, index); 1743 index += newEvents.CountItems(); 1744 count = events.CountItems(); 1745 } else 1746 count--; 1747 } else 1748 index++; 1749 } 1750 1751 1752 status_t 1753 InputServer::_DispatchEvent(BMessage* event) 1754 { 1755 CALLED(); 1756 1757 switch (event->what) { 1758 case B_MOUSE_MOVED: 1759 case B_MOUSE_DOWN: 1760 case B_MOUSE_UP: 1761 if (fCursorBuffer) { 1762 atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL 1763 | ((uint32)fMousePos.y & 0xffff)); 1764 if (atomic_or(&fCursorBuffer->read, 1) == 0) 1765 release_sem(fCursorSem); 1766 } 1767 break; 1768 1769 case B_KEY_DOWN: 1770 case B_KEY_UP: 1771 case B_UNMAPPED_KEY_DOWN: 1772 case B_UNMAPPED_KEY_UP: 1773 case B_MODIFIERS_CHANGED: 1774 { 1775 // update or add modifiers 1776 uint32 modifiers; 1777 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1778 fKeyInfo.modifiers = modifiers; 1779 else 1780 event->AddInt32("modifiers", fKeyInfo.modifiers); 1781 1782 // update or add key states 1783 const uint8 *data; 1784 ssize_t size; 1785 if (event->FindData("states", B_UINT8_TYPE, 1786 (const void**)&data, &size) == B_OK) { 1787 PRINT(("updated keyinfo\n")); 1788 if (size == sizeof(fKeyInfo.key_states)) 1789 memcpy(fKeyInfo.key_states, data, size); 1790 } else { 1791 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1792 sizeof(fKeyInfo.key_states)); 1793 } 1794 1795 break; 1796 } 1797 1798 default: 1799 break; 1800 } 1801 1802 BMessenger reply; 1803 BMessage::Private messagePrivate(event); 1804 return messagePrivate.SendMessage(fAppServerPort, fAppServerTeam, 0, 0, 1805 false, reply); 1806 } 1807 1808 1809 // #pragma mark - 1810 1811 1812 extern "C" void 1813 RegisterDevices(input_device_ref** devices) 1814 { 1815 CALLED(); 1816 } 1817 1818 1819 BView * 1820 instantiate_deskbar_item() 1821 { 1822 return new MethodReplicant(INPUTSERVER_SIGNATURE); 1823 } 1824 1825 1826 // #pragma mark - 1827 1828 1829 int 1830 main(int /*argc*/, char** /*argv*/) 1831 { 1832 InputServer *inputServer = new InputServer; 1833 1834 inputServer->Run(); 1835 delete inputServer; 1836 1837 return 0; 1838 } 1839