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