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