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