forked from quickshell/quickshell
		
	widgets: add ClippingRectangle
This commit is contained in:
		
							parent
							
								
									68ba5005ce
								
							
						
					
					
						commit
						fdc13023b7
					
				
					 9 changed files with 168 additions and 2 deletions
				
			
		
							
								
								
									
										1
									
								
								BUILD.md
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								BUILD.md
									
										
									
									
									
								
							| 
						 | 
					@ -41,6 +41,7 @@ Quickshell has a set of base dependencies you will always need, names vary by di
 | 
				
			||||||
- `cmake`
 | 
					- `cmake`
 | 
				
			||||||
- `qt6base`
 | 
					- `qt6base`
 | 
				
			||||||
- `qt6declarative`
 | 
					- `qt6declarative`
 | 
				
			||||||
 | 
					- `qtshadertools` (build-time only)
 | 
				
			||||||
- `pkg-config`
 | 
					- `pkg-config`
 | 
				
			||||||
- `cli11`
 | 
					- `cli11`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,7 @@ if (NOT CMAKE_BUILD_TYPE)
 | 
				
			||||||
	set(CMAKE_BUILD_TYPE Debug)
 | 
						set(CMAKE_BUILD_TYPE Debug)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(QT_FPDEPS Gui Qml Quick QuickControls2 Widgets)
 | 
					set(QT_FPDEPS Gui Qml Quick QuickControls2 Widgets ShaderTools)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include(cmake/pch.cmake)
 | 
					include(cmake/pch.cmake)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
  cmake,
 | 
					  cmake,
 | 
				
			||||||
  ninja,
 | 
					  ninja,
 | 
				
			||||||
  qt6,
 | 
					  qt6,
 | 
				
			||||||
 | 
					  spirv-tools,
 | 
				
			||||||
  cli11,
 | 
					  cli11,
 | 
				
			||||||
  breakpad,
 | 
					  breakpad,
 | 
				
			||||||
  jemalloc,
 | 
					  jemalloc,
 | 
				
			||||||
