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