[Libreoffice-commits] core.git: vcl/inc vcl/qt5

Jan-Marek Glogowski (via logerrit) logerrit at kemper.freedesktop.org
Wed Jun 12 21:23:44 UTC 2019


 vcl/inc/qt5/Qt5Object.hxx    |   20 ++++++++++++-
 vcl/inc/qt5/Qt5Widget.hxx    |   45 +++++++++++++++++++++---------
 vcl/qt5/Qt5Object.cxx        |   35 +++++++++++++++++++++--
 vcl/qt5/Qt5OpenGLContext.cxx |    3 +-
 vcl/qt5/Qt5Widget.cxx        |   63 +++++++++++++++++++++++++------------------
 5 files changed, 122 insertions(+), 44 deletions(-)

New commits:
commit 25edbded9946801effd117b9c46de0f8b4bc5632
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Thu May 30 13:39:11 2019 +0000
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Wed Jun 12 23:22:06 2019 +0200

    tdf#125517 Qt5 implement a minimal Qt5ObjectWindow
    
    Since we can't use an input and visual transparent widget, like a
    GtkGrid, we have to implement input forwarding in the QWindow.
    
    Using a Qt5Widget directly results in other problems on Qt 5.12+,
    like these warnings (depending on the tested Qt::WA_* flags):
    * Attempted flush to non-raster surface QWidgetWindow(0xa386c10,
      name="QWidgetClassWindow") of type QSurface::OpenGLSurface
      (consider using Qt::WA_PaintOnScreen to exclude from
      backingstore sync)
    * QWidget::paintEngine: Should no longer be called
    
    So the current QWidget::createWindowContainer has to stay and key
    and mouse handling must be implemented as in Qt5Widget. And the
    QWindow is strangely not accessible through the windowHandle() of
    the container QWwidget.
    
    As a result this patch is mostly boilerplate code, publishing the
    Qt5Widget mouse and key handling as static functions.
    
    Change-Id: I5be5f5fa1379c6bdefab0f96604251801c252b38
    Reviewed-on: https://gerrit.libreoffice.org/73566
    Tested-by: Jenkins
    Reviewed-by: Jan-Marek Glogowski <glogow at fbihome.de>

diff --git a/vcl/inc/qt5/Qt5Object.hxx b/vcl/inc/qt5/Qt5Object.hxx
index 88cd8baa78da..e27d549ca51d 100644
--- a/vcl/inc/qt5/Qt5Object.hxx
+++ b/vcl/inc/qt5/Qt5Object.hxx
@@ -24,10 +24,10 @@
 
 #include <QtCore/QObject>
 #include <QtGui/QRegion>
+#include <QtGui/QWindow>
 
 class Qt5Frame;
 class QWidget;
-class QWindow;
 
 class Qt5Object : public QObject, public SalObject
 {
@@ -44,6 +44,10 @@ class Qt5Object : public QObject, public SalObject
 public:
     Qt5Object(Qt5Frame* pParent, bool bShow);
 
+    Qt5Frame* frame() const { return m_pParent; }
+    QWidget* widget() const { return m_pQWidget; }
+    QWindow* windowHandle() const { return m_pQWindow; }
+
     virtual void ResetClipRegion() override;
     virtual void BeginSetClipRegion(sal_uInt32 nRects) override;
     virtual void UnionClipRegion(long nX, long nY, long nWidth, long nHeight) override;
@@ -57,4 +61,18 @@ public:
     virtual const SystemEnvData* GetSystemData() const override { return &m_aSystemData; }
 };
 
+class Qt5ObjectWindow : public QWindow
+{
+    Qt5Object& m_rParent;
+
+    bool event(QEvent*) override;
+    void mousePressEvent(QMouseEvent*) override;
+    void mouseReleaseEvent(QMouseEvent*) override;
+    // keyPressEvent(QKeyEvent*) is handled via event(QEvent*); see comment in Qt5Widget::event
+    void keyReleaseEvent(QKeyEvent*) override;
+
+public:
+    explicit Qt5ObjectWindow(Qt5Object& rParent);
+};
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/qt5/Qt5Widget.hxx b/vcl/inc/qt5/Qt5Widget.hxx
index ce4e068cbbec..8ead4b3ec945 100644
--- a/vcl/inc/qt5/Qt5Widget.hxx
+++ b/vcl/inc/qt5/Qt5Widget.hxx
@@ -27,17 +27,6 @@
 
 class Qt5Frame;
 class Qt5Object;
