* 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
This commit is contained in:
Axel Dörfler 2006-04-01 15:43:25 +00:00
parent 4436fae24d
commit a1a04a4742
4 changed files with 70 additions and 30 deletions

View File

@ -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();
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);