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