-class QEvent;
-class QFocusEvent;
-class QInputMethodEvent;
-class QKeyEvent;
-class QMouseEvent;
-class QMoveEvent;
-class QPaintEvent;
-class QResizeEvent;
-class QShowEvent;
-class QWheelEvent;
-class QVariant;
 
 class Qt5Widget : public QWidget
 {
@@ -48,9 +37,15 @@ class Qt5Widget : public QWidget
     int m_nDeltaX;
     int m_nDeltaY;
 
-    bool handleKeyEvent(QKeyEvent*, bool);
-    void handleMouseButtonEvent(QMouseEvent*, bool);
-    void commitText(const QString& aText) const;
+    enum class ButtonKeyState
+    {
+        Pressed,
+        Released
+    };
+
+    static void commitText(Qt5Frame&, const QString& aText);
+    static bool handleKeyEvent(Qt5Frame&, const QWidget&, QKeyEvent*, const ButtonKeyState);
+    static void handleMouseButtonEvent(const Qt5Frame&, QMouseEvent*, const ButtonKeyState);
 
     virtual bool event(QEvent*) override;
 
@@ -84,6 +79,28 @@ public:
     Qt5Frame& getFrame() const { return m_rFrame; }
     void startDrag(sal_Int8 nSourceActions);
     void endExtTextInput();
+
+    static bool handleEvent(Qt5Frame&, const QWidget&, QEvent*);
+    // key events might be propagated further down => call base on false
+    static inline bool handleKeyReleaseEvent(Qt5Frame&, const QWidget&, QKeyEvent*);
+    // mouse events are always accepted
+    static inline void handleMousePressEvent(const Qt5Frame&, QMouseEvent*);
+    static inline void handleMouseReleaseEvent(const Qt5Frame&, QMouseEvent*);
 };
 
+bool Qt5Widget::handleKeyReleaseEvent(Qt5Frame& rFrame, const QWidget& rWidget, QKeyEvent* pEvent)
+{
+    return handleKeyEvent(rFrame, rWidget, pEvent, ButtonKeyState::Released);
+}
+
+void Qt5Widget::handleMousePressEvent(const Qt5Frame& rFrame, QMouseEvent* pEvent)
+{
+    handleMouseButtonEvent(rFrame, pEvent, ButtonKeyState::Pressed);
+}
+
+void Qt5Widget::handleMouseReleaseEvent(const Qt5Frame& rFrame, QMouseEvent* pEvent)
+{
+    handleMouseButtonEvent(rFrame, pEvent, ButtonKeyState::Released);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Object.cxx b/vcl/qt5/Qt5Object.cxx
index a635a5931886..12d8b39a52ae 100644
--- a/vcl/qt5/Qt5Object.cxx
+++ b/vcl/qt5/Qt5Object.cxx
@@ -21,10 +21,9 @@
 #include <Qt5Object.moc>
 
 #include <Qt5Frame.hxx>
+#include <Qt5Widget.hxx>
 
-#include <QtWidgets/QWidget>
 #include <QtGui/QGuiApplication>
-#include <QtGui/QWindow>
 
 Qt5Object::Qt5Object(Qt5Frame* pParent, bool bShow)
     : m_pParent(pParent)
@@ -34,8 +33,9 @@ Qt5Object::Qt5Object(Qt5Frame* pParent, bool bShow)
     if (!m_pParent || !pParent->GetQWidget())
         return;
 
-    m_pQWindow = new QWindow;
+    m_pQWindow = new Qt5ObjectWindow(*this);
     m_pQWidget = QWidget::createWindowContainer(m_pQWindow, pParent->GetQWidget());
+    m_pQWidget->setAttribute(Qt::WA_NoSystemBackground);
 
     if (bShow)
         m_pQWidget->show();
@@ -103,4 +103,33 @@ void Qt5Object::Show(bool bVisible)
 
 void Qt5Object::SetForwardKey(bool /*bEnable*/) {}
 
+Qt5ObjectWindow::Qt5ObjectWindow(Qt5Object& rParent)
+    : m_rParent(rParent)
+{
+    assert(m_rParent.frame() && m_rParent.frame()->GetQWidget());
+}
+
+void Qt5ObjectWindow::mousePressEvent(QMouseEvent* pEvent)
+{
+    m_rParent.CallCallback(SalObjEvent::ToTop);
+    Qt5Widget::handleMousePressEvent(*m_rParent.frame(), pEvent);
+}
+
+void Qt5ObjectWindow::mouseReleaseEvent(QMouseEvent* pEvent)
+{
+    Qt5Widget::handleMouseReleaseEvent(*m_rParent.frame(), pEvent);
+}
+
+bool Qt5ObjectWindow::event(QEvent* pEvent)
+{
+    return Qt5Widget::handleEvent(*m_rParent.frame(), *m_rParent.widget(), pEvent)
+           || QWindow::event(pEvent);
+}
+
+void Qt5ObjectWindow::keyReleaseEvent(QKeyEvent* pEvent)
+{
+    if (!Qt5Widget::handleKeyReleaseEvent(*m_rParent.frame(), *m_rParent.widget(), pEvent))
+        QWindow::keyReleaseEvent(pEvent);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5OpenGLContext.cxx b/vcl/qt5/Qt5OpenGLContext.cxx
index 6f095e7cc857..a33f7abde2f5 100644
--- a/vcl/qt5/Qt5OpenGLContext.cxx
+++ b/vcl/qt5/Qt5OpenGLContext.cxx
@@ -147,5 +147,6 @@ void Qt5OpenGLContext::initWindow()
         InitChildWindow(m_pChildWindow.get());
     }
 
-    m_pWindow = static_cast<Qt5Object*>(m_pChildWindow->ImplGetWindowImpl()->mpSysObj)->m_pQWindow;
+    m_pWindow
+        = static_cast<Qt5Object*>(m_pChildWindow->ImplGetWindowImpl()->mpSysObj)->windowHandle();
 }
