1 /* 2 * Copyright 2002-2008, 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 status_t 927 InputServer::EnqueueDeviceMessage(BMessage* message) 928 { 929 CALLED(); 930 931 BAutolock _(fEventQueueLock); 932 if (!fEventQueue.AddItem(message)) 933 return B_NO_MEMORY; 934 935 if (fEventQueue.CountItems() == 1) { 936 // notify event loop only if we haven't already done so 937 write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0); 938 } 939 return B_OK; 940 } 941 942 943 /*! Enqueues the message into the method queue. 944 The message must only be deleted in case this method returns an error. 945 */ 946 status_t 947 InputServer::EnqueueMethodMessage(BMessage* message) 948 { 949 CALLED(); 950 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what >> 24, 951 message->what >> 16, message->what >> 8, message->what)); 952 953 #ifdef DEBUG 954 if (message->what == 'IMEV') { 955 int32 code; 956 message->FindInt32("be:opcode", &code); 957 PRINT(("%s be:opcode %li\n", __PRETTY_FUNCTION__, code)); 958 } 959 #endif 960 961 BAutolock _(fEventQueueLock); 962 if (!fMethodQueue.AddItem(message)) 963 return B_NO_MEMORY; 964 965 if (fMethodQueue.CountItems() == 1) { 966 // notify event loop only if we haven't already done so 967 write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0); 968 } 969 return B_OK; 970 } 971 972 973 status_t 974 InputServer::SetNextMethod(bool direction) 975 { 976 gInputMethodListLocker.Lock(); 977 978 int32 index = gInputMethodList.IndexOf(fActiveMethod); 979 index += (direction ? 1 : -1); 980 981 if (index < -1) 982 index = gInputMethodList.CountItems() - 1; 983 if (index >= gInputMethodList.CountItems()) 984 index = -1; 985 986 BInputServerMethod *method = &gKeymapMethod; 987 988 if (index != -1) 989 method = (BInputServerMethod *)gInputMethodList.ItemAt(index); 990 991 SetActiveMethod(method); 992 993 gInputMethodListLocker.Unlock(); 994 return B_OK; 995 } 996 997 998 void 999 InputServer::SetActiveMethod(BInputServerMethod* method) 1000 { 1001 CALLED(); 1002 if (fActiveMethod) 1003 fActiveMethod->fOwner->MethodActivated(false); 1004 1005 fActiveMethod = method; 1006 1007 if (fActiveMethod) 1008 fActiveMethod->fOwner->MethodActivated(true); 1009 } 1010 1011 1012 const BMessenger* 1013 InputServer::MethodReplicant() 1014 { 1015 return fReplicantMessenger; 1016 } 1017 1018 1019 void 1020 InputServer::SetMethodReplicant(const BMessenger* messenger) 1021 { 1022 fReplicantMessenger = messenger; 1023 } 1024 1025 1026 bool 1027 InputServer::EventLoopRunning() 1028 { 1029 return fEventLooperPort >= B_OK; 1030 } 1031 1032 1033 /*! The fInputDeviceListLocker must be locked when calling this function */ 1034 InputDeviceListItem* 1035 InputServer::_FindInputDeviceListItem(BInputServerDevice& device) 1036 { 1037 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1038 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1039 1040 if (item->ServerDevice() == &device) 1041 return item; 1042 } 1043 1044 return NULL; 1045 } 1046 1047 1048 status_t 1049 InputServer::GetDeviceInfo(const char* name, input_device_type *_type, 1050 bool *_isRunning) 1051 { 1052 BAutolock lock(fInputDeviceListLocker); 1053 1054 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1055 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1056 1057 if (item->HasName(name)) { 1058 if (_type) 1059 *_type = item->Type(); 1060 if (_isRunning) 1061 *_isRunning = item->Running(); 1062 1063 return B_OK; 1064 } 1065 } 1066 1067 return B_NAME_NOT_FOUND; 1068 } 1069 1070 1071 status_t 1072 InputServer::GetDeviceInfos(BMessage *msg) 1073 { 1074 CALLED(); 1075 BAutolock lock(fInputDeviceListLocker); 1076 1077 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1078 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1079 msg->AddString("device", item->Name()); 1080 msg->AddInt32("type", item->Type()); 1081 } 1082 return B_OK; 1083 } 1084 1085 1086 status_t 1087 InputServer::UnregisterDevices(BInputServerDevice& serverDevice, 1088 input_device_ref **devices) 1089 { 1090 CALLED(); 1091 BAutolock lock(fInputDeviceListLocker); 1092 1093 if (devices != NULL) { 1094 // remove the devices as specified only 1095 input_device_ref *device = NULL; 1096 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1097 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1098 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1099 1100 if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) { 1101 item->Stop(); 1102 fInputDeviceList.RemoveItem(j); 1103 delete item; 1104 break; 1105 } 1106 } 1107 } 1108 } else { 1109 // remove all devices from this BInputServerObject 1110 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1111 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1112 1113 if (item->ServerDevice() == &serverDevice) { 1114 item->Stop(); 1115 fInputDeviceList.RemoveItem(i); 1116 delete item; 1117 } 1118 } 1119 } 1120 1121 return B_OK; 1122 } 1123 1124 1125 status_t 1126 InputServer::RegisterDevices(BInputServerDevice& serverDevice, 1127 input_device_ref** devices) 1128 { 1129 if (devices == NULL) 1130 return B_BAD_VALUE; 1131 1132 BAutolock lock(fInputDeviceListLocker); 1133 1134 input_device_ref *device = NULL; 1135 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1136 if (device->type != B_POINTING_DEVICE 1137 && device->type != B_KEYBOARD_DEVICE 1138 && device->type != B_UNDEFINED_DEVICE) 1139 continue; 1140 1141 // find existing input server device 1142 1143 bool found = false; 1144 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1145 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1146 1147 if (item->HasName(device->name)) { 1148 PRINT(("RegisterDevices found %s\n", device->name)); 1149 found = true; 1150 break; 1151 } 1152 } 1153 1154 if (!found) { 1155 PRINT(("RegisterDevices not found %s\n", device->name)); 1156 InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice, 1157 *device); 1158 if (item != NULL && fInputDeviceList.AddItem(item)) { 1159 item->Start(); 1160 } else { 1161 delete item; 1162 return B_NO_MEMORY; 1163 } 1164 } 1165 } 1166 1167 return B_OK; 1168 } 1169 1170 1171 status_t 1172 InputServer::StartStopDevices(const char* name, input_device_type type, bool doStart) 1173 { 1174 CALLED(); 1175 BAutolock lock(fInputDeviceListLocker); 1176 1177 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1178 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1179 if (!item) 1180 continue; 1181 1182 if (item->Matches(name, type)) { 1183 if (!doStart ^ item->Running()) 1184 return B_ERROR; 1185 1186 if (doStart) 1187 item->Start(); 1188 else 1189 item->Stop(); 1190 1191 if (name) 1192 return B_OK; 1193 } 1194 } 1195 1196 if (name) 1197 return B_ERROR; 1198 1199 return B_OK; 1200 } 1201 1202 1203 1204 status_t 1205 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart) 1206 { 1207 CALLED(); 1208 BAutolock lock(fInputDeviceListLocker); 1209 1210 InputDeviceListItem* item = _FindInputDeviceListItem(serverDevice); 1211 if (item != NULL) { 1212 if (!doStart ^ item->Running()) 1213 return B_ERROR; 1214 1215 if (doStart) 1216 item->Start(); 1217 else 1218 item->Stop(); 1219 } 1220 EXIT(); 1221 1222 return B_OK; 1223 } 1224 1225 1226 status_t 1227 InputServer::ControlDevices(const char* name, input_device_type type, 1228 uint32 code, BMessage* message) 1229 { 1230 CALLED(); 1231 BAutolock lock(fInputDeviceListLocker); 1232 1233 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1234 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1235 if (!item) 1236 continue; 1237 1238 if (item->Matches(name, type)) { 1239 item->Control(code, message); 1240 1241 if (name) 1242 return B_OK; 1243 } 1244 } 1245 1246 if (name) 1247 return B_ERROR; 1248 1249 return B_OK; 1250 } 1251 1252 1253 bool 1254 InputServer::DoMouseAcceleration(int32* _x, int32* _y) 1255 { 1256 CALLED(); 1257 int32 speed = fMouseSettings.MouseSpeed() >> 15; 1258 1259 // ToDo: implement mouse acceleration 1260 (void)speed; 1261 //*_y = *_x * speed; 1262 PRINT(("DoMouse : %ld %ld %ld %ld\n", *_x, *_y, speed, fMouseSettings.MouseSpeed())); 1263 return true; 1264 } 1265 1266 1267 bool 1268 InputServer::SetMousePos(long *, long *, long, long) 1269 { 1270 CALLED(); 1271 return true; 1272 } 1273 1274 1275 bool 1276 InputServer::SetMousePos(long *, long *, BPoint) 1277 { 1278 CALLED(); 1279 return true; 1280 } 1281 1282 1283 bool 1284 InputServer::SetMousePos(long *, long *, float, float) 1285 { 1286 CALLED(); 1287 return true; 1288 } 1289 1290 1291 bool 1292 InputServer::SafeMode() 1293 { 1294 return fSafeMode; 1295 } 1296 1297 1298 status_t 1299 InputServer::_StartEventLoop() 1300 { 1301 CALLED(); 1302 fEventLooperPort = create_port(100, "input server events"); 1303 if (fEventLooperPort < 0) { 1304 PRINTERR(("InputServer: create_port error: (0x%x) %s\n", 1305 fEventLooperPort, strerror(fEventLooperPort))); 1306 return fEventLooperPort; 1307 } 1308 1309 thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_", 1310 B_REAL_TIME_DISPLAY_PRIORITY + 3, this); 1311 if (thread < B_OK || resume_thread(thread) < B_OK) { 1312 if (thread >= B_OK) 1313 kill_thread(thread); 1314 delete_port(fEventLooperPort); 1315 fEventLooperPort = -1; 1316 return thread < B_OK ? thread : B_ERROR; 1317 } 1318 1319 return B_OK; 1320 } 1321 1322 1323 status_t 1324 InputServer::_EventLooper(void* arg) 1325 { 1326 InputServer* self = (InputServer*)arg; 1327 self->_EventLoop(); 1328 1329 return B_OK; 1330 } 1331 1332 1333 void 1334 InputServer::_EventLoop() 1335 { 1336 while (true) { 1337 // Block until we find the size of the next message 1338 ssize_t length = port_buffer_size(fEventLooperPort); 1339 if (length < B_OK) { 1340 PRINT(("[Event Looper] port gone, exiting.\n")); 1341 return; 1342 } 1343 1344 PRINT(("[Event Looper] BMessage Size = %lu\n", length)); 1345 1346 char buffer[length]; 1347 int32 code; 1348 status_t err = read_port(fEventLooperPort, &code, buffer, length); 1349 if (err != length) { 1350 if (err >= 0) { 1351 PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length)); 1352 } else { 1353 PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err))); 1354 } 1355 continue; 1356 } 1357 1358 EventList events; 1359 if (fEventQueueLock.Lock()) { 1360 // move the items to our own list to block the event queue as short as possible 1361 events.AddList(&fEventQueue); 1362 fEventQueue.MakeEmpty(); 1363 fEventQueueLock.Unlock(); 1364 } 1365 1366 if (length > 0) { 1367 BMessage* event = new BMessage; 1368 1369 if ((err = event->Unflatten(buffer)) < 0) { 1370 PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err))); 1371 delete event; 1372 } 1373 1374 events.AddItem(event); 1375 } 1376 1377 // This is where the message should be processed. 1378 1379 if (_SanitizeEvents(events) 1380 && _MethodizeEvents(events) 1381 && _FilterEvents(events)) 1382 _DispatchEvents(events); 1383 } 1384 } 1385 1386 1387 /*! Frees events from unwanted fields, adds missing fields, and removes 1388 unwanted events altogether. 1389 As a side effect, it will also update the internal mouse states. 1390 */ 1391 bool 1392 InputServer::_SanitizeEvents(EventList& events) 1393 { 1394 CALLED(); 1395 int32 index = 0; 1396 BMessage *event; 1397 1398 while ((event = (BMessage*)events.ItemAt(index)) != NULL) { 1399 switch (event->what) { 1400 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 1401 case IS_SCREEN_BOUNDS_UPDATED: 1402 { 1403 // This is what the R5 app_server sends us when the screen 1404 // configuration changes 1405 BRect frame; 1406 if (event->FindRect("screen_bounds", &frame) != B_OK) 1407 frame = fScreen.Frame(); 1408 1409 if (frame != fFrame) { 1410 fMousePos.x = fMousePos.x * frame.Width() / fFrame.Width(); 1411 fMousePos.y = fMousePos.y * frame.Height() / fFrame.Height(); 1412 fFrame = frame; 1413 } else { 1414 // TODO: discard event 1415 } 1416 1417 event->what = B_MOUSE_MOVED; 1418 event->AddPoint("where", fMousePos); 1419 // supposed to fall through 1420 } 1421 #endif 1422 case B_MOUSE_MOVED: 1423 case B_MOUSE_DOWN: 1424 { 1425 int32 buttons; 1426 if (event->FindInt32("buttons", &buttons) != B_OK) 1427 event->AddInt32("buttons", 0); 1428 1429 // supposed to fall through 1430 } 1431 case B_MOUSE_UP: 1432 { 1433 BPoint where; 1434 int32 x, y; 1435 float absX, absY; 1436 1437 if (event->FindInt32("x", &x) == B_OK 1438 && event->FindInt32("y", &y) == B_OK) { 1439 fMousePos.x += x; 1440 fMousePos.y -= y; 1441 fMousePos.ConstrainTo(fFrame); 1442 1443 event->RemoveName("x"); 1444 event->RemoveName("y"); 1445 event->AddPoint("where", fMousePos); 1446 event->AddInt32("be:delta_x", x); 1447 event->AddInt32("be:delta_y", y); 1448 1449 PRINT(("new position: %f, %f, %ld, %ld\n", 1450 fMousePos.x, fMousePos.y, x, y)); 1451 } else if (event->FindFloat("x", &absX) == B_OK 1452 && event->FindFloat("y", &absY) == B_OK) { 1453 // device gives us absolute screen coords 1454 // in range 0..1 1455 // convert to absolute screen pos 1456 // (the message is supposed to contain the original 1457 // absolute coordinates as "be:tablet_x/y") 1458 fMousePos.x = absX * fFrame.Width(); 1459 fMousePos.y = absY * fFrame.Height(); 1460 fMousePos.ConstrainTo(fFrame); 1461 1462 event->RemoveName("x"); 1463 event->RemoveName("y"); 1464 event->AddPoint("where", fMousePos); 1465 PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y)); 1466 } else if (event->FindPoint("where", &where) == B_OK) { 1467 fMousePos = where; 1468 fMousePos.ConstrainTo(fFrame); 1469 1470 event->ReplacePoint("where", fMousePos); 1471 PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y)); 1472 } 1473 1474 event->AddInt32("modifiers", fKeyInfo.modifiers); 1475 break; 1476 } 1477 case B_KEY_DOWN: 1478 case B_UNMAPPED_KEY_DOWN: 1479 // update or add modifiers 1480 uint32 modifiers; 1481 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1482 fKeyInfo.modifiers = modifiers; 1483 else 1484 event->AddInt32("modifiers", fKeyInfo.modifiers); 1485 1486 // update or add key states 1487 const uint8 *data; 1488 ssize_t size; 1489 if (event->FindData("states", B_UINT8_TYPE, 1490 (const void**)&data, &size) == B_OK) { 1491 PRINT(("updated keyinfo\n")); 1492 if (size == sizeof(fKeyInfo.key_states)) 1493 memcpy(fKeyInfo.key_states, data, size); 1494 } else { 1495 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1496 sizeof(fKeyInfo.key_states)); 1497 } 1498 if (fActiveMethod == NULL) 1499 break; 1500 1501 // we scan for Alt+Space key down events which means we change 1502 // to next input method 1503 // (pressing "shift" will let us switch to the previous method) 1504 1505 PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers, 1506 fKeyInfo.key_states[KEY_Spacebar >> 3])); 1507 1508 int8 byte; 1509 if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 1510 && event->FindInt8("byte", &byte) == B_OK && byte == ' ') { 1511 SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY); 1512 1513 // this event isn't sent to the user 1514 events.RemoveItemAt(index); 1515 delete event; 1516 continue; 1517 } 1518 break; 1519 } 1520 1521 index++; 1522 } 1523 1524 return true; 1525 } 1526 1527 1528 /*! Applies the filters of the active input method to the 1529 incoming events. It will also move the events in the method 1530 queue to the event list. 1531 */ 1532 bool 1533 InputServer::_MethodizeEvents(EventList& events) 1534 { 1535 CALLED(); 1536 1537 if (fActiveMethod == NULL) 1538 return true; 1539 1540 int32 count = events.CountItems(); 1541 for (int32 i = 0; i < count;) { 1542 _FilterEvent(fActiveMethod, events, i, count); 1543 } 1544 1545 { 1546 // move the method events into the event queue - they are not 1547 // "methodized" either 1548 BAutolock _(fEventQueueLock); 1549 events.AddList(&fMethodQueue); 1550 fMethodQueue.MakeEmpty(); 1551 } 1552 1553 if (!fInputMethodAware) { 1554 // special handling for non-input-method-aware views 1555 1556 int32 newCount = events.CountItems(); 1557 // we may add new events in this loop that don't need to be checked again 1558 1559 for (int32 i = 0; i < newCount; i++) { 1560 BMessage* event = events.ItemAt(i); 1561 1562 if (event->what != B_INPUT_METHOD_EVENT) 1563 continue; 1564 1565 SERIAL_PRINT(("IME received\n")); 1566 1567 bool removeEvent = true; 1568 1569 int32 opcode; 1570 if (event->FindInt32("be:opcode", &opcode) == B_OK) { 1571 bool inlineOnly; 1572 if (event->FindBool("be:inline_only", &inlineOnly) != B_OK) 1573 inlineOnly = false; 1574 1575 if (inlineOnly) { 1576 BMessage translated; 1577 bool confirmed; 1578 if (opcode == B_INPUT_METHOD_CHANGED 1579 && event->FindBool("be:confirmed", &confirmed) == B_OK && confirmed 1580 && event->FindMessage("be:translated", &translated) == B_OK) { 1581 // translate event for the non-aware view 1582 *event = translated; 1583 removeEvent = false; 1584 } 1585 } else { 1586 if (fInputMethodWindow == NULL 1587 && opcode == B_INPUT_METHOD_STARTED) 1588 fInputMethodWindow = new (nothrow) BottomlineWindow(); 1589 1590 if (fInputMethodWindow != NULL) { 1591 EventList newEvents; 1592 fInputMethodWindow->HandleInputMethodEvent(event, newEvents); 1593 1594 if (!newEvents.IsEmpty()) { 1595 events.AddList(&newEvents); 1596 opcode = B_INPUT_METHOD_STOPPED; 1597 } 1598 1599 if (opcode == B_INPUT_METHOD_STOPPED) { 1600 fInputMethodWindow->PostMessage(B_QUIT_REQUESTED); 1601 fInputMethodWindow = NULL; 1602 } 1603 } 1604 } 1605 } 1606 1607 if (removeEvent) { 1608 // the inline/bottom window has eaten the event 1609 events.RemoveItemAt(i--); 1610 delete event; 1611 newCount--; 1612 } 1613 } 1614 } 1615 1616 return events.CountItems() > 0; 1617 } 1618 1619 1620 /*! This method applies all defined filters to each event in the 1621 supplied list. The supplied list is modified to reflect the 1622 output of the filters. 1623 The method returns true if the filters were applied to all 1624 events without error and false otherwise. 1625 */ 1626 bool 1627 InputServer::_FilterEvents(EventList& events) 1628 { 1629 CALLED(); 1630 BAutolock _(gInputFilterListLocker); 1631 1632 int32 count = gInputFilterList.CountItems(); 1633 int32 eventCount = events.CountItems(); 1634 1635 for (int32 i = 0; i < count; i++) { 1636 BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i); 1637 1638 // Apply the current filter to all available event messages. 1639 1640 for (int32 eventIndex = 0; eventIndex < eventCount;) { 1641 _FilterEvent(filter, events, eventIndex, eventCount); 1642 } 1643 } 1644 1645 return eventCount != 0; 1646 } 1647 1648 1649 void 1650 InputServer::_DispatchEvents(EventList& events) 1651 { 1652 CALLED(); 1653 1654 int32 count = events.CountItems(); 1655 1656 for (int32 i = 0; i < count; i++) { 1657 BMessage* event = events.ItemAt(i); 1658 1659 // now we must send each event to the app_server 1660 _DispatchEvent(event); 1661 delete event; 1662 } 1663 1664 events.MakeEmpty(); 1665 } 1666 1667 1668 /*! Applies the given filter to the event list. 1669 For your convenience, it also alters the \a index and \a count arguments 1670 ready for the next call to this method. 1671 */ 1672 void 1673 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events, 1674 int32& index, int32& count) 1675 { 1676 BMessage* event = events.ItemAt(index); 1677 1678 BList newEvents; 1679 filter_result result = filter->Filter(event, &newEvents); 1680 1681 if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) { 1682 // we no longer need the current event 1683 events.RemoveItemAt(index); 1684 delete event; 1685 1686 if (result == B_DISPATCH_MESSAGE) { 1687 // add the new events - but don't methodize them again 1688 events.AsBList()->AddList(&newEvents, index); 1689 index += newEvents.CountItems(); 1690 count = events.CountItems(); 1691 } else 1692 count--; 1693 } else 1694 index++; 1695 } 1696 1697 1698 status_t 1699 InputServer::_DispatchEvent(BMessage* event) 1700 { 1701 CALLED(); 1702 1703 switch (event->what) { 1704 case B_MOUSE_MOVED: 1705 case B_MOUSE_DOWN: 1706 case B_MOUSE_UP: 1707 if (fCursorBuffer) { 1708 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 1709 fCursorBuffer[0] = (0x3 << 30L) 1710 | ((uint32)fMousePos.x & 0x7fff) << 15 1711 | ((uint32)fMousePos.y & 0x7fff); 1712 1713 PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0])); 1714 release_sem(fCursorSem); 1715 #else 1716 atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL 1717 | ((uint32)fMousePos.y & 0xffff)); 1718 if (atomic_or(&fCursorBuffer->read, 1) == 0) 1719 release_sem(fCursorSem); 1720 #endif 1721 } 1722 break; 1723 1724 case B_KEY_DOWN: 1725 case B_KEY_UP: 1726 case B_UNMAPPED_KEY_DOWN: 1727 case B_UNMAPPED_KEY_UP: 1728 case B_MODIFIERS_CHANGED: 1729 { 1730 // update or add modifiers 1731 uint32 modifiers; 1732 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1733 fKeyInfo.modifiers = modifiers; 1734 else 1735 event->AddInt32("modifiers", fKeyInfo.modifiers); 1736 1737 // update or add key states 1738 const uint8 *data; 1739 ssize_t size; 1740 if (event->FindData("states", B_UINT8_TYPE, 1741 (const void**)&data, &size) == B_OK) { 1742 PRINT(("updated keyinfo\n")); 1743 if (size == sizeof(fKeyInfo.key_states)) 1744 memcpy(fKeyInfo.key_states, data, size); 1745 } else { 1746 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1747 sizeof(fKeyInfo.key_states)); 1748 } 1749 1750 break; 1751 } 1752 1753 default: 1754 break; 1755 } 1756 1757 #if defined(HAIKU_TARGET_PLATFORM_HAIKU) 1758 BMessenger reply; 1759 BMessage::Private messagePrivate(event); 1760 return messagePrivate.SendMessage(fAppServerPort, -1, 0, true, 0, reply); 1761 #else 1762 ssize_t length = event->FlattenedSize(); 1763 char buffer[length]; 1764 status_t err; 1765 if ((err = event->Flatten(buffer,length)) < B_OK) 1766 return err; 1767 1768 return write_port(fAppServerPort, 0, buffer, length); 1769 #endif 1770 } 1771 1772 1773 // #pragma mark - 1774 1775 1776 extern "C" void 1777 RegisterDevices(input_device_ref** devices) 1778 { 1779 CALLED(); 1780 } 1781 1782 1783 BView * 1784 instantiate_deskbar_item() 1785 { 1786 return new MethodReplicant(INPUTSERVER_SIGNATURE); 1787 } 1788 1789 1790 // #pragma mark - 1791 1792 1793 int 1794 main(int /*argc*/, char** /*argv*/) 1795 { 1796 InputServer *inputServer = new InputServer; 1797 1798 inputServer->Run(); 1799 delete inputServer; 1800 1801 return 0; 1802 } 1803 1804 1805