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