diff --git a/vcl/qt5/Qt5Widget.cxx b/vcl/qt5/Qt5Widget.cxx
index 27ce382cb349..b46b48b35366 100644
--- a/vcl/qt5/Qt5Widget.cxx
+++ b/vcl/qt5/Qt5Widget.cxx
@@ -120,7 +120,8 @@ void Qt5Widget::resizeEvent(QResizeEvent* pEvent)
     m_rFrame.CallCallback(SalEvent::Resize, nullptr);
 }
 
-void Qt5Widget::handleMouseButtonEvent(QMouseEvent* pEvent, bool bReleased)
+void Qt5Widget::handleMouseButtonEvent(const Qt5Frame& rFrame, QMouseEvent* pEvent,
+                                       const ButtonKeyState eState)
 {
     SalMouseEvent aEvent;
     switch (pEvent->button())
@@ -144,16 +145,19 @@ void Qt5Widget::handleMouseButtonEvent(QMouseEvent* pEvent, bool bReleased)
     aEvent.mnCode = GetKeyModCode(pEvent->modifiers()) | GetMouseModCode(pEvent->buttons());
 
     SalEvent nEventType;
-    if (bReleased)
-        nEventType = SalEvent::MouseButtonUp;
-    else
+    if (eState == ButtonKeyState::Pressed)
         nEventType = SalEvent::MouseButtonDown;
-    m_rFrame.CallCallback(nEventType, &aEvent);
+    else
+        nEventType = SalEvent::MouseButtonUp;
+    rFrame.CallCallback(nEventType, &aEvent);
 }
 
-void Qt5Widget::mousePressEvent(QMouseEvent* pEvent) { handleMouseButtonEvent(pEvent, false); }
+void Qt5Widget::mousePressEvent(QMouseEvent* pEvent) { handleMousePressEvent(m_rFrame, pEvent); }
 
-void Qt5Widget::mouseReleaseEvent(QMouseEvent* pEvent) { handleMouseButtonEvent(pEvent, true); }
+void Qt5Widget::mouseReleaseEvent(QMouseEvent* pEvent)
+{
+    handleMouseReleaseEvent(m_rFrame, pEvent);
+}
 
 void Qt5Widget::mouseMoveEvent(QMouseEvent* pEvent)
 {
@@ -405,7 +409,7 @@ static sal_uInt16 GetKeyCode(int keyval, Qt::KeyboardModifiers modifiers)
     return nCode;
 }
 
-void Qt5Widget::commitText(const QString& aText) const
+void Qt5Widget::commitText(Qt5Frame& rFrame, const QString& aText)
 {
     SalExtTextInputEvent aInputEvent;
     aInputEvent.mpTextAttr = nullptr;
@@ -414,19 +418,21 @@ void Qt5Widget::commitText(const QString& aText) const
     aInputEvent.mnCursorPos = aInputEvent.maText.getLength();
 
     SolarMutexGuard aGuard;
-    vcl::DeletionListener aDel(&m_rFrame);
-    m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
+    vcl::DeletionListener aDel(&rFrame);
+    rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
     if (!aDel.isDeleted())
-        m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
+        rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
 }
 
-bool Qt5Widget::handleKeyEvent(QKeyEvent* pEvent, bool bDown)
+bool Qt5Widget::handleKeyEvent(Qt5Frame& rFrame, const QWidget& rWidget, QKeyEvent* pEvent,
+                               const ButtonKeyState eState)
 {
     sal_uInt16 nCode = GetKeyCode(pEvent->key(), pEvent->modifiers());
-    if (bDown && nCode == 0 && !pEvent->text().isEmpty()
-        && testAttribute(Qt::WA_InputMethodEnabled))
+    if (eState == ButtonKeyState::Pressed && nCode == 0 && !pEvent->text().isEmpty()
+        && rWidget.testAttribute(Qt::WA_InputMethodEnabled))
     {
-        commitText(pEvent->text());
+        commitText(rFrame, pEvent->text());
+        pEvent->accept();
         return true;
     }
 
@@ -439,14 +445,16 @@ bool Qt5Widget::handleKeyEvent(QKeyEvent* pEvent, bool bDown)
     QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle);
 
     bool bStopProcessingKey;
-    if (bDown)
-        bStopProcessingKey = m_rFrame.CallCallback(SalEvent::KeyInput, &aEvent);
+    if (eState == ButtonKeyState::Pressed)
+        bStopProcessingKey = rFrame.CallCallback(SalEvent::KeyInput, &aEvent);
     else
-        bStopProcessingKey = m_rFrame.CallCallback(SalEvent::KeyUp, &aEvent);
+        bStopProcessingKey = rFrame.CallCallback(SalEvent::KeyUp, &aEvent);
+    if (bStopProcessingKey)
+        pEvent->accept();
     return bStopProcessingKey;
 }
 
-bool Qt5Widget::event(QEvent* pEvent)
+bool Qt5Widget::handleEvent(Qt5Frame& rFrame, const QWidget& rWidget, QEvent* pEvent)
 {
     if (pEvent->type() == QEvent::ShortcutOverride)
     {
@@ -459,17 +467,22 @@ bool Qt5Widget::event(QEvent* pEvent)
         // and if it's handled - disable the shortcut, it should have been activated.
         // Don't process keyPressEvent generated after disabling shortcut since it was handled here.
         // If event is not handled, don't accept it and let Qt activate related shortcut.
-        if (handleKeyEvent(static_cast<QKeyEvent*>(pEvent), true))
-            pEvent->accept();
+        if (handleKeyEvent(rFrame, rWidget, static_cast<QKeyEvent*>(pEvent),
+                           ButtonKeyState::Pressed))
+            return true;
     }
+    return false;
+}
 
-    return QWidget::event(pEvent);
+bool Qt5Widget::event(QEvent* pEvent)
+{
+    return handleEvent(m_rFrame, *this, pEvent) || QWidget::event(pEvent);
 }
 
 void Qt5Widget::keyReleaseEvent(QKeyEvent* pEvent)
 {
-    if (handleKeyEvent(pEvent, false))
-        pEvent->accept();
+    if (!handleKeyReleaseEvent(m_rFrame, *this, pEvent))
+        QWidget::keyReleaseEvent(pEvent);
 }
 
 void Qt5Widget::focusInEvent(QFocusEvent*) { m_rFrame.CallCallback(SalEvent::GetFocus, nullptr); }
@@ -519,7 +532,7 @@ static ExtTextInputAttr lcl_MapUndrelineStyle(QTextCharFormat::UnderlineStyle us
 void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent)
 {
     if (!pEvent->commitString().isEmpty())
-        commitText(pEvent->commitString());
+        commitText(m_rFrame, pEvent->commitString());
     else
     {
         SalExtTextInputEvent aInputEvent;


More information about the Libreoffice-commits mailing list