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