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