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