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.cpp" 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 fAddOnManager->SaveState(); 372 gDeviceManager.SaveState(); 373 374 delete_port(fEventLooperPort); 375 // the event looper thread will exit after this 376 fEventLooperPort = -1; 377 return true; 378 } 379 380 381 void 382 InputServer::ReadyToRun() 383 { 384 CALLED(); 385 386 // say hello to the app_server 387 388 BPrivate::AppServerLink link; 389 link.StartMessage(AS_REGISTER_INPUT_SERVER); 390 link.Flush(); 391 } 392 393 394 status_t 395 InputServer::_AcquireInput(BMessage& message, BMessage& reply) 396 { 397 // TODO: it currently just gets everything we have 398 area_id area; 399 if (message.FindInt32("cursor area", &area) == B_OK) { 400 // try to clone the area 401 fCursorBuffer = NULL; 402 403 fCursorSem = create_sem(0, "cursor semaphore"); 404 if (fCursorSem >= B_OK) { 405 fCursorArea = clone_area("input server cursor", (void**)&fCursorBuffer, 406 B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area); 407 } 408 } 409 410 fAppServerPort = create_port(200, "input server target"); 411 if (fAppServerPort < B_OK) { 412 _ReleaseInput(&message); 413 return fAppServerPort; 414 } 415 416 reply.AddBool("has keyboard", true); 417 reply.AddBool("has mouse", true); 418 reply.AddInt32("event port", fAppServerPort); 419 420 if (fCursorBuffer != NULL) { 421 // cursor shared buffer is supported 422 reply.AddInt32("cursor semaphore", fCursorSem); 423 } 424 425 return B_OK; 426 } 427 428 429 void 430 InputServer::_ReleaseInput(BMessage* /*message*/) 431 { 432 if (fCursorBuffer != NULL) { 433 fCursorBuffer = NULL; 434 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 435 delete_sem(fCursorSem); 436 #endif 437 delete_area(fCursorArea); 438 439 fCursorSem = -1; 440 fCursorArea = -1; 441 } 442 443 delete_port(fAppServerPort); 444 } 445 446 447 void 448 InputServer::MessageReceived(BMessage* message) 449 { 450 CALLED(); 451 452 BMessage reply; 453 status_t status = B_OK; 454 455 PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what >> 24, 456 message->what >> 16, message->what >> 8, message->what)); 457 458 switch (message->what) { 459 case IS_SET_METHOD: 460 HandleSetMethod(message); 461 break; 462 case IS_GET_MOUSE_TYPE: 463 status = HandleGetSetMouseType(message, &reply); 464 break; 465 case IS_SET_MOUSE_TYPE: 466 status = HandleGetSetMouseType(message, &reply); 467 break; 468 case IS_GET_MOUSE_ACCELERATION: 469 status = HandleGetSetMouseAcceleration(message, &reply); 470 break; 471 case IS_SET_MOUSE_ACCELERATION: 472 status = HandleGetSetMouseAcceleration(message, &reply); 473 break; 474 case IS_GET_KEY_REPEAT_DELAY: 475 status = HandleGetSetKeyRepeatDelay(message, &reply); 476 break; 477 case IS_SET_KEY_REPEAT_DELAY: 478 status = HandleGetSetKeyRepeatDelay(message, &reply); 479 break; 480 case IS_GET_KEY_INFO: 481 status = HandleGetKeyInfo(message, &reply); 482 break; 483 case IS_GET_MODIFIERS: 484 status = HandleGetModifiers(message, &reply); 485 break; 486 case IS_SET_MODIFIER_KEY: 487 status = HandleSetModifierKey(message, &reply); 488 break; 489 case IS_SET_KEYBOARD_LOCKS: 490 status = HandleSetKeyboardLocks(message, &reply); 491 break; 492 case IS_GET_MOUSE_SPEED: 493 status = HandleGetSetMouseSpeed(message, &reply); 494 break; 495 case IS_SET_MOUSE_SPEED: 496 status = HandleGetSetMouseSpeed(message, &reply); 497 break; 498 case IS_SET_MOUSE_POSITION: 499 status = HandleSetMousePosition(message, &reply); 500 break; 501 case IS_GET_MOUSE_MAP: 502 status = HandleGetSetMouseMap(message, &reply); 503 break; 504 case IS_SET_MOUSE_MAP: 505 status = HandleGetSetMouseMap(message, &reply); 506 break; 507 case IS_GET_KEYBOARD_ID: 508 status = HandleGetKeyboardID(message, &reply); 509 break; 510 case IS_GET_CLICK_SPEED: 511 status = HandleGetSetClickSpeed(message, &reply); 512 break; 513 case IS_SET_CLICK_SPEED: 514 status = HandleGetSetClickSpeed(message, &reply); 515 break; 516 case IS_GET_KEY_REPEAT_RATE: 517 status = HandleGetSetKeyRepeatRate(message, &reply); 518 break; 519 case IS_SET_KEY_REPEAT_RATE: 520 status = HandleGetSetKeyRepeatRate(message, &reply); 521 break; 522 case IS_GET_KEY_MAP: 523 status = HandleGetSetKeyMap(message, &reply); 524 break; 525 case IS_RESTORE_KEY_MAP: 526 status = HandleGetSetKeyMap(message, &reply); 527 break; 528 case IS_FOCUS_IM_AWARE_VIEW: 529 status = HandleFocusUnfocusIMAwareView(message, &reply); 530 break; 531 case IS_UNFOCUS_IM_AWARE_VIEW: 532 status = HandleFocusUnfocusIMAwareView(message, &reply); 533 break; 534 535 // app_server communication 536 case IS_ACQUIRE_INPUT: 537 status = _AcquireInput(*message, reply); 538 break; 539 case IS_RELEASE_INPUT: 540 _ReleaseInput(message); 541 return; 542 case IS_SCREEN_BOUNDS_UPDATED: 543 { 544 // This is what the R5 app_server sends us when the screen 545 // configuration changes 546 BRect frame; 547 if (message->FindRect("screen_bounds", &frame) != B_OK) 548 frame = fScreen.Frame(); 549 550 if (frame == fFrame) 551 break; 552 553 BPoint pos(fMousePos.x * frame.Width() / fFrame.Width(), 554 fMousePos.y * frame.Height() / fFrame.Height()); 555 fFrame = frame; 556 557 BMessage set; 558 set.AddPoint("where", pos); 559 HandleSetMousePosition(&set, NULL); 560 break; 561 } 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::GetDeviceInfos(BMessage *msg) 1054 { 1055 CALLED(); 1056 BAutolock lock(fInputDeviceListLocker); 1057 1058 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1059 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1060 msg->AddString("device", item->Name()); 1061 msg->AddInt32("type", item->Type()); 1062 } 1063 return B_OK; 1064 } 1065 1066 1067 status_t 1068 InputServer::UnregisterDevices(BInputServerDevice& serverDevice, 1069 input_device_ref **devices) 1070 { 1071 CALLED(); 1072 BAutolock lock(fInputDeviceListLocker); 1073 1074 if (devices != NULL) { 1075 // remove the devices as specified only 1076 input_device_ref *device = NULL; 1077 for (int32 i = 0; NULL != (device = devices[i]); i++) { 1078 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1079 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1080 1081 if (item->ServerDevice() == &serverDevice && item->HasName(device->name)) { 1082 item->Stop(); 1083 fInputDeviceList.RemoveItem(j); 1084 delete item; 1085 break; 1086 } 1087 } 1088 } 1089 } else { 1090 // remove all devices from this BInputServerObject 1091 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1092 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1093 1094 if (item->ServerDevice() == &serverDevice) { 1095 item->Stop(); 1096 fInputDeviceList.RemoveItem(i); 1097 delete item; 1098 } 1099 } 1100 } 1101 1102 return B_OK; 1103 } 1104 1105 1106 status_t 1107 InputServer::RegisterDevices(BInputServerDevice& serverDevice, 1108 input_device_ref** devices) 1109 { 1110 if (devices == NULL) 1111 return B_BAD_VALUE; 1112 1113 BAutolock lock(fInputDeviceListLocker); 1114 1115 input_device_ref *device = NULL; 1116 for (int32 i = 0; (device = devices[i]) != NULL; i++) { 1117 if (device->type != B_POINTING_DEVICE 1118 && device->type != B_KEYBOARD_DEVICE 1119 && device->type != B_UNDEFINED_DEVICE) 1120 continue; 1121 1122 // find existing input server device 1123 1124 bool found = false; 1125 for (int32 j = fInputDeviceList.CountItems() - 1; j >= 0; j--) { 1126 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(j); 1127 1128 if (item->HasName(device->name)) { 1129 PRINT(("RegisterDevices found %s\n", device->name)); 1130 found = true; 1131 break; 1132 } 1133 } 1134 1135 if (!found) { 1136 PRINT(("RegisterDevices not found %s\n", device->name)); 1137 InputDeviceListItem* item = new (nothrow) InputDeviceListItem(serverDevice, 1138 *device); 1139 if (item != NULL && fInputDeviceList.AddItem(item)) { 1140 item->Start(); 1141 } else { 1142 delete item; 1143 return B_NO_MEMORY; 1144 } 1145 } 1146 } 1147 1148 return B_OK; 1149 } 1150 1151 1152 status_t 1153 InputServer::StartStopDevices(const char* name, input_device_type type, bool doStart) 1154 { 1155 CALLED(); 1156 BAutolock lock(fInputDeviceListLocker); 1157 1158 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1159 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1160 if (!item) 1161 continue; 1162 1163 if (item->Matches(name, type)) { 1164 if (!doStart ^ item->Running()) 1165 return B_ERROR; 1166 1167 if (doStart) 1168 item->Start(); 1169 else 1170 item->Stop(); 1171 1172 if (name) 1173 return B_OK; 1174 } 1175 } 1176 1177 if (name) 1178 return B_ERROR; 1179 1180 return B_OK; 1181 } 1182 1183 1184 1185 status_t 1186 InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart) 1187 { 1188 CALLED(); 1189 BAutolock lock(fInputDeviceListLocker); 1190 1191 InputDeviceListItem* item = _FindInputDeviceListItem(serverDevice); 1192 if (item != NULL) { 1193 if (!doStart ^ item->Running()) 1194 return B_ERROR; 1195 1196 if (doStart) 1197 item->Start(); 1198 else 1199 item->Stop(); 1200 } 1201 EXIT(); 1202 1203 return B_OK; 1204 } 1205 1206 1207 status_t 1208 InputServer::ControlDevices(const char* name, input_device_type type, 1209 uint32 code, BMessage* message) 1210 { 1211 CALLED(); 1212 BAutolock lock(fInputDeviceListLocker); 1213 1214 for (int32 i = fInputDeviceList.CountItems() - 1; i >= 0; i--) { 1215 InputDeviceListItem* item = (InputDeviceListItem*)fInputDeviceList.ItemAt(i); 1216 if (!item) 1217 continue; 1218 1219 if (item->Matches(name, type)) { 1220 item->Control(code, message); 1221 1222 if (name) 1223 return B_OK; 1224 } 1225 } 1226 1227 if (name) 1228 return B_ERROR; 1229 1230 return B_OK; 1231 } 1232 1233 1234 bool 1235 InputServer::DoMouseAcceleration(int32* _x, int32* _y) 1236 { 1237 CALLED(); 1238 int32 speed = fMouseSettings.MouseSpeed() >> 15; 1239 1240 // ToDo: implement mouse acceleration 1241 (void)speed; 1242 //*_y = *_x * speed; 1243 PRINT(("DoMouse : %ld %ld %ld %ld\n", *_x, *_y, speed, fMouseSettings.MouseSpeed())); 1244 return true; 1245 } 1246 1247 1248 bool 1249 InputServer::SetMousePos(long *, long *, long, long) 1250 { 1251 CALLED(); 1252 return true; 1253 } 1254 1255 1256 bool 1257 InputServer::SetMousePos(long *, long *, BPoint) 1258 { 1259 CALLED(); 1260 return true; 1261 } 1262 1263 1264 bool 1265 InputServer::SetMousePos(long *, long *, float, float) 1266 { 1267 CALLED(); 1268 return true; 1269 } 1270 1271 1272 bool 1273 InputServer::SafeMode() 1274 { 1275 return fSafeMode; 1276 } 1277 1278 1279 status_t 1280 InputServer::_StartEventLoop() 1281 { 1282 CALLED(); 1283 fEventLooperPort = create_port(100, "input server events"); 1284 if (fEventLooperPort < 0) { 1285 PRINTERR(("InputServer: create_port error: (0x%x) %s\n", 1286 fEventLooperPort, strerror(fEventLooperPort))); 1287 return fEventLooperPort; 1288 } 1289 1290 thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_", 1291 B_REAL_TIME_DISPLAY_PRIORITY + 3, this); 1292 if (thread < B_OK || resume_thread(thread) < B_OK) { 1293 if (thread >= B_OK) 1294 kill_thread(thread); 1295 delete_port(fEventLooperPort); 1296 fEventLooperPort = -1; 1297 return thread < B_OK ? thread : B_ERROR; 1298 } 1299 1300 return B_OK; 1301 } 1302 1303 1304 status_t 1305 InputServer::_EventLooper(void* arg) 1306 { 1307 InputServer* self = (InputServer*)arg; 1308 self->_EventLoop(); 1309 1310 return B_OK; 1311 } 1312 1313 1314 void 1315 InputServer::_EventLoop() 1316 { 1317 while (true) { 1318 // Block until we find the size of the next message 1319 ssize_t length = port_buffer_size(fEventLooperPort); 1320 if (length < B_OK) { 1321 PRINT(("[Event Looper] port gone, exiting.\n")); 1322 return; 1323 } 1324 1325 PRINT(("[Event Looper] BMessage Size = %lu\n", length)); 1326 1327 char buffer[length]; 1328 int32 code; 1329 status_t err = read_port(fEventLooperPort, &code, buffer, length); 1330 if (err != length) { 1331 if (err >= 0) { 1332 PRINTERR(("InputServer: failed to read full packet (read %lu of %lu)\n", err, length)); 1333 } else { 1334 PRINTERR(("InputServer: read_port error: (0x%lx) %s\n", err, strerror(err))); 1335 } 1336 continue; 1337 } 1338 1339 EventList events; 1340 if (fEventQueueLock.Lock()) { 1341 // move the items to our own list to block the event queue as short as possible 1342 events.AddList(&fEventQueue); 1343 fEventQueue.MakeEmpty(); 1344 fEventQueueLock.Unlock(); 1345 } 1346 1347 if (length > 0) { 1348 BMessage* event = new BMessage; 1349 1350 if ((err = event->Unflatten(buffer)) < 0) { 1351 PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err))); 1352 delete event; 1353 } 1354 1355 events.AddItem(event); 1356 } 1357 1358 // This is where the message should be processed. 1359 1360 if (_SanitizeEvents(events) 1361 && _MethodizeEvents(events) 1362 && _FilterEvents(events)) 1363 _DispatchEvents(events); 1364 } 1365 } 1366 1367 1368 /** Frees events from unwanted fields, adds missing fields, and removes 1369 * unwanted events altogether. 1370 * As a side effect, it will also update the internal mouse states. 1371 */ 1372 1373 bool 1374 InputServer::_SanitizeEvents(EventList& events) 1375 { 1376 CALLED(); 1377 int32 index = 0; 1378 BMessage *event; 1379 1380 while ((event = (BMessage*)events.ItemAt(index)) != NULL) { 1381 switch (event->what) { 1382 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 1383 case IS_SCREEN_BOUNDS_UPDATED: 1384 { 1385 // This is what the R5 app_server sends us when the screen 1386 // configuration changes 1387 BRect frame; 1388 if (event->FindRect("screen_bounds", &frame) != B_OK) 1389 frame = fScreen.Frame(); 1390 1391 if (frame != fFrame) { 1392 fMousePos.x = fMousePos.x * frame.Width() / fFrame.Width(); 1393 fMousePos.y = fMousePos.y * frame.Height() / fFrame.Height(); 1394 fFrame = frame; 1395 } else { 1396 // TODO: discard event 1397 } 1398 1399 event->what = B_MOUSE_MOVED; 1400 event->AddPoint("where", fMousePos); 1401 // supposed to fall through 1402 } 1403 #endif 1404 case B_MOUSE_MOVED: 1405 case B_MOUSE_DOWN: 1406 { 1407 int32 buttons; 1408 if (event->FindInt32("buttons", &buttons) != B_OK) 1409 event->AddInt32("buttons", 0); 1410 1411 // supposed to fall through 1412 } 1413 case B_MOUSE_UP: 1414 { 1415 BPoint where; 1416 int32 x, y; 1417 1418 if (event->FindInt32("x", &x) == B_OK 1419 && event->FindInt32("y", &y) == B_OK) { 1420 fMousePos.x += x; 1421 fMousePos.y -= y; 1422 fMousePos.ConstrainTo(fFrame); 1423 1424 event->RemoveName("x"); 1425 event->RemoveName("y"); 1426 event->AddPoint("where", fMousePos); 1427 1428 PRINT(("new position: %f, %f, %ld, %ld\n", 1429 fMousePos.x, fMousePos.y, x, y)); 1430 } else if (event->FindPoint("where", &where) == B_OK) { 1431 fMousePos = where; 1432 fMousePos.ConstrainTo(fFrame); 1433 1434 event->ReplacePoint("where", fMousePos); 1435 PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y)); 1436 } 1437 1438 event->AddInt32("modifiers", fKeyInfo.modifiers); 1439 break; 1440 } 1441 case B_KEY_DOWN: 1442 case B_UNMAPPED_KEY_DOWN: 1443 // update or add modifiers 1444 uint32 modifiers; 1445 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1446 fKeyInfo.modifiers = modifiers; 1447 else 1448 event->AddInt32("modifiers", fKeyInfo.modifiers); 1449 1450 // update or add key states 1451 const uint8 *data; 1452 ssize_t size; 1453 if (event->FindData("states", B_UINT8_TYPE, 1454 (const void**)&data, &size) == B_OK) { 1455 PRINT(("updated keyinfo\n")); 1456 if (size == sizeof(fKeyInfo.key_states)) 1457 memcpy(fKeyInfo.key_states, data, size); 1458 } else { 1459 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1460 sizeof(fKeyInfo.key_states)); 1461 } 1462 if (fActiveMethod == NULL) 1463 break; 1464 1465 // we scan for Alt+Space key down events which means we change 1466 // to next input method 1467 // (pressing "shift" will let us switch to the previous method) 1468 1469 PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers, 1470 fKeyInfo.key_states[KEY_Spacebar >> 3])); 1471 1472 int8 byte; 1473 if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0 1474 && event->FindInt8("byte", &byte) == B_OK && byte == ' ') { 1475 SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY); 1476 1477 // this event isn't sent to the user 1478 events.RemoveItemAt(index); 1479 delete event; 1480 continue; 1481 } 1482 break; 1483 } 1484 1485 index++; 1486 } 1487 1488 return true; 1489 } 1490 1491 1492 /** Applies the filters of the active input method to the 1493 * incoming events. It will also move the events in the method 1494 * queue to the event list. 1495 */ 1496 1497 bool 1498 InputServer::_MethodizeEvents(EventList& events) 1499 { 1500 CALLED(); 1501 1502 if (fActiveMethod == NULL) 1503 return true; 1504 1505 int32 count = events.CountItems(); 1506 for (int32 i = 0; i < count;) { 1507 _FilterEvent(fActiveMethod, events, i, count); 1508 } 1509 1510 { 1511 // move the method events into the event queue - they are not 1512 // "methodized" either 1513 BAutolock _(fEventQueueLock); 1514 events.AddList(&fMethodQueue); 1515 fMethodQueue.MakeEmpty(); 1516 } 1517 1518 int32 newCount = events.CountItems(); 1519 1520 if (!fInputMethodAware) { 1521 // special handling for non-input-method-aware views 1522 for (int32 i = 0; i < newCount; i++) { 1523 BMessage* event = events.ItemAt(i); 1524 1525 if (event->what != B_INPUT_METHOD_EVENT) 1526 continue; 1527 1528 SERIAL_PRINT(("IME received\n")); 1529 1530 int32 opcode; 1531 if (event->FindInt32("be:opcode", &opcode) == B_OK) { 1532 if (fInputMethodWindow == NULL 1533 && opcode == B_INPUT_METHOD_STARTED) 1534 fInputMethodWindow = new (nothrow) BottomlineWindow(); 1535 1536 if (fInputMethodWindow != NULL) { 1537 EventList newEvents; 1538 fInputMethodWindow->HandleInputMethodEvent(event, newEvents); 1539 1540 // replace event with new events (but don't scan them again 1541 // for input method messages) 1542 events.RemoveItemAt(i--); 1543 delete event; 1544 newCount--; 1545 1546 if (!newEvents.IsEmpty()) { 1547 events.AddList(&newEvents); 1548 opcode = B_INPUT_METHOD_STOPPED; 1549 } 1550 1551 if (opcode == B_INPUT_METHOD_STOPPED) { 1552 fInputMethodWindow->PostMessage(B_QUIT_REQUESTED); 1553 fInputMethodWindow = NULL; 1554 } 1555 } 1556 } 1557 } 1558 } 1559 1560 return events.CountItems() > 0; 1561 } 1562 1563 1564 /** This method applies all defined filters to each event in the 1565 * supplied list. The supplied list is modified to reflect the 1566 * output of the filters. 1567 * The method returns true if the filters were applied to all 1568 * events without error and false otherwise. 1569 */ 1570 1571 bool 1572 InputServer::_FilterEvents(EventList& events) 1573 { 1574 CALLED(); 1575 BAutolock _(gInputFilterListLocker); 1576 1577 int32 count = gInputFilterList.CountItems(); 1578 int32 eventCount = events.CountItems(); 1579 1580 for (int32 i = 0; i < count; i++) { 1581 BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i); 1582 1583 // Apply the current filter to all available event messages. 1584 1585 for (int32 eventIndex = 0; eventIndex < eventCount;) { 1586 _FilterEvent(filter, events, eventIndex, eventCount); 1587 } 1588 } 1589 1590 return eventCount != 0; 1591 } 1592 1593 1594 void 1595 InputServer::_DispatchEvents(EventList& events) 1596 { 1597 CALLED(); 1598 1599 int32 count = events.CountItems(); 1600 1601 for (int32 i = 0; i < count; i++) { 1602 BMessage* event = events.ItemAt(i); 1603 1604 // now we must send each event to the app_server 1605 _DispatchEvent(event); 1606 delete event; 1607 } 1608 1609 events.MakeEmpty(); 1610 } 1611 1612 1613 /** Applies the given filter to the event list. 1614 * For your convenience, it also alters the \a index and \a count arguments 1615 * ready for the next call to this method. 1616 */ 1617 1618 void 1619 InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events, 1620 int32& index, int32& count) 1621 { 1622 BMessage* event = events.ItemAt(index); 1623 1624 BList newEvents; 1625 filter_result result = filter->Filter(event, &newEvents); 1626 1627 if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) { 1628 // we no longer need the current event 1629 events.RemoveItemAt(index); 1630 delete event; 1631 1632 if (result == B_DISPATCH_MESSAGE) { 1633 // add the new events - but don't methodize them again 1634 events.AsBList()->AddList(&newEvents, index); 1635 index += newEvents.CountItems(); 1636 count = events.CountItems(); 1637 } else 1638 count--; 1639 } else 1640 index++; 1641 } 1642 1643 1644 status_t 1645 InputServer::_DispatchEvent(BMessage* event) 1646 { 1647 CALLED(); 1648 1649 switch (event->what) { 1650 case B_MOUSE_MOVED: 1651 case B_MOUSE_DOWN: 1652 case B_MOUSE_UP: 1653 if (fCursorBuffer) { 1654 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 1655 fCursorBuffer[0] = (0x3 << 30L) 1656 | ((uint32)fMousePos.x & 0x7fff) << 15 1657 | ((uint32)fMousePos.y & 0x7fff); 1658 1659 PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0])); 1660 release_sem(fCursorSem); 1661 #else 1662 atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL 1663 | ((uint32)fMousePos.y & 0xffff)); 1664 if (atomic_or(&fCursorBuffer->read, 1) == 0) 1665 release_sem(fCursorSem); 1666 #endif 1667 } 1668 break; 1669 1670 case B_KEY_DOWN: 1671 case B_KEY_UP: 1672 case B_UNMAPPED_KEY_DOWN: 1673 case B_UNMAPPED_KEY_UP: 1674 case B_MODIFIERS_CHANGED: 1675 { 1676 // update or add modifiers 1677 uint32 modifiers; 1678 if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK) 1679 fKeyInfo.modifiers = modifiers; 1680 else 1681 event->AddInt32("modifiers", fKeyInfo.modifiers); 1682 1683 // update or add key states 1684 const uint8 *data; 1685 ssize_t size; 1686 if (event->FindData("states", B_UINT8_TYPE, 1687 (const void**)&data, &size) == B_OK) { 1688 PRINT(("updated keyinfo\n")); 1689 if (size == sizeof(fKeyInfo.key_states)) 1690 memcpy(fKeyInfo.key_states, data, size); 1691 } else { 1692 event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 1693 sizeof(fKeyInfo.key_states)); 1694 } 1695 1696 break; 1697 } 1698 1699 default: 1700 break; 1701 } 1702 1703 #if defined(HAIKU_TARGET_PLATFORM_HAIKU) 1704 BMessenger reply; 1705 BMessage::Private messagePrivate(event); 1706 return messagePrivate.SendMessage(fAppServerPort, 0, true, 0, reply); 1707 #else 1708 ssize_t length = event->FlattenedSize(); 1709 char buffer[length]; 1710 status_t err; 1711 if ((err = event->Flatten(buffer,length)) < B_OK) 1712 return err; 1713 1714 return write_port(fAppServerPort, 0, buffer, length); 1715 #endif 1716 } 1717 1718 1719 // #pragma mark - 1720 1721 1722 extern "C" void 1723 RegisterDevices(input_device_ref** devices) 1724 { 1725 CALLED(); 1726 }; 1727 1728 1729 BView * 1730 instantiate_deskbar_item() 1731 { 1732 return new MethodReplicant(INPUTSERVER_SIGNATURE); 1733 } 1734 1735 1736 int 1737 main() 1738 { 1739 InputServer *inputServer = new InputServer; 1740 1741 inputServer->Run(); 1742 delete inputServer; 1743 1744 return 0; 1745 } 1746 1747 1748