tdf#122920 Send UNO mouse events to parent window listeners as well
When user registers a mouse listener to a window, he expects to receive mouse events when a user clicks in somewhere in that window, even if it's technically a widget inside that window Change-Id: Ie6d3f8b140e4a5b516051014282b43775ecec59e Reviewed-on: https://gerrit.libreoffice.org/70512 Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt@cib.de> Tested-by: Samuel Mehrbrodt <Samuel.Mehrbrodt@cib.de>
This commit is contained in:
@@ -43,15 +43,13 @@ class XMouseListenerExtended(unohelper.Base, XMouseListener):
|
|||||||
# is invoked when the mouse enters a window.
|
# is invoked when the mouse enters a window.
|
||||||
@classmethod
|
@classmethod
|
||||||
def mouseEntered(self, xMouseEvent):
|
def mouseEntered(self, xMouseEvent):
|
||||||
global mouseEventsIntercepted
|
# doesn't work in UI tests
|
||||||
mouseEventsIntercepted += 1
|
|
||||||
return super(XMouseListenerExtended, self).mouseEntered(xMouseEvent)
|
return super(XMouseListenerExtended, self).mouseEntered(xMouseEvent)
|
||||||
|
|
||||||
# is invoked when the mouse exits a window.
|
# is invoked when the mouse exits a window.
|
||||||
@classmethod
|
@classmethod
|
||||||
def mouseExited(self, xMouseEvent):
|
def mouseExited(self, xMouseEvent):
|
||||||
global mouseEventsIntercepted
|
# doesn't work in UI tests
|
||||||
mouseEventsIntercepted += 1
|
|
||||||
return super(XMouseListenerExtended, self).mouseExited(xMouseEvent)
|
return super(XMouseListenerExtended, self).mouseExited(xMouseEvent)
|
||||||
|
|
||||||
|
|
||||||
@@ -142,8 +140,8 @@ class XWindow(UITestCase):
|
|||||||
self.assertEqual(0, keymouseEventsIntercepted)
|
self.assertEqual(0, keymouseEventsIntercepted)
|
||||||
|
|
||||||
global mouseEventsIntercepted
|
global mouseEventsIntercepted
|
||||||
# Not expected 3 interceptions
|
# mousePressed, mouseReleased and mouseEntered should be triggered
|
||||||
self.assertEqual(0, mouseEventsIntercepted)
|
self.assertEqual(2, mouseEventsIntercepted)
|
||||||
|
|
||||||
# close document
|
# close document
|
||||||
self.ui_test.close_doc()
|
self.ui_test.close_doc()
|
||||||
|
@@ -703,50 +703,66 @@ void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
|
|||||||
case VclEventId::WindowMouseMove:
|
case VclEventId::WindowMouseMove:
|
||||||
{
|
{
|
||||||
MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rVclWindowEvent.GetData());
|
MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rVclWindowEvent.GetData());
|
||||||
if ( mpImpl->getMouseListeners().getLength() && ( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() ) )
|
VclPtr<vcl::Window> pWin = GetWindow();
|
||||||
|
while (pWin)
|
||||||
{
|
{
|
||||||
awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *pMouseEvt, *this ) );
|
VCLXWindow* pXWindow = pWin->GetWindowPeer();
|
||||||
bool const isEnter(pMouseEvt->IsEnterWindow());
|
if (!pXWindow || pXWindow->mpImpl->getMouseListeners().getLength() == 0)
|
||||||
Callback aCallback = [ this, isEnter, aEvent ]()
|
{
|
||||||
{ MouseListenerMultiplexer& rMouseListeners = this->mpImpl->getMouseListeners();
|
pWin = pWin->GetWindow(GetWindowType::RealParent);
|
||||||
isEnter
|
continue;
|
||||||
? rMouseListeners.mouseEntered(aEvent)
|
}
|
||||||
: rMouseListeners.mouseExited(aEvent); };
|
awt::MouseEvent aEvent(VCLUnoHelper::createMouseEvent(*pMouseEvt, *pXWindow));
|
||||||
|
|
||||||
ImplExecuteAsyncWithoutSolarLock( aCallback );
|
if (pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow())
|
||||||
|
{
|
||||||
|
bool const isEnter(pMouseEvt->IsEnterWindow());
|
||||||
|
Callback aCallback = [pXWindow, isEnter, aEvent]() {
|
||||||
|
isEnter ? pXWindow->mpImpl->getMouseListeners().mouseEntered(aEvent)
|
||||||
|
: pXWindow->mpImpl->getMouseListeners().mouseExited(aEvent);
|
||||||
|
};
|
||||||
|
ImplExecuteAsyncWithoutSolarLock(aCallback);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aEvent.ClickCount = 0;
|
||||||
|
MouseMotionListenerMultiplexer& rMouseListeners
|
||||||
|
= pXWindow->mpImpl->getMouseMotionListeners();
|
||||||
|
if (pMouseEvt->GetMode() & MouseEventModifiers::SIMPLEMOVE)
|
||||||
|
rMouseListeners.mouseMoved(aEvent);
|
||||||
|
else
|
||||||
|
rMouseListeners.mouseDragged(aEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mpImpl->getMouseMotionListeners().getLength() && !pMouseEvt->IsEnterWindow() && !pMouseEvt->IsLeaveWindow() )
|
// Next window (parent)
|
||||||
{
|
pWin = pWin->GetWindow(GetWindowType::RealParent);
|
||||||
awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *pMouseEvt, *this ) );
|
|
||||||
aEvent.ClickCount = 0;
|
|
||||||
if ( pMouseEvt->GetMode() & MouseEventModifiers::SIMPLEMOVE )
|
|
||||||
mpImpl->getMouseMotionListeners().mouseMoved( aEvent );
|
|
||||||
else
|
|
||||||
mpImpl->getMouseMotionListeners().mouseDragged( aEvent );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VclEventId::WindowMouseButtonDown:
|
case VclEventId::WindowMouseButtonDown:
|
||||||
{
|
|
||||||
if ( mpImpl->getMouseListeners().getLength() )
|
|
||||||
{
|
|
||||||
awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *static_cast<MouseEvent*>(rVclWindowEvent.GetData()), *this ) );
|
|
||||||
Callback aCallback = [ this, aEvent ]()
|
|
||||||
{ this->mpImpl->getMouseListeners().mousePressed( aEvent ); };
|
|
||||||
ImplExecuteAsyncWithoutSolarLock( aCallback );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VclEventId::WindowMouseButtonUp:
|
case VclEventId::WindowMouseButtonUp:
|
||||||
{
|
{
|
||||||
if ( mpImpl->getMouseListeners().getLength() )
|
VclPtr<vcl::Window> pWin = GetWindow();
|
||||||
|
while (pWin)
|
||||||
{
|
{
|
||||||
awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *static_cast<MouseEvent*>(rVclWindowEvent.GetData()), *this ) );
|
VCLXWindow* pXWindow = pWin->GetWindowPeer();
|
||||||
|
if (!pXWindow || pXWindow->mpImpl->getMouseListeners().getLength() == 0)
|
||||||
|
{
|
||||||
|
pWin = pWin->GetWindow(GetWindowType::RealParent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rVclWindowEvent.GetData());
|
||||||
|
awt::MouseEvent aEvent(VCLUnoHelper::createMouseEvent(*pMouseEvt, *pXWindow));
|
||||||
|
VclEventId eventId = rVclWindowEvent.GetId();
|
||||||
|
Callback aCallback = [pXWindow, aEvent, eventId]() {
|
||||||
|
eventId == VclEventId::WindowMouseButtonDown
|
||||||
|
? pXWindow->mpImpl->getMouseListeners().mousePressed(aEvent)
|
||||||
|
: pXWindow->mpImpl->getMouseListeners().mouseReleased(aEvent);
|
||||||
|
};
|
||||||
|
ImplExecuteAsyncWithoutSolarLock(aCallback);
|
||||||
|
|
||||||
Callback aCallback = [ this, aEvent ]()
|
// Next window (parent)
|
||||||
{ this->mpImpl->getMouseListeners().mouseReleased( aEvent ); };
|
pWin = pWin->GetWindow(GetWindowType::RealParent);
|
||||||
ImplExecuteAsyncWithoutSolarLock( aCallback );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user