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