1 /* 2 * Copyright 2005-2008, 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 fLastButtons(0), 241 fLastUpdate(system_time()), 242 fDragBitmap(NULL), 243 fCursorLock("cursor loop lock"), 244 fHWInterface(NULL), 245 fDesktop(NULL) 246 { 247 } 248 249 250 EventDispatcher::~EventDispatcher() 251 { 252 _Unset(); 253 } 254 255 256 status_t 257 EventDispatcher::SetTo(EventStream* stream) 258 { 259 ETRACE(("event dispatcher: stream = %p\n", stream)); 260 261 _Unset(); 262 263 if (stream == NULL) 264 return B_OK; 265 266 fStream = stream; 267 return _Run(); 268 } 269 270 271 status_t 272 EventDispatcher::InitCheck() 273 { 274 if (fStream != NULL) { 275 if (fThread < B_OK) 276 return fThread; 277 278 return B_OK; 279 } 280 return B_NO_INIT; 281 } 282 283 284 void 285 EventDispatcher::_Unset() 286 { 287 if (fStream == NULL) 288 return; 289 290 fStream->SendQuit(); 291 292 status_t status; 293 wait_for_thread(fThread, &status); 294 wait_for_thread(fCursorThread, &status); 295 296 fThread = fCursorThread = -1; 297 298 gInputManager->PutStream(fStream); 299 fStream = NULL; 300 } 301 302 303 status_t 304 EventDispatcher::_Run() 305 { 306 fThread = spawn_thread(_event_looper, "event loop", 307 B_REAL_TIME_DISPLAY_PRIORITY - 10, this); 308 if (fThread < B_OK) 309 return fThread; 310 311 if (fStream->SupportsCursorThread()) { 312 ETRACE(("event stream supports cursor thread!\n")); 313 314 fCursorThread = spawn_thread(_cursor_looper, "cursor loop", 315 B_REAL_TIME_DISPLAY_PRIORITY - 5, this); 316 if (resume_thread(fCursorThread) != B_OK) { 317 kill_thread(fCursorThread); 318 fCursorThread = -1; 319 } 320 } 321 322 return resume_thread(fThread); 323 } 324 325 326 /*! 327 \brief Removes any reference to the target, but doesn't delete it. 328 */ 329 void 330 EventDispatcher::RemoveTarget(EventTarget& target) 331 { 332 BAutolock _(this); 333 334 if (fFocus == &target) 335 fFocus = NULL; 336 if (fPreviousMouseTarget == &target) 337 fPreviousMouseTarget = NULL; 338 339 if (fKeyboardFilter != NULL) 340 fKeyboardFilter->RemoveTarget(&target); 341 if (fMouseFilter != NULL) 342 fMouseFilter->RemoveTarget(&target); 343 344 fTargets.RemoveItem(&target); 345 } 346 347 348 /*! 349 \brief Adds the specified listener or updates its event mask and options 350 if already added. 351 352 It follows the BView semantics in that specifiying an event mask of zero 353 leaves the event mask untouched and just updates the options. 354 */ 355 bool 356 EventDispatcher::_AddListener(EventTarget& target, int32 token, 357 uint32 eventMask, uint32 options, bool temporary) 358 { 359 BAutolock _(this); 360 361 if (temporary && fLastButtons == 0) { 362 // only allow to add temporary listeners in case a buttons is pressed 363 return false; 364 } 365 366 if (!fTargets.HasItem(&target)) 367 fTargets.AddItem(&target); 368 369 event_listener* listener = target.FindListener(token); 370 if (listener != NULL) { 371 // we already have this target, update its event mask 372 if (temporary) { 373 if (eventMask != 0) 374 listener->temporary_event_mask = eventMask; 375 listener->temporary_options = options; 376 } else { 377 if (eventMask != 0) 378 listener->event_mask = eventMask; 379 listener->options = options; 380 } 381 382 return true; 383 } 384 385 if (eventMask == 0) 386 return false; 387 388 ETRACE(("events: add listener: token %ld, eventMask = %ld, options = %ld, %s\n", 389 token, eventMask, options, temporary ? "temporary" : "permanent")); 390 391 // we need a new target 392 393 bool success = target.AddListener(token, eventMask, options, temporary); 394 if (!success) { 395 if (target.IsEmpty()) 396 fTargets.RemoveItem(&target); 397 } else { 398 if (options & B_SUSPEND_VIEW_FOCUS) 399 fSuspendFocus = true; 400 } 401 402 return success; 403 } 404 405 406 void 407 EventDispatcher::_RemoveTemporaryListeners() 408 { 409 for (int32 i = fTargets.CountItems(); i-- > 0;) { 410 EventTarget* target = fTargets.ItemAt(i); 411 412 target->RemoveTemporaryListeners(); 413 } 414 } 415 416 417 bool 418 EventDispatcher::AddListener(EventTarget& target, int32 token, 419 uint32 eventMask, uint32 options) 420 { 421 options &= B_NO_POINTER_HISTORY; 422 // that's currently the only allowed option 423 424 return _AddListener(target, token, eventMask, options, false); 425 } 426 427 428 bool 429 EventDispatcher::AddTemporaryListener(EventTarget& target, 430 int32 token, uint32 eventMask, uint32 options) 431 { 432 return _AddListener(target, token, eventMask, options, true); 433 } 434 435 436 void 437 EventDispatcher::RemoveListener(EventTarget& target, int32 token) 438 { 439 BAutolock _(this); 440 ETRACE(("events: remove listener token %ld\n", token)); 441 442 if (target.RemoveListener(token) && target.IsEmpty()) 443 fTargets.RemoveItem(&target); 444 } 445 446 447 void 448 EventDispatcher::RemoveTemporaryListener(EventTarget& target, int32 token) 449 { 450 BAutolock _(this); 451 ETRACE(("events: remove temporary listener token %ld\n", token)); 452 453 if (target.RemoveTemporaryListener(token) && target.IsEmpty()) 454 fTargets.RemoveItem(&target); 455 } 456 457 458 void 459 EventDispatcher::SetMouseFilter(EventFilter* filter) 460 { 461 BAutolock _(this); 462 463 if (fMouseFilter == filter) 464 return; 465 466 delete fMouseFilter; 467 fMouseFilter = filter; 468 } 469 470 471 void 472 EventDispatcher::SetKeyboardFilter(EventFilter* filter) 473 { 474 BAutolock _(this); 475 476 if (fKeyboardFilter == filter) 477 return; 478 479 delete fKeyboardFilter; 480 fKeyboardFilter = filter; 481 } 482 483 484 void 485 EventDispatcher::GetMouse(BPoint& where, int32& buttons) 486 { 487 BAutolock _(this); 488 489 where = fLastCursorPosition; 490 buttons = fLastButtons; 491 } 492 493 494 void 495 EventDispatcher::SendFakeMouseMoved(EventTarget& target, int32 viewToken) 496 { 497 BAutolock _(this); 498 499 BMessage moved(B_MOUSE_MOVED); 500 moved.AddPoint("screen_where", fLastCursorPosition); 501 moved.AddInt32("buttons", fLastButtons); 502 503 if (fDraggingMessage) 504 moved.AddMessage("be:drag_message", &fDragMessage); 505 506 if (fPreviousMouseTarget != NULL 507 && fPreviousMouseTarget != &target) { 508 _AddTokens(&moved, fPreviousMouseTarget, B_POINTER_EVENTS); 509 _SendMessage(fPreviousMouseTarget->Messenger(), &moved, 510 kMouseTransitImportance); 511 512 _RemoveTokens(&moved); 513 } 514 515 moved.AddInt32("_view_token", viewToken); 516 // this only belongs to the new target 517 518 _SendMessage(target.Messenger(), &moved, kMouseTransitImportance); 519 fPreviousMouseTarget = ⌖ 520 } 521 522 523 bigtime_t 524 EventDispatcher::IdleTime() 525 { 526 BAutolock _(this); 527 return system_time() - fLastUpdate; 528 } 529 530 531 bool 532 EventDispatcher::HasCursorThread() 533 { 534 return fCursorThread >= B_OK; 535 } 536 537 538 /*! 539 \brief Sets the HWInterface to use when moving the mouse cursor. 540 \a interface is allowed to be NULL. 541 */ 542 void 543 EventDispatcher::SetHWInterface(HWInterface* interface) 544 { 545 BAutolock _(fCursorLock); 546 547 fHWInterface = interface; 548 549 // adopt the cursor position of the new HW interface 550 if (interface != NULL) 551 fLastCursorPosition = interface->CursorPosition(); 552 } 553 554 555 void 556 EventDispatcher::SetDragMessage(BMessage& message, 557 ServerBitmap* bitmap, const BPoint& offsetFromCursor) 558 { 559 ETRACE(("EventDispatcher::SetDragMessage()\n")); 560 561 BAutolock _(this); 562 563 if (fLastButtons == 0) { 564 // mouse buttons has already been released or was never pressed 565 gBitmapManager->DeleteBitmap(bitmap); 566 return; 567 } 568 569 if (fDragBitmap != bitmap) { 570 if (fDragBitmap) 571 gBitmapManager->DeleteBitmap(fDragBitmap); 572 fDragBitmap = bitmap; 573 574 if (fDragBitmap != NULL) 575 fDragBitmap->Acquire(); 576 } 577 578 fHWInterface->SetDragBitmap(bitmap, offsetFromCursor); 579 580 fDragMessage = message; 581 fDraggingMessage = true; 582 fDragOffset = offsetFromCursor; 583 } 584 585 586 void 587 EventDispatcher::SetDesktop(Desktop* desktop) 588 { 589 fDesktop = desktop; 590 } 591 592 593 // #pragma mark - Message methods 594 595 596 /*! 597 \brief Sends \a message to the provided \a messenger. 598 599 TODO: the following feature is not yet implemented: 600 If the message could not be delivered immediately, it is included 601 in a waiting message queue with a fixed length - the least important 602 messages are removed first when that gets full. 603 604 Returns "false" if the target port does not exist anymore, "true" 605 if it doesn't. 606 */ 607 bool 608 EventDispatcher::_SendMessage(BMessenger& messenger, BMessage* message, 609 float importance) 610 { 611 // TODO: add failed messages to a queue, and start dropping them by importance 612 // (and use the same mechanism in ServerWindow::SendMessageToClient()) 613 614 status_t status = messenger.SendMessage(message, (BHandler*)NULL, 0); 615 if (status != B_OK) { 616 printf("EventDispatcher: failed to send message '%.4s' to target: %s\n", 617 (char*)&message->what, strerror(status)); 618 } 619 620 if (status == B_BAD_PORT_ID) { 621 // the target port is gone 622 return false; 623 } 624 625 return true; 626 } 627 628 629 bool 630 EventDispatcher::_AddTokens(BMessage* message, EventTarget* target, 631 uint32 eventMask, BMessage* nextMouseMoved, int32* _viewToken) 632 { 633 _RemoveTokens(message); 634 635 int32 count = target->CountListeners(); 636 int32 added = 0; 637 638 for (int32 i = 0; i < count; i++) { 639 event_listener* listener = target->ListenerAt(i); 640 if ((listener->EffectiveEventMask() & eventMask) == 0) 641 continue; 642 643 if (nextMouseMoved != NULL && message->what == B_MOUSE_MOVED 644 && (listener->EffectiveOptions() & B_NO_POINTER_HISTORY) != 0 645 && message != nextMouseMoved 646 && _viewToken != NULL) { 647 if (listener->token == *_viewToken) { 648 // focus view doesn't want to get pointer history 649 *_viewToken = B_NULL_TOKEN; 650 } 651 continue; 652 } 653 654 ETRACE((" add token %ld\n", listener->token)); 655 656 if (message->AddInt32(kTokenName, listener->token) == B_OK) 657 added++; 658 } 659 660 return added != 0; 661 } 662 663 664 void 665 EventDispatcher::_RemoveTokens(BMessage* message) 666 { 667 message->RemoveName(kTokenName); 668 } 669 670 671 void 672 EventDispatcher::_SetFeedFocus(BMessage* message) 673 { 674 if (message->ReplaceBool("_feed_focus", true) != B_OK) 675 message->AddBool("_feed_focus", true); 676 } 677 678 679 void 680 EventDispatcher::_UnsetFeedFocus(BMessage* message) 681 { 682 message->RemoveName("_feed_focus"); 683 } 684 685 686 void 687 EventDispatcher::_DeliverDragMessage() 688 { 689 ETRACE(("EventDispatcher::_DeliverDragMessage()\n")); 690 691 if (fDraggingMessage && fPreviousMouseTarget != NULL) { 692 BMessage::Private(fDragMessage).SetWasDropped(true); 693 fDragMessage.RemoveName("_original_what"); 694 fDragMessage.AddInt32("_original_what", fDragMessage.what); 695 fDragMessage.AddPoint("_drop_point_", fLastCursorPosition); 696 fDragMessage.AddPoint("_drop_offset_", fDragOffset); 697 fDragMessage.what = _MESSAGE_DROPPED_; 698 699 _SendMessage(fPreviousMouseTarget->Messenger(), 700 &fDragMessage, 100.0); 701 } 702 703 fDragMessage.MakeEmpty(); 704 fDragMessage.what = 0; 705 fDraggingMessage = false; 706 707 fHWInterface->SetDragBitmap(NULL, B_ORIGIN); 708 gBitmapManager->DeleteBitmap(fDragBitmap); 709 fDragBitmap = NULL; 710 } 711 712 713 // #pragma mark - Event loops 714 715 716 void 717 EventDispatcher::_EventLoop() 718 { 719 BMessage* event; 720 while (fStream->GetNextEvent(&event)) { 721 if (event == NULL) { 722 // may happen in out of memory situations or junk at the port 723 // we can't do anything about those yet 724 continue; 725 } 726 727 BAutolock _(this); 728 fLastUpdate = system_time(); 729 730 EventTarget* current = NULL; 731 EventTarget* previous = NULL; 732 bool pointerEvent = false; 733 bool keyboardEvent = false; 734 bool addedTokens = false; 735 736 switch (event->what) { 737 case B_MOUSE_MOVED: 738 { 739 BPoint where; 740 if (event->FindPoint("where", &where) == B_OK) 741 fLastCursorPosition = where; 742 743 if (fDraggingMessage) 744 event->AddMessage("be:drag_message", &fDragMessage); 745 746 if (!HasCursorThread()) { 747 // There is no cursor thread, we need to move the cursor 748 // ourselves 749 BAutolock _(fCursorLock); 750 751 if (fHWInterface != NULL) { 752 fHWInterface->MoveCursorTo(fLastCursorPosition.x, 753 fLastCursorPosition.y); 754 } 755 } 756 757 // This is for B_NO_POINTER_HISTORY - we always want the 758 // latest mouse moved event in the queue only 759 if (fNextLatestMouseMoved == NULL) 760 fNextLatestMouseMoved = fStream->PeekLatestMouseMoved(); 761 else if (fNextLatestMouseMoved != event) { 762 // Drop older mouse moved messages if the server is lagging 763 // too much (if the message is older than 100 msecs) 764 bigtime_t eventTime; 765 if (event->FindInt64("when", &eventTime) == B_OK) { 766 if (system_time() - eventTime > 100000) 767 break; 768 } 769 } 770 771 // supposed to fall through 772 } 773 case B_MOUSE_DOWN: 774 case B_MOUSE_UP: 775 { 776 #ifdef TRACE_EVENTS 777 if (event->what != B_MOUSE_MOVED) 778 printf("mouse up/down event, previous target = %p\n", fPreviousMouseTarget); 779 #endif 780 pointerEvent = true; 781 782 if (fMouseFilter == NULL) 783 break; 784 785 EventTarget* mouseTarget = fPreviousMouseTarget; 786 int32 viewToken = B_NULL_TOKEN; 787 if (fMouseFilter->Filter(event, &mouseTarget, &viewToken, 788 fNextLatestMouseMoved) == B_SKIP_MESSAGE) { 789 // this is a work-around if the wrong B_MOUSE_UP 790 // event is filtered out 791 if (event->what == B_MOUSE_UP 792 && event->FindInt32("buttons") == 0) { 793 fSuspendFocus = false; 794 _RemoveTemporaryListeners(); 795 } 796 break; 797 } 798 799 int32 buttons; 800 if (event->FindInt32("buttons", &buttons) == B_OK) 801 fLastButtons = buttons; 802 else 803 fLastButtons = 0; 804 805 // The "where" field will be filled in by the receiver 806 // (it's supposed to be expressed in local window coordinates) 807 event->RemoveName("where"); 808 event->AddPoint("screen_where", fLastCursorPosition); 809 810 if (event->what == B_MOUSE_MOVED 811 && fPreviousMouseTarget != NULL 812 && mouseTarget != fPreviousMouseTarget) { 813 // Target has changed, we need to notify the previous target 814 // that the mouse has exited its views 815 addedTokens = _AddTokens(event, fPreviousMouseTarget, 816 B_POINTER_EVENTS); 817 818 _SendMessage(fPreviousMouseTarget->Messenger(), event, 819 kMouseTransitImportance); 820 previous = fPreviousMouseTarget; 821 } 822 823 current = fPreviousMouseTarget = mouseTarget; 824 825 if (current != NULL) { 826 int32 focusView = viewToken; 827 addedTokens |= _AddTokens(event, current, B_POINTER_EVENTS, 828 fNextLatestMouseMoved, &focusView); 829 830 bool noPointerHistoryFocus = focusView != viewToken; 831 832 if (viewToken != B_NULL_TOKEN) 833 event->AddInt32("_view_token", viewToken); 834 835 if (addedTokens && !noPointerHistoryFocus) 836 _SetFeedFocus(event); 837 else if (noPointerHistoryFocus) { 838 // No tokens were added or the focus shouldn't get a 839 // mouse moved 840 break; 841 } 842 843 _SendMessage(current->Messenger(), event, 844 event->what == B_MOUSE_MOVED 845 ? kMouseMovedImportance : kStandardImportance); 846 } 847 break; 848 } 849 850 case B_KEY_DOWN: 851 case B_KEY_UP: 852 case B_UNMAPPED_KEY_DOWN: 853 case B_UNMAPPED_KEY_UP: 854 case B_MODIFIERS_CHANGED: 855 case B_INPUT_METHOD_EVENT: 856 ETRACE(("key event, focus = %p\n", fFocus)); 857 858 if (fKeyboardFilter != NULL 859 && fKeyboardFilter->Filter(event, &fFocus) == B_SKIP_MESSAGE) 860 break; 861 862 keyboardEvent = true; 863 864 if (fFocus != NULL && _AddTokens(event, fFocus, 865 B_KEYBOARD_EVENTS)) { 866 // if tokens were added, we need to explicetly suspend 867 // focus in the event - if not, the event is simply not 868 // forwarded to the target 869 addedTokens = true; 870 871 if (!fSuspendFocus) 872 _SetFeedFocus(event); 873 } 874 875 // supposed to fall through 876 877 default: 878 // TODO: the keyboard filter sets the focus - ie. no other 879 // focus messages that go through the event dispatcher can 880 // go through. 881 if (event->what == B_MOUSE_WHEEL_CHANGED) 882 current = fPreviousMouseTarget; 883 else 884 current = fFocus; 885 886 if (current != NULL && (!fSuspendFocus || addedTokens)) { 887 _SendMessage(current->Messenger(), event, 888 kStandardImportance); 889 } 890 break; 891 } 892 893 if (keyboardEvent || pointerEvent) { 894 // send the event to the additional listeners 895 896 if (addedTokens) { 897 _RemoveTokens(event); 898 _UnsetFeedFocus(event); 899 } 900 if (pointerEvent) { 901 // this is added in the Desktop mouse processing 902 // but it's only intended for the focus view 903 event->RemoveName("_view_token"); 904 } 905 906 for (int32 i = fTargets.CountItems(); i-- > 0;) { 907 EventTarget* target = fTargets.ItemAt(i); 908 909 // We already sent the event to the all focus and last focus 910 // tokens 911 if (current == target || previous == target) 912 continue; 913 914 // Don't send the message if there are no tokens for this event 915 if (!_AddTokens(event, target, 916 keyboardEvent ? B_KEYBOARD_EVENTS : B_POINTER_EVENTS, 917 event->what == B_MOUSE_MOVED 918 ? fNextLatestMouseMoved : NULL)) 919 continue; 920 921 if (!_SendMessage(target->Messenger(), event, 922 event->what == B_MOUSE_MOVED 923 ? kMouseMovedImportance : kListenerImportance)) { 924 // the target doesn't seem to exist anymore, let's remove it 925 fTargets.RemoveItemAt(i); 926 } 927 } 928 929 if (event->what == B_MOUSE_UP && fLastButtons == 0) { 930 // no buttons are pressed anymore 931 fSuspendFocus = false; 932 _RemoveTemporaryListeners(); 933 if (fDraggingMessage) 934 _DeliverDragMessage(); 935 } 936 } 937 938 if (fNextLatestMouseMoved == event) 939 fNextLatestMouseMoved = NULL; 940 delete event; 941 } 942 943 // The loop quit, therefore no more events are coming from the input 944 // server, it must have died. Unset ourselves and notify the desktop. 945 fThread = -1; 946 // Needed to avoid problems with wait_for_thread in _Unset() 947 _Unset(); 948 949 if (fDesktop) 950 fDesktop->PostMessage(AS_EVENT_STREAM_CLOSED); 951 } 952 953 954 void 955 EventDispatcher::_CursorLoop() 956 { 957 BPoint where; 958 while (fStream->GetNextCursorPosition(where)) { 959 BAutolock _(fCursorLock); 960 961 if (fHWInterface != NULL) 962 fHWInterface->MoveCursorTo(where.x, where.y); 963 } 964 965 fCursorThread = -1; 966 } 967 968 969 /*static*/ 970 status_t 971 EventDispatcher::_event_looper(void* _dispatcher) 972 { 973 EventDispatcher* dispatcher = (EventDispatcher*)_dispatcher; 974 975 ETRACE(("Start event loop\n")); 976 dispatcher->_EventLoop(); 977 return B_OK; 978 } 979 980 981 /*static*/ 982 status_t 983 EventDispatcher::_cursor_looper(void* _dispatcher) 984 { 985 EventDispatcher* dispatcher = (EventDispatcher*)_dispatcher; 986 987 ETRACE(("Start cursor loop\n")); 988 dispatcher->_CursorLoop(); 989 return B_OK; 990 } 991