sw/qa/uitest/writer_tests/xwindow.py | 150 +++++++++++++++++++++++++++++++++++ toolkit/source/awt/vclxwindow.cxx | 84 +++++++++++-------- 2 files changed, 200 insertions(+), 34 deletions(-)
New commits: commit a2fcf51a77f4a37fb1c14f47bab450eea79a0dcb Author: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> AuthorDate: Wed Apr 10 11:21:32 2019 +0200 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Tue Apr 23 17:48:40 2019 +0200 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.mehrbr...@cib.de> Tested-by: Samuel Mehrbrodt <samuel.mehrbr...@cib.de> (cherry picked from commit 6f43902b12dd36fa2b69401065df198ef9ffdb09) Reviewed-on: https://gerrit.libreoffice.org/71139 Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Tested-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/sw/qa/uitest/writer_tests/xwindow.py b/sw/qa/uitest/writer_tests/xwindow.py index d63df73c69ea..428dd3723a05 100644 --- a/sw/qa/uitest/writer_tests/xwindow.py +++ b/sw/qa/uitest/writer_tests/xwindow.py @@ -43,15 +43,13 @@ class XMouseListenerExtended(unohelper.Base, XMouseListener): # is invoked when the mouse enters a window. @classmethod def mouseEntered(self, xMouseEvent): - global mouseEventsIntercepted - mouseEventsIntercepted += 1 + # doesn't work in UI tests return super(XMouseListenerExtended, self).mouseEntered(xMouseEvent) # is invoked when the mouse exits a window. @classmethod def mouseExited(self, xMouseEvent): - global mouseEventsIntercepted - mouseEventsIntercepted += 1 + # doesn't work in UI tests return super(XMouseListenerExtended, self).mouseExited(xMouseEvent) @@ -142,8 +140,8 @@ class XWindow(UITestCase): self.assertEqual(0, keymouseEventsIntercepted) global mouseEventsIntercepted - # Not expected 3 interceptions - self.assertEqual(0, mouseEventsIntercepted) + # mousePressed, mouseReleased and mouseEntered should be triggered + self.assertEqual(2, mouseEventsIntercepted) # close document self.ui_test.close_doc() diff --git a/toolkit/source/awt/vclxwindow.cxx b/toolkit/source/awt/vclxwindow.cxx index 6d89c13f3697..31438dfec9e2 100644 --- a/toolkit/source/awt/vclxwindow.cxx +++ b/toolkit/source/awt/vclxwindow.cxx @@ -704,50 +704,66 @@ void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) case VclEventId::WindowMouseMove: { 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 ) ); - bool const isEnter(pMouseEvt->IsEnterWindow()); - Callback aCallback = [ this, isEnter, aEvent ]() - { MouseListenerMultiplexer& rMouseListeners = this->mpImpl->getMouseListeners(); - isEnter - ? rMouseListeners.mouseEntered(aEvent) - : rMouseListeners.mouseExited(aEvent); }; - - ImplExecuteAsyncWithoutSolarLock( aCallback ); - } + VCLXWindow* pXWindow = pWin->GetWindowPeer(); + if (!pXWindow || pXWindow->mpImpl->getMouseListeners().getLength() == 0) + { + pWin = pWin->GetWindow(GetWindowType::RealParent); + continue; + } + awt::MouseEvent aEvent(VCLUnoHelper::createMouseEvent(*pMouseEvt, *pXWindow)); - if ( mpImpl->getMouseMotionListeners().getLength() && !pMouseEvt->IsEnterWindow() && !pMouseEvt->IsLeaveWindow() ) - { - awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *pMouseEvt, *this ) ); - aEvent.ClickCount = 0; - if ( pMouseEvt->GetMode() & MouseEventModifiers::SIMPLEMOVE ) - mpImpl->getMouseMotionListeners().mouseMoved( aEvent ); + 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 - mpImpl->getMouseMotionListeners().mouseDragged( aEvent ); + { + aEvent.ClickCount = 0; + MouseMotionListenerMultiplexer& rMouseListeners + = pXWindow->mpImpl->getMouseMotionListeners(); + if (pMouseEvt->GetMode() & MouseEventModifiers::SIMPLEMOVE) + rMouseListeners.mouseMoved(aEvent); + else + rMouseListeners.mouseDragged(aEvent); + } + + // Next window (parent) + pWin = pWin->GetWindow(GetWindowType::RealParent); } } break; 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: { - if ( mpImpl->getMouseListeners().getLength() ) + VclPtr<vcl::Window> pWin = GetWindow(); + while (pWin) { - awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *static_cast<MouseEvent*>(rVclWindowEvent.GetData()), *this ) ); - - Callback aCallback = [ this, aEvent ]() - { this->mpImpl->getMouseListeners().mouseReleased( aEvent ); }; - ImplExecuteAsyncWithoutSolarLock( aCallback ); + 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); + + // Next window (parent) + pWin = pWin->GetWindow(GetWindowType::RealParent); } } break; commit dcf4f3804d394df5c6184e6d2487c5517ba9e7cc Author: Serge Krot <serge.k...@cib.de> AuthorDate: Thu Jan 24 10:25:16 2019 +0100 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Tue Apr 23 17:48:27 2019 +0200 tdf#122920 uitest: XMouseListener is not called for top most window Reviewed-on: https://gerrit.libreoffice.org/66856 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> (cherry picked from commit 5723d303a44597cdb2ea242cf3fb0ac0e8c15b83) Change-Id: Ia6f79e50b93004b8bf896e24450ce8666b303037 Reviewed-on: https://gerrit.libreoffice.org/71138 Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Tested-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/sw/qa/uitest/writer_tests/xwindow.py b/sw/qa/uitest/writer_tests/xwindow.py new file mode 100644 index 000000000000..d63df73c69ea --- /dev/null +++ b/sw/qa/uitest/writer_tests/xwindow.py @@ -0,0 +1,152 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +from uitest.framework import UITestCase +import unittest +import unohelper +from org.libreoffice.unotest import UnoInProcess +from com.sun.star.awt import XMouseListener +from com.sun.star.awt import XToolkitRobot +from com.sun.star.awt import MouseEvent +from com.sun.star.awt import KeyEvent +from com.sun.star.awt import XKeyListener + + +mouseListenerCount = 0 +mouseEventsIntercepted = 0 +keymouseEventsIntercepted = 0 + + +class XMouseListenerExtended(unohelper.Base, XMouseListener): + def __init__(self): + global mouseListenerCount + mouseListenerCount += 1 + super().__init__() + + # is invoked when a mouse button has been pressed on a window. + @classmethod + def mousePressed(self, xMouseEvent): + global mouseEventsIntercepted + mouseEventsIntercepted += 1 + return super(XMouseListenerExtended, self).mousePressed(xMouseEvent) + + # is invoked when a mouse button has been released on a window. + @classmethod + def mouseReleased(self, xMouseEvent): + global mouseEventsIntercepted + mouseEventsIntercepted += 1 + return super(XMouseListenerExtended, self).mouseReleased(xMouseEvent) + + # is invoked when the mouse enters a window. + @classmethod + def mouseEntered(self, xMouseEvent): + global mouseEventsIntercepted + mouseEventsIntercepted += 1 + return super(XMouseListenerExtended, self).mouseEntered(xMouseEvent) + + # is invoked when the mouse exits a window. + @classmethod + def mouseExited(self, xMouseEvent): + global mouseEventsIntercepted + mouseEventsIntercepted += 1 + return super(XMouseListenerExtended, self).mouseExited(xMouseEvent) + + +class XKeyListenerExtended(unohelper.Base, XKeyListener): + # is invoked when a key has been pressed + @classmethod + def keyPressed(self, xKeyEvent): + global keymouseEventsIntercepted + keymouseEventsIntercepted += 1 + return super(XKeyListenerExtended, self).keyPressed(xKeyEvent) + + # is invoked when a key has been released + @classmethod + def keyReleased(self, xKeyEvent): + global keymouseEventsIntercepted + keymouseEventsIntercepted += 1 + return super(XKeyListenerExtended, self).keyReleased(xKeyEvent) + +# registered mouse/key listeners for top window +# do not receive any mouse/key events while +# everything is passed only to focused child window +# where we have no any registered mouse/key listeners +class XWindow(UITestCase): + def test_listeners(self): + global mouseListenerCount + + writer_doc = self.ui_test.create_doc_in_start_center("writer") + xDoc = self.ui_test.get_component() + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + # create new mouse listener + xFrame = xDoc.getCurrentController().getFrame() + self.assertIsNotNone(xFrame) + xWindow = xFrame.getContainerWindow() + self.assertIsNotNone(xWindow) + + # add new mouse listener + xMouseListener = XMouseListenerExtended() + self.assertIsNotNone(xMouseListener) + xWindow.addMouseListener(xMouseListener) + self.assertEqual(1, mouseListenerCount) + + # add new key listener + xKeyListener = XKeyListenerExtended() + self.assertIsNotNone(xKeyListener) + xWindow.addKeyListener(xKeyListener) + + # create dummy mouse event + xMouseEvent = MouseEvent() + xMouseEvent.Modifiers = 0 + xMouseEvent.Buttons = 0 + xMouseEvent.X = 10 + xMouseEvent.Y = 10 + xMouseEvent.ClickCount = 1 + xMouseEvent.PopupTrigger = False + xMouseEvent.Source = xWindow + + # send mouse event + xToolkitRobot = xWindow.getToolkit() + self.assertIsNotNone(xToolkitRobot) + + xToolkitRobot.mousePress(xMouseEvent) + xToolkitRobot.mouseMove(xMouseEvent) + xToolkitRobot.mouseRelease(xMouseEvent) + + # send key press event + xKeyEvent = KeyEvent() + xKeyEvent.Modifiers = 0 + xKeyEvent.KeyCode = 70 + xKeyEvent.KeyChar = 70 + xKeyEvent.Source = xWindow + + xToolkitRobot.keyPress(xKeyEvent) + xToolkitRobot.keyRelease(xKeyEvent) + + # remove moue listener + xWindow.removeMouseListener(xMouseListener) + self.assertEqual(1, mouseListenerCount) + del xMouseListener + + # remove key listener + xWindow.removeKeyListener(xKeyListener) + del xKeyListener + + global keymouseEventsIntercepted + # Not expected 2 interceptions + self.assertEqual(0, keymouseEventsIntercepted) + + global mouseEventsIntercepted + # Not expected 3 interceptions + self.assertEqual(0, mouseEventsIntercepted) + + # close document + self.ui_test.close_doc() + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits