[vlc-commits] [Git][videolan/vlc][master] 9 commits: qt/MainInterface: implement acrylic surface notifiers
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Sun Sep 12 15:28:35 UTC 2021
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
87cb513e by Prince Gupta at 2021-09-12T12:46:25+00:00
qt/MainInterface: implement acrylic surface notifiers
- - - - -
034edad6 by Steve Lhomme at 2021-09-12T12:46:25+00:00
contrib: pthreads: patch dcomp.h from mingw64 to add gaussian effect
- - - - -
b74b0758 by Prince Gupta at 2021-09-12T12:46:25+00:00
qt/compositor_dcomp: force Win 8.1 compilation
To allow use of IDCompositionGaussianBlurEffect and others
- - - - -
606d8cfa by Prince Gupta at 2021-09-12T12:46:25+00:00
qt/compositor_dcomp: allow adding visual from outside
- - - - -
c6afb90a by Prince Gupta at 2021-09-12T12:46:25+00:00
qt/compositor_dcomp: implement acrylicsurface
- - - - -
dcd3d543 by Prince Gupta at 2021-09-12T12:46:25+00:00
qml: implement AcrylicBackground
- - - - -
ca242d7b by Prince Gupta at 2021-09-12T12:46:25+00:00
qml/BannerSource: use AcrylicBackground
- - - - -
2d6c4156 by Prince Gupta at 2021-09-12T12:46:25+00:00
qml/MusicArtistsAlbums: use AcrylicBackground for list
- - - - -
b605fd25 by Prince Gupta at 2021-09-12T12:46:25+00:00
qml/PlaylistListView: use AcrylicBackground
- - - - -
16 changed files:
- + contrib/src/pthreads/0001-dcomp.h-add-some-missing-interfaces.patch
- contrib/src/pthreads/rules.mak
- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/compositor_dcomp.cpp
- modules/gui/qt/maininterface/compositor_dcomp.hpp
- + modules/gui/qt/maininterface/compositor_dcomp_acrylicsurface.cpp
- + modules/gui/qt/maininterface/compositor_dcomp_acrylicsurface.hpp
- modules/gui/qt/maininterface/compositor_dcomp_uisurface.hpp
- modules/gui/qt/maininterface/main_interface.cpp
- modules/gui/qt/maininterface/main_interface.hpp
- modules/gui/qt/maininterface/qml/BannerSources.qml
- modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
- modules/gui/qt/player/qml/Player.qml
- modules/gui/qt/playlist/qml/PlaylistListView.qml
- modules/gui/qt/vlc.qrc
- + modules/gui/qt/widgets/qml/AcrylicBackground.qml
Changes:
=====================================
contrib/src/pthreads/0001-dcomp.h-add-some-missing-interfaces.patch
=====================================
@@ -0,0 +1,111 @@
+From 9de58105bbe6fb870c746d3f5c4ed97d91ba1b7c Mon Sep 17 00:00:00 2001
+From: Steve Lhomme <robux4 at ycbcr.xyz>
+Date: Tue, 7 Sep 2021 14:36:16 +0200
+Subject: [PATCH] dcomp.h: add some missing interfaces
+
+* IDCompositionFilterEffect: https://docs.microsoft.com/en-us/windows/win32/api/dcomp/nn-dcomp-idcompositionfiltereffect
+* IDCompositionSaturationEffect: https://docs.microsoft.com/en-us/windows/win32/api/dcomp/nn-dcomp-idcompositionsaturationeffect
+* IDCompositionGaussianBlurEffect: https://docs.microsoft.com/en-us/windows/win32/api/dcomp/nn-dcomp-idcompositiongaussianblureffect
+* IDCompositionDevice3: https://docs.microsoft.com/en-us/windows/win32/api/dcomp/nn-dcomp-idcompositiondevice3
+
+The order of methods can be found from
+https://github.com/terrafx/terrafx.interop.windows/tree/main/sources/Interop/Windows/um/dcomp
+
+As for other IDCompositionEffect interfaces, some methods are inverted for MSVC
+compilation in C++ (which is odd).
+
+Co-authored-by: Prince Gupta <guptaprince8832 at gmail.com>
+---
+ mingw-w64-headers/include/dcomp.h | 74 +++++++++++++++++++++++++++++++
+ 1 file changed, 74 insertions(+)
+
+diff --git a/mingw-w64-headers/include/dcomp.h b/mingw-w64-headers/include/dcomp.h
+index 58f4b8466..7f124ca99 100644
+--- a/mingw-w64-headers/include/dcomp.h
++++ b/mingw-w64-headers/include/dcomp.h
+@@ -524,8 +524,82 @@ __CRT_UUID_DECL(IDCompositionVisualDebug,0xfed2b808,0x5eb4,0x43a0,0xae,0xa3,0x35
+ #endif
+
+
++#undef INTERFACE
++#define INTERFACE IDCompositionFilterEffect
++DECLARE_INTERFACE_IID_(IDCompositionFilterEffect, IDCompositionEffect, "30C421D5-8CB2-4E9F-B133-37BE270D4AC2")
++{
++ STDMETHOD(SetInput)(THIS_ UINT index, IUnknown *input, UINT flags) PURE;
++};
++
++#ifdef __CRT_UUID_DECL
++__CRT_UUID_DECL(IDCompositionFilterEffect,0x30c421d5,0x8cb2,0x4e9f,0xb1,0x33,0x37,0xbe,0x27,0x0d,0x4a,0xc2);
+ #endif
+
++
++#undef INTERFACE
++#define INTERFACE IDCompositionSaturationEffect
++DECLARE_INTERFACE_IID_(IDCompositionSaturationEffect, IDCompositionFilterEffect, "A08DEBDA-3258-4FA4-9F16-9174D3FE93B1")
++{
++#if defined(_MSC_VER) && defined(__cplusplus)
++ STDMETHOD(SetSaturation)(THIS_ float ratio) PURE;
++ STDMETHOD(SetSaturation)(THIS_ IDCompositionAnimation* animation) PURE;
++#else
++ STDMETHOD(SetSaturation)(THIS_ IDCompositionAnimation* animation) PURE;
++ STDMETHOD(SetSaturation)(THIS_ float ratio ) PURE;
++#endif
++};
++
++#ifdef __CRT_UUID_DECL
++__CRT_UUID_DECL(IDCompositionSaturationEffect,0xa08debda,0x3258,0x4fa4,0x9f,0x16,0x91,0x74,0xd3,0xfe,0x93,0xb1);
++#endif
++
++
++#undef INTERFACE
++#define INTERFACE IDCompositionGaussianBlurEffect
++DECLARE_INTERFACE_IID_(IDCompositionGaussianBlurEffect, IDCompositionFilterEffect, "45D4D0B7-1BD4-454E-8894-2BFA68443033")
++{
++
++#if defined(_MSC_VER) && defined(__cplusplus)
++ STDMETHOD(SetStandardDeviation)(THIS_ float amount) PURE;
++ STDMETHOD(SetStandardDeviation)(THIS_ IDCompositionAnimation* animation) PURE;
++#else
++ STDMETHOD(SetStandardDeviation)(THIS_ IDCompositionAnimation* animation) PURE;
++ STDMETHOD(SetStandardDeviation)(THIS_ float amount) PURE;
++#endif
++ STDMETHOD(SetBorderMode)(THIS_ D2D1_BORDER_MODE mode) PURE;
++};
++
++#ifdef __CRT_UUID_DECL
++__CRT_UUID_DECL(IDCompositionGaussianBlurEffect,0x45d4d0b7,0x1bd4,0x454e,0x88,0x94,0x2b,0xfa,0x68,0x44,0x30,0x33);
++#endif
++
++
++// WARNING: some of the arguments are replaced with void*, only what's used has been kept
++#undef INTERFACE
++#define INTERFACE IDCompositionDevice3
++DECLARE_INTERFACE_IID_(IDCompositionDevice3, IDCompositionDevice2, "0987CB06-F916-48BF-8D35-CE7641781BD9")
++{
++ STDMETHOD(CreateGaussianBlurEffect)(THIS_ IDCompositionGaussianBlurEffect **gaussianBlurEffect) PURE;
++ STDMETHOD(CreateBrightnessEffect)(THIS_ void **brightnessEffect) PURE;
++ STDMETHOD(CreateColorMatrixEffect)(THIS_ void **colorMatrixEffect) PURE;
++ STDMETHOD(CreateShadowEffect)(THIS_ void **shadowEffect) PURE;
++ STDMETHOD(CreateHueRotationEffect)(THIS_ void **hueRotationEffect) PURE;
++ STDMETHOD(CreateSaturationEffect)(THIS_ IDCompositionSaturationEffect **saturationEffect) PURE;
++ STDMETHOD(CreateTurbulenceEffect)(THIS_ void **turbulenceEffect) PURE;
++ STDMETHOD(CreateLinearTransferEffect)(THIS_ void **linearTransferEffect) PURE;
++ STDMETHOD(CreateTableTransferEffect)(THIS_ void **tableTransferEffect) PURE;
++ STDMETHOD(CreateCompositeEffect)(THIS_ void **compositeEffect) PURE;
++ STDMETHOD(CreateBlendEffect)(THIS_ void **blendEffect) PURE;
++ STDMETHOD(CreateArithmeticCompositeEffect)(THIS_ void **arithmeticCompositeEffect) PURE;
++ STDMETHOD(CreateAffineTransform2DEffect)(THIS_ void **affineTransform2dEffect) PURE;
++};
++
++#ifdef __CRT_UUID_DECL
++__CRT_UUID_DECL(IDCompositionDevice3,0x0987cb06,0xf916,0x48bf,0x8d,0x35,0xce,0x76,0x41,0x78,0x1b,0xd9);
++#endif
++
++#endif // WINAPI_PARTITION_DESKTOP
++
+ #if (_WIN32_WINNT >= 0x0A00)
+
+ STDAPI DCompositionCreateDevice3(IUnknown *renderingDevice, REFIID iid, void **dcompositionDevice);
+--
+2.27.0.windows.1
+
=====================================
contrib/src/pthreads/rules.mak
=====================================
@@ -13,8 +13,8 @@ ifdef HAVE_WINSTORE
PKGS += winrt_headers
PKGS_ALL += winrt_headers
endif
-PKGS += dxvahd
-PKGS_ALL += dxvahd
+PKGS += dxvahd dcomp
+PKGS_ALL += dxvahd dcomp
ifeq ($(HAVE_MINGW64_V8),true)
PKGS_FOUND += winrt_headers dxvahd
endif
@@ -33,6 +33,7 @@ $(TARBALLS)/mingw-w64-v$(WINPTHREADS_VERSION).tar.bz2:
pthreads: mingw-w64-v$(WINPTHREADS_VERSION).tar.bz2 .sum-pthreads
#pthreads: mingw-w64-$(WINPTHREADS_HASH).tar.xz .sum-pthreads
$(UNPACK)
+ $(APPLY) $(SRC)/pthreads/0001-dcomp.h-add-some-missing-interfaces.patch
$(MOVE)
.pthreads: pthreads
@@ -55,3 +56,11 @@ pthreads: mingw-w64-v$(WINPTHREADS_VERSION).tar.bz2 .sum-pthreads
mkdir -p -- "$(PREFIX)/include"
cd $< && cp mingw-w64-headers/include/dxvahd.h "$(PREFIX)/include"
touch $@
+
+.sum-dcomp: .sum-pthreads
+ touch $@
+
+.dcomp: pthreads
+ mkdir -p -- "$(PREFIX)/include"
+ cd $< && cp mingw-w64-headers/include/dcomp.h "$(PREFIX)/include"
+ touch $@
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -278,6 +278,8 @@ libqt_plugin_la_SOURCES += \
gui/qt/maininterface/compositor_dcomp.cpp \
gui/qt/maininterface/compositor_dcomp.hpp \
gui/qt/maininterface/compositor_dcomp_error.hpp \
+ gui/qt/maininterface/compositor_dcomp_acrylicsurface.hpp \
+ gui/qt/maininterface/compositor_dcomp_acrylicsurface.cpp \
gui/qt/maininterface/compositor_dcomp_uisurface.cpp \
gui/qt/maininterface/compositor_dcomp_uisurface.hpp
endif
@@ -413,6 +415,7 @@ nodist_libqt_plugin_la_SOURCES += gui/qt/maininterface/main_interface_win32.moc.
if HAVE_DCOMP
nodist_libqt_plugin_la_SOURCES += \
+ gui/qt/maininterface/compositor_dcomp_acrylicsurface.moc.cpp \
gui/qt/maininterface/compositor_dcomp.moc.cpp \
gui/qt/maininterface/compositor_dcomp_uisurface.moc.cpp
endif
@@ -770,6 +773,7 @@ libqt_plugin_la_QML = \
gui/qt/widgets/qml/CheckedDelegate.qml \
gui/qt/widgets/qml/ComboBoxExt.qml \
gui/qt/widgets/qml/ContextButton.qml \
+ gui/qt/widgets/qml/AcrylicBackground.qml \
gui/qt/widgets/qml/AnimatedBackground.qml \
gui/qt/widgets/qml/CoverShadow.qml \
gui/qt/widgets/qml/CSDWindowButton.qml \
=====================================
modules/gui/qt/maininterface/compositor_dcomp.cpp
=====================================
@@ -30,6 +30,7 @@
#include <QDesktopWidget>
#include <QQuickWidget>
#include <QLibrary>
+#include <QScreen>
#include <QOpenGLFunctions>
#include <QOpenGLFramebufferObject>
@@ -338,6 +339,16 @@ MainInterface* CompositorDirectComposition::makeMainInterface()
m_uiSurface->setContent(m_ui->getComponent(), m_ui->createRootItem());
HR(m_rootVisual->AddVisual(m_uiVisual.Get(), FALSE, nullptr), "add ui visual to root");
HR(m_dcompDevice->Commit(), "commit UI visual");
+
+ auto resetAcrylicSurface = [this](QScreen * = nullptr)
+ {
+ m_acrylicSurface.reset(new CompositorDCompositionAcrylicSurface(m_intf, m_d3d11Device.Get()));
+ };
+
+ resetAcrylicSurface();
+ connect(qGuiApp, &QGuiApplication::screenAdded, this, resetAcrylicSurface);
+ connect(qGuiApp, &QGuiApplication::screenRemoved, this, resetAcrylicSurface);
+
return m_mainInterface;
}
catch (const DXError& err)
@@ -380,6 +391,7 @@ void CompositorDirectComposition::unloadGUI()
m_rootVisual->RemoveVisual(m_uiVisual.Get());
m_uiVisual.Reset();
}
+ m_acrylicSurface.reset();
m_uiSurface.reset();
m_ui.reset();
m_taskbarWidget.reset();
@@ -436,4 +448,24 @@ Compositor::Type CompositorDirectComposition::type() const
return Compositor::DirectCompositionCompositor;
}
+void CompositorDirectComposition::addVisual(Microsoft::WRL::ComPtr<IDCompositionVisual> visual)
+{
+ vlc_assert(m_rootVisual);
+
+ HRESULT hr = m_rootVisual->AddVisual(visual.Get(), FALSE, m_videoVisual ? m_videoVisual.Get() : m_uiVisual.Get());
+ if (FAILED(hr))
+ msg_Err(m_intf, "failed to add visual, code: 0x%lX", hr);
+
+ m_dcompDevice->Commit();
+}
+
+void CompositorDirectComposition::removeVisual(Microsoft::WRL::ComPtr<IDCompositionVisual> visual)
+{
+ auto hr = m_rootVisual->RemoveVisual(visual.Get());
+ if (FAILED(hr))
+ msg_Err(m_intf, "failed to remove visual, code: 0x%lX", hr);
+
+ m_dcompDevice->Commit();
+}
+
}
=====================================
modules/gui/qt/maininterface/compositor_dcomp.hpp
=====================================
@@ -21,12 +21,18 @@
#include "compositor.hpp"
#include <windows.h>
+
+# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x603)
+# undef _WIN32_WINNT
+# define _WIN32_WINNT 0x0603
+# endif
#include <dcomp.h>
#include <d3d11.h>
#include <wrl.h>
#include <dwmapi.h>
#include "maininterface/mainui.hpp"
+#include "compositor_dcomp_acrylicsurface.hpp"
#include "compositor_dcomp_uisurface.hpp"
#include "videosurface.hpp"
#include "interface_window_handler.hpp"
@@ -58,6 +64,9 @@ public:
Type type() const override;
+ void addVisual(Microsoft::WRL::ComPtr<IDCompositionVisual> visual);
+ void removeVisual(Microsoft::WRL::ComPtr<IDCompositionVisual> visual);
+
private slots:
void onSurfacePositionChanged(QPointF position);
@@ -77,6 +86,7 @@ private:
std::unique_ptr<WinTaskbarWidget> m_taskbarWidget;
std::unique_ptr<CompositorDCompositionUISurface> m_uiSurface;
+ std::unique_ptr<CompositorDCompositionAcrylicSurface> m_acrylicSurface;
vout_window_t *m_window = nullptr;
std::unique_ptr<MainUI> m_ui;
std::unique_ptr<VideoWindowHandler> m_videoWindowHandler;
=====================================
modules/gui/qt/maininterface/compositor_dcomp_acrylicsurface.cpp
=====================================
@@ -0,0 +1,445 @@
+/*****************************************************************************
+ * Copyright (C) 2021 the VideoLAN team
+ *
+ * Authors: Prince Gupta <guptaprince8832 at gmail.com>
+ *
+ * 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.
+ *****************************************************************************/
+
+#include "compositor_dcomp_acrylicsurface.hpp"
+
+#include <QWindow>
+#include <QScreen>
+#include <QLibrary>
+#include <versionhelpers.h>
+
+#include "compositor_dcomp.hpp"
+
+namespace
+{
+
+template <typename F>
+F loadFunction(QLibrary &library, const char *symbol)
+{
+ vlc_assert(library.isLoaded());
+
+ auto f = library.resolve(symbol);
+ if (!f)
+ {
+ const auto err = GetLastError();
+ throw std::runtime_error(QString("failed to load %1, code %2").arg(QString(symbol), QString::number(err)).toStdString());
+ }
+
+ return reinterpret_cast<F>(f);
+}
+
+bool isWinPreIron()
+{
+ typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
+
+ auto ntdll = GetModuleHandleW(L"ntdll.dll");
+ auto GetVersionInfo = reinterpret_cast<RtlGetVersionPtr>(GetProcAddress(ntdll, "RtlGetVersion"));
+
+ if (GetVersionInfo)
+ {
+ RTL_OSVERSIONINFOW versionInfo = { };
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ if (!GetVersionInfo(&versionInfo))
+ return versionInfo.dwMajorVersion <= 10
+ && versionInfo.dwBuildNumber < 20000;
+ }
+
+ return false;
+}
+
+}
+
+namespace vlc
+{
+
+CompositorDCompositionAcrylicSurface::CompositorDCompositionAcrylicSurface(qt_intf_t *intf_t, ID3D11Device *device, QObject *parent)
+ : QObject(parent)
+ , m_intf {intf_t}
+{
+ if (!init(device))
+ {
+ m_intf = nullptr;
+ return;
+ }
+
+ if (auto w = window())
+ setActive(w->isActive());
+
+ qApp->installNativeEventFilter(this);
+}
+
+CompositorDCompositionAcrylicSurface::~CompositorDCompositionAcrylicSurface()
+{
+ setActive(false);
+
+ if (m_dummyWindow)
+ DestroyWindow(m_dummyWindow);
+}
+
+bool CompositorDCompositionAcrylicSurface::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+{
+ MSG* msg = static_cast<MSG*>( message );
+
+ if (!m_intf || msg->hwnd != hwnd())
+ return false;
+
+ switch (msg->message)
+ {
+ case WM_WINDOWPOSCHANGED:
+ {
+ sync();
+ commitChanges();
+
+ requestReset(); // incase z-order changed
+ break;
+ }
+ case WM_ACTIVATE:
+ {
+ const int activeType = LOWORD(msg->wParam);
+ if ((activeType == WA_ACTIVE) || (activeType == WA_CLICKACTIVE))
+ setActive(true);
+ else if (activeType == WA_INACTIVE)
+ setActive(false);
+
+ break;
+ }
+ }
+
+ return false;
+}
+
+
+bool CompositorDCompositionAcrylicSurface::init(ID3D11Device *device)
+{
+ if (!loadFunctions())
+ return false;
+
+ if (!createDevice(device))
+ return false;
+
+ if (!createDesktopVisual())
+ return false;
+
+ if (!createBackHostVisual())
+ return false;
+
+ m_leftMostScreenX = 0;
+ m_topMostScreenY = 0;
+ for (const auto screen : qGuiApp->screens())
+ {
+ const auto geometry = screen->geometry();
+ m_leftMostScreenX = std::min<int>(geometry.left(), m_leftMostScreenX);
+ m_topMostScreenY = std::min<int>(geometry.top(), m_topMostScreenY);
+ }
+
+ return true;
+}
+
+bool CompositorDCompositionAcrylicSurface::loadFunctions()
+try
+{
+ QLibrary dwmapi("dwmapi.dll");
+ if (!dwmapi.load())
+ throw std::runtime_error("failed to dwmapi.dll, reason: " + dwmapi.errorString().toStdString());
+
+ lDwmpCreateSharedThumbnailVisual = loadFunction<DwmpCreateSharedThumbnailVisual>(dwmapi, MAKEINTRESOURCEA(147));
+ lDwmpCreateSharedMultiWindowVisual = loadFunction<DwmpCreateSharedMultiWindowVisual>(dwmapi, MAKEINTRESOURCEA(163));
+
+ if (isWinPreIron())
+ lDwmpUpdateSharedVirtualDesktopVisual = loadFunction<DwmpUpdateSharedVirtualDesktopVisual>(dwmapi, MAKEINTRESOURCEA(164)); //PRE-IRON
+ else
+ lDwmpUpdateSharedMultiWindowVisual = loadFunction<DwmpUpdateSharedMultiWindowVisual>(dwmapi, MAKEINTRESOURCEA(164)); //20xxx+
+
+
+ QLibrary user32("user32.dll");
+ if (!user32.load())
+ throw std::runtime_error("failed to user32.dll, reason: " + user32.errorString().toStdString());
+
+ lSetWindowCompositionAttribute = loadFunction<SetWindowCompositionAttribute>(user32, "SetWindowCompositionAttribute");
+ lGetWindowCompositionAttribute = loadFunction<GetWindowCompositionAttribute>(user32, "GetWindowCompositionAttribute");
+
+ return true;
+}
+catch (std::exception &err)
+{
+ msg_Err(m_intf, err.what());
+ return false;
+}
+
+bool CompositorDCompositionAcrylicSurface::createDevice(ID3D11Device *device)
+try
+{
+ QLibrary dcompDll("DCOMP.dll");
+ if (!dcompDll.load())
+ throw DXError("failed to load DCOMP.dll", static_cast<HRESULT>(GetLastError()));
+
+ DCompositionCreateDeviceFun myDCompositionCreateDevice3 =
+ reinterpret_cast<DCompositionCreateDeviceFun>(dcompDll.resolve("DCompositionCreateDevice3"));
+ if (!myDCompositionCreateDevice3)
+ throw DXError("failed to load DCompositionCreateDevice3 function", static_cast<HRESULT>(GetLastError()));
+
+ using namespace Microsoft::WRL;
+
+ ComPtr<IDXGIDevice> dxgiDevice;
+ HR(device->QueryInterface(dxgiDevice.GetAddressOf()), "query dxgi device");
+
+ ComPtr<IDCompositionDevice> dcompDevice1;
+ HR(myDCompositionCreateDevice3(
+ dxgiDevice.Get(),
+ __uuidof(IDCompositionDevice),
+ (void**)dcompDevice1.GetAddressOf()), "create composition device");
+
+ HR(dcompDevice1->QueryInterface(m_dcompDevice.GetAddressOf()), "dcompdevice not an IDCompositionDevice3");
+
+ HR(m_dcompDevice->CreateVisual(m_rootVisual.GetAddressOf()), "create root visual");
+
+ HR(m_dcompDevice->CreateRectangleClip(m_rootClip.GetAddressOf()), "create root clip");
+
+ HR(m_dcompDevice->CreateTranslateTransform(m_translateTransform.GetAddressOf()), "create translate transform");
+
+ HR(m_dcompDevice->CreateSaturationEffect(m_saturationEffect.GetAddressOf()), "create saturation effect");
+
+ HR(m_dcompDevice->CreateGaussianBlurEffect(m_gaussianBlur.GetAddressOf()), "create gaussian effect");
+
+ m_saturationEffect->SetSaturation(2);
+
+ m_gaussianBlur->SetBorderMode(D2D1_BORDER_MODE_HARD);
+ m_gaussianBlur->SetStandardDeviation(20);
+ m_gaussianBlur->SetInput(0, m_saturationEffect.Get(), 0);
+ m_rootVisual->SetEffect(m_gaussianBlur.Get());
+
+ return true;
+}
+catch (const DXError &err)
+{
+ msg_Err(m_intf, "failed to initialise compositor acrylic surface: '%s' code: 0x%lX", err.what(), err.code());
+ return false;
+}
+
+
+bool CompositorDCompositionAcrylicSurface::createDesktopVisual()
+try
+{
+ vlc_assert(!m_desktopVisual);
+ auto desktopWindow = GetShellWindow();
+ if (!desktopWindow)
+ throw DXError("failed to get desktop window", static_cast<HRESULT>(GetLastError()));
+
+ const int desktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ const int desktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+
+ DWM_THUMBNAIL_PROPERTIES thumbnail;
+ thumbnail.dwFlags = DWM_TNP_SOURCECLIENTAREAONLY | DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_RECTSOURCE | DWM_TNP_OPACITY | DWM_TNP_ENABLE3D;
+ thumbnail.opacity = 255;
+ thumbnail.fVisible = TRUE;
+ thumbnail.fSourceClientAreaOnly = FALSE;
+ thumbnail.rcDestination = RECT{ 0, 0, desktopWidth, desktopHeight };
+ thumbnail.rcSource = RECT{ 0, 0, desktopWidth, desktopHeight };
+
+ HTHUMBNAIL desktopThumbnail;
+ HR(lDwmpCreateSharedThumbnailVisual(hwnd(), desktopWindow, 2, &thumbnail, m_dcompDevice.Get(), (void**)m_desktopVisual.GetAddressOf(), &desktopThumbnail), "create desktop visual");
+ HR(m_rootVisual->AddVisual(m_desktopVisual.Get(), FALSE, nullptr), "Add desktop visual");
+
+ return true;
+}
+catch (const DXError &err)
+{
+ msg_Err(m_intf, "failed to create desktop visual: '%s' code: 0x%lX", err.what(), err.code());
+ return false;
+}
+
+bool CompositorDCompositionAcrylicSurface::createBackHostVisual()
+try
+{
+ vlc_assert(!m_dummyWindow);
+ // lDwmpCreateSharedMultiWindowVisual requires a window with disabled live (thumbnail) preview
+ // use a hidden dummy window to avoid disabling live preview of main window
+ m_dummyWindow = ::CreateWindowExA(WS_EX_TOOLWINDOW, "STATIC", "dummy", WS_VISIBLE, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
+ if (!m_dummyWindow)
+ throw DXError("failed to create dummy window", static_cast<HRESULT>(GetLastError()));
+
+ int attr = DWM_CLOAKED_APP;
+ DwmSetWindowAttribute(m_dummyWindow, DWMWA_CLOAK, &attr, sizeof attr);
+
+ BOOL enable = TRUE;
+ WINDOWCOMPOSITIONATTRIBDATA CompositionAttribute{};
+ CompositionAttribute.Attrib = WCA_EXCLUDED_FROM_LIVEPREVIEW;
+ CompositionAttribute.pvData = &enable;
+ CompositionAttribute.cbData = sizeof(BOOL);
+ lSetWindowCompositionAttribute(m_dummyWindow, &CompositionAttribute);
+
+ vlc_assert(!m_backHostVisual);
+ HR(lDwmpCreateSharedMultiWindowVisual(m_dummyWindow, m_dcompDevice.Get(), (void**)m_backHostVisual.GetAddressOf(), &m_backHostThumbnail)
+ , "failed to create shared multi visual");
+
+ updateVisual();
+
+ HR(m_rootVisual->AddVisual(m_backHostVisual.Get(), TRUE, m_desktopVisual.Get()), "Add backhost visual");
+
+ return true;
+}
+catch (const DXError &err)
+{
+ msg_Err(m_intf, "failed to create acrylic back host visual: '%s' code: 0x%lX", err.what(), err.code());
+ return false;
+}
+
+void CompositorDCompositionAcrylicSurface::sync()
+{
+ if (!m_intf || !hwnd())
+ return;
+
+ const int dx = std::abs(m_leftMostScreenX);
+ const int dy = std::abs(m_topMostScreenY);
+
+ // window()->geometry()/frameGeometry() returns incorrect rect with CSD
+ RECT rect;
+ GetWindowRect(hwnd(), &rect);
+ m_rootClip->SetLeft((float)rect.left + dx);
+ m_rootClip->SetRight((float)rect.right + dx);
+ m_rootClip->SetTop((float)rect.top);
+ m_rootClip->SetBottom((float)rect.bottom);
+ m_rootVisual->SetClip(m_rootClip.Get());
+
+ int frameX = 0;
+ int frameY = 0;
+
+ if (!m_intf->p_mi->useClientSideDecoration())
+ {
+ frameX = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
+ frameY = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION)
+ + GetSystemMetrics(SM_CXPADDEDBORDER);
+ }
+ else if (window()->visibility() & QWindow::Maximized)
+ {
+ // in maximized state CSDWin32EventHandler re-adds border
+ frameX = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
+ frameY = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
+ }
+
+ m_translateTransform->SetOffsetX(-1 * (float)rect.left - frameX - dx);
+ m_translateTransform->SetOffsetY(-1 * (float)rect.top - frameY - dy);
+ m_rootVisual->SetTransform(m_translateTransform.Get());
+}
+
+void CompositorDCompositionAcrylicSurface::updateVisual()
+{
+ const auto w = window();
+ if (!w || !w->screen())
+ return;
+
+ const auto screenRect = w->screen()->availableVirtualGeometry();
+ RECT sourceRect {screenRect.left(), screenRect.top(), screenRect.right(), screenRect.bottom()};
+ SIZE destinationSize {screenRect.width(), screenRect.height()};
+
+ HWND hwndExclusionList[2];
+ hwndExclusionList[0] = hwnd();
+ hwndExclusionList[1] = m_dummyWindow;
+
+ HRESULT hr = S_FALSE;
+
+ if (lDwmpUpdateSharedVirtualDesktopVisual)
+ hr = lDwmpUpdateSharedVirtualDesktopVisual(m_backHostThumbnail, NULL, 0, hwndExclusionList, 2, &sourceRect, &destinationSize);
+ else if (lDwmpUpdateSharedMultiWindowVisual)
+ hr = lDwmpUpdateSharedMultiWindowVisual(m_backHostThumbnail, NULL, 0, hwndExclusionList, 2, &sourceRect, &destinationSize, 1);
+ else
+ vlc_assert_unreachable();
+
+ if (FAILED(hr))
+ qDebug("failed to update shared multi window visual");
+}
+
+void CompositorDCompositionAcrylicSurface::commitChanges()
+{
+ m_dcompDevice->Commit();
+ DwmFlush();
+}
+
+void CompositorDCompositionAcrylicSurface::requestReset()
+{
+ if (m_resetPending)
+ return;
+
+ m_resetPending = true;
+ m_resetTimer.start(5, Qt::PreciseTimer, this);
+}
+
+void CompositorDCompositionAcrylicSurface::setActive(const bool newActive)
+{
+ if (newActive == m_active)
+ return;
+
+ m_active = newActive;
+ if (m_active)
+ {
+ auto dcompositor = static_cast<vlc::CompositorDirectComposition *>(m_intf->p_compositor);
+ dcompositor->addVisual(m_rootVisual);
+
+ updateVisual();
+ sync();
+ commitChanges();
+
+ // delay propagating changes to avoid flickering
+ QMetaObject::invokeMethod(this, [this]()
+ {
+ m_intf->p_mi->setHasAcrylicSurface(true);
+ }, Qt::QueuedConnection);
+ }
+ else
+ {
+ m_intf->p_mi->setHasAcrylicSurface(false);
+
+ // delay propagating changes to avoid flickering
+ QMetaObject::invokeMethod(this, [this]()
+ {
+ auto dcompositor = static_cast<vlc::CompositorDirectComposition *>(m_intf->p_compositor);
+ dcompositor->removeVisual(m_rootVisual);
+ }, Qt::QueuedConnection);
+ }
+}
+
+QWindow *CompositorDCompositionAcrylicSurface::window()
+{
+ return m_intf ? m_intf->p_compositor->interfaceMainWindow() : nullptr;
+}
+
+HWND CompositorDCompositionAcrylicSurface::hwnd()
+{
+ auto w = window();
+ return w->handle() ? (HWND)w->winId() : nullptr;
+}
+
+void CompositorDCompositionAcrylicSurface::timerEvent(QTimerEvent *event)
+{
+ if (!event)
+ return;
+
+ if (event->timerId() == m_resetTimer.timerId())
+ {
+ m_resetPending = false;
+ m_resetTimer.stop();
+
+ updateVisual();
+ sync();
+ commitChanges();
+ }
+}
+
+}
=====================================
modules/gui/qt/maininterface/compositor_dcomp_acrylicsurface.hpp
=====================================
@@ -0,0 +1,233 @@
+/*****************************************************************************
+ * Copyright (C) 2021 the VideoLAN team
+ *
+ * Authors: Prince Gupta <guptaprince8832 at gmail.com>
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef COMPOSITOR_DCOMP_ACRYLICSURFACE_HPP
+#define COMPOSITOR_DCOMP_ACRYLICSURFACE_HPP
+
+#include <QAbstractNativeEventFilter>
+#include <QBasicTimer>
+
+#include <windows.h>
+
+# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x603)
+# undef _WIN32_WINNT
+# define _WIN32_WINNT 0x0603
+# endif
+
+#include <dcomp.h>
+#include <d3d11.h>
+#include <wrl.h>
+#include <dwmapi.h>
+
+#include "compositor_dcomp_error.hpp"
+#include "main_interface.hpp"
+
+// Windows Private APIs, taken from https://blog.adeltax.com/dwm-thumbnails-but-with-idcompositionvisual/
+
+enum THUMBNAIL_TYPE {
+ TT_DEFAULT = 0x0,
+ TT_SNAPSHOT = 0x1,
+ TT_ICONIC = 0x2,
+ TT_BITMAPPENDING = 0x3,
+ TT_BITMAP = 0x4
+};
+
+typedef HRESULT(WINAPI* DwmpCreateSharedThumbnailVisual)(
+ IN HWND hwndDestination,
+ IN HWND hwndSource,
+ IN DWORD dwThumbnailFlags,
+ IN DWM_THUMBNAIL_PROPERTIES* pThumbnailProperties,
+ IN VOID* pDCompDevice,
+ OUT VOID** ppVisual,
+ OUT PHTHUMBNAIL phThumbnailId);
+
+typedef HRESULT(WINAPI* DwmpQueryWindowThumbnailSourceSize)(
+ IN HWND hwndSource,
+ IN BOOL fSourceClientAreaOnly,
+ OUT SIZE* pSize);
+
+typedef HRESULT(WINAPI* DwmpQueryThumbnailType)(
+ IN HTHUMBNAIL hThumbnailId,
+ OUT THUMBNAIL_TYPE* thumbType);
+
+typedef HRESULT(WINAPI* DwmpCreateSharedMultiWindowVisual)(
+ IN HWND hwndDestination,
+ IN VOID* pDCompDevice,
+ OUT VOID** ppVisual,
+ OUT PHTHUMBNAIL phThumbnailId);
+
+//pre-cobalt/pre-iron
+typedef HRESULT(WINAPI* DwmpUpdateSharedVirtualDesktopVisual)(
+ IN HTHUMBNAIL hThumbnailId,
+ IN HWND* phwndsInclude,
+ IN DWORD chwndsInclude,
+ IN HWND* phwndsExclude,
+ IN DWORD chwndsExclude,
+ OUT RECT* prcSource,
+ OUT SIZE* pDestinationSize);
+
+
+//cobalt/iron (20xxx+)
+//Change: function name + new DWORD parameter.
+//Pass "1" in dwFlags. Feel free to explore other flags.
+typedef HRESULT(WINAPI* DwmpUpdateSharedMultiWindowVisual)(
+ IN HTHUMBNAIL hThumbnailId,
+ IN HWND* phwndsInclude,
+ IN DWORD chwndsInclude,
+ IN HWND* phwndsExclude,
+ IN DWORD chwndsExclude,
+ OUT RECT* prcSource,
+ OUT SIZE* pDestinationSize,
+ IN DWORD dwFlags);
+
+#define DWM_TNP_FREEZE 0x100000
+#define DWM_TNP_ENABLE3D 0x4000000
+#define DWM_TNP_DISABLE3D 0x8000000
+#define DWM_TNP_FORCECVI 0x40000000
+#define DWM_TNP_DISABLEFORCECVI 0x80000000
+
+enum WINDOWCOMPOSITIONATTRIB {
+ WCA_UNDEFINED = 0x0,
+ WCA_NCRENDERING_ENABLED = 0x1,
+ WCA_NCRENDERING_POLICY = 0x2,
+ WCA_TRANSITIONS_FORCEDISABLED = 0x3,
+ WCA_ALLOW_NCPAINT = 0x4,
+ WCA_CAPTION_BUTTON_BOUNDS = 0x5,
+ WCA_NONCLIENT_RTL_LAYOUT = 0x6,
+ WCA_FORCE_ICONIC_REPRESENTATION = 0x7,
+ WCA_EXTENDED_FRAME_BOUNDS = 0x8,
+ WCA_HAS_ICONIC_BITMAP = 0x9,
+ WCA_THEME_ATTRIBUTES = 0xA,
+ WCA_NCRENDERING_EXILED = 0xB,
+ WCA_NCADORNMENTINFO = 0xC,
+ WCA_EXCLUDED_FROM_LIVEPREVIEW = 0xD,
+ WCA_VIDEO_OVERLAY_ACTIVE = 0xE,
+ WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 0xF,
+ WCA_DISALLOW_PEEK = 0x10,
+ WCA_CLOAK = 0x11,
+ WCA_CLOAKED = 0x12,
+ WCA_ACCENT_POLICY = 0x13,
+ WCA_FREEZE_REPRESENTATION = 0x14,
+ WCA_EVER_UNCLOAKED = 0x15,
+ WCA_VISUAL_OWNER = 0x16,
+ WCA_HOLOGRAPHIC = 0x17,
+ WCA_EXCLUDED_FROM_DDA = 0x18,
+ WCA_PASSIVEUPDATEMODE = 0x19,
+ WCA_LAST = 0x1A,
+};
+
+struct WINDOWCOMPOSITIONATTRIBDATA {
+ WINDOWCOMPOSITIONATTRIB Attrib;
+ void* pvData;
+ DWORD cbData;
+};
+
+typedef BOOL(WINAPI* SetWindowCompositionAttribute)(
+ IN HWND hwnd,
+ IN WINDOWCOMPOSITIONATTRIBDATA* pwcad);
+
+typedef BOOL(WINAPI* GetWindowCompositionAttribute)(
+ IN HWND hwnd,
+ OUT WINDOWCOMPOSITIONATTRIBDATA* pAttrData
+);
+
+//Signature for DCompositionCreateDevice
+typedef HRESULT (*DCompositionCreateDeviceFun)(IDXGIDevice *dxgiDevice, REFIID iid, void** dcompositionDevice);
+
+namespace vlc
+{
+
+/**
+ * @brief The CompositorDCompositionAcrylicSurface class
+ * Adds acrylic surface to the compositor_dcomp when the main window becomes active
+ * This acrylic surface is only valid for screen configuration at the time of initialization
+ */
+
+class CompositorDCompositionAcrylicSurface
+ : public QObject
+ , public QAbstractNativeEventFilter
+{
+ Q_OBJECT
+
+public:
+ CompositorDCompositionAcrylicSurface(qt_intf_t *intf_t, ID3D11Device *device, QObject *parent = nullptr);
+
+ ~CompositorDCompositionAcrylicSurface();
+
+protected:
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
+
+ void timerEvent(QTimerEvent *event) override;
+
+private:
+ bool init(ID3D11Device *device);
+ bool loadFunctions();
+ bool createDevice(ID3D11Device *device);
+ bool createDesktopVisual();
+ bool createBackHostVisual();
+
+ void sync();
+ void updateVisual();
+ void commitChanges();
+ void requestReset();
+
+ void setActive(bool newActive);
+
+ QWindow *window();
+
+ HWND hwnd();
+
+ DwmpCreateSharedThumbnailVisual lDwmpCreateSharedThumbnailVisual {};
+
+ DwmpCreateSharedMultiWindowVisual lDwmpCreateSharedMultiWindowVisual {};
+
+ // use to update visual created with lDwmpCreateSharedMultiWindowVisual
+ //PRE-IRON
+ DwmpUpdateSharedVirtualDesktopVisual lDwmpUpdateSharedVirtualDesktopVisual {};
+
+ //20xxx+
+ DwmpUpdateSharedMultiWindowVisual lDwmpUpdateSharedMultiWindowVisual {};
+
+ SetWindowCompositionAttribute lSetWindowCompositionAttribute {};
+ GetWindowCompositionAttribute lGetWindowCompositionAttribute {};
+
+ HTHUMBNAIL m_backHostThumbnail = NULL;
+ HWND m_dummyWindow {};
+
+ Microsoft::WRL::ComPtr<IDCompositionDevice3> m_dcompDevice;
+ Microsoft::WRL::ComPtr<IDCompositionVisual2> m_rootVisual;
+ Microsoft::WRL::ComPtr<IDCompositionVisual2> m_backHostVisual;
+ Microsoft::WRL::ComPtr<IDCompositionVisual2> m_desktopVisual;
+ Microsoft::WRL::ComPtr<IDCompositionRectangleClip> m_rootClip;
+ Microsoft::WRL::ComPtr<IDCompositionTranslateTransform> m_translateTransform;
+ Microsoft::WRL::ComPtr<IDCompositionSaturationEffect> m_saturationEffect;
+ Microsoft::WRL::ComPtr<IDCompositionGaussianBlurEffect> m_gaussianBlur;
+
+ qt_intf_t *m_intf {};
+ QBasicTimer m_resetTimer;
+ bool m_resetPending = false;
+ bool m_active = false;
+ int m_leftMostScreenX = 0;
+ int m_topMostScreenY = 0;
+};
+
+}
+
+#endif
=====================================
modules/gui/qt/maininterface/compositor_dcomp_uisurface.hpp
=====================================
@@ -28,6 +28,12 @@
#include <vlc_interface.h> /* intf_thread_t */
#include <windows.h>
+
+# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x603)
+# undef _WIN32_WINNT
+# define _WIN32_WINNT 0x0603
+# endif
+
#include <d3d11.h>
#include <dcomp.h>
#include <wrl.h>
=====================================
modules/gui/qt/maininterface/main_interface.cpp
=====================================
@@ -342,6 +342,24 @@ void MainInterface::onWindowVisibilityChanged(QWindow::Visibility visibility)
m_windowVisibility = visibility;
}
+void MainInterface::setUseAcrylicBackground(const bool v)
+{
+ if (m_useAcrylicBackground == v)
+ return;
+
+ m_useAcrylicBackground = v;
+ emit useAcrylicBackgroundChanged();
+}
+
+void MainInterface::setHasAcrylicSurface(const bool v)
+{
+ if (m_hasAcrylicSurface == v)
+ return;
+
+ m_hasAcrylicSurface = v;
+ emit hasAcrylicSurfaceChanged();
+}
+
void MainInterface::incrementIntfUserScaleFactor(bool increment)
{
if (increment)
=====================================
modules/gui/qt/maininterface/main_interface.hpp
=====================================
@@ -163,6 +163,8 @@ class MainInterface : public QObject
Q_PROPERTY(bool canShowVideoPIP READ canShowVideoPIP CONSTANT FINAL)
Q_PROPERTY(bool pinVideoControls READ pinVideoControls WRITE setPinVideoControls NOTIFY pinVideoControlsChanged FINAL)
Q_PROPERTY(ControlbarProfileModel* controlbarProfileModel READ controlbarProfileModel CONSTANT FINAL)
+ Q_PROPERTY(bool useAcrylicBackground READ useAcrylicBackground NOTIFY useAcrylicBackgroundChanged FINAL)
+ Q_PROPERTY(bool hasAcrylicSurface READ hasAcrylicSurface NOTIFY hasAcrylicSurfaceChanged FINAL)
public:
/* tors */
@@ -217,6 +219,8 @@ public:
inline ControlbarProfileModel* controlbarProfileModel() const { return m_controlbarProfileModel; }
inline QUrl getDialogFilePath() const { return m_dialogFilepath; }
inline void setDialogFilePath(const QUrl& filepath ){ m_dialogFilepath = filepath; }
+ inline bool useAcrylicBackground() const { return m_useAcrylicBackground; }
+ inline bool hasAcrylicSurface() const { return m_hasAcrylicSurface; }
bool hasEmbededVideo() const;
VideoSurfaceProvider* getVideoSurfaceProvider() const;
@@ -290,6 +294,9 @@ protected:
ControlbarProfileModel* m_controlbarProfileModel;
+ bool m_useAcrylicBackground = true;
+ bool m_hasAcrylicSurface = false;
+
public slots:
void toggleUpdateSystrayMenu();
void showUpdateSystrayMenu();
@@ -306,6 +313,8 @@ public slots:
void setPinVideoControls( bool );
void updateIntfScaleFactor();
void onWindowVisibilityChanged(QWindow::Visibility);
+ void setUseAcrylicBackground(bool);
+ void setHasAcrylicSurface(bool);
void emitBoss();
void emitRaise();
@@ -356,6 +365,8 @@ signals:
void intfScaleFactorChanged();
void pinVideoControlsChanged( bool );
+ void useAcrylicBackgroundChanged();
+ void hasAcrylicSurfaceChanged();
};
#endif
=====================================
modules/gui/qt/maininterface/qml/BannerSources.qml
=====================================
@@ -60,15 +60,18 @@ FocusScope {
searchBox.expanded = true
}
- Rectangle {
+ Widgets.AcrylicBackground {
+ alternativeColor: VLCStyle.colors.topBanner
+ anchors.fill: parent
+ }
+
+ Item {
id: pLBannerSources
property alias model: globalMenuGroup.model
anchors.fill: parent
- color: VLCStyle.colors.topBanner
-
Column {
id: col
anchors {
@@ -161,6 +164,7 @@ FocusScope {
delegate: Widgets.BannerTabButton {
iconTxt: model.icon
+ color: "transparent"
showText: globalToolbar.colapseTabButtons
selected: model.index === selectedIndex
onClicked: root.itemClicked(model.index)
=====================================
modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
=====================================
@@ -101,11 +101,10 @@ FocusScope {
focus: visible
anchors.fill: parent
- Rectangle {
+ Widgets.AcrylicBackground {
width: artistList.width
height: artistList.height
- color: VLCStyle.colors.bgAlt
- opacity: .8
+ alternativeColor: VLCStyle.colors.bgAlt
}
Row {
=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -567,6 +567,8 @@ FocusScope {
PL.PlaylistListView {
id: playlistView
+
+ useAcrylic: false
focus: true
anchors.fill: parent
=====================================
modules/gui/qt/playlist/qml/PlaylistListView.qml
=====================================
@@ -32,6 +32,8 @@ FocusScope {
property alias model: listView.model
+ property alias useAcrylic: acrylicBackground.enabled
+
readonly property real minimumWidth: noContentInfoColumn.implicitWidth +
leftPadding +
rightPadding +
@@ -102,10 +104,16 @@ FocusScope {
}
}
- Rectangle {
+ Widgets.AcrylicBackground {
+ id: acrylicBackground
+
+ anchors.fill: parent
+ alternativeColor: colors.bgAlt
+ }
+
+ Item {
id: parentRect
anchors.fill: parent
- color: colors.topBanner
Widgets.DragItem {
id: dragItem
=====================================
modules/gui/qt/vlc.qrc
=====================================
@@ -196,6 +196,7 @@
<file alias="ActionButtonPrimary.qml">widgets/qml/ActionButtonPrimary.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>
<file alias="AnimatedBackground.qml">widgets/qml/AnimatedBackground.qml</file>
<file alias="CSDWindowButton.qml">widgets/qml/CSDWindowButton.qml</file>
<file alias="CSDWindowButtonSet.qml">widgets/qml/CSDWindowButtonSet.qml</file>
=====================================
modules/gui/qt/widgets/qml/AcrylicBackground.qml
=====================================
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * Authors: Prince Gupta <guptaprince8832 at gmail.com>
+ *
+ * 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 "qrc:///style/"
+
+// This Component uses layering, avoid adding children to this widget
+Item {
+ id: root
+
+ readonly property bool usingAcrylic: visible && enabled && mainInterface.useAcrylicBackground && mainInterface.hasAcrylicSurface
+
+ property color tintColor: VLCStyle.colors.setColorAlpha(VLCStyle.colors.bg, 0.7)
+
+ property color alternativeColor: VLCStyle.colors.bgAlt
+
+ layer.enabled: true
+ layer.effect: ShaderEffect {
+ property color overlay: root.usingAcrylic ? root.tintColor : root.alternativeColor
+
+ blending: false
+ fragmentShader: "
+ uniform lowp vec4 overlay;
+ void main() { gl_FragColor = overlay; }
+ "
+ }
+}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9ace5912de874bceb95a777f19cd36c2cfc3d437...b605fd25e97c75aa147b9bfd7fb530904eed27c7
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9ace5912de874bceb95a777f19cd36c2cfc3d437...b605fd25e97c75aa147b9bfd7fb530904eed27c7
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list