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 <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 gBitmapManager->DeleteBitmap(bitmap); 610 return; 611 } 612 613 if (fDragBitmap != bitmap) { 614 if (fDragBitmap) 615 gBitmapManager->DeleteBitmap(fDragBitmap); 616 fDragBitmap = bitmap; 617 618 if (fDragBitmap != NULL) 619 fDragBitmap->Acquire(); 620 } 621 622 fHWInterface->SetDragBitmap(bitmap, offsetFromCursor); 623 624 fDragMessage = message; 625 fDraggingMessage = true; 626 fDragOffset = offsetFromCursor; 627 } 628 629 630 void 631 EventDispatcher::SetDesktop(Desktop* desktop) 632 { 633 fDesktop = desktop; 634 } 635 636 637 // #pragma mark - Message methods 638 639 640 /*! 641 \brief Sends \a message to the provided \a messenger. 642 643 TODO: the following feature is not yet implemented: 644 If the message could not be delivered immediately, it is included 645 in a waiting message queue with a fixed length - the least important 646 messages are removed first when that gets full. 647 648 Returns "false" if the target port does not exist anymore, "true" 649 if it doesn't. 650 */ 651 bool 652 EventDispatcher::_SendMessage(BMessenger& messenger, BMessage* message, 653 float importance) 654 { 655 // TODO: add failed messages to a queue, and start dropping them by importance 656 // (and use the same mechanism in ServerWindow::SendMessageToClient()) 657 658 status_t status = messenger.SendMessage(message, (BHandler*)NULL, 0); 659 if (status != B_OK) { 660 printf("EventDispatcher: failed to send message '%.4s' to target: %s\n", 661 (char*)&message->what, strerror(status)); 662 } 663 664 if (status == B_BAD_PORT_ID) { 665 // the target port is gone 666 return false; 667 } 668 669 return true; 670 } 671 672 673 bool 674 EventDispatcher::_AddTokens(BMessage* message, EventTarget* target, 675 uint32 eventMask, BMessage* nextMouseMoved, int32* _viewToken) 676 { 677 _RemoveTokens(message); 678 679 int32 count = target->CountListeners(); 680 int32 added = 0; 681 682 for (int32 i = 0; i < count; i++) { 683 event_listener* listener = target->ListenerAt(i); 684 if ((listener->EffectiveEventMask() & eventMask) == 0) 685 continue; 686 687 if (nextMouseMoved != NULL && message->what == B_MOUSE_MOVED 688 && (listener->EffectiveOptions() & B_NO_POINTER_HISTORY) != 0 689 && message != nextMouseMoved 690 && _viewToken != NULL) { 691 if (listener->token == *_viewToken) { 692 // focus view doesn't want to get pointer history 693 *_viewToken = B_NULL_TOKEN; 694 } 695 continue; 696 } 697 698 ETRACE((" add token %ld\n", listener->token)); 699 700 if (message->AddInt32(kTokenName, listener->token) == B_OK) 701 added++; 702 } 703 704 return added != 0; 705 } 706 707 708 void 709 EventDispatcher::_RemoveTokens(BMessage* message) 710 { 711 message->RemoveName(kTokenName); 712 } 713 714 715 void 716 EventDispatcher::_SetFeedFocus(BMessage* message) 717 { 718 if (message->ReplaceBool("_feed_focus", true) != B_OK) 719 message->AddBool("_feed_focus", true); 720 } 721 722 723 void 724 EventDispatcher::_UnsetFeedFocus(BMessage* message) 725 { 726 message->RemoveName("_feed_focus"); 727 } 728 729 730 void 731 EventDispatcher::_DeliverDragMessage() 732 { 733 ETRACE(("EventDispatcher::_DeliverDragMessage()\n")); 734 735 if (fDraggingMessage && fPreviousMouseTarget != NULL) { 736 BMessage::Private(fDragMessage).SetWasDropped(true); 737 fDragMessage.RemoveName("_original_what"); 738 fDragMessage.AddInt32("_original_what", fDragMessage.what); 739 fDragMessage.AddPoint("_drop_point_", fLastCursorPosition); 740 fDragMessage.AddPoint("_drop_offset_", fDragOffset); 741 fDragMessage.what = _MESSAGE_DROPPED_; 742 743 _SendMessage(fPreviousMouseTarget->Messenger(), 744 &fDragMessage, 100.0); 745 } 746 747 fDragMessage.MakeEmpty(); 748 fDragMessage.what = 0; 749 fDraggingMessage = false; 750 751 fHWInterface->SetDragBitmap(NULL, B_ORIGIN); 752 gBitmapManager->DeleteBitmap(fDragBitmap); 753 fDragBitmap = NULL; 754 } 755 756 757 // #pragma mark - Event loops 758 759 760 void 761 EventDispatcher::_EventLoop() 762 { 763 BMessage* event; 764 while (fStream->GetNextEvent(&event)) { 765 BAutolock _(this); 766 fLastUpdate = system_time(); 767 768 EventTarget* current = NULL; 769 EventTarget* previous = NULL; 770 bool pointerEvent = false; 771 bool keyboardEvent = false; 772 bool addedTokens = false; 773 774 switch (event->what) { 775 case kFakeMouseMoved: 776 _SendFakeMouseMoved(event); 777 break; 778 case B_MOUSE_MOVED: 779 { 780 BPoint where; 781 if (event->FindPoint("where", &where) == B_OK) 782 fLastCursorPosition = where; 783 784 if (fDraggingMessage) 785 event->AddMessage("be:drag_message", &fDragMessage); 786 787 if (!HasCursorThread()) { 788 // There is no cursor thread, we need to move the cursor 789 // ourselves 790 BAutolock _(fCursorLock); 791 792 if (fHWInterface != NULL) { 793 fHWInterface->MoveCursorTo(fLastCursorPosition.x, 794 fLastCursorPosition.y); 795 } 796 } 797 798 // This is for B_NO_POINTER_HISTORY - we always want the 799 // latest mouse moved event in the queue only 800 if (fNextLatestMouseMoved == NULL) 801 fNextLatestMouseMoved = fStream->PeekLatestMouseMoved(); 802 else if (fNextLatestMouseMoved != event) { 803 // Drop older mouse moved messages if the server is lagging 804 // too much (if the message is older than 100 msecs) 805 bigtime_t eventTime; 806 if (event->FindInt64("when", &eventTime) == B_OK) { 807 if (system_time() - eventTime > 100000) 808 break; 809 } 810 } 811 812 // supposed to fall through 813 } 814 case B_MOUSE_DOWN: 815 case B_MOUSE_UP: 816 { 817 #ifdef TRACE_EVENTS 818 if (event->what != B_MOUSE_MOVED) 819 printf("mouse up/down event, previous target = %p\n", fPreviousMouseTarget); 820 #endif 821 pointerEvent = true; 822 823 if (fMouseFilter == NULL) 824 break; 825 826 EventTarget* mouseTarget = fPreviousMouseTarget; 827 int32 viewToken = B_NULL_TOKEN; 828 if (fMouseFilter->Filter(event, &mouseTarget, &viewToken, 829 fNextLatestMouseMoved) == B_SKIP_MESSAGE) { 830 // this is a work-around if the wrong B_MOUSE_UP 831 // event is filtered out 832 if (event->what == B_MOUSE_UP 833 && event->FindInt32("buttons") == 0) { 834 fSuspendFocus = false; 835 _RemoveTemporaryListeners(); 836 } 837 break; 838 } 839 840 int32 buttons; 841 if (event->FindInt32("buttons", &buttons) == B_OK) 842 fLastButtons = buttons; 843 else 844 fLastButtons = 0; 845 846 // The "where" field will be filled in by the receiver 847 // (it's supposed to be expressed in local window coordinates) 848 event->RemoveName("where"); 849 event->AddPoint("screen_where", fLastCursorPosition); 850 851 if (event->what == B_MOUSE_MOVED 852 && fPreviousMouseTarget != NULL 853 && mouseTarget != fPreviousMouseTarget) { 854 // Target has changed, we need to notify the previous target 855 // that the mouse has exited its views 856 addedTokens = _AddTokens(event, fPreviousMouseTarget, 857 B_POINTER_EVENTS); 858 if (addedTokens) 859 _SetFeedFocus(event); 860 861 _SendMessage(fPreviousMouseTarget->Messenger(), event, 862 kMouseTransitImportance); 863 previous = fPreviousMouseTarget; 864 } 865 866 current = fPreviousMouseTarget = mouseTarget; 867 868 if (current != NULL) { 869 int32 focusView = viewToken; 870 addedTokens |= _AddTokens(event, current, B_POINTER_EVENTS, 871 fNextLatestMouseMoved, &focusView); 872 873 bool noPointerHistoryFocus = focusView != viewToken; 874 875 if (viewToken != B_NULL_TOKEN) 876 event->AddInt32("_view_token", viewToken); 877 878 if (addedTokens && !noPointerHistoryFocus) 879 _SetFeedFocus(event); 880 else if (noPointerHistoryFocus) { 881 // No tokens were added or the focus shouldn't get a 882 // mouse moved 883 break; 884 } 885 886 _SendMessage(current->Messenger(), event, 887 event->what == B_MOUSE_MOVED 888 ? kMouseMovedImportance : kStandardImportance); 889 } 890 break; 891 } 892 893 case B_KEY_DOWN: 894 case B_KEY_UP: 895 case B_UNMAPPED_KEY_DOWN: 896 case B_UNMAPPED_KEY_UP: 897 case B_MODIFIERS_CHANGED: 898 case B_INPUT_METHOD_EVENT: 899 ETRACE(("key event, focus = %p\n", fFocus)); 900 901 if (fKeyboardFilter != NULL 902 && fKeyboardFilter->Filter(event, &fFocus) == B_SKIP_MESSAGE) 903 break; 904 905 keyboardEvent = true; 906 907 if (fFocus != NULL && _AddTokens(event, fFocus, 908 B_KEYBOARD_EVENTS)) { 909 // if tokens were added, we need to explicetly suspend 910 // focus in the event - if not, the event is simply not 911 // forwarded to the target 912 addedTokens = true; 913 914 if (!fSuspendFocus) 915 _SetFeedFocus(event); 916 } 917 918 // supposed to fall through 919 920 default: 921 // TODO: the keyboard filter sets the focus - ie. no other 922 // focus messages that go through the event dispatcher can 923 // go through. 924 if (event->what == B_MOUSE_WHEEL_CHANGED) 925 current = fPreviousMouseTarget; 926 else 927 current = fFocus; 928 929 if (current != NULL && (!fSuspendFocus || addedTokens)) { 930 _SendMessage(current->Messenger(), event, 931 kStandardImportance); 932 } 933 break; 934 } 935 936 if (keyboardEvent || pointerEvent) { 937 // send the event to the additional listeners 938 939 if (addedTokens) { 940 _RemoveTokens(event); 941 _UnsetFeedFocus(event); 942 } 943 if (pointerEvent) { 944 // this is added in the Desktop mouse processing 945 // but it's only intended for the focus view 946 event->RemoveName("_view_token"); 947 } 948 949 for (int32 i = fTargets.CountItems(); i-- > 0;) { 950 EventTarget* target = fTargets.ItemAt(i); 951 952 // We already sent the event to the all focus and last focus 953 // tokens 954 if (current == target || previous == target) 955 continue; 956 957 // Don't send the message if there are no tokens for this event 958 if (!_AddTokens(event, target, 959 keyboardEvent ? B_KEYBOARD_EVENTS : B_POINTER_EVENTS, 960 event->what == B_MOUSE_MOVED 961 ? fNextLatestMouseMoved : NULL)) 962 continue; 963 964 if (!_SendMessage(target->Messenger(), event, 965 event->what == B_MOUSE_MOVED 966 ? kMouseMovedImportance : kListenerImportance)) { 967 // the target doesn't seem to exist anymore, let's remove it 968 fTargets.RemoveItemAt(i); 969 } 970 } 971 972 if (event->what == B_MOUSE_UP && fLastButtons == 0) { 973 // no buttons are pressed anymore 974 fSuspendFocus = false; 975 _RemoveTemporaryListeners(); 976 if (fDraggingMessage) 977 _DeliverDragMessage(); 978 } 979 } 980 981 if (fNextLatestMouseMoved == event) 982 fNextLatestMouseMoved = NULL; 983 delete event; 984 } 985 986 // The loop quit, therefore no more events are coming from the input 987 // server, it must have died. Unset ourselves and notify the desktop. 988 fThread = -1; 989 // Needed to avoid problems with wait_for_thread in _Unset() 990 _Unset(); 991 992 if (fDesktop) 993 fDesktop->PostMessage(AS_EVENT_STREAM_CLOSED); 994 } 995 996 997 void 998 EventDispatcher::_CursorLoop() 999 { 1000 BPoint where; 1001 while (fStream->GetNextCursorPosition(where)) { 1002 BAutolock _(fCursorLock); 1003 1004 if (fHWInterface != NULL) 1005 fHWInterface->MoveCursorTo(where.x, where.y); 1006 } 1007 1008 fCursorThread = -1; 1009 } 1010 1011 1012 /*static*/ 1013 status_t 1014 EventDispatcher::_event_looper(void* _dispatcher) 1015 { 1016 EventDispatcher* dispatcher = (EventDispatcher*)_dispatcher; 1017 1018 ETRACE(("Start event loop\n")); 1019 dispatcher->_EventLoop(); 1020 return B_OK; 1021 } 1022 1023 1024 /*static*/ 1025 status_t 1026 EventDispatcher::_cursor_looper(void* _dispatcher) 1027 { 1028 EventDispatcher* dispatcher = (EventDispatcher*)_dispatcher; 1029 1030 ETRACE(("Start cursor loop\n")); 1031 dispatcher->_CursorLoop(); 1032 return B_OK; 1033 } 1034