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