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