[vlc-commits] [Git][videolan/vlc][master] 2 commits: qt: add DismissPopupEventFilter from KDE Plasma

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Fri May 12 16:34:33 UTC 2023



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
466f7b7b by Fatih Uzunoglu at 2023-05-12T16:02:36+00:00
qt: add DismissPopupEventFilter from KDE Plasma

- - - - -
46e494fc by Fatih Uzunoglu at 2023-05-12T16:02:36+00:00
qt: use DismissPopupEventFilter

- - - - -


5 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/meson.build
- modules/gui/qt/qt.cpp
- + modules/gui/qt/util/dismiss_popup_event_filter.cpp
- + modules/gui/qt/util/dismiss_popup_event_filter.hpp


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -326,6 +326,8 @@ libqt_plugin_la_SOURCES = \
 	gui/qt/util/effects_image_provider.hpp \
 	gui/qt/util/qsgroundedrectangularimagenode.cpp \
 	gui/qt/util/qsgroundedrectangularimagenode.hpp \
+	gui/qt/util/dismiss_popup_event_filter.cpp \
+	gui/qt/util/dismiss_popup_event_filter.hpp \
 	gui/qt/widgets/native/animators.cpp \
 	gui/qt/widgets/native/animators.hpp \
 	gui/qt/widgets/native/customwidgets.cpp gui/qt/widgets/native/customwidgets.hpp \
@@ -511,6 +513,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/util/vlctick.moc.cpp \
 	gui/qt/util/qmlinputitem.moc.cpp \
 	gui/qt/util/qsgroundedrectangularimagenode.moc.cpp \
+	gui/qt/util/dismiss_popup_event_filter.moc.cpp \
 	gui/qt/widgets/native/animators.moc.cpp \
 	gui/qt/widgets/native/csdthemeimage.moc.cpp \
 	gui/qt/widgets/native/customwidgets.moc.cpp \


=====================================
modules/gui/qt/meson.build
=====================================
@@ -137,6 +137,7 @@ moc_headers = files(
     'util/vlctick.hpp',
     'util/qmlinputitem.hpp',
     'util/qsgroundedrectangularimagenode.hpp',
+    'util/dismiss_popup_event_filter.hpp',
     'widgets/native/animators.hpp',
     'widgets/native/csdthemeimage.hpp',
     'widgets/native/customwidgets.hpp',
@@ -453,6 +454,8 @@ some_sources = files(
     'util/effects_image_provider.hpp',
     'util/qsgroundedrectangularimagenode.cpp',
     'util/qsgroundedrectangularimagenode.hpp',
+    'util/dismiss_popup_event_filter.cpp',
+    'util/dismiss_popup_event_filter.hpp',
     'widgets/native/animators.cpp',
     'widgets/native/animators.hpp',
     'widgets/native/customwidgets.cpp',


=====================================
modules/gui/qt/qt.cpp
=====================================
@@ -67,6 +67,7 @@ extern "C" char **environ;
 #include "dialogs/extensions/extensions_manager.hpp" /* Extensions manager */
 #include "dialogs/plugins/addons_manager.hpp" /* Addons manager */
 #include "dialogs/help/help.hpp"     /* Launch Update */
+#include "util/dismiss_popup_event_filter.hpp"
 #include "maininterface/compositor.hpp"
 
 #include <QVector>
@@ -822,14 +823,18 @@ static void *Thread( void *obj )
         /* Check window type from the Qt platform back-end */
         bool known_type = true;
 
-        QString platform = app.platformName();
-        if( platform == qfu("xcb") )
+        const QString& platform = app.platformName();
+        if( platform == QLatin1String("xcb") )
             p_intf->voutWindowType = VLC_WINDOW_TYPE_XID;
-        else if( platform == qfu("wayland") || platform == qfu("wayland-egl") )
+        else if( platform == QLatin1String("wayland") || platform == QLatin1String("wayland-egl") ) {
             p_intf->voutWindowType = VLC_WINDOW_TYPE_WAYLAND;
-        else if( platform == qfu("windows") )
+
+            // Workaround for popup widgets not closing on mouse press on wayland:
+            app.installEventFilter(new DismissPopupEventFilter(&app));
+        }
+        else if( platform == QLatin1String("windows") )
             p_intf->voutWindowType = VLC_WINDOW_TYPE_HWND;
-        else if( platform == qfu("cocoa" ) )
+        else if( platform == QLatin1String("cocoa") )
             p_intf->voutWindowType = VLC_WINDOW_TYPE_NSOBJECT;
         else
         {


=====================================
modules/gui/qt/util/dismiss_popup_event_filter.cpp
=====================================
@@ -0,0 +1,69 @@
+/*
+    SPDX-FileCopyrightText: 2008 Aaron Seigo <aseigo at kde.org>
+    SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas at kde.org>
+    SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic at kde.org>
+    SPDX-FileCopyrightText: 2013 Marco Martin <mart at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+/*
+    This file is part of the KDE Plasma project.
+    Origin: plasma-workspace/shell/shellcorona.cpp
+*/
+
+#include "dismiss_popup_event_filter.hpp"
+
+#include <QMouseEvent>
+#include <QWidget>
+#include <QWindow>
+#include <QApplication>
+
+DismissPopupEventFilter::DismissPopupEventFilter(QObject *parent)
+    : QObject{parent}
+{
+
+}
+
+bool DismissPopupEventFilter::eventFilter(QObject *watched, QEvent *event)
+{
+    if (event->type() == QEvent::MouseButtonPress) {
+        if (m_filterMouseEvents) {
+            // Eat events until all mouse buttons are released.
+            return true;
+        }
+
+        QWidget *popup = QApplication::activePopupWidget();
+        if (!popup) {
+            return false;
+        }
+
+        QWindow *window = qobject_cast<QWindow *>(watched);
+        if (popup->windowHandle() == window) {
+            // The popup window handles mouse events before the widget.
+            return false;
+        }
+
+        QWidget *widget = qobject_cast<QWidget *>(watched);
+        if (widget) {
+            // Let the popup widget handle the mouse press event.
+            return false;
+        }
+
+        popup->close();
+        m_filterMouseEvents = true;
+        return true;
+
+    } else if (event->type() == QEvent::MouseButtonRelease) {
+        if (m_filterMouseEvents) {
+            // Eat events until all mouse buttons are released.
+            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
+            if (mouseEvent->buttons() == Qt::NoButton) {
+                m_filterMouseEvents = false;
+            }
+            return true;
+        }
+    }
+
+    return false;
+}


=====================================
modules/gui/qt/util/dismiss_popup_event_filter.hpp
=====================================
@@ -0,0 +1,66 @@
+/*
+    SPDX-FileCopyrightText: 2008 Aaron Seigo <aseigo at kde.org>
+    SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas at kde.org>
+    SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic at kde.org>
+    SPDX-FileCopyrightText: 2013 Marco Martin <mart at kde.org>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+/*
+    This file is part of the KDE Plasma project.
+    Origin: plasma-workspace/shell/shellcorona.cpp
+*/
+
+#ifndef DISMISSPOPUPEVENTFILTER_HPP
+#define DISMISSPOPUPEVENTFILTER_HPP
+
+#include <QObject>
+
+/**
+ * @internal
+ *
+ * The DismissPopupEventFilter class monitors mouse button press events and
+ * when needed dismisses the active popup widget.
+ *
+ * plasmashell uses both QtQuick and QtWidgets under a single roof, QtQuick is
+ * used for most of things, while QtWidgets is used for things such as context
+ * menus, etc.
+ *
+ * If user clicks outside a popup window, it's expected that the popup window
+ * will be closed.  On X11, it's achieved by establishing both a keyboard grab
+ * and a pointer grab. But on Wayland, you can't grab keyboard or pointer. If
+ * user clicks a surface of another app, the compositor will dismiss the popup
+ * surface.  However, if user clicks some surface of the same application, the
+ * popup surface won't be dismissed, it's up to the application to decide
+ * whether the popup must be closed. In 99% cases, it must.
+ *
+ * Qt has some code that dismisses the active popup widget if another window
+ * of the same app has been clicked. But, that code works only if the
+ * application uses solely Qt widgets. See QTBUG-83972. For plasma it doesn't
+ * work, because as we said previously, it uses both Qt Quick and Qt Widgets.
+ *
+ * Ideally, this bug needs to be fixed upstream, but given that it'll involve
+ * major changes in Qt, the chances of it being fixed any time soon are slim.
+ *
+ * In order to work around the popup dismissal bug, we install an event filter
+ * that monitors Qt::MouseButtonPress events. If it happens that user has
+ * clicked outside an active popup widget, that popup will be closed. This
+ * event filter is not needed on X11!
+ */
+class DismissPopupEventFilter : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit DismissPopupEventFilter(QObject *parent = nullptr);
+
+protected:
+    bool eventFilter(QObject *watched, QEvent *event) override;
+
+private:
+    bool m_filterMouseEvents = false;
+
+};
+
+#endif // DISMISSPOPUPEVENTFILTER_HPP



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e2d4c69d79ed8f19b4bdd9cee7ed8227400842d3...46e494fcc31b0a433d609b5d96c08cf37b0223c7

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e2d4c69d79ed8f19b4bdd9cee7ed8227400842d3...46e494fcc31b0a433d609b5d96c08cf37b0223c7
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list