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