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