Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
dff96634 by Prince Gupta at 2023-01-26T15:15:53+00:00
qt: implement System Menu Button in CSDButtonModel

- - - - -
cc82771e by Prince Gupta at 2023-01-26T15:15:53+00:00
qt: provide CSD system menu button on windows

- - - - -
6afdbe34 by Prince Gupta at 2023-01-26T15:15:53+00:00
qml: implement BannerCone

- - - - -
139dc4cd by Prince Gupta at 2023-01-26T15:15:53+00:00
qml: use BannerCone widget in main view banner

widget handles sys menu button with CSD

- - - - -
a17b8d5b by Prince Gupta at 2023-01-26T15:15:53+00:00
qml: use BannerCone widget in TopBar

widget handles sys menu button with CSD

- - - - -


8 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/mainctx_win32.cpp
- modules/gui/qt/maininterface/qml/BannerSources.qml
- modules/gui/qt/player/qml/TopBar.qml
- modules/gui/qt/util/csdbuttonmodel.cpp
- modules/gui/qt/util/csdbuttonmodel.hpp
- modules/gui/qt/vlc.qrc
- + modules/gui/qt/widgets/qml/BannerCone.qml


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -982,6 +982,7 @@ libqt_plugin_la_QML = \
        gui/qt/widgets/qml/ActionButtonOverlay.qml \
        gui/qt/widgets/qml/ActionButtonPrimary.qml \
        gui/qt/widgets/qml/BannerTabButton.qml \
+       gui/qt/widgets/qml/BannerCone.qml \
        gui/qt/widgets/qml/BusyIndicatorExt.qml \
        gui/qt/widgets/qml/CaptionLabel.qml \
        gui/qt/widgets/qml/CheckButton.qml \


=====================================
modules/gui/qt/maininterface/mainctx_win32.cpp
=====================================
@@ -35,6 +35,7 @@
 #include "util/csdbuttonmodel.hpp"
 
 #include <QBitmap>
+#include <QTimer>
 
 #include <assert.h>
 
@@ -114,6 +115,103 @@ HWND WinId( QWindow *windowHandle )
         return 0;
 }
 
+
+bool isWindowFixedSize(const QWindow *window)
+{
+    if (window->flags() & Qt::MSWindowsFixedSizeDialogHint)
+        return true;
+
+    const auto minSize = window->minimumSize();
+    const auto maxSize = window->maximumSize();
+
+    return minSize.isValid() && maxSize.isValid() && minSize == maxSize;
+}
+
+
+class WinSystemMenuButton : public SystemMenuButton
+{
+public:
+    WinSystemMenuButton(QWindow *window, QObject *parent)
+        : SystemMenuButton {parent}
+        , m_window {window}
+    {
+        connect(this, &CSDButton::clicked, this, 
&WinSystemMenuButton::handleClick);
+        connect(this, &CSDButton::doubleClicked, this, 
&WinSystemMenuButton::handleDoubleClick);
+    }
+
+    void showSystemMenu() override
+    {
+        HWND hwnd = (HWND)m_window->winId();
+        HMENU hmenu = ::GetSystemMenu(hwnd, FALSE);
+        if (!hmenu)
+            return;
+
+        // Tweak the menu items according to the current window status.
+        const auto winState = m_window->windowStates();
+        const bool maxOrFull = (winState.testFlag(Qt::WindowMaximized) || 
winState.testFlag(Qt::WindowFullScreen));
+        const bool fixedSize = isWindowFixedSize(m_window);
+
+        EnableMenuItem(hmenu, SC_MOVE, (MF_BYCOMMAND | (!maxOrFull ? 
MFS_ENABLED : MFS_DISABLED)));
+        EnableMenuItem(hmenu, SC_SIZE, (MF_BYCOMMAND | ((!maxOrFull && 
!fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
+
+        EnableMenuItem(hmenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && 
!fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
+        EnableMenuItem(hmenu, SC_MINIMIZE, (MF_BYCOMMAND | MFS_ENABLED));
+        EnableMenuItem(hmenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((!maxOrFull && 
!fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
+        EnableMenuItem(hmenu, SC_CLOSE, (MF_BYCOMMAND | MFS_ENABLED));
+
+        // calculate screen point 'margin' down from system menu button's rect
+        const QPoint margin {0, 4};
+        const auto bottomLeft = rect().bottomLeft();
+        const auto screenPoints = m_window->mapToGlobal(bottomLeft) + margin;
+
+        const auto alignment = (QGuiApplication::isRightToLeft() ? 
TPM_RIGHTALIGN : TPM_LEFTALIGN);
+
+        // show menu
+        emit systemMenuVisibilityChanged(true);
+
+        const int action = TrackPopupMenu(hmenu, (TPM_RETURNCMD | alignment)
+                                          , screenPoints.x(), screenPoints.y()
+                                          , NULL, hwnd, 0);
+
+        // unlike native system menu which sends WM_SYSCOMMAND, TrackPopupMenu 
sends WM_COMMAND
+        // imitate native system menu by sending the action manually as 
WM_SYSCOMMAND
+        PostMessageW(hwnd, WM_SYSCOMMAND, action, 0);
+
+        emit systemMenuVisibilityChanged(false);
+    }
+
+private:
+    // target window
+    QWindow *m_window = {};
+
+    // used to reject click() incase a doubleClick() is followed
+    bool m_triggerSystemMenu = false;
+
+    void handleClick()
+    {
+        // delay the show of sytem menu to check if this 'click' is
+        // a double click, 'm_triggerSystemMenu' is used to reject the
+        // queued 'showSystemMenu' call in case this is a double click
+
+        m_triggerSystemMenu = true;
+        QTimer::singleShot(100, this, [this]()
+        {
+            if (!m_triggerSystemMenu)
+                return;
+
+            showSystemMenu();
+        });
+    }
+
+    void handleDoubleClick()
+    {
+        // reject any queued showSystemMenu call
+        m_triggerSystemMenu = false;
+
+        m_window->close();
+    }
+};
+
 class CSDWin32EventHandler : public QObject, public QAbstractNativeEventFilter
 {
 public:
@@ -654,6 +752,9 @@ 
InterfaceWindowHandlerWin32::InterfaceWindowHandlerWin32(qt_intf_t *_p_intf, Mai
 #endif
 
 {
+    auto systemMenuButton = 
std::make_shared<WinSystemMenuButton>(mainCtx->intfMainWindow(), nullptr);
+    mainCtx->csdButtonModel()->setSystemMenuButton(systemMenuButton);
+
     QApplication::instance()->installNativeEventFilter(this);
 }
 


=====================================
modules/gui/qt/maininterface/qml/BannerSources.qml
=====================================
@@ -160,17 +160,11 @@ FocusScope {
                                  Navigation.parentItem: root
                                  Navigation.rightItem: globalMenuGroup
                                  Navigation.downItem: localMenuGroup.visible ? 
localMenuGroup : localToolbarBg
-                             }
-
-                            Image {
-                                sourceSize.width: VLCStyle.icon_normal
-                                sourceSize.height: VLCStyle.icon_normal
-                                source: 
SVGColorImage.colorize("qrc:///misc/cone.svg")
-                                                .accent(VLCStyle.colors.accent)
-                                                .uri()
-                                enabled: false
                             }
 
+                            Widgets.BannerCone {
+
+                            }
                         }
 
                         /* Button for the sources */


=====================================
modules/gui/qt/player/qml/TopBar.qml
=====================================
@@ -226,19 +226,20 @@ FocusScope{
                 onHoveredChanged: root.requestLockUnlockAutoHide(hovered)
             }
 
-            Image {
+            Widgets.BannerCone {
                 id: logo
 
                 anchors.verticalCenter: parent.verticalCenter
                 anchors.left: backBtn.right
                 anchors.leftMargin: VLCStyle.margin_xxsmall
 
-                sourceSize.width: VLCStyle.icon_normal
-                sourceSize.height: VLCStyle.icon_normal
-                source: SVGColorImage.colorize("qrc:///misc/cone.svg")
-                            .accent(root.colors.accent)
-                            .uri()
-                enabled: false
+                Connections {
+                    target: logo.button
+
+                    onSystemMenuVisibilityChanged: {
+                        root.requestLockUnlockAutoHide(visible)
+                    }
+                }
             }
         }
 


=====================================
modules/gui/qt/util/csdbuttonmodel.cpp
=====================================
@@ -67,6 +67,11 @@ void CSDButton::click()
     emit clicked();
 }
 
+void CSDButton::doubleClick()
+{
+    emit doubleClicked();
+}
+
 CSDButtonModel::CSDButtonModel(MainCtx *mainCtx, QObject *parent)
     : QObject {parent}
     , m_mainCtx {mainCtx}
@@ -88,6 +93,17 @@ QList<CSDButton *> CSDButtonModel::windowCSDButtons() const
     return m_windowCSDButtons;
 }
 
+CSDButton *CSDButtonModel::systemMenuButton() const
+{
+    return m_systemMenuButton.get();
+}
+
+void CSDButtonModel::setSystemMenuButton(std::shared_ptr<SystemMenuButton> 
button)
+{
+    m_systemMenuButton = std::move(button);
+}
+
+
 void CSDButtonModel::minimizeButtonClicked()
 {
     emit m_mainCtx->requestInterfaceMinimized();


=====================================
modules/gui/qt/util/csdbuttonmodel.hpp
=====================================
@@ -23,6 +23,7 @@
 
 #include <QObject>
 #include <QRect>
+#include <memory>
 
 class CSDButton : public QObject
 {
@@ -37,6 +38,7 @@ public:
         Minimize,
         MaximizeRestore,
         Close,
+        SystemMenu,
 
         TypeCount
     };
@@ -61,12 +63,15 @@ public:
 
 public slots:
     // signals to perfrom action associated with button
+    // actions are dependent on implmentation
     void click();
+    void doubleClick();
 
 signals:
     void showHoveredChanged();
     void rectChanged();
     void clicked();
+    void doubleClicked();
 
 private:
     const ButtonType m_type;
@@ -75,17 +80,39 @@ private:
 };
 
 
+class SystemMenuButton : public CSDButton
+{
+    Q_OBJECT
+
+public:
+    SystemMenuButton(QObject *parent = nullptr) : CSDButton 
{SystemMenuButton::SystemMenu, parent} {}
+
+    virtual void showSystemMenu() = 0;
+
+signals:
+    void systemMenuVisibilityChanged(bool visible);
+};
+
+
 class MainCtx;
 
+
 class CSDButtonModel : public QObject
 {
     Q_OBJECT
     Q_PROPERTY(QList<CSDButton *> windowCSDButtons READ windowCSDButtons 
CONSTANT)
 
+    Q_PROPERTY(CSDButton *systemMenuButton READ systemMenuButton CONSTANT)
+
 public:
     CSDButtonModel(MainCtx *mainCtx, QObject *parent = nullptr);
 
     QList<CSDButton *> windowCSDButtons() const;
+    CSDButton *systemMenuButton() const;
+
+    // set by internal implmentation
+    // all the actions are also handled by implementation
+    void setSystemMenuButton(std::shared_ptr<SystemMenuButton> button);
 
 private slots:
     void minimizeButtonClicked();
@@ -94,7 +121,12 @@ private slots:
 
 private:
     MainCtx *m_mainCtx;
+
+    // CSD window action buttons i.e minimize, maximize, close
     QList<CSDButton *> m_windowCSDButtons;
+
+    // sysmenu button, available on windows only
+    std::shared_ptr<SystemMenuButton> m_systemMenuButton = nullptr;
 };
 
 


=====================================
modules/gui/qt/vlc.qrc
=====================================
@@ -155,6 +155,7 @@
     <qresource prefix="/widgets">
         <file 
alias="ActionButtonOverlay.qml">widgets/qml/ActionButtonOverlay.qml</file>
         <file 
alias="ActionButtonPrimary.qml">widgets/qml/ActionButtonPrimary.qml</file>
+        <file alias="BannerCone.qml">widgets/qml/BannerCone.qml</file>
         <file 
alias="BannerTabButton.qml">widgets/qml/BannerTabButton.qml</file>
         <file 
alias="BusyIndicatorExt.qml">widgets/qml/BusyIndicatorExt.qml</file>
         <file 
alias="AcrylicBackground.qml">widgets/qml/AcrylicBackground.qml</file>


=====================================
modules/gui/qt/widgets/qml/BannerCone.qml
=====================================
@@ -0,0 +1,76 @@
+/*****************************************************************************
+ * Copyright (C) 2023 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+import QtQuick 2.11
+
+import org.videolan.vlc 0.1
+
+import "qrc:///widgets/" as Widgets
+import "qrc:///style/"
+
+Image {
+    id: root
+
+    property var button: MainCtx.csdButtonModel.systemMenuButton
+
+    sourceSize.width: VLCStyle.icon_normal
+    sourceSize.height: VLCStyle.icon_normal
+    source: SVGColorImage.colorize("qrc:///misc/cone.svg")
+                    .accent(VLCStyle.colors.accent)
+                    .uri()
+
+    focus: false
+
+    Loader {
+        anchors.fill: root
+        enabled: MainCtx.clientSideDecoration && root.button
+
+        sourceComponent: MouseArea {
+            onClicked: { root.button.click() }
+            onDoubleClicked: { root.button.doubleClick() }
+
+            Connections {
+                // don't target MouseArea for position since we
+                // need position updates of cone, inresepect of BannerSources
+                // to correctly track cone's global position
+                target: root
+
+                // handles VLCStyle.scale changes
+                onXChanged: Qt.callLater(root.updateRect)
+                onYChanged: Qt.callLater(root.updateRect)
+                onWidthChanged: Qt.callLater(root.updateRect)
+                onHeightChanged: Qt.callLater(root.updateRect)
+            }
+
+            Connections {
+                target: VLCStyle
+
+                // handle window resize
+                onAppWidthChanged: Qt.callLater(root.updateRect)
+                onAppHeightChanged: Qt.callLater(root.updateRect)
+            }
+        }
+    }
+
+    function updateRect() {
+        var rect = root.mapToItem(null, 0, 0, width, height)
+
+        if (button)
+            button.rect = rect
+    }
+}



View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/dda6d04f76de934b1caf4d40d634f58a3d08dd09...a17b8d5be1dc3b0845401be8fffbd17877fa04e5

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


VideoLAN code repository instance
_______________________________________________
vlc-commits mailing list
vlc-commits@videolan.org
https://mailman.videolan.org/listinfo/vlc-commits

Reply via email to