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