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