[vlc-commits] [Git][videolan/vlc][master] qml: make FrostedGlassEffect a layer effect
François Cartegnie (@fcartegnie)
gitlab at videolan.org
Mon Dec 26 11:33:17 UTC 2022
François Cartegnie pushed to branch master at VideoLAN / VLC
Commits:
e3b28612 by Fatih Uzunoglu at 2022-12-26T10:31:42+00:00
qml: make FrostedGlassEffect a layer effect
... so that we can set background on it.
Also,
- Make MiniPlayer a control.
- Refactor ScanProgressBar and make it a control.
- - - - -
4 changed files:
- modules/gui/qt/maininterface/qml/MainDisplay.qml
- modules/gui/qt/player/qml/MiniPlayer.qml
- modules/gui/qt/widgets/qml/FrostedGlassEffect.qml
- modules/gui/qt/widgets/qml/ScanProgressBar.qml
Changes:
=====================================
modules/gui/qt/maininterface/qml/MainDisplay.qml
=====================================
@@ -213,16 +213,36 @@ FocusScope {
onContentModelChanged: modelSortSettingHandler.set(sourcesBanner.contentModel, History.viewPath)
}
- Rectangle {
- color: VLCStyle.colors.bg
+ FocusScope {
+ focus: true
+ id: medialibId
anchors.fill: parent
- FocusScope {
- focus: true
- id: medialibId
+ Navigation.parentItem: root
+
+ Rectangle {
+ id: parentRectangle
anchors.fill: parent
- Navigation.parentItem: root
+ color: VLCStyle.colors.bg
+
+ layer.enabled: (((GraphicsInfo.shaderType === GraphicsInfo.GLSL)) &&
+ ((GraphicsInfo.shaderSourceType & GraphicsInfo.ShaderSourceString))) &&
+ (miniPlayer.visible || (loaderProgress.active && loaderProgress.item.visible))
+
+ layer.effect: Widgets.FrostedGlassEffect {
+ tint: VLCStyle.colors.lowerBanner
+
+ effectRect: {
+ var _height = 0
+ if (loaderProgress.active && loaderProgress.item.visible)
+ _height += loaderProgress.item.height
+ if (miniPlayer.visible)
+ _height += miniPlayer.height
+
+ return Qt.rect(0, height - _height, width, _height)
+ }
+ }
ColumnLayout {
id: mainColumn
@@ -281,27 +301,6 @@ FocusScope {
: VLCStyle.applicationHorizontalMargin
leftMargin: VLCStyle.applicationHorizontalMargin
}
-
- // This item is the root of a large hierarchy
- // which requires many batches to be rendered.
- // When the miniPlayer effect is active, this
- // item (source item) gets rendered in an offscreen
- // surface. If we don't enable layer here,
- // it (along with children) gets rendered again
- // in the assigned window.
- // If layer is enabled, instead of rendering one
- // more time with many batches, a dynamic texture
- // from the offscreen surface is used. This behavior
- // reduces the amount of batches from 2x to x+1.
- // A side effect is having to draw a large texture
- // with blending on, but this must be cheaper redrawing
- // all the batches.
- // TODO: Reconsider this behavior when batching is optimized.
- layer.enabled: miniPlayer.visible && miniPlayer.effectAvailable
-
- // Enable clipping so that the effect does not sit
- // on top of the source.
- clip: miniPlayer.visible && miniPlayer.effectAvailable
}
FocusScope {
@@ -430,114 +429,110 @@ FocusScope {
}
}
}
+ }
- Loader {
- id: loaderProgress
+ Loader {
+ id: loaderProgress
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: miniPlayer.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: miniPlayer.top
- active: (MainCtx.mediaLibraryAvailable && MainCtx.mediaLibrary.idle === false)
+ active: (MainCtx.mediaLibraryAvailable && MainCtx.mediaLibrary.idle === false)
- source: "qrc:///widgets/ScanProgressBar.qml"
+ source: "qrc:///widgets/ScanProgressBar.qml"
- onItemChanged: {
- if (item === null) return
+ onLoaded: {
+ item.background.visible = Qt.binding(function() { return !parentRectangle.layer.enabled })
- // NOTE: These are required for the FrostedGlassEffect.
+ item.leftPadding = Qt.binding(function() { return VLCStyle.margin_large + VLCStyle.applicationHorizontalMargin })
+ item.rightPadding = Qt.binding(function() { return VLCStyle.margin_large + VLCStyle.applicationHorizontalMargin })
+ item.bottomPadding = Qt.binding(function() { return VLCStyle.margin_small + (miniPlayer.visible ? 0 : VLCStyle.applicationVerticalMargin) })
+ }
+ }
- item.source = Qt.binding(function() { return stackView })
+ P.PIPPlayer {
+ id: playerPip
+ anchors {
+ bottom: miniPlayer.top
+ left: parent.left
+ bottomMargin: VLCStyle.margin_normal
+ leftMargin: VLCStyle.margin_normal + VLCStyle.applicationHorizontalMargin
+ }
- item.sourceRect = Qt.binding(function() {
- return stackView.mapFromItem(parent, x, y, width, height)
- })
+ width: VLCStyle.dp(320, VLCStyle.scale)
+ height: VLCStyle.dp(180, VLCStyle.scale)
+ z: 2
+ visible: !root._inhibitMiniPlayer && root._showMiniPlayer && MainCtx.hasEmbededVideo
+ enabled: !root._inhibitMiniPlayer && root._showMiniPlayer && MainCtx.hasEmbededVideo
+
+ dragXMin: 0
+ dragXMax: root.width - playerPip.width
+ dragYMin: sourcesBanner.y + sourcesBanner.height
+ dragYMax: miniPlayer.y - playerPip.height
+
+ //keep the player visible on resize
+ Connections {
+ target: root
+ onWidthChanged: {
+ if (playerPip.x > playerPip.dragXMax)
+ playerPip.x = playerPip.dragXMax
+ }
+ onHeightChanged: {
+ if (playerPip.y > playerPip.dragYMax)
+ playerPip.y = playerPip.dragYMax
}
}
+ }
- P.PIPPlayer {
- id: playerPip
- anchors {
- bottom: miniPlayer.top
- left: parent.left
- bottomMargin: VLCStyle.margin_normal
- leftMargin: VLCStyle.margin_normal + VLCStyle.applicationHorizontalMargin
- }
+ DG.Dialogs {
+ z: 10
+ bgContent: root
- width: VLCStyle.dp(320, VLCStyle.scale)
- height: VLCStyle.dp(180, VLCStyle.scale)
- z: 2
- visible: !root._inhibitMiniPlayer && root._showMiniPlayer && MainCtx.hasEmbededVideo
- enabled: !root._inhibitMiniPlayer && root._showMiniPlayer && MainCtx.hasEmbededVideo
-
- dragXMin: 0
- dragXMax: root.width - playerPip.width
- dragYMin: sourcesBanner.y + sourcesBanner.height
- dragYMax: miniPlayer.y - playerPip.height
-
- //keep the player visible on resize
- Connections {
- target: root
- onWidthChanged: {
- if (playerPip.x > playerPip.dragXMax)
- playerPip.x = playerPip.dragXMax
- }
- onHeightChanged: {
- if (playerPip.y > playerPip.dragYMax)
- playerPip.y = playerPip.dragYMax
- }
- }
+ anchors {
+ bottom: miniPlayer.visible ? miniPlayer.top : parent.bottom
+ left: parent.left
+ right: parent.right
}
+ }
- DG.Dialogs {
- z: 10
- bgContent: root
+ P.MiniPlayer {
+ id: miniPlayer
- anchors {
- bottom: miniPlayer.visible ? miniPlayer.top : parent.bottom
- left: parent.left
- right: parent.right
- }
+ BindingCompat on state {
+ when: root._inhibitMiniPlayer && !miniPlayer.visible
+ value: ""
}
- P.MiniPlayer {
- id: miniPlayer
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
- BindingCompat on state {
- when: root._inhibitMiniPlayer && !miniPlayer.visible
- value: ""
- }
+ z: 3
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
-
- z: 3
- Navigation.parentItem: medialibId
- Navigation.upItem: stackView
- Navigation.cancelItem:sourcesBanner
- onVisibleChanged: {
- if (!visible && miniPlayer.activeFocus)
- stackView.forceActiveFocus()
- }
+ rightPadding: VLCStyle.applicationHorizontalMargin
+ leftPadding: VLCStyle.applicationHorizontalMargin
+ bottomPadding: VLCStyle.applicationVerticalMargin
+
+ background.visible: !parentRectangle.layer.enabled
- effectSource: stackView
- effectSourceRect: effectSource.mapFromItem(parent,
- x,
- y,
- width,
- height)
+ Navigation.parentItem: medialibId
+ Navigation.upItem: stackView
+ Navigation.cancelItem:sourcesBanner
+ onVisibleChanged: {
+ if (!visible && miniPlayer.activeFocus)
+ stackView.forceActiveFocus()
}
+ }
- Connections {
- target: Player
- onHasVideoOutputChanged: {
- if (Player.hasVideoOutput && MainCtx.hasEmbededVideo) {
- if (History.current.view !== "player")
- g_mainDisplay.showPlayer()
- } else {
- _showMiniPlayer = false;
- }
+ Connections {
+ target: Player
+ onHasVideoOutputChanged: {
+ if (Player.hasVideoOutput && MainCtx.hasEmbededVideo) {
+ if (History.current.view !== "player")
+ g_mainDisplay.showPlayer()
+ } else {
+ _showMiniPlayer = false;
}
}
}
=====================================
modules/gui/qt/player/qml/MiniPlayer.qml
=====================================
@@ -17,6 +17,7 @@
*****************************************************************************/
import QtQuick 2.11
import QtQuick.Controls 2.4
+import QtQuick.Templates 2.4 as T
import QtQuick.Layouts 1.11
import QtGraphicalEffects 1.0
@@ -25,17 +26,15 @@ import org.videolan.vlc 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///style/"
-FocusScope {
+T.Pane {
id: root
- implicitHeight: controlBar.implicitHeight
height: 0
- visible: false
+ implicitWidth: Math.max(background ? background.implicitWidth : 0, contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0, contentItem.implicitHeight + topPadding + bottomPadding)
- property alias effectSource: effect.source
- property alias effectSourceRect: effect.sourceRect
- property alias effectAvailable: effect.effectAvailable
+ visible: false
state: (Player.playingState === Player.PLAYING_STATE_STOPPED) ? ""
: "expanded"
@@ -68,22 +67,11 @@ FocusScope {
acceptedButtons: Qt.AllButtons
}
- Widgets.FrostedGlassEffect {
- id: effect
- anchors.fill: parent
-
- tint: VLCStyle.colors.lowerBanner
+ background: Rectangle {
+ color: VLCStyle.colors.bg
}
- ControlBar {
- id: controlBar
-
- anchors.fill: parent
-
- rightPadding: VLCStyle.applicationHorizontalMargin
- leftPadding: rightPadding
- bottomPadding: VLCStyle.applicationVerticalMargin
-
+ contentItem: ControlBar {
focus: true
colors: VLCStyle.colors
textPosition: ControlBar.TimeTextPosition.Hide
@@ -94,7 +82,7 @@ FocusScope {
Navigation.parentItem: root
Keys.onPressed: {
- controlBar.Navigation.defaultKeyAction(event)
+ Navigation.defaultKeyAction(event)
if (!event.accepted) {
MainCtx.sendHotkey(event.key, event.modifiers)
=====================================
modules/gui/qt/widgets/qml/FrostedGlassEffect.qml
=====================================
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (C) 2020 VLC authors and VideoLAN
+ * Copyright (C) 2022 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
@@ -21,101 +21,114 @@ import QtGraphicalEffects 1.0
import "qrc:///style/"
+// This item can be used as a layer effect.
+// Right now, it has the following limitations:
+// * The blur effect is processed for the whole source,
+// even though it is only shown for the area denoted
+// by effectRect. This is caused by FastBlur not
+// accepting a source rectangle.
+// * The source is sampled and displayed as a whole,
+// however it is stacked below of the blur effect
+// so it is only partly seen as intended.
+// * As a corollary of the previous limitation, you should
+// always have a solid background for the source item.
+// otherwise, the effect can not work properly.
Item {
id: effect
- property Item source
- property rect sourceRect: mapToItem(source, x, y, width, height)
+ property var source
- property bool recursive: false
- property real blurRadius: 64
- property color tint
+ // Rectangular area where the effect should be applied:
+ property alias effectRect: blurProxy.sourceRect
- property real tintStrength: 0.7
+ property alias blurRadius: blurEffect.radius
+
+ property color tint: "transparent"
+ property real tintStrength: Qt.colorEqual(tint, "transparent") ? 0.0 : 0.7
property real noiseStrength: 0.02
property real exclusionStrength: 0.09
- readonly property bool effectAvailable: (GraphicsInfo.shaderType === GraphicsInfo.GLSL) &&
- (GraphicsInfo.shaderSourceType & GraphicsInfo.ShaderSourceString)
+ ShaderEffect {
+ anchors.fill: parent
+
+ property alias source: effect.source
- opacity: source.opacity
+ cullMode: ShaderEffect.BackFaceCulling
+ }
- Loader {
- id: loader
+ FastBlur {
+ id: blurEffect
anchors.fill: parent
- sourceComponent: effect.effectAvailable ? effectComponent : rectComponent
+ source: effect.source
- Component {
- id: rectComponent
+ radius: 64
- Rectangle {
- color: effect.tint
- }
- }
+ visible: false
+ }
- Component {
- id: effectComponent
+ ShaderEffectSource {
+ id: blurProxy
- FastBlur {
- id: blurEffect
+ x: Math.floor(sourceRect.x)
+ y: Math.floor(sourceRect.y)
+ width: sourceRect.width > 0 ? Math.ceil(sourceRect.width)
+ : implicitWidth
+ height: sourceRect.height > 0 ? Math.ceil(sourceRect.height)
+ : implicitHeight
- source: ShaderEffectSource {
- id: effectSource
- smooth: false
- sourceItem: effect.source
- sourceRect: effect.sourceRect
- visible: false
- samples: 0
- }
+ implicitWidth: Math.ceil(parent.width)
+ implicitHeight: Math.ceil(parent.height)
+
+ sourceItem: blurEffect
+ recursive: false
+ samples: 0
+ smooth: false
- radius: effect.blurRadius
+ mipmap: false
- layer.enabled: true
- layer.effect: ShaderEffect {
- readonly property color tint: effect.tint
- readonly property real tintStrength: effect.tintStrength
- readonly property real noiseStrength: effect.noiseStrength
- readonly property real exclusionStrength: effect.exclusionStrength
+ layer.enabled: true
+ layer.effect: ShaderEffect {
+ readonly property color tint: effect.tint
+ readonly property real tintStrength: effect.tintStrength
+ readonly property real noiseStrength: effect.noiseStrength
+ readonly property real exclusionStrength: effect.exclusionStrength
- cullMode: ShaderEffect.BackFaceCulling
+ cullMode: ShaderEffect.BackFaceCulling
- fragmentShader: "
- uniform lowp sampler2D source; // this item
- varying highp vec2 qt_TexCoord0;
+ fragmentShader: "
+ uniform lowp sampler2D source; // this item
+ varying highp vec2 qt_TexCoord0;
- uniform lowp float qt_Opacity;
+ uniform lowp float qt_Opacity;
- uniform lowp vec4 tint;
+ uniform lowp vec4 tint;
- uniform lowp float exclusionStrength;
- uniform lowp float noiseStrength;
- uniform lowp float tintStrength;
+ uniform lowp float exclusionStrength;
+ uniform lowp float noiseStrength;
+ uniform lowp float tintStrength;
- mediump float rand(highp vec2 co){
- return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
- }
+ mediump float rand(highp vec2 co){
+ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+ }
- mediump vec4 exclude(mediump vec4 src, mediump vec4 dst)
- {
- return src + dst - 2.0 * src * dst;
- }
+ mediump vec4 exclude(mediump vec4 src, mediump vec4 dst)
+ {
+ return src + dst - 2.0 * src * dst;
+ }
- void main() {
- mediump float r = rand(qt_TexCoord0) - 0.5;
- mediump vec4 noise = vec4(r,r,r,1.0) * noiseStrength;
- mediump vec4 blurred = texture2D(source, qt_TexCoord0);
+ void main() {
+ mediump float r = rand(qt_TexCoord0) - 0.5;
+ mediump vec4 noise = vec4(r,r,r,1.0) * noiseStrength;
+ mediump vec4 blurred = texture2D(source, qt_TexCoord0);
- mediump vec4 exclColor = vec4(exclusionStrength, exclusionStrength, exclusionStrength, 0.0);
+ mediump vec4 exclColor = vec4(exclusionStrength, exclusionStrength, exclusionStrength, 0.0);
- blurred = exclude(blurred, exclColor);
+ blurred = exclude(blurred, exclColor);
- gl_FragColor = (mix(blurred, tint, tintStrength) + noise) * qt_Opacity;
- }"
- }
- }
+ gl_FragColor = (mix(blurred, tint, tintStrength) + noise) * qt_Opacity;
+ }"
}
-
}
}
=====================================
modules/gui/qt/widgets/qml/ScanProgressBar.qml
=====================================
@@ -19,138 +19,115 @@
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Templates 2.4 as T
-import QtQuick.Layouts 1.11
import org.videolan.vlc 0.1
import org.videolan.medialib 0.1
import "qrc:///style/"
-FrostedGlassEffect {
- // Settings
+T.ProgressBar {
+ id: control
- height: _getHeight()
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
- tint: VLCStyle.colors.lowerBanner
+ rightPadding: VLCStyle.margin_large
+ leftPadding: VLCStyle.margin_large
+ bottomPadding: VLCStyle.margin_small
+ topPadding: VLCStyle.margin_small
- // Functions
+ from: 0
+ to: 100
- // Private
+ value: MediaLib.parsingProgress
- function _getHeight() {
- var height = column.implicitHeight + VLCStyle.margin_small * 2
+ indeterminate: MediaLib.discoveryPending
- // NOTE: We don't need to take the vertical safe area into consideration when the
- // miniPlayer is visible.
- if (g_mainDisplay.hasMiniPlayer)
- return height
- else
- return height + VLCStyle.applicationVerticalMargin
+ background: Rectangle {
+ color: VLCStyle.colors.bg
}
- // Children
-
- ColumnLayout {
- id: column
-
- anchors.fill: parent
-
- anchors.leftMargin: VLCStyle.margin_large + VLCStyle.applicationHorizontalMargin
- anchors.rightMargin: anchors.leftMargin
-
- anchors.topMargin: VLCStyle.margin_small
-
- anchors.bottomMargin: (g_mainDisplay.hasMiniPlayer) ? VLCStyle.margin_small
- : VLCStyle.margin_small
- + VLCStyle.applicationVerticalMargin
-
+ contentItem: Column {
spacing: VLCStyle.margin_small
- T.ProgressBar {
- id: control
-
- Layout.fillWidth: true
-
- height: VLCStyle.heightBar_xxsmall
+ Item {
+ anchors.left: parent.left
+ anchors.right: parent.right
- from: 0
- to: 100
+ implicitHeight: VLCStyle.heightBar_xxsmall
+ implicitWidth: 200
- value: MediaLib.parsingProgress
+ Rectangle {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
- indeterminate: MediaLib.discoveryPending
+ implicitHeight: VLCStyle.heightBar_xxxsmall
- contentItem: Item {
- Rectangle {
- anchors.left: parent.left
- anchors.right: parent.right
-
- anchors.verticalCenter: parent.verticalCenter
-
- height: VLCStyle.heightBar_xxxsmall
-
- color: VLCStyle.colors.sliderBarMiniplayerBgColor
- }
+ color: VLCStyle.colors.sliderBarMiniplayerBgColor
+ }
- Rectangle {
- anchors.verticalCenter: parent.verticalCenter
+ Rectangle {
+ anchors.verticalCenter: parent.verticalCenter
- width: parent.width * control.visualPosition
- height: VLCStyle.heightBar_xxsmall
+ implicitWidth: parent.width * control.visualPosition
+ implicitHeight: VLCStyle.heightBar_xxsmall
- // NOTE: We want round corners.
- radius: height
+ // NOTE: We want round corners.
+ radius: height
- visible: (control.indeterminate === false)
+ visible: !control.indeterminate
- color: VLCStyle.colors.accent
- }
+ color: VLCStyle.colors.accent
+ }
- Rectangle {
- property real position: 0
+ Rectangle {
+ property real position: 0
- anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenter: parent.verticalCenter
- // NOTE: Why 0.24 though ?
- width: parent.width * 0.24
- height: VLCStyle.heightBar_xxsmall
+ // NOTE: Why 0.24 though ?
+ implicitWidth: parent.width * 0.24
+ implicitHeight: VLCStyle.heightBar_xxsmall
- x: Math.round((parent.width - width) * position)
+ x: Math.round((parent.width - width) * position)
- // NOTE: We want round corners.
- radius: height
+ // NOTE: We want round corners.
+ radius: height
- visible: control.indeterminate
+ visible: control.indeterminate
- color: VLCStyle.colors.accent
+ color: VLCStyle.colors.accent
- SequentialAnimation on position {
- loops: Animation.Infinite
+ SequentialAnimation on position {
+ loops: Animation.Infinite
- running: visible
+ running: visible
- NumberAnimation {
- from: 0
- to: 1.0
+ NumberAnimation {
+ from: 0
+ to: 1.0
- duration: VLCStyle.durationSliderBouncing
- easing.type: Easing.OutBounce
- }
+ duration: VLCStyle.durationSliderBouncing
+ easing.type: Easing.OutBounce
+ }
- NumberAnimation {
- from: 1.0
- to: 0
+ NumberAnimation {
+ from: 1.0
+ to: 0
- duration: VLCStyle.durationSliderBouncing
- easing.type: Easing.OutBounce
- }
+ duration: VLCStyle.durationSliderBouncing
+ easing.type: Easing.OutBounce
}
}
}
}
SubtitleLabel {
- Layout.fillWidth: true
+ anchors.left: parent.left
+ anchors.right: parent.right
text: (MediaLib.discoveryPending) ? I18n.qtr("Scanning %1")
.arg(MediaLib.discoveryEntryPoint)
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/e3b28612d38f925d92f9d7fd45ee6b337fe2dfe5
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/e3b28612d38f925d92f9d7fd45ee6b337fe2dfe5
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