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