1 /* 2 * Copyright 2005-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "EventDispatcher.h" 11 12 #include "BitmapManager.h" 13 #include "Desktop.h" 14 #include "EventStream.h" 15 #include "HWInterface.h" 16 #include "InputManager.h" 17 #include "ServerBitmap.h" 18 19 #include <MessagePrivate.h> 20 #include <MessengerPrivate.h> 21 #include <ServerProtocol.h> 22 #include <TokenSpace.h> 23 24 #include <Autolock.h> 25 #include <View.h> 26 27 #include <new> 28 #include <stdio.h> 29 #include <string.h> 30 31 32 //#define TRACE_EVENTS 33 #ifdef TRACE_EVENTS 34 # define ETRACE(x) printf x 35 #else 36 # define ETRACE(x) ; 37 #endif 38 39 40 /*! 41 The EventDispatcher is a per Desktop object that handles all input 42 events for that desktop. 43 44 The events are processed as needed in the Desktop class (via EventFilters), 45 and then forwarded to the actual target of the event, a client window 46 (or more correctly, to its EventTarget). 47 You cannot set the target of an event directly - the event filters need 48 to specify the targets. 49 The event loop will make sure that every target and interested listener 50 will get the event - it also delivers mouse moved events to the previous 51 target once so that this target can then spread the B_EXITED_VIEW transit 52 to the local target handler (usually a BView). 53 54 If you look at the event_listener structure below, the differentiation 55 between target and token may look odd, but it really has a reason as 56 well: 57 All events are sent to the preferred window handler only - the window 58 may then use the token or token list to identify the specific target 59 view(s). This makes it possible to send every event only once, no 60 matter how many local target handlers there are. 61 */ 62 63 struct event_listener { 64 int32 token; 65 uint32 event_mask; 66 uint32 options; 67 uint32 temporary_event_mask; 68 uint32 temporary_options; 69 70 uint32 EffectiveEventMask() const { return event_mask | temporary_event_mask; } 71 uint32 EffectiveOptions() const { return options | temporary_options; } 72 }; 73 74 static const char* kTokenName = "_token"; 75 76 static const uint32 kFakeMouseMoved = 'fake'; 77 78 static const float kMouseMovedImportance = 0.1f; 79 static const float kMouseTransitImportance = 1.0f; 80 static const float kStandardImportance = 0.9f; 81 static const float kListenerImportance = 0.8f; 82 83 84 EventTarget::EventTarget() 85 : 86 fListeners(2, true) 87 { 88 } 89 90 91 EventTarget::~EventTarget() 92 { 93 } 94 95 96 void 97 EventTarget::SetTo(const BMessenger& messenger) 98 { 99 fMessenger = messenger; 100 } 101 102 103 event_listener* 104 EventTarget::FindListener(int32 token, int32* _index) 105 { 106 for (int32 i = fListeners.CountItems(); i-- > 0;) { 107 event_listener* listener = fListeners.ItemAt(i); 108 109 if (listener->token == token) { 110 if (_index) 111 *_index = i; 112 return listener; 113 } 114 } 115 116 return NULL; 117 } 118 119 120 bool 121 EventTarget::_RemoveTemporaryListener(event_listener* listener, int32 index) 122 { 123 if (listener->event_mask == 0) { 124 // this is only a temporary target 125 ETRACE(("events: remove temp. listener: token %ld, eventMask = %ld, options = %ld\n", 126 listener->token, listener->temporary_event_mask, listener->temporary_options)); 127 128 fListeners.RemoveItemAt(index); 129 delete listener; 130 return true; 131 } 132 133 if (listener->temporary_event_mask != 0) { 134 ETRACE(("events: clear temp. listener: token %ld, eventMask = %ld, options = %ld\n", 135 listener->token, listener->temporary_event_mask, listener->temporary_options)); 136 137 listener->temporary_event_mask = 0; 138 listener->temporary_options = 0; 139 } 140 141 return false; 142 } 143 144 145 void 146 EventTarget::RemoveTemporaryListeners() 147 { 148 for (int32 index = CountListeners(); index-- > 0;) { 149 event_listener* listener = ListenerAt(index); 150 151 _RemoveTemporaryListener(listener, index); 152 } 153 } 154 155 156 bool 157 EventTarget::RemoveTemporaryListener(int32 token) 158 { 159 int32 index; 160 event_listener* listener = FindListener(token, &index); 161 if (listener == NULL) 162 return false; 163 164 return _RemoveTemporaryListener(listener, index); 165 } 166 167 168 bool 169 EventTarget::RemoveListener(int32 token) 170 { 171 int32 index; 172 event_listener* listener = FindListener(token, &index); 173 if (listener == NULL) 174 return false; 175 176 if (listener->temporary_event_mask != 0) { 177 // we still need this event 178 listener->event_mask = 0; 179 listener->options = 0; 180 return false; 181 } 182 183 fListeners.RemoveItemAt(index); 184 delete listener; 185 return true; 186 } 187 188 189 bool 190 EventTarget::AddListener(int32 token, uint32 eventMask, 191 uint32 options, bool temporary) 192 { 193 event_listener* listener = new (std::nothrow) event_listener; 194 if (listener == NULL) 195 return false; 196 197 listener->token = token; 198 199 if (temporary) { 200 listener->event_mask = 0; 201 listener->options = 0; 202 listener->temporary_event_mask = eventMask; 203 listener->temporary_options = options; 204 } else { 205 listener->event_mask = eventMask; 206 listener->options = options; 207 listener->temporary_event_mask = 0; 208 listener->temporary_options = 0; 209 } 210 211 bool success = fListeners.AddItem(listener); 212 if (!success) 213 delete listener; 214 215 return success; 216 } 217 218 219 // #pragma mark - 220 221 222 void 223 EventFilter::RemoveTarget(EventTarget* target) 224 { 225 } 226 227 228 // #pragma mark - 229 230 231 EventDispatcher::EventDispatcher() 232 : BLocker("event dispatcher"), 233 fStream(NULL), 234 fThread(-1), 235 fCursorThread(-1), 236 fPreviousMouseTarget(NULL), 237 fFocus(NULL), 238 fSuspendFocus(false), 239 fMouseFilter(NULL), 240 fKeyboardFilter(NULL), 241 fTargets(10), 242 fNextLatestMouseMoved(NULL), 243 fLastButtons(0), 244 fLastUpdate(system_time()), 245 fDraggingMessage(false), 246 fDragBitmap(NULL), 247 fCursorLock("cursor loop lock"), 248 fHWInterface(NULL), 249 fDesktop(NULL) 250 { 251 } 252 253 254 EventDispatcher::~EventDispatcher() 255 { 256 _Unset(); 257 } 258 259 260 status_t 261 EventDispatcher::SetTo(EventStream* stream) 262 { 263 ETRACE(("event dispatcher: stream = %p\n", stream)); 264 265 _Unset(); 266 267 if (stream == NULL) 268 return B_OK; 269 270 fStream = stream; 271 return _Run(); 272 } 273 274 275 status_t 276 EventDispatcher::InitCheck() 277 { 278 if (fStream != NULL) { 279 if (fThread < B_OK) 280 return fThread; 281 282 return B_OK; 283 } 284 return B_NO_INIT; 285 } 286 287 288 void 289 EventDispatcher::_Unset() 290 { 291 if (fStream == NULL) 292 return; 293 294 fStream->SendQuit(); 295 296 status_t status; 297 wait_for_thread(fThread, &status); 298 wait_for_thread(fCursorThread, &status); 299 300 fThread = fCursorThread = -1; 301 302 gInputManager->PutStream(fStream); 303 fStream = NULL; 304 } 305 306 307 status_t 308 EventDispatcher::_Run() 309 { 310 fThread = spawn_thread(_event_looper, "event loop", 311 B_REAL_TIME_DISPLAY_PRIORITY - 10, this); 312 if (fThread < B_OK) 313 return fThread; 314 315 if (fStream->SupportsCursorThread()) { 316 ETRACE(("event stream supports cursor thread!\n")); 317 318 fCursorThread = spawn_thread(_cursor_looper, "cursor loop", 319 B_REAL_TIME_DISPLAY_PRIORITY - 5, this); 320 if (resume_thread(fCursorThread) != B_OK) { 321 kill_thread(fCursorThread); 322 fCursorThread = -1; 323 } 324 } 325 326 return resume_thread(fThread); 327 } 328 329 330 /*! 331 \brief Removes any reference to the target, but doesn't delete it. 332 */ 333 void 334 EventDispatcher::RemoveTarget(EventTarget& target) 335 { 336 BAutolock _(this); 337 338 if (fFocus == &target) 339 fFocus = NULL; 340 if (fPreviousMouseTarget == &target) 341 fPreviousMouseTarget = NULL; 342 343 if (fKeyboardFilter != NULL) 344 fKeyboardFilter->RemoveTarget(&target); 345 if (fMouseFilter != NULL) 346 fMouseFilter->RemoveTarget(&target); 347 348 fTargets.RemoveItem(&target); 349 } 350 351 352 /*! 353 \brief Adds the specified listener or updates its event mask and options 354 if already added. 355 356 It follows the BView semantics in that specifiying an event mask of zero 357 leaves the event mask untouched and just updates the options. 358 */ 359 bool 360 EventDispatcher::_AddListener(EventTarget& target, int32 token, 361 uint32 eventMask, uint32 options, bool temporary) 362 { 363 BAutolock _(this); 364 365 if (temporary && fLastButtons == 0) { 366 // only allow to add temporary listeners in case a buttons is pressed 367 return false; 368 } 369 370 if (!fTargets.HasItem(&target)) 371 fTargets.AddItem(&target); 372 373 event_listener* listener = target.FindListener(token); 374 if (listener != NULL) { 375 // we already have this target, update its event mask 376 if (temporary) { 377 if (eventMask != 0) 378 listener->temporary_event_mask = eventMask; 379 listener->temporary_options = options; 380 } else { 381 if (eventMask != 0) 382 listener->event_mask = eventMask; 383 listener->options = options; 384 } 385 386 return true; 387 } 388 389 if (eventMask == 0) 390 return false; 391 392 ETRACE(("events: add listener: token %ld, eventMask = %ld, options = %ld, %s\n", 393 token, eventMask, options, temporary ? "temporary" : "permanent")); 394 395 // we need a new target 396 397 bool success = target.AddListener(token, eventMask, options, temporary); 398 if (!success) { 399 if (target.IsEmpty()) 400 fTargets.RemoveItem(&target); 401 } else { 402 if (options & B_SUSPEND_VIEW_FOCUS) 403 fSuspendFocus = true; 404 } 405 406 return success; 407 } 408 409 410 void 411 EventDispatcher::_RemoveTemporaryListeners() 412 { 413 for (int32 i = fTargets.CountItems(); i-- > 0;) { 414 EventTarget* target = fTargets.ItemAt(i); 415 416 target->RemoveTemporaryListeners(); 417 } 418 } 419 420 421 bool 422 EventDispatcher::AddListener(EventTarget& target, int32 token, 423 uint32 eventMask, uint32 options) 424 { 425 options &= B_NO_POINTER_HISTORY; 426 // that's currently the only allowed option 427 428 return _AddListener(target, token, eventMask, options, false); 429 } 430 431 432 bool 433 EventDispatcher::AddTemporaryListener(EventTarget& target, 434 int32 token, uint32 eventMask, uint32 options) 435 { 436 return _AddListener(target, token, eventMask, options, true); 437 } 438 439 440 void 441 EventDispatcher::RemoveListener(EventTarget& target, int32 token) 442 { 443 BAutolock _(this); 444 ETRACE(("events: remove listener token %ld\n", token)); 445 446 if (target.RemoveListener(token) && target.IsEmpty()) 447 fTargets.RemoveItem(&target); 448 } 449 450 451 void 452 EventDispatcher::RemoveTemporaryListener(EventTarget& target, int32 token) 453 { 454 BAutolock _(this); 455 ETRACE(("events: remove temporary listener token %ld\n", token)); 456 457 if (target.RemoveTemporaryListener(token) && target.IsEmpty()) 458 fTargets.RemoveItem(&target); 459 } 460 461 462 void 463 EventDispatcher::SetMouseFilter(EventFilter* filter) 464 { 465 BAutolock _(this); 466 467 if (fMouseFilter == filter) 468 return; 469 470 delete fMouseFilter; 471 fMouseFilter = filter; 472 } 473 474 475 void 476 EventDispatcher::SetKeyboardFilter(EventFilter* filter) 477 { 478 BAutolock _(this); 479 480 if (fKeyboardFilter == filter) 481 return; 482 483 delete fKeyboardFilter; 484 fKeyboardFilter = filter; 485 } 486 487 488 void 489 EventDispatcher::GetMouse(BPoint& where, int32& buttons) 490 { 491 BAutolock _(this); 492 493 where = fLastCursorPosition; 494 buttons = fLastButtons; 495 } 496 497 498 void 499 EventDispatcher::SendFakeMouseMoved(EventTarget& target, int32 viewToken) 500 { 501 if (fStream == NULL) 502 return; 503 504 BMessage* fakeMove = new BMessage(kFakeMouseMoved); 505 if (fakeMove == NULL) 506 return; 507 508 fakeMove->AddMessenger("target", target.Messenger()); 509 fakeMove->AddInt32("view_token", viewToken); 510 511 fStream->InsertEvent(fakeMove); 512 } 513 514 515 void 516 EventDispatcher::_SendFakeMouseMoved(BMessage* message) 517 { 518 BMessenger target; 519 int32 viewToken; 520 if (message->FindInt32("view_token", &viewToken) != B_OK 521 || message->FindMessenger("target", &target) != B_OK) 522 return; 523 524 if (fDesktop == NULL) 525 return; 526 527 // Check if the target is still valid 528 ::EventTarget* eventTarget = NULL; 529 530 fDesktop->LockSingleWindow(); 531 532 if (target.IsValid()) 533 eventTarget = fDesktop->FindTarget(target); 534 535 fDesktop->UnlockSingleWindow(); 536 537 if (eventTarget == NULL) 538 return; 539 540 BMessage moved(B_MOUSE_MOVED); 541 moved.AddPoint("screen_where", fLastCursorPosition); 542 moved.AddInt32("buttons", fLastButtons); 543 544 if (fDraggingMessage) 545 moved.AddMessage("be:drag_message", &fDragMessage); 546 547 if (fPreviousMouseTarget != NULL 548 && fPreviousMouseTarget->Messenger() != target) { 549 _AddTokens(&moved, fPreviousMouseTarget, B_POINTER_EVENTS); 550 _SendMessage(fPreviousMouseTarget->Messenger(), &moved, 551 kMouseTransitImportance); 552 553 _RemoveTokens(&moved); 554 } 555 556 moved.AddInt32("_view_token", viewToken); 557 // this only belongs to the new target 558 559 moved.AddBool("be:transit_only", true); 560 // let the view know this what not user generated 561 562 _SendMessage(target, &moved, kMouseTransitImportance); 563 564 fPreviousMouseTarget = eventTarget; 565 } 566 567 568 bigtime_t 569 EventDispatcher::IdleTime() 570 { 571 BAutolock _(this); 572 return system_time() - fLastUpdate; 573 } 574 575 576 bool 577 EventDispatcher::HasCursorThread() 578 { 579 return fCursorThread >= B_OK; 580 } 581 582 583 /*! 584 \brief Sets the HWInterface to use when moving the mouse cursor. 585 \a interface is allowed to be NULL. 586 */ 587 void 588 EventDispatcher::SetHWInterface(HWInterface* interface) 589 { 590 BAutolock _(fCursorLock); 591 592 fHWInterface = interface; 593 594 // adopt the cursor position of the new HW interface 595 if (interface != NULL) 596 fLastCursorPosition = interface->CursorPosition(); 597 } 598 599 600 void 601 EventDispatcher::SetDragMessage(BMessage& message, 602 ServerBitmap* bitmap, const BPoint& offsetFromCursor) 603 { 604 ETRACE(("EventDispatcher::SetDragMessage()\n")); 605 606 BAutolock _(this); 607 608 if (fLastButtons == 0) { 609 // mouse buttons has already been released or was never pressed 610 bitmap->ReleaseReference(); 611 return; 612 } 613 614 if (fDragBitmap != bitmap) { 615 if (fDragBitmap) 616 fDragBitmap->ReleaseReference(); 617 618 fDragBitmap = bitmap; 619 620 if (fDragBitmap != NULL) 621 fDragBitmap->AcquireReference(); 622 } 623 624 fHWInterface->SetDragBitmap(bitmap, offsetFromCursor); 625 626 fDragMessage = message; 627 fDraggingMessage = true; 628 fDragOffset = offsetFromCursor; 629 } 630 631 632 void 633 EventDispatcher::SetDesktop(Desktop* desktop) 634 { 635 fDesktop = desktop; 636 } 637 638 639 // #pragma mark - Message methods 640 641 642 /*! 643 \brief Sends \a message to the provided \a messenger. 644 645 TODO: the following feature is not yet implemented: 646 If the message could not be delivered immediately, it is included 647 in a waiting message queue with a fixed length - the least important 648 messages are removed first when that gets full. 649 650 Returns "false" if the target port does not exist anymore, "true" 651 if it doesn't. 652 */ 653 bool 654 EventDispatcher::_SendMessage(BMessenger& messenger, BMessage* message, 655 float importance) 656 { 657 // TODO: add failed messages to a queue, and start dropping them by importance 658 // (and use the same mechanism in ServerWindow::SendMessageToClient()) 659 660 status_t status = messenger.SendMessage(message, (BHandler*)NULL, 0); 661 if (status != B_OK) { 662 printf("EventDispatcher: failed to send message '%.4s' to target: %s\n", 663 (char*)&message->what, strerror(status)); 664 } 665 666 if (status == B_BAD_PORT_ID) { 667 // the target port is gone 668 return false; 669 } 670 671 return true; 672 } 673 674 675 bool 676 EventDispatcher::_AddTokens(BMessage* message, EventTarget* target, 677 uint32 eventMask, BMessage* nextMouseMoved, int32* _viewToken) 678 { 679 _RemoveTokens(message); 680 681 int32 count = target->CountListeners(); 682 int32 added = 0; 683 684 for (int32 i = 0; i < count; i++) { 685 event_listener* listener = target->ListenerAt(i); 686 if ((listener->EffectiveEventMask() & eventMask) == 0) 687 continue; 688 689 if (nextMouseMoved != NULL && message->what == B_MOUSE_MOVED 690 && (listener->EffectiveOptions() & B_NO_POINTER_HISTORY) != 0 691 && message != nextMouseMoved 692 && _viewToken != NULL) { 693 if (listener->token == *_viewToken) { 694 // focus view doesn't want to get pointer history 695 *_viewToken = B_NULL_TOKEN; 696 } 697 continue; 698 } 699 700 ETRACE((" add token %ld\n", listener->token)); 701 702 if (message->AddInt32(kTokenName, listener->token) == B_OK) 703 added++; 704 } 705 706 return added != 0; 707 } 708 709 710 void 711 EventDispatcher::_RemoveTokens(BMessage* message) 712 { 713 message->RemoveName(kTokenName); 714 } 715 716 717 void 718 EventDispatcher::_SetFeedFocus(BMessage* message) 719 { 720 if (message->ReplaceBool("_feed_focus", true) != B_OK) 721 message->AddBool("_feed_focus", true); 722 } 723 724 725 void 726 EventDispatcher::_UnsetFeedFocus(BMessage* message) 727 { 728 message->RemoveName("_feed_focus"); 729 } 730 731 732 void 733 EventDispatcher::_DeliverDragMessage() 734 { 735 ETRACE(("EventDispatcher::_DeliverDragMessage()\n")); 736 737 if (fDraggingMessage && fPreviousMouseTarget != NULL) { 738 BMessage::Private(fDragMessage).SetWasDropped(true); 739 fDragMessage.RemoveName("_original_what"); 740 fDragMessage.AddInt32("_original_what", fDragMessage.what); 741 fDragMessage.AddPoint("_drop_point_", fLastCursorPosition); 742 fDragMessage.AddPoint("_drop_offset_", fDragOffset); 743 fDragMessage.what = _MESSAGE_DROPPED_; 744 745 _SendMessage(fPreviousMouseTarget->Messenger(), 746 &fDragMessage, 100.0); 747 } 748 749 fDragMessage.MakeEmpty(); 750 fDragMessage.what = 0; 751 fDraggingMessage = false; 752 753 fHWInterface->SetDragBitmap(NULL, B_ORIGIN); 754 if (fDragBitmap != NULL) { 755 fDragBitmap->ReleaseReference(); 756 fDragBitmap = NULL; 757 } 758 } 759 760 761 // #pragma mark - Event loops 762 763 764 void 765 EventDispatcher::_EventLoop() 766 { 767 BMessage* event; 768 while (fStream->GetNextEvent(&event)) { 769 BAutolock _(this); 770 fLastUpdate = system_time(); 771 772 EventTarget* current = NULL; 773 EventTarget* previous = NULL; 774 bool pointerEvent = false; 775 bool keyboardEvent = false; 776 bool addedTokens = false; 777 778 switch (event->what) { 779 case kFakeMouseMoved: 780 _SendFakeMouseMoved(event); 781 break; 782 case B_MOUSE_MOVED: 783 { 784 BPoint where; 785 if (event->FindPoint("where", &where) == B_OK) 786 fLastCursorPosition = where; 787 788 if (fDraggingMessage) 789 event->AddMessage("be:drag_message", &fDragMessage); 790 791 if (!HasCursorThread()) { 792 // There is no cursor thread, we need to move the cursor 793 // ourselves 794 BAutolock _(fCursorLock); 795 796 if (fHWInterface != NULL) { 797 fHWInterface->MoveCursorTo(fLastCursorPosition.x, 798 fLastCursorPosition.y); 799 } 800 } 801 802 // This is for B_NO_POINTER_HISTORY - we always want the 803 // latest mouse moved event in the queue only 804 if (fNextLatestMouseMoved == NULL) 805 fNextLatestMouseMoved = fStream->PeekLatestMouseMoved(); 806 else if (fNextLatestMouseMoved != event) { 807 // Drop older mouse moved messages if the server is lagging 808 // too much (if the message is older than 100 msecs) 809 bigtime_t eventTime; 810 if (event->FindInt64("when", &eventTime) == B_OK) { 811 if (system_time() - eventTime > 100000) 812 break; 813 } 814 } 815 816 // supposed to fall through 817 } 818 case B_MOUSE_DOWN: 819 case B_MOUSE_UP: 820 { 821 #ifdef TRACE_EVENTS 822 if (event->what != B_MOUSE_MOVED) 823 printf("mouse up/down event, previous target = %p\n", fPreviousMouseTarget); 824 #endif 825 pointerEvent = true; 826 827 if (fMouseFilter == NULL) 828 break; 829 830 EventTarget* mouseTarget = fPreviousMouseTarget; 831 int32 viewToken = B_NULL_TOKEN; 832 if (fMouseFilter->Filter(event, &mouseTarget, &viewToken, 833 fNextLatestMouseMoved) == B_SKIP_MESSAGE) { 834 // this is a work-around if the wrong B_MOUSE_UP 835 // event is filtered out 836 if (event->what == B_MOUSE_UP 837 && event->FindInt32("buttons") == 0) { 838 fSuspendFocus = false; 839 _RemoveTemporaryListeners(); 840 } 841 break; 842 } 843 844 int32 buttons; 845 if (event->FindInt32("buttons", &buttons) == B_OK) 846 fLastButtons = buttons; 847 else 848 fLastButtons = 0; 849 850 // The "where" field will be filled in by the receiver 851 // (it's supposed to be expressed in local window coordinates) 852 event->RemoveName("where"); 853 event->AddPoint("screen_where", fLastCursorPosition); 854 855 if (event->what == B_MOUSE_MOVED 856 && fPreviousMouseTarget != NULL 857 && mouseTarget != fPreviousMouseTarget) { 858 // Target has changed, we need to notify the previous target 859 // that the mouse has exited its views 860 addedTokens = _AddTokens(event, fPreviousMouseTarget, 861 B_POINTER_EVENTS); 862 if (addedTokens) 863 _SetFeedFocus(event); 864 865 _SendMessage(fPreviousMouseTarget->Messenger(), event, 866 kMouseTransitImportance); 867 previous = fPreviousMouseTarget; 868 } 869 870 current = fPreviousMouseTarget = mouseTarget; 871 872 if (current != NULL) { 873 int32 focusView = viewToken; 874 addedTokens |= _AddTokens(event, current, B_POINTER_EVENTS, 875 fNextLatestMouseMoved, &focusView); 876 877 bool noPointerHistoryFocus = focusView != viewToken; 878 879 if (viewToken != B_NULL_TOKEN) 880 event->AddInt32("_view_token", viewToken); 881 882 if (addedTokens && !noPointerHistoryFocus) 883 _SetFeedFocus(event); 884 else if (noPointerHistoryFocus) { 885 // No tokens were added or the focus shouldn't get a 886 // mouse moved 887 break; 888 } 889 890 _SendMessage(current->Messenger(), event, 891 event->what == B_MOUSE_MOVED 892 ? kMouseMovedImportance : kStandardImportance); 893 } 894 break; 895 } 896 897 case B_KEY_DOWN: 898 case B_KEY_UP: 899 case B_UNMAPPED_KEY_DOWN: 900 case B_UNMAPPED_KEY_UP: 901 case B_MODIFIERS_CHANGED: 902 case B_INPUT_METHOD_EVENT: 903 ETRACE(("key event, focus = %p\n", fFocus)); 904 905 if (fKeyboardFilter != NULL 906 && fKeyboardFilter->Filter(event, &fFocus) == B_SKIP_MESSAGE) 907 break; 908 909 keyboardEvent = true; 910 911 if (fFocus != NULL && _AddTokens(event, fFocus, 912 B_KEYBOARD_EVENTS)) { 913 // if tokens were added, we need to explicetly suspend 914 // focus in the event - if not, the event is simply not 915 // forwarded to the target 916 addedTokens = true; 917 918 if (!fSuspendFocus) 919 _SetFeedFocus(event); 920 } 921 922 // supposed to fall through 923 924 default: 925 // TODO: the keyboard filter sets the focus - ie. no other 926 // focus messages that go through the event dispatcher can 927 // go through. 928 if (event->what == B_MOUSE_WHEEL_CHANGED) 929 current = fPreviousMouseTarget; 930 else 931 current = fFocus; 932 933 if (current != NULL && (!fSuspendFocus || addedTokens)) { 934 _SendMessage(current->Messenger(), event, 935 kStandardImportance); 936 } 937 break; 938 } 939 940 if (keyboardEvent || pointerEvent) { 941 // send the event to the additional listeners 942 943 if (addedTokens) { 944 _RemoveTokens(event); 945 _UnsetFeedFocus(event); 946 } 947 if (pointerEvent) { 948 // this is added in the Desktop mouse processing 949 // but it's only intended for the focus view 950 event->RemoveName("_view_token"); 951 } 952 953 for (int32 i = fTargets.CountItems(); i-- > 0;) { 954 EventTarget* target = fTargets.ItemAt(i); 955 956 // We already sent the event to the all focus and last focus 957 // tokens 958 if (current == target || previous == target) 959 continue; 960 961 // Don't send the message if there are no tokens for this event 962 if (!_AddTokens(event, target, 963 keyboardEvent ? B_KEYBOARD_EVENTS : B_POINTER_EVENTS, 964 event->what == B_MOUSE_MOVED 965 ? fNextLatestMouseMoved : NULL)) 966 continue; 967 968 if (!_SendMessage(target->Messenger(), event, 969 event->what == B_MOUSE_MOVED 970 ? kMouseMovedImportance : kListenerImportance)) { 971 // the target doesn't seem to exist anymore, let's remove it 972 fTargets.RemoveItemAt(i); 973 } 974 } 975 976 if (event->what == B_MOUSE_UP && fLastButtons == 0) { 977 // no buttons are pressed anymore 978 fSuspendFocus = false; 979 _RemoveTemporaryListeners(); 980 if (fDraggingMessage) 981 _DeliverDragMessage(); 982 } 983 } 984 985 if (fNextLatestMouseMoved == event) 986 fNextLatestMouseMoved = NULL; 987 delete event; 988 } 989 990 // The loop quit, therefore no more events are coming from the input 991 // server, it must have died. Unset ourselves and notify the desktop. 992 fThread = -1; 993 // Needed to avoid problems with wait_for_thread in _Unset() 994 _Unset(); 995 996 if (fDesktop) 997 fDesktop->PostMessage(AS_EVENT_STREAM_CLOSED); 998 } 999 1000 1001 void 1002 EventDispatcher::_CursorLoop() 1003 { 1004 BPoint where; 1005 while (fStream->GetNextCursorPosition(where)) { 1006 BAutolock _(fCursorLock); 1007 1008 if (fHWInterface != NULL) 1009 fHWInterface->MoveCursorTo(where.x, where.y); 1010 } 1011 1012 fCursorThread = -1; 1013 } 1014 1015 1016 /*static*/ 1017 status_t 1018 EventDispatcher::_event_looper(void* _dispatcher) 1019 { 1020 EventDispatcher* dispatcher = (EventDispatcher*)_dispatcher; 1021 1022 ETRACE(("Start event loop\n")); 1023 dispatcher->_EventLoop(); 1024 return B_OK; 1025 } 1026 1027 1028 /*static*/ 1029 status_t 1030 EventDispatcher::_cursor_looper(void* _dispatcher) 1031 { 1032 EventDispatcher* dispatcher = (EventDispatcher*)_dispatcher; 1033 1034 ETRACE(("Start cursor loop\n")); 1035 dispatcher->_CursorLoop(); 1036 return B_OK; 1037 } 1038