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