forked from Shinonome/dots-hyprland
background widgets
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Bar, wallpaper
|
# Bar, wallpaper
|
||||||
exec-once = swww-daemon --format xrgb --no-cache
|
exec-once = swww-daemon --format xrgb --no-cache
|
||||||
exec-once = sleep 0.5; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1
|
exec-once = sleep 0.5; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1
|
||||||
exec-once = /usr/lib/geoclue-2.0/demos/agent & gammastep
|
exec-once = /usr/lib/geoclue-2.0/demos/agent & gammastep
|
||||||
exec-once = qs &
|
exec-once = qs &
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ layerrule = animation slide bottom, quickshell:osk
|
|||||||
layerrule = blur, quickshell:session
|
layerrule = blur, quickshell:session
|
||||||
layerrule = noanim, quickshell:session
|
layerrule = noanim, quickshell:session
|
||||||
layerrule = animation fade, quickshell:notificationPopup
|
layerrule = animation fade, quickshell:notificationPopup
|
||||||
|
layerrule = blur, quickshell:backgroundWidgets
|
||||||
|
layerrule = ignorealpha 0.05, quickshell:backgroundWidgets
|
||||||
|
|
||||||
# layerrule = blurpopups, quickshell:.*
|
# layerrule = blurpopups, quickshell:.*
|
||||||
# layerrule = blur, quickshell:.*
|
# layerrule = blur, quickshell:.*
|
||||||
|
|||||||
@@ -45,4 +45,4 @@ post_hook = '~/.config/matugen/templates/kde/kde-material-you-colors-wrapper.sh'
|
|||||||
|
|
||||||
[templates.wallpaper]
|
[templates.wallpaper]
|
||||||
input_path = '~/.config/matugen/templates/wallpaper.txt'
|
input_path = '~/.config/matugen/templates/wallpaper.txt'
|
||||||
output_path = '~/.local/state/quickshell/user/generated/wallpaper.txt'
|
output_path = '~/.local/state/quickshell/user/generated/wallpaper/path.txt'
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
import "root:/"
|
||||||
|
import "root:/modules/common"
|
||||||
|
import "root:/modules/common/widgets"
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/modules/common/functions/color_utils.js" as ColorUtils
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import Quickshell.Services.UPower
|
||||||
|
|
||||||
|
Scope {
|
||||||
|
id: root
|
||||||
|
property string filePath: `${Directories.state}/user/generated/wallpaper/least_busy_region.json`
|
||||||
|
property real centerX: 0
|
||||||
|
property real centerY: 0
|
||||||
|
property color dominantColor: Appearance.m3colors.m3primary
|
||||||
|
property bool dominantColorIsDark: dominantColor.hslLightness < 0.5
|
||||||
|
property color colBackground: ColorUtils.transparentize(ColorUtils.mix(Appearance.m3colors.m3primary, Appearance.m3colors.m3secondaryContainer), 1)
|
||||||
|
property color colText: ColorUtils.colorWithLightness(Appearance.m3colors.m3primary, (root.dominantColorIsDark ? 0.8 : 0.12))
|
||||||
|
|
||||||
|
function updateWidgetPosition(fileContent) {
|
||||||
|
console.log("[BackgroundWidgets] Updating widget position with content:", fileContent)
|
||||||
|
const parsedContent = JSON.parse(fileContent)
|
||||||
|
root.centerX = parsedContent.center_x
|
||||||
|
root.centerY = parsedContent.center_y
|
||||||
|
root.dominantColor = parsedContent.dominant_color || Appearance.m3colors.m3primary
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: delayedFileRead
|
||||||
|
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
|
||||||
|
running: false
|
||||||
|
onTriggered: {
|
||||||
|
root.updateWidgetPosition(leastBusyRegionFileView.text())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileView {
|
||||||
|
id: leastBusyRegionFileView
|
||||||
|
path: Qt.resolvedUrl(root.filePath)
|
||||||
|
watchChanges: true
|
||||||
|
onFileChanged: {
|
||||||
|
this.reload()
|
||||||
|
delayedFileRead.start()
|
||||||
|
}
|
||||||
|
onLoadedChanged: {
|
||||||
|
const fileContent = leastBusyRegionFileView.text()
|
||||||
|
root.updateWidgetPosition(fileContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variants { // For each monitor
|
||||||
|
model: Quickshell.screens
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
required property var modelData
|
||||||
|
active: !ToplevelManager.activeToplevel?.activated
|
||||||
|
sourceComponent: PanelWindow { // Window
|
||||||
|
id: windowRoot
|
||||||
|
screen: modelData
|
||||||
|
property var textHorizontalAlignment: root.centerX < windowRoot.width / 3 ? Text.AlignLeft :
|
||||||
|
(root.centerX > windowRoot.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter)
|
||||||
|
|
||||||
|
WlrLayershell.layer: WlrLayer.Bottom
|
||||||
|
WlrLayershell.namespace: "quickshell:backgroundWidgets"
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: true
|
||||||
|
bottom:true
|
||||||
|
left: true
|
||||||
|
right: true
|
||||||
|
}
|
||||||
|
color: "transparent"
|
||||||
|
HyprlandWindow.visibleMask: Region {
|
||||||
|
item: widgetBackground
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: widgetBackground
|
||||||
|
property real verticalPadding: 20
|
||||||
|
property real horizontalPadding: 30
|
||||||
|
radius: 40
|
||||||
|
color: root.colBackground
|
||||||
|
implicitHeight: columnLayout.implicitHeight + verticalPadding * 2
|
||||||
|
implicitWidth: columnLayout.implicitWidth + horizontalPadding * 2
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
top: parent.top
|
||||||
|
leftMargin: root.centerX - implicitWidth / 2
|
||||||
|
topMargin: root.centerY - implicitHeight / 2
|
||||||
|
Behavior on leftMargin {
|
||||||
|
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
Behavior on topMargin {
|
||||||
|
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: columnLayout
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: -5
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: windowRoot.textHorizontalAlignment
|
||||||
|
font.pixelSize: 95
|
||||||
|
color: root.colText
|
||||||
|
style: Text.Raised
|
||||||
|
styleColor: Appearance.colors.colShadow
|
||||||
|
text: DateTime.time
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: windowRoot.textHorizontalAlignment
|
||||||
|
font.pixelSize: 25
|
||||||
|
color: root.colText
|
||||||
|
style: Text.Raised
|
||||||
|
styleColor: Appearance.colors.colShadow
|
||||||
|
text: DateTime.date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -39,6 +39,30 @@ function colorWithSaturationOf(color1, color2) {
|
|||||||
return Qt.hsva(hue, sat, val, alpha);
|
return Qt.hsva(hue, sat, val, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a color with the given lightness and the hue, saturation, and alpha of the input color (using HSL).
|
||||||
|
*
|
||||||
|
* @param {string} color - The base color (any Qt.color-compatible string).
|
||||||
|
* @param {number} lightness - The lightness value to use (0-1).
|
||||||
|
* @returns {Qt.rgba} The resulting color.
|
||||||
|
*/
|
||||||
|
function colorWithLightness(color, lightness) {
|
||||||
|
var c = Qt.color(color);
|
||||||
|
return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a color with the lightness of color2 and the hue, saturation, and alpha of color1 (using HSL).
|
||||||
|
*
|
||||||
|
* @param {string} color1 - The base color (any Qt.color-compatible string).
|
||||||
|
* @param {string} color2 - The color to take lightness from.
|
||||||
|
* @returns {Qt.rgba} The resulting color.
|
||||||
|
*/
|
||||||
|
function colorWithLightnessOf(color1, color2) {
|
||||||
|
var c2 = Qt.color(color2);
|
||||||
|
return colorWithLightness(color1, c2.hslLightness);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts color1 to the accent (hue and saturation) of color2 using HSL, keeping lightness and alpha from color1.
|
* Adapts color1 to the accent (hue and saturation) of color2 using HSL, keeping lightness and alpha from color1.
|
||||||
*
|
*
|
||||||
@@ -66,7 +90,7 @@ function adaptToAccent(color1, color2) {
|
|||||||
* @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2.
|
* @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2.
|
||||||
* @returns {Qt.rgba} The resulting mixed color.
|
* @returns {Qt.rgba} The resulting mixed color.
|
||||||
*/
|
*/
|
||||||
function mix(color1, color2, percentage) {
|
function mix(color1, color2, percentage = 0.5) {
|
||||||
var c1 = Qt.color(color1);
|
var c1 = Qt.color(color1);
|
||||||
var c2 = Qt.color(color2);
|
var c2 = Qt.color(color2);
|
||||||
return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a);
|
return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ CONFIG_DIR="$XDG_CONFIG_HOME/quickshell"
|
|||||||
CACHE_DIR="$XDG_CACHE_HOME/quickshell"
|
CACHE_DIR="$XDG_CACHE_HOME/quickshell"
|
||||||
STATE_DIR="$XDG_STATE_HOME/quickshell"
|
STATE_DIR="$XDG_STATE_HOME/quickshell"
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
MATUGEN_DIR="$XDG_CONFIG_HOME/matugen"
|
||||||
terminalscheme="$XDG_CONFIG_HOME/quickshell/scripts/terminal/scheme-base.json"
|
terminalscheme="$XDG_CONFIG_HOME/quickshell/scripts/terminal/scheme-base.json"
|
||||||
|
|
||||||
pre_process() {
|
pre_process() {
|
||||||
@@ -26,7 +27,19 @@ pre_process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
post_process() {
|
post_process() {
|
||||||
true
|
local screen_width="$1"
|
||||||
|
local screen_height="$2"
|
||||||
|
local wallpaper_path="$3"
|
||||||
|
|
||||||
|
# Determine the largest region on the wallpaper that's sufficiently un-busy to put widgets in
|
||||||
|
if [ ! -f "$MATUGEN_DIR/scripts/least_busy_region.py" ]; then
|
||||||
|
echo "Error: least_busy_region.py script not found in $MATUGEN_DIR/scripts/"
|
||||||
|
else
|
||||||
|
"$MATUGEN_DIR/scripts/least_busy_region.py" \
|
||||||
|
--screen-width "$screen_width" --screen-height "$screen_height" \
|
||||||
|
--width 300 --height 200 \
|
||||||
|
"$wallpaper_path" > "$STATE_DIR"/user/generated/wallpaper/least_busy_region.json
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_and_prompt_upscale() {
|
check_and_prompt_upscale() {
|
||||||
@@ -219,7 +232,10 @@ switch() {
|
|||||||
"$SCRIPT_DIR"/applycolor.sh
|
"$SCRIPT_DIR"/applycolor.sh
|
||||||
deactivate
|
deactivate
|
||||||
|
|
||||||
post_process
|
# Pass screen width, height, and wallpaper path to post_process
|
||||||
|
min_width_desired="$(hyprctl monitors -j | jq '([.[].width] | max)' | xargs)"
|
||||||
|
min_height_desired="$(hyprctl monitors -j | jq '([.[].height] | max)' | xargs)"
|
||||||
|
post_process "$min_width_desired" "$min_height_desired" "$imgpath"
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
//@ pragma Env QT_QUICK_CONTROLS_STYLE=Basic
|
//@ pragma Env QT_QUICK_CONTROLS_STYLE=Basic
|
||||||
|
|
||||||
import "./modules/common/"
|
import "./modules/common/"
|
||||||
|
import "./modules/backgroundWidgets/"
|
||||||
import "./modules/bar/"
|
import "./modules/bar/"
|
||||||
import "./modules/cheatsheet/"
|
import "./modules/cheatsheet/"
|
||||||
import "./modules/dock/"
|
import "./modules/dock/"
|
||||||
@@ -26,6 +27,7 @@ ShellRoot {
|
|||||||
// Enable/disable modules here. False = not loaded at all, so rest assured
|
// Enable/disable modules here. False = not loaded at all, so rest assured
|
||||||
// no unnecessary stuff will take up memory if you decide to only use, say, the overview.
|
// no unnecessary stuff will take up memory if you decide to only use, say, the overview.
|
||||||
property bool enableBar: true
|
property bool enableBar: true
|
||||||
|
property bool enableBackgroundWidgets: true
|
||||||
property bool enableCheatsheet: true
|
property bool enableCheatsheet: true
|
||||||
property bool enableDock: true
|
property bool enableDock: true
|
||||||
property bool enableMediaControls: true
|
property bool enableMediaControls: true
|
||||||
@@ -49,19 +51,20 @@ ShellRoot {
|
|||||||
FirstRunExperience.load()
|
FirstRunExperience.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader { active: enableBar; sourceComponent: Bar {} }
|
LazyLoader { active: enableBar; component: Bar {} }
|
||||||
Loader { active: enableCheatsheet; sourceComponent: Cheatsheet {} }
|
LazyLoader { active: enableBackgroundWidgets; component: BackgroundWidgets {} }
|
||||||
Loader { active: (enableDock && ConfigOptions?.dock.enable); sourceComponent: Dock {} }
|
LazyLoader { active: enableCheatsheet; component: Cheatsheet {} }
|
||||||
Loader { active: enableMediaControls; sourceComponent: MediaControls {} }
|
LazyLoader { active: (enableDock && ConfigOptions?.dock.enable); component: Dock {} }
|
||||||
Loader { active: enableNotificationPopup; sourceComponent: NotificationPopup {} }
|
LazyLoader { active: enableMediaControls; component: MediaControls {} }
|
||||||
Loader { active: enableOnScreenDisplayBrightness; sourceComponent: OnScreenDisplayBrightness {} }
|
LazyLoader { active: enableNotificationPopup; component: NotificationPopup {} }
|
||||||
Loader { active: enableOnScreenDisplayVolume; sourceComponent: OnScreenDisplayVolume {} }
|
LazyLoader { active: enableOnScreenDisplayBrightness; component: OnScreenDisplayBrightness {} }
|
||||||
Loader { active: enableOnScreenKeyboard; sourceComponent: OnScreenKeyboard {} }
|
LazyLoader { active: enableOnScreenDisplayVolume; component: OnScreenDisplayVolume {} }
|
||||||
Loader { active: enableOverview; sourceComponent: Overview {} }
|
LazyLoader { active: enableOnScreenKeyboard; component: OnScreenKeyboard {} }
|
||||||
Loader { active: enableReloadPopup; sourceComponent: ReloadPopup {} }
|
LazyLoader { active: enableOverview; component: Overview {} }
|
||||||
Loader { active: enableScreenCorners; sourceComponent: ScreenCorners {} }
|
LazyLoader { active: enableReloadPopup; component: ReloadPopup {} }
|
||||||
Loader { active: enableSession; sourceComponent: Session {} }
|
LazyLoader { active: enableScreenCorners; component: ScreenCorners {} }
|
||||||
Loader { active: enableSidebarLeft; sourceComponent: SidebarLeft {} }
|
LazyLoader { active: enableSession; component: Session {} }
|
||||||
Loader { active: enableSidebarRight; sourceComponent: SidebarRight {} }
|
LazyLoader { active: enableSidebarLeft; component: SidebarLeft {} }
|
||||||
|
LazyLoader { active: enableSidebarRight; component: SidebarRight {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user