| 
						 | 
					@ -45,6 +46,8 @@
 | 
				
			||||||
  nativeBuildInputs = with pkgs; [
 | 
					  nativeBuildInputs = with pkgs; [
 | 
				
			||||||
    cmake
 | 
					    cmake
 | 
				
			||||||
    ninja
 | 
					    ninja
 | 
				
			||||||
 | 
					    qt6.qtshadertools
 | 
				
			||||||
 | 
					    spirv-tools
 | 
				
			||||||
    qt6.wrapQtAppsHook
 | 
					    qt6.wrapQtAppsHook
 | 
				
			||||||
    pkg-config
 | 
					    pkg-config
 | 
				
			||||||
  ] ++ (lib.optionals withWayland [
 | 
					  ] ++ (lib.optionals withWayland [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,28 @@
 | 
				
			||||||
qt_add_library(quickshell-widgets STATIC)
 | 
					qt_add_library(quickshell-widgets STATIC
 | 
				
			||||||
 | 
						cliprect.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qt_add_qml_module(quickshell-widgets
 | 
					qt_add_qml_module(quickshell-widgets
 | 
				
			||||||
	URI Quickshell.Widgets
 | 
						URI Quickshell.Widgets
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	QML_FILES
 | 
						QML_FILES
 | 
				
			||||||
		IconImage.qml
 | 
							IconImage.qml
 | 
				
			||||||
 | 
							ClippingRectangle.qml
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qt6_add_shaders(quickshell-widgets "widgets-cliprect"
 | 
				
			||||||
 | 
						NOHLSL NOMSL BATCHABLE PRECOMPILE OPTIMIZED QUIET
 | 
				
			||||||
 | 
						PREFIX "/Quickshell/Widgets"
 | 
				
			||||||
 | 
						FILES shaders/cliprect.frag
 | 
				
			||||||
 | 
						OUTPUTS shaders/cliprect.frag.qsb
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qt6_add_shaders(quickshell-widgets "widgets-cliprect-ub"
 | 
				
			||||||
 | 
						NOHLSL NOMSL BATCHABLE PRECOMPILE OPTIMIZED QUIET
 | 
				
			||||||
 | 
						PREFIX "/Quickshell/Widgets"
 | 
				
			||||||
 | 
						FILES shaders/cliprect.frag
 | 
				
			||||||
 | 
						OUTPUTS shaders/cliprect-ub.frag.qsb
 | 
				
			||||||
 | 
						DEFINES CONTENT_UNDER_BORDER
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-widgets)
 | 
					install_qml_module(quickshell-widgets)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										82
									
								
								src/widgets/ClippingRectangle.qml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/widgets/ClippingRectangle.qml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					import QtQuick
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///! Rectangle capable of clipping content inside its border.
 | 
				
			||||||
 | 
					/// > [!WARNING] This type requires at least Qt 6.7.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// This is a specialized version of @@QtQuick.Rectangle that clips content
 | 
				
			||||||
 | 
					/// inside of its border, including rounded rectangles. It costs more than
 | 
				
			||||||
 | 
					/// @@QtQuick.Rectangle, so it should not be used unless you need to clip
 | 
				
			||||||
 | 
					/// items inside of it to the border.
 | 
				
			||||||
 | 
					Item {
 | 
				
			||||||
 | 
						id: root
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// If content should be displayed underneath the border.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// Defaults to false, does nothing if the border is opaque.
 | 
				
			||||||
 | 
						property bool contentUnderBorder: false;
 | 
				
			||||||
 | 
						/// If the content item should be resized to fit inside the border.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// Defaults to `!contentUnderBorder`. Most useful when combined with
 | 
				
			||||||
 | 
						/// `anchors.fill: parent` on an item passed to the ClippingRectangle.
 | 
				
			||||||
 | 
						property bool contentInsideBorder: !root.contentUnderBorder;
 | 
				
			||||||
 | 
						/// If the rectangle should be antialiased.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// Defaults to true if any corner has a non-zero radius, otherwise false.
 | 
				
			||||||
 | 
						property /*bool*/alias antialiasing: rectangle.antialiasing;
 | 
				
			||||||
 | 
						/// The background color of the rectangle, which goes under its content.
 | 
				
			||||||
 | 
						property /*color*/alias color: shader.backgroundColor;
 | 
				
			||||||
 | 
						/// See @@QtQuick.Rectangle.border.
 | 
				
			||||||
 | 
						property clippingRectangleBorder border;
 | 
				
			||||||
 | 
						/// Radius of all corners. Defaults to 0.
 | 
				
			||||||
 | 
						property /*real*/alias radius: rectangle.radius
 | 
				
			||||||
 | 
						/// Radius of the top left corner. Defaults to @@radius.
 | 
				
			||||||
 | 
						property /*real*/alias topLeftRadius: rectangle.topLeftRadius
 | 
				
			||||||
 | 
						/// Radius of the top right corner. Defaults to @@radius.
 | 
				
			||||||
 | 
						property /*real*/alias topRightRadius: rectangle.topRightRadius
 | 
				
			||||||
 | 
						/// Radius of the bottom left corner. Defaults to @@radius.
 | 
				
			||||||
 | 
						property /*real*/alias bottomLeftRadius: rectangle.bottomLeftRadius
 | 
				
			||||||
 | 
						/// Radius of the bottom right corner. Defaults to @@radius.
 | 
				
			||||||
 | 
						property /*real*/alias borromRightRadius: rectangle.bottomRightRadius
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Visual children of the ClippingRectangle's @@contentItem. (`list<Item>`).
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// See @@QtQuick.Item.children for details.
 | 
				
			||||||
 | 
						default property alias children: contentItem.children;
 | 
				
			||||||
 | 
						/// The item containing the rectangle's content.
 | 
				
			||||||
 | 
						/// There is usually no reason to use this directly.
 | 
				
			||||||
 | 
						readonly property alias contentItem: contentItem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Rectangle {
 | 
				
			||||||
 | 
							id: rectangle
 | 
				
			||||||
 | 
							anchors.fill: root
 | 
				
			||||||
 | 
							color: "#ffff0000"
 | 
				
			||||||
 | 
							border.color: "#ff00ff00"
 | 
				
			||||||
 | 
							border.pixelAligned: root.border.pixelAligned
 | 
				
			||||||
 | 
							border.width: root.border.width
 | 
				
			||||||
 | 
							layer.enabled: true
 | 
				
			||||||
 | 
							visible: false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Item {
 | 
				
			||||||
 | 
							id: contentItemContainer
 | 
				
			||||||
 | 
							anchors.fill: root
 | 
				
			||||||
 | 
							layer.enabled: true
 | 
				
			||||||
 | 
							visible: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Item {
 | 
				
			||||||
 | 
								id: contentItem
 | 
				
			||||||
 | 
								anchors.fill: parent
 | 
				
			||||||
 | 
								anchors.margins: root.contentInsideBorder ? root.border.width : 0
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ShaderEffect {
 | 
				
			||||||
 | 
							id: shader
 | 
				
			||||||
 | 
							anchors.fill: root
 | 
				
			||||||
 | 
							fragmentShader: `qrc:/Quickshell/Widgets/shaders/cliprect${root.contentUnderBorder ? "-ub" : ""}.frag.qsb`
 | 
				
			||||||
 | 
							property Rectangle rect: rectangle;
 | 
				
			||||||
 | 
							property color backgroundColor;
 | 
				
			||||||
 | 
							property color borderColor: root.border.color;
 | 
				
			||||||
 | 
							property Item content: contentItemContainer;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/widgets/cliprect.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/widgets/cliprect.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					#include "cliprect.hpp" // NOLINT
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/widgets/cliprect.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/widgets/cliprect.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qcolor.h>
 | 
				
			||||||
 | 
					#include <qmetaobject.h>
 | 
				
			||||||
 | 
					#include <qnamespace.h>
 | 
				
			||||||
 | 
					#include <qqmlintegration.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ClippingRectangleBorder {
 | 
				
			||||||
 | 
						Q_GADGET;
 | 
				
			||||||
 | 
						Q_PROPERTY(QColor color MEMBER color);
 | 
				
			||||||
 | 
						Q_PROPERTY(bool pixelAligned MEMBER pixelAligned);
 | 
				
			||||||
 | 
						Q_PROPERTY(int width MEMBER width);
 | 
				
			||||||
 | 
						QML_VALUE_TYPE(clippingRectangleBorder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						QColor color = Qt::black;
 | 
				
			||||||
 | 
						bool pixelAligned = true;
 | 
				
			||||||
 | 
						int width = 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -2,5 +2,6 @@ name = "Quickshell.Widgets"
 | 
				
			||||||
description = "Bundled widgets"
 | 
					description = "Bundled widgets"
 | 
				
			||||||
qml_files = [
 | 
					qml_files = [
 | 
				
			||||||
	"IconImage.qml",
 | 
						"IconImage.qml",
 | 
				
			||||||
 | 
						"ClippingRectangle.qml",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
-----
 | 
					-----
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										40
									
								
								src/widgets/shaders/cliprect.frag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/widgets/shaders/cliprect.frag
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					#version 440
 | 
				
			||||||
 | 
					layout(location = 0) in vec2 qt_TexCoord0;
 | 
				
			||||||
 | 
					layout(location = 0) out vec4 fragColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(std140, binding = 0) uniform buf {
 | 
				
			||||||
 | 
						mat4 qt_Matrix;
 | 
				
			||||||
 | 
						float qt_Opacity;
 | 
				
			||||||
 | 
						vec4 backgroundColor;
 | 
				
			||||||
 | 
						vec4 borderColor;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(binding = 1) uniform sampler2D rect;
 | 
				
			||||||
 | 
					layout(binding = 2) uniform sampler2D content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vec4 overlay(vec4 base, vec4 overlay) {
 | 
				
			||||||
 | 
						if (overlay.a == 0.0) return base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float baseMul = 1.0 - overlay.a;
 | 
				
			||||||
 | 
						float newAlpha = overlay.a + base.a * baseMul;
 | 
				
			||||||
 | 
						vec3 rgb = (overlay.rgb * overlay.a + base.rgb * base.a * baseMul) / newAlpha;
 | 
				
			||||||
 | 
						return vec4(rgb, newAlpha);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
						vec4 contentColor = texture(content, qt_TexCoord0.xy);
 | 
				
			||||||
 | 
						vec4 rectColor = texture(rect, qt_TexCoord0.xy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONTENT_UNDER_BORDER
 | 
				
			||||||
 | 
						float contentAlpha = rectColor.a;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						float contentAlpha = rectColor.r;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float borderAlpha = rectColor.g;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vec4 innerColor = overlay(backgroundColor, contentColor) * contentAlpha;
 | 
				
			||||||
 | 
						vec4 borderColor = borderColor * borderAlpha;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fragColor = (innerColor * (1.0 - borderColor.a) + borderColor) * qt_Opacity;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue