forms/qa/unoapi/forms_2.sce | 2 sw/qa/uitest/writer_tests/xwindow.py | 106 +++++++++++++++++++++++------------ toolkit/source/awt/vclxwindow.cxx | 33 +++++----- vcl/source/window/event.cxx | 6 + 4 files changed, 95 insertions(+), 52 deletions(-)
New commits: commit 3b137aaaa1232f0f22730898fcfd1112f68af1bf Author: Samuel Mehrbrodt <[email protected]> AuthorDate: Thu Jan 24 10:25:16 2019 +0100 Commit: Thorsten Behrens <[email protected]> CommitDate: Thu May 23 20:48:40 2019 +0200 tdf#122920 Send UNO mouse/key events to parent window listeners as well This is a squashed commit consisting of: Wait for async events to be delivered Follow-up fix for 6f43902b12dd36fa2b69401065df198ef9ffdb09 Also remove calling to super class (doesn't work and those methods return void anyway) Reviewed-on: https://gerrit.libreoffice.org/70878 Reviewed-by: Samuel Mehrbrodt <[email protected]> Tested-by: Samuel Mehrbrodt <[email protected]> (cherry picked from commit 0fb575b34d039f7c732820467b6db6f8cebd485d) tdf#125170 Deliver mouse events also when clicking into document content Event listeners are added once VCLXWindow::SetWindow is called. This never happened for the document content window. So we need to call Window::GetComponentInterface which will create an XWindowPeer and then call UnoWrapper::SetWindowInterface which calls VCLXWindow::SetWindow. After that, event listeners are registered so that we can deliver events. Reviewed-on: https://gerrit.libreoffice.org/71948 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <[email protected]> (cherry picked from commit f9905401d8cf2d73576231ebd84cfa5f4f73bcac) More precisely count different event types in xwindow.py Reviewed-on: https://gerrit.libreoffice.org/72426 Reviewed-by: Stephan Bergmann <[email protected]> Tested-by: Stephan Bergmann <[email protected]> (cherry picked from commit 141c75847a0fc470915a16c83e80f8effb7a22b6) Fix comment Reviewed-on: https://gerrit.libreoffice.org/71949 Reviewed-by: Samuel Mehrbrodt <[email protected]> Tested-by: Samuel Mehrbrodt <[email protected]> (cherry picked from commit 3d6e2081f0ab71ad4515fed864c3f36566e466c3) Fix typo Reviewed-on: https://gerrit.libreoffice.org/68787 Tested-by: Jenkins Reviewed-by: Julien Nabet <[email protected]> (cherry picked from commit 3061ca82a323ec922dbdf2f5dcc008ade81f23a8) Make xwindow.py test more robust ...by waiting for all events to be processed before the listeners are removed Reviewed-on: https://gerrit.libreoffice.org/72432 Reviewed-by: Stephan Bergmann <[email protected]> Tested-by: Stephan Bergmann <[email protected]> (cherry picked from commit edeb858b57d5b45dbc20e04d323085cf9ce95f55) Temporarily disable broken part of xwindow.py test Apparently, at least for many builds there is am additional mouseExited/ mouseEntered event pair (making mouseEnteredEventsIntercepted = 2 and mouseExitedEventsIntercepted = 1) initiated by the xToolkitRobot.mousePress(xMouseEvent2) when the mouse pointer moves from the "Standard" window to the "writer_edit" sub-window. This needs further investigation. Reviewed-on: https://gerrit.libreoffice.org/72433 Reviewed-by: Stephan Bergmann <[email protected]> Tested-by: Stephan Bergmann <[email protected]> (cherry picked from commit acd4625f2f1bf418452ffdafeac1b83fe1b2acde) Fix expected mouseEntered/Exited values in xwindow.py test (see <https://gerrit.libreoffice.org/#/c/72433/> "Temporarily disable broken part of xwindow.py test") Reviewed-on: https://gerrit.libreoffice.org/72477 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <[email protected]> (cherry picked from commit 9976aa7b8420daa9f7a5290ae433e2ab338ca146) Remove some unused variables Reviewed-on: https://gerrit.libreoffice.org/72478 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <[email protected]> (cherry picked from commit c5968b68c51503f791cdffac2b9689b7de775054) Move xwindow.py to writer_tests Folder writer_tests5 does not exist on this branch tdf#125370 Fix crash when opening basic editor Reviewed-on: https://gerrit.libreoffice.org/72609 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <[email protected]> (cherry picked from commit 08509b747c9077e4753759338a899b76514ba3b7) Related tdf#122920 Treat UNO key events the same as mouse events by sending the notifications to the parent windows as well Reviewed-on: https://gerrit.libreoffice.org/72675 Reviewed-by: Samuel Mehrbrodt <[email protected]> Tested-by: Samuel Mehrbrodt <[email protected]> (cherry picked from commit 9e0e97b716ab074d4558c76a62a66bf597f332a5) Change-Id: Ibad84b0b37faccee875f6daad17e3e3680df0557 Reviewed-on: https://gerrit.libreoffice.org/72861 Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: Thorsten Behrens <[email protected]> diff --git a/forms/qa/unoapi/forms_2.sce b/forms/qa/unoapi/forms_2.sce index 30f4b2401875..c12d87f9977a 100644 --- a/forms/qa/unoapi/forms_2.sce +++ b/forms/qa/unoapi/forms_2.sce @@ -15,7 +15,7 @@ # except in compliance with the License. You may obtain a copy of # the License at http://www.apache.org/licenses/LICENSE-2.0 . # --o forms.ODateModel +# Flaky since tdf#125170 -o forms.ODateModel -o forms.OEditControl -o forms.OEditModel #i109939 -o forms.OFileControlModel diff --git a/sw/qa/uitest/writer_tests/xwindow.py b/sw/qa/uitest/writer_tests/xwindow.py index 428dd3723a05..a1be89bf2981 100644 --- a/sw/qa/uitest/writer_tests/xwindow.py +++ b/sw/qa/uitest/writer_tests/xwindow.py @@ -10,14 +10,20 @@ 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 MouseButton 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 +keyListenerCount = 0 +mousePressedEventsIntercepted = 0 +mouseReleasedEventsIntercepted = 0 +mouseEnteredEventsIntercepted = 0 +mouseExitedEventsIntercepted = 0 +keyPressedEventsIntercepted = 0 +keyReleasedEventsIntercepted = 0 class XMouseListenerExtended(unohelper.Base, XMouseListener): @@ -29,57 +35,54 @@ class XMouseListenerExtended(unohelper.Base, XMouseListener): # 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) + global mousePressedEventsIntercepted + mousePressedEventsIntercepted += 1 # 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) + global mouseReleasedEventsIntercepted + mouseReleasedEventsIntercepted += 1 # is invoked when the mouse enters a window. @classmethod def mouseEntered(self, xMouseEvent): - # doesn't work in UI tests - return super(XMouseListenerExtended, self).mouseEntered(xMouseEvent) + global mouseEnteredEventsIntercepted + mouseEnteredEventsIntercepted += 1 # is invoked when the mouse exits a window. @classmethod def mouseExited(self, xMouseEvent): - # doesn't work in UI tests - return super(XMouseListenerExtended, self).mouseExited(xMouseEvent) + global mouseExitedEventsIntercepted + mouseExitedEventsIntercepted += 1 class XKeyListenerExtended(unohelper.Base, XKeyListener): + def __init__(self): + global keyListenerCount + keyListenerCount += 1 + super().__init__() + # is invoked when a key has been pressed @classmethod def keyPressed(self, xKeyEvent): - global keymouseEventsIntercepted - keymouseEventsIntercepted += 1 - return super(XKeyListenerExtended, self).keyPressed(xKeyEvent) + global keyPressedEventsIntercepted + keyPressedEventsIntercepted += 1 # 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 + global keyReleasedEventsIntercepted + keyReleasedEventsIntercepted += 1 + +# Test that registered mouse/key listeners for top window receive mouse/key events class XWindow(UITestCase): def test_listeners(self): global mouseListenerCount + global keyListenerCount - writer_doc = self.ui_test.create_doc_in_start_center("writer") + 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() @@ -97,25 +100,39 @@ class XWindow(UITestCase): xKeyListener = XKeyListenerExtended() self.assertIsNotNone(xKeyListener) xWindow.addKeyListener(xKeyListener) + self.assertEqual(1, keyListenerCount) # create dummy mouse event xMouseEvent = MouseEvent() xMouseEvent.Modifiers = 0 - xMouseEvent.Buttons = 0 + xMouseEvent.Buttons = MouseButton.LEFT xMouseEvent.X = 10 xMouseEvent.Y = 10 xMouseEvent.ClickCount = 1 xMouseEvent.PopupTrigger = False xMouseEvent.Source = xWindow - # send mouse event + xMouseEvent2 = MouseEvent() + xMouseEvent2.Modifiers = 0 + xMouseEvent2.Buttons = MouseButton.LEFT + xMouseEvent2.X = 300 + xMouseEvent2.Y = 300 + xMouseEvent2.ClickCount = 1 + xMouseEvent2.PopupTrigger = False + xMouseEvent2.Source = xWindow + xToolkitRobot = xWindow.getToolkit() self.assertIsNotNone(xToolkitRobot) - xToolkitRobot.mousePress(xMouseEvent) + # Click in the menubar/toolbar area xToolkitRobot.mouseMove(xMouseEvent) + xToolkitRobot.mousePress(xMouseEvent) xToolkitRobot.mouseRelease(xMouseEvent) + # Click into the document content + xToolkitRobot.mousePress(xMouseEvent2) + xToolkitRobot.mouseRelease(xMouseEvent2) + # send key press event xKeyEvent = KeyEvent() xKeyEvent.Modifiers = 0 @@ -126,7 +143,11 @@ class XWindow(UITestCase): xToolkitRobot.keyPress(xKeyEvent) xToolkitRobot.keyRelease(xKeyEvent) - # remove moue listener + # Wait for async events to be processed + xToolkit = self.xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit') + xToolkit.processEventsToIdle() + + # remove mouse listener xWindow.removeMouseListener(xMouseListener) self.assertEqual(1, mouseListenerCount) del xMouseListener @@ -135,13 +156,26 @@ class XWindow(UITestCase): xWindow.removeKeyListener(xKeyListener) del xKeyListener - global keymouseEventsIntercepted - # Not expected 2 interceptions - self.assertEqual(0, keymouseEventsIntercepted) + global keyPressedEventsIntercepted + # Not expected any interceptions + self.assertEqual(1, keyPressedEventsIntercepted) + + global keyReleasedEventsIntercepted + # Not expected any interceptions + self.assertEqual(1, keyReleasedEventsIntercepted) + + global mousePressedEventsIntercepted + self.assertEqual(2, mousePressedEventsIntercepted) + + global mouseReleasedEventsIntercepted + self.assertEqual(2, mouseReleasedEventsIntercepted) - global mouseEventsIntercepted - # mousePressed, mouseReleased and mouseEntered should be triggered - self.assertEqual(2, mouseEventsIntercepted) + # Upon xMouseEvent, enter the vcl::Window with GetText() being "Standard", then upon + # xMouseEvent2, exit that vcl::Window and enter the one with get_id() being "writer_edit": + global mouseEnteredEventsIntercepted + self.assertEqual(2, mouseEnteredEventsIntercepted) + global mouseExitedEventsIntercepted + self.assertEqual(1, mouseExitedEventsIntercepted) # close document self.ui_test.close_doc() diff --git a/toolkit/source/awt/vclxwindow.cxx b/toolkit/source/awt/vclxwindow.cxx index 31438dfec9e2..dc4cbe2d7309 100644 --- a/toolkit/source/awt/vclxwindow.cxx +++ b/toolkit/source/awt/vclxwindow.cxx @@ -654,24 +654,27 @@ void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) } break; case VclEventId::WindowKeyInput: - { - if ( mpImpl->getKeyListeners().getLength() ) - { - css::awt::KeyEvent aEvent( VCLUnoHelper::createKeyEvent( - *static_cast<KeyEvent*>(rVclWindowEvent.GetData()), *this - ) ); - mpImpl->getKeyListeners().keyPressed( aEvent ); - } - } - break; case VclEventId::WindowKeyUp: { - if ( mpImpl->getKeyListeners().getLength() ) + VclPtr<vcl::Window> pWin = GetWindow(); + while (pWin) { - css::awt::KeyEvent aEvent( VCLUnoHelper::createKeyEvent( - *static_cast<KeyEvent*>(rVclWindowEvent.GetData()), *this - ) ); - mpImpl->getKeyListeners().keyReleased( aEvent ); + VCLXWindow* pXWindow = pWin->GetWindowPeer(); + if (!pXWindow || pXWindow->mpImpl->getKeyListeners().getLength() == 0) + { + pWin = pWin->GetWindow(GetWindowType::RealParent); + continue; + } + + awt::KeyEvent aEvent(VCLUnoHelper::createKeyEvent( + *static_cast<KeyEvent*>(rVclWindowEvent.GetData()), *this)); + if (rVclWindowEvent.GetId() == VclEventId::WindowKeyInput) + pXWindow->mpImpl->getKeyListeners().keyPressed(aEvent); + else + pXWindow->mpImpl->getKeyListeners().keyReleased(aEvent); + + // Next window (parent) + pWin = pWin->GetWindow(GetWindowType::RealParent); } } break; diff --git a/vcl/source/window/event.cxx b/vcl/source/window/event.cxx index d03d3d3c9540..6f092ce3729a 100644 --- a/vcl/source/window/event.cxx +++ b/vcl/source/window/event.cxx @@ -30,6 +30,7 @@ #include <com/sun/star/awt/MouseEvent.hpp> #include <com/sun/star/awt/KeyModifier.hpp> #include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/awt/XWindow.hpp> #include <comphelper/scopeguard.hxx> namespace vcl { @@ -213,6 +214,11 @@ void Window::CallEventListeners( VclEventId nEvent, void* pData ) if ( xWindow->IsDisposed() ) return; + // If maEventListeners is empty, the XVCLWindow has not yet been initialized. + // Calling GetComponentInterface will do that. + if (mpWindowImpl->maEventListeners.empty() && pData) + xWindow->GetComponentInterface(); + if (!mpWindowImpl->maEventListeners.empty()) { // Copy the list, because this can be destroyed when calling a Link... _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
