From a1a04a47421178983ce94aa6050922b23f57cbff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 1 Apr 2006 15:43:25 +0000 Subject: [PATCH] * A fake B_MOUSE_MOVED message is now send on workspace change, and when a window is closed, too (only happened when a new window was shown before). This is done via the new Desktop::_SendFakeMouseMoved() method. This fixes bug #342. * The MouseFilter now always sets Desktop::fWindowUnderMouse, so that one can differentiate between no window under mouse, and decorator under mouse. * EventDispatcher::SendFakeMouseMoved() now expects a BMessenger instead of an EventTarget as target - this guarantees that it can safely be called with any window now (instead of only the current window). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16953 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 93 ++++++++++++++++++++--------- src/servers/app/Desktop.h | 1 + src/servers/app/EventDispatcher.cpp | 4 +- src/servers/app/EventDispatcher.h | 2 +- 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index cc5f8c1127..bae1ed1436 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -218,6 +218,8 @@ MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken, if (!fDesktop->LockAllWindows()) return B_DISPATCH_MESSAGE; + int32 viewToken = B_NULL_TOKEN; + WindowLayer* window = fDesktop->MouseEventWindow(); if (window == NULL) window = fDesktop->WindowAt(where); @@ -226,30 +228,33 @@ MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken, // dispatch event in the window layers switch (message->what) { case B_MOUSE_DOWN: - window->MouseDown(message, where, _viewToken); + window->MouseDown(message, where, &viewToken); break; case B_MOUSE_UP: - window->MouseUp(message, where, _viewToken); + window->MouseUp(message, where, &viewToken); fDesktop->SetMouseEventWindow(NULL); break; case B_MOUSE_MOVED: - window->MouseMoved(message, where, _viewToken, + window->MouseMoved(message, where, &viewToken, latestMouseMoved == NULL || latestMouseMoved == message); break; } - if (*_viewToken != B_NULL_TOKEN) { - fDesktop->SetViewUnderMouse(window, *_viewToken); + if (viewToken != B_NULL_TOKEN) { + fDesktop->SetViewUnderMouse(window, viewToken); + + *_viewToken = viewToken; *_target = &window->EventTarget(); - } else { - fDesktop->SetViewUnderMouse(NULL, B_NULL_TOKEN); - *_target = NULL; } - } else { - fDesktop->SetViewUnderMouse(NULL, B_NULL_TOKEN); + } + + if (window == NULL || viewToken == B_NULL_TOKEN) { + // mouse is not over a window or over a decorator + fDesktop->SetViewUnderMouse(window, B_NULL_TOKEN); fDesktop->SetCursor(NULL); + *_target = NULL; } @@ -784,6 +789,8 @@ Desktop::SetWorkspace(int32 index) MarkDirty(dirty); UnlockAllWindows(); + + _SendFakeMouseMoved(); } @@ -980,6 +987,51 @@ Desktop::_WindowChanged(WindowLayer* window) } +/*! + \brief Sends a fake B_MOUSE_MOVED event to the window under the mouse, + and also updates the current view under the mouse. + + This has only to be done in case the view changed without user interaction, + ie. because of a workspace change or a closing window. + + Windows must not be locked when calling this method. +*/ +void +Desktop::_SendFakeMouseMoved(WindowLayer* window) +{ + BPoint where; + int32 buttons; + EventDispatcher().GetMouse(where, buttons); + + int32 viewToken = B_NULL_TOKEN; + BMessenger target; + + LockAllWindows(); + + if (window == NULL) + window = MouseEventWindow(); + if (window == NULL) + window = WindowAt(where); + + if (window != NULL) { + BMessage message; + window->MouseMoved(&message, where, &viewToken, true); + } + + if (viewToken != B_NULL_TOKEN) + SetViewUnderMouse(window, viewToken); + else { + SetViewUnderMouse(NULL, B_NULL_TOKEN); + SetCursor(NULL); + } + + UnlockAllWindows(); + + if (viewToken != B_NULL_TOKEN) + EventDispatcher().SendFakeMouseMoved(target, viewToken); +} + + void Desktop::SetFocusWindow(WindowLayer* focus) { @@ -1245,23 +1297,7 @@ Desktop::ShowWindow(WindowLayer* window) // we'll send a fake mouse moved message to the window, so that // it knows the mouse is over it. - BPoint where; - int32 buttons; - EventDispatcher().GetMouse(where, buttons); - - int32 viewToken = B_NULL_TOKEN; - - LockAllWindows(); - - if (WindowAt(where) == window) { - ViewLayer* view = window->ViewAt(where); - if (view != NULL) - viewToken = view->Token(); - } - UnlockAllWindows(); - - if (viewToken != B_NULL_TOKEN) - EventDispatcher().SendFakeMouseMoved(window->EventTarget(), viewToken); + _SendFakeMouseMoved(window); } @@ -1294,6 +1330,9 @@ Desktop::HideWindow(WindowLayer* window) fWorkspacesLayer = NULL; UnlockAllWindows(); + + if (window == fWindowUnderMouse) + _SendFakeMouseMoved(); } diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 7c6171034b..d49c04ad70 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -184,6 +184,7 @@ class Desktop : public MessageLooper, public ScreenOwner { void _BringWindowsToFront(WindowList& windows, int32 list, bool wereVisible); status_t _ActivateApp(team_id team); + void _SendFakeMouseMoved(WindowLayer* window = NULL); void _RebuildClippingForAllWindows(BRegion& stillAvailableOnScreen); void _TriggerWindowRedrawing(BRegion& newDirtyRegion); diff --git a/src/servers/app/EventDispatcher.cpp b/src/servers/app/EventDispatcher.cpp index 5826bbdb9d..a079155f6d 100644 --- a/src/servers/app/EventDispatcher.cpp +++ b/src/servers/app/EventDispatcher.cpp @@ -466,7 +466,7 @@ EventDispatcher::GetMouse(BPoint& where, int32& buttons) void -EventDispatcher::SendFakeMouseMoved(EventTarget& target, int32 viewToken) +EventDispatcher::SendFakeMouseMoved(BMessenger& target, int32 viewToken) { BAutolock _(this); @@ -482,7 +482,7 @@ EventDispatcher::SendFakeMouseMoved(EventTarget& target, int32 viewToken) moved.AddMessage("be:drag_message", &fDragMessage); } - _SendMessage(target.Messenger(), &moved, kMouseTransitImportance); + _SendMessage(target, &moved, kMouseTransitImportance); } diff --git a/src/servers/app/EventDispatcher.h b/src/servers/app/EventDispatcher.h index 4f1c37c272..0224dc090b 100644 --- a/src/servers/app/EventDispatcher.h +++ b/src/servers/app/EventDispatcher.h @@ -80,7 +80,7 @@ class EventDispatcher : public BLocker { void SetKeyboardFilter(EventFilter* filter); void GetMouse(BPoint& where, int32& buttons); - void SendFakeMouseMoved(EventTarget& target, int32 viewToken); + void SendFakeMouseMoved(BMessenger& target, int32 viewToken); bool HasCursorThread(); void SetHWInterface(HWInterface* interface);