Merge branch 'end-4:main' into main

This commit is contained in:
jwihardi
2025-11-30 15:32:19 -05:00
committed by GitHub
43 changed files with 861 additions and 158 deletions
+16 -16
View File
@@ -4,27 +4,27 @@
#!
##! Shell
# These absolutely need to be on top, or they won't work consistently
bindid = Super, Super_L, Toggle overview, global, quickshell:overviewToggleRelease # Toggle overview/launcher
bindid = Super, Super_R, Toggle overview, global, quickshell:overviewToggleRelease # [hidden] Toggle overview/launcher
bindid = Super, Super_L, Toggle search, global, quickshell:searchToggleRelease # Toggle search
bindid = Super, Super_R, Toggle search, global, quickshell:searchToggleRelease # [hidden] Toggle search
bind = Super, Super_L, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill fuzzel || fuzzel # [hidden] Launcher (fallback)
bind = Super, Super_R, exec, qs -c $qsConfig ipc call TEST_ALIVE || pkill fuzzel || fuzzel # [hidden] Launcher (fallback)
binditn = Super, catchall, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Ctrl, Super_L, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Ctrl, Super_R, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse:272, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse:273, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse:274, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse:275, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse:276, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse:277, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse_up, global, quickshell:overviewToggleReleaseInterrupt # [hidden]
bind = Super, mouse_down,global, quickshell:overviewToggleReleaseInterrupt # [hidden]
binditn = Super, catchall, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Ctrl, Super_L, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Ctrl, Super_R, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse:272, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse:273, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse:274, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse:275, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse:276, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse:277, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse_up, global, quickshell:searchToggleReleaseInterrupt # [hidden]
bind = Super, mouse_down,global, quickshell:searchToggleReleaseInterrupt # [hidden]
bindit = ,Super_L, global, quickshell:workspaceNumber # [hidden]
bindit = ,Super_R, global, quickshell:workspaceNumber # [hidden]
bind = Super, Tab, global, quickshell:overviewWorkspacesToggle # Toggle overview
bindd = Super, V, Clipboard history >> clipboard, global, quickshell:overviewClipboardToggle # Clipboard history >> clipboard
bindd = Super, Period, Emoji >> clipboard, global, quickshell:overviewEmojiToggle # Emoji >> clipboard
bind = Super, Tab, global, quickshell:overviewWorkspacesToggle # [hidden] Toggle overview/launcher (alt)
bind = Super, A, global, quickshell:sidebarLeftToggle # Toggle left sidebar
bind = Super+Alt, A, global, quickshell:sidebarLeftToggleDetach # [hidden]
bind = Super, B, global, quickshell:sidebarLeftToggle # [hidden]
@@ -218,8 +218,8 @@ submap = global
#!
# Testing
bind = Super+Alt, f11, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification with body image" "This notification should contain your user account <b>image</b> and <a href=\"https://discord.com/app\">Discord</a> <b>icon</b>. Oh and here is a random image in your Pictures folder: <img src=\"$RANDOM_IMAGE\" alt=\"Testing image\"/>" -a "Hyprland keybind" -p -h "string:image-path:/var/lib/AccountsService/icons/$USER" -t 6000 -i "discord" -A "openImage=Open profile image" -A "action2=Open the random image" -A "action3=Useless button"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"; [[ $ACTION == *action2 ]] && xdg-open \"$RANDOM_IMAGE\"' # [hidden]
bind = Super+Alt, f12, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification" "This notification should contain a random image in your <b>Pictures</b> folder and <a href=\"https://discord.com/app\">Discord</a> <b>icon</b>.\n<i>Flick right to dismiss!</i>" -a "Discord (fake)" -p -h "string:image-path:$RANDOM_IMAGE" -t 6000 -i "discord" -A "openImage=Open profile image" -A "action2=Useless button" -A "action3=Cry more"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"' # [hidden]
bind = Super+Alt, f11, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification with body image" "This notification should contain your user account <b>image</b> and <a href=\"https://discord.com/app\">Discord</a> <b>icon</b>. Oh and here is a random image in your Pictures folder: <img src=\"$RANDOM_IMAGE\" alt=\"Testing image\"/>" -a "Hyprland keybind" -p -h "string:image-path:/var/lib/AccountsService/icons/$USER" -t 6000 -i "discord" -A "openImage=Profile image" -A "action2=Open the random image" -A "action3=Useless button"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"; [[ $ACTION == *action2 ]] && xdg-open \"$RANDOM_IMAGE\"' # [hidden]
bind = Super+Alt, f12, exec, bash -c 'RANDOM_IMAGE=$(find ~/Pictures -type f | grep -v -i "nipple" | grep -v -i "pussy" | shuf -n 1); ACTION=$(notify-send "Test notification" "This notification should contain a random image in your <b>Pictures</b> folder and <a href=\"https://discord.com/app\">Discord</a> <b>icon</b>.\n<i>Flick right to dismiss!</i>" -a "Discord (fake)" -p -h "string:image-path:$RANDOM_IMAGE" -t 6000 -i "discord" -A "openImage=Profile image" -A "action2=Useless button"); [[ $ACTION == *openImage ]] && xdg-open "/var/lib/AccountsService/icons/$USER"' # [hidden]
bind = Super+Alt, Equal, exec, notify-send "Urgent notification" "Ah hell no" -u critical -a 'Hyprland keybind' # [hidden]
##! Session
@@ -20,6 +20,7 @@ Singleton {
property bool overlayOpen: false
property bool overviewOpen: false
property bool regionSelectorOpen: false
property bool searchOpen: false
property bool screenLocked: false
property bool screenLockContainsCharacters: false
property bool screenUnlockFailed: false
@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M8.20514 4.84312C8.70586 4.61008 9.30068 4.82707 9.53372 5.32778C9.76676 5.82849 9.54977 6.42331 9.04906 6.65635C6.59946 7.79644 5 10.2547 5 13.003C5 16.8671 8.13391 19.9997 12 19.9997C15.8661 19.9997 19 16.8671 19 13.003C19 10.2604 17.4072 7.80631 14.9653 6.66304C14.4651 6.42887 14.2495 5.83355 14.4836 5.33337C14.7178 4.83319 15.3131 4.61756 15.8133 4.85173C18.9517 6.32109 21 9.47689 21 13.003C21 17.9719 16.9705 21.9997 12 21.9997C7.02953 21.9997 3 17.9719 3 13.003C3 9.46957 5.05682 6.30841 8.20514 4.84312ZM12 1.99902C12.5128 1.99902 12.9355 2.38506 12.9933 2.8824L13 2.99902V10.0004C13 10.5527 12.5523 11.0004 12 11.0004C11.4872 11.0004 11.0645 10.6144 11.0067 10.1171L11 10.0004V2.99902C11 2.44674 11.4477 1.99902 12 1.99902Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 906 B

@@ -0,0 +1,4 @@
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#000000">
<path d="M8.2042 4.82046C8.57962 4.64545 9.02584 4.80792 9.20085 5.18334C9.37586 5.55876 9.2134 6.00498 8.83797 6.18C6.21382 7.4033 4.5 10.0416 4.5 12.9914C4.5 17.1386 7.85759 20.5002 11.9989 20.5002C16.1403 20.5002 19.4979 17.1386 19.4979 12.9914C19.4979 10.0477 17.7912 7.41389 15.1753 6.18718C14.8002 6.01131 14.6388 5.56472 14.8147 5.1897C14.9905 4.81467 15.4371 4.65322 15.8121 4.82909C18.9502 6.30065 20.9979 9.46066 20.9979 12.9914C20.9979 17.9666 16.9691 22.0002 11.9989 22.0002C7.02876 22.0002 3 17.9666 3 12.9914C3 9.45334 5.05623 6.28796 8.2042 4.82046ZM11.9989 2.49609C12.3786 2.49609 12.6924 2.77825 12.7421 3.14432L12.7489 3.24609V10.746C12.7489 11.1602 12.4132 11.496 11.9989 11.496C11.6192 11.496 11.3055 11.2139 11.2558 10.8478L11.2489 10.746V3.24609C11.2489 2.83188 11.5847 2.49609 11.9989 2.49609Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 979 B

@@ -26,8 +26,8 @@
inkscape:zoom="4.65625"
inkscape:cx="32"
inkscape:cy="32"
inkscape:window-width="1197"
inkscape:window-height="1020"
inkscape:window-width="1595"
inkscape:window-height="664"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
@@ -48,10 +48,10 @@
</linearGradient>
<linearGradient
id="linearGradient919"
x1="4.3106"
x2="14.36"
y1="8.4665"
y2="8.4665"
x1="4.4818125"
x2="14.188787"
y1="7.1660123"
y2="9.7669888"
gradientTransform="matrix(1.226575,0,0,1.226575,-0.82407803,-6.4497629)"
gradientUnits="userSpaceOnUse">
<stop
@@ -61,7 +61,7 @@
style="stop-color:#5fe277;stop-opacity:1;" />
<stop
stop-color="#55b4ff"
offset="1"
offset="0.40375727"
id="stop2"
style="stop-color:#0078d3;stop-opacity:1;" />
</linearGradient>

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

@@ -23,10 +23,10 @@
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="6.5849319"
inkscape:cx="26.95548"
inkscape:cx="27.031411"
inkscape:cy="26.423963"
inkscape:window-width="1257"
inkscape:window-height="1020"
inkscape:window-width="1621"
inkscape:window-height="820"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
@@ -35,10 +35,10 @@
id="defs2">
<linearGradient
id="linearGradient919"
x1="4.3106"
x2="14.36"
y1="8.4665"
y2="8.4665"
x1="4.4818139"
x2="14.188786"
y1="7.1660118"
y2="9.7669868"
gradientTransform="matrix(1.226575,0,0,1.226575,-0.82407803,-6.4497629)"
gradientUnits="userSpaceOnUse">
<stop
@@ -48,7 +48,7 @@
style="stop-color:#5fe277;stop-opacity:1;" />
<stop
stop-color="#55b4ff"
offset="1"
offset="0.40380999"
id="stop2"
style="stop-color:#0078d3;stop-opacity:1;" />
</linearGradient>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -1,6 +1,7 @@
pragma Singleton
pragma ComponentBehavior: Bound
import qs.services
import qs.modules.common.functions
import QtCore
import QtQuick
@@ -46,6 +47,9 @@ Singleton {
property string aiChats: FileUtils.trimFileProtocol(`${Directories.state}/user/ai/chats`)
property string aiTranslationScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/ai/gemini-translate.sh`)
property string recordScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/videos/record.sh`)
property string userAvatarPathAccountsService: FileUtils.trimFileProtocol(`/var/lib/AccountsService/icons/${SystemInfo.username}`)
property string userAvatarPathRicersAndWeirdSystems: FileUtils.trimFileProtocol(`${Directories.home}.face`)
property string userAvatarPathRicersAndWeirdSystems2: FileUtils.trimFileProtocol(`${Directories.home}.face.icon`)
// Cleanup on init
Component.onCompleted: {
Quickshell.execDetached(["mkdir", "-p", `${shellConfig}`])
@@ -84,4 +84,28 @@ Singleton {
// Older dates
return Qt.formatDateTime(messageTime, "MMMM dd");
}
function processNotificationBody(body, appName) {
let processedBody = body
// Clean Chromium-based browsers notifications - remove first line
if (appName) {
const lowerApp = appName.toLowerCase()
const chromiumBrowsers = [
"brave", "chrome", "chromium", "vivaldi", "opera", "microsoft edge"
]
if (chromiumBrowsers.some(name => lowerApp.includes(name))) {
const lines = body.split('\n\n')
if (lines.length > 1 && lines[0].startsWith('<a')) {
processedBody = lines.slice(1).join('\n\n')
}
}
}
processedBody = processedBody.replace(/<img/gi, '\n\n<img');
return processedBody
}
}
@@ -31,28 +31,6 @@ Item { // Notification item area
implicitHeight: background.implicitHeight
function processNotificationBody(body, appName) {
let processedBody = body
// Clean Chromium-based browsers notifications - remove first line
if (appName) {
const lowerApp = appName.toLowerCase()
const chromiumBrowsers = [
"brave", "chrome", "chromium", "vivaldi", "opera", "microsoft edge"
]
if (chromiumBrowsers.some(name => lowerApp.includes(name))) {
const lines = body.split('\n\n')
if (lines.length > 1 && lines[0].startsWith('<a')) {
processedBody = lines.slice(1).join('\n\n')
}
}
}
return processedBody
}
function destroyWithAnimation(left = false) {
root.qmlParent.resetDrag()
background.anchors.leftMargin = background.anchors.leftMargin; // Break binding
@@ -196,12 +174,13 @@ Item { // Notification item area
maximumLineCount: 1
textFormat: Text.StyledText
text: {
return processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "<br/>")
return NotificationUtils.processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "<br/>")
}
}
}
ColumnLayout { // Expanded content
id: expandedContentColumn
Layout.fillWidth: true
opacity: root.expanded ? 1 : 0
visible: opacity > 0
@@ -218,8 +197,8 @@ Item { // Notification item area
elide: Text.ElideRight
textFormat: Text.RichText
text: {
return `<style>img{max-width:${300 /* binding to notificationBodyText.width would cause a binding loop */}px;}</style>` +
`${processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "<br/>")}`
return `<style>img{max-width:${expandedContentColumn.width}px;}</style>` +
`${NotificationUtils.processNotificationBody(notificationObject.body, notificationObject.appName || notificationObject.summary).replace(/\n/g, "<br/>")}`
}
onLinkActivated: (link) => {
@@ -293,6 +272,8 @@ Item { // Notification item area
id: actionRepeater
model: notificationObject.actions
NotificationActionButton {
id: notifAction
required property var modelData
Layout.fillWidth: true
buttonText: modelData.text
urgency: notificationObject.urgency
@@ -12,4 +12,14 @@ Image {
Behavior on opacity {
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
}
property list<string> fallbacks: []
property int currentFallbackIndex: 0
onStatusChanged: {
if (status === Image.Error && currentFallbackIndex < fallbacks.length) {
source = fallbacks[currentFallbackIndex];
currentFallbackIndex += 1;
}
}
}
@@ -20,6 +20,7 @@ ToolTip {
hintingPreference: Font.PreferNoHinting // Prevent shaky text
}
delay: 0
visible: internalVisibleCondition
contentItem: StyledToolTipContent {
@@ -162,7 +162,7 @@ Scope {
}
IpcHandler {
target: "overview"
target: "search"
function toggle() {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
@@ -185,8 +185,8 @@ Scope {
}
GlobalShortcut {
name: "overviewToggle"
description: "Toggles overview on press"
name: "searchToggle"
description: "Toggles search on press"
onPressed: {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
@@ -201,16 +201,8 @@ Scope {
}
}
GlobalShortcut {
name: "overviewClose"
description: "Closes overview"
onPressed: {
GlobalStates.overviewOpen = false;
}
}
GlobalShortcut {
name: "overviewToggleRelease"
description: "Toggles overview on release"
name: "searchToggleRelease"
description: "Toggles search on release"
onPressed: {
GlobalStates.superReleaseMightTrigger = true;
@@ -225,8 +217,8 @@ Scope {
}
}
GlobalShortcut {
name: "overviewToggleReleaseInterrupt"
description: "Interrupts possibility of overview being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything."
name: "searchToggleReleaseInterrupt"
description: "Interrupts possibility of search being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything."
onPressed: {
GlobalStates.superReleaseMightTrigger = false;
@@ -66,7 +66,7 @@ BarButton {
}
}
AppIcon {
WAppIcon {
id: iconWidget
anchors.centerIn: parent
iconName: root.iconName
@@ -5,17 +5,12 @@ import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
WButton {
AcrylicButton {
id: root
property var altAction: () => {}
property var middleClickAction: () => {}
colBackground: ColorUtils.transparentize(Looks.colors.bg1)
colBackgroundHover: Looks.colors.bg1Hover
colBackgroundActive: Looks.colors.bg1Active
property color colBackgroundBorder
property color color
Layout.fillHeight: true
topInset: 4
bottomInset: 4
@@ -23,16 +18,7 @@ WButton {
rightInset: 0
horizontalPadding: 8
colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, (root.checked || root.hovered) ? Looks.backgroundTransparency : 1)
color: {
if (root.down) {
return root.colBackgroundActive
} else if ((root.hovered && !root.down) || root.checked) {
return root.colBackgroundHover
} else {
return root.colBackground
}
}
colBackground: ColorUtils.transparentize(Looks.colors.bg1)
MouseArea {
anchors.fill: parent
@@ -50,15 +36,4 @@ WButton {
}
}
background: AcrylicRectangle {
shiny: ((root.hovered && !root.down) || root.checked)
color: root.color
radius: Looks.radius.medium
border.width: 1
border.color: root.colBackgroundBorder
Behavior on border.color {
animation: Looks.transition.color.createObject(this)
}
}
}
@@ -7,14 +7,16 @@ import qs.services
import qs.modules.common
import qs.modules.waffle.looks
// TODO: Replace the icon with QMLized svg (with /usr/lib/qt6/bin/svgtoqml) for proper micro-animation
AppButton {
id: root
leftInset: Config.options.waffles.bar.leftAlignApps ? 12 : 0
iconName: down ? "start-here-pressed" : "start-here"
checked: GlobalStates.searchOpen
onClicked: {
GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now...
GlobalStates.searchOpen = !GlobalStates.searchOpen;
}
BarToolTip {
@@ -42,7 +42,7 @@ AppButton {
}
spacing: 6
AppIcon {
WAppIcon {
id: iconWidget
anchors.verticalCenter: parent.verticalCenter
iconName: root.iconName
@@ -43,7 +43,7 @@ Button {
Layout.fillHeight: false
spacing: 8
AppIcon {
WAppIcon {
id: appIcon
Layout.leftMargin: Looks.radius.large - root.padding + 2
Layout.alignment: Qt.AlignVCenter
@@ -0,0 +1,42 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
WButton {
id: root
colBackground: Looks.colors.bg1
colBackgroundHover: Looks.colors.bg1Hover
colBackgroundActive: Looks.colors.bg1Active
property color colBackgroundBorder
property color color
property alias border: background.border
property alias shinyColor: background.borderColor
colBackgroundBorder: ColorUtils.transparentize(color, (root.checked || root.hovered) ? Looks.backgroundTransparency : 0)
color: {
if (root.down) {
return root.colBackgroundActive
} else if ((root.hovered && !root.down) || root.checked) {
return root.colBackgroundHover
} else {
return root.colBackground
}
}
background: AcrylicRectangle {
id: background
shiny: ((root.hovered && !root.down) || root.checked)
color: root.color
radius: Looks.radius.medium
border.width: 1
border.color: root.colBackgroundBorder
Behavior on border.color {
animation: Looks.transition.color.createObject(this)
}
}
}
@@ -9,16 +9,17 @@ Rectangle {
id: root
property bool shiny: true // Top border
property color borderColor: ColorUtils.transparentize(Looks.colors.bg2Border, shiny ? 0.5 : 1)
property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Hover, 0.7)
property color internalBorderColor: ColorUtils.transparentize(borderColor, shiny ? 0.0 : 1)
color: Looks.colors.bg1Hover
radius: Looks.radius.medium
Behavior on color {
animation: Looks.transition.color.createObject(this)
}
Behavior on borderColor {
Behavior on internalBorderColor {
animation: Looks.transition.color.createObject(this)
}
onBorderColorChanged: {
onInternalBorderColorChanged: {
borderCanvas.requestPaint();
}
@@ -32,7 +33,7 @@ Rectangle {
var ctx = getContext("2d");
ctx.clearRect(0, 0, width, height);
var borderColor = root.borderColor;
var borderColor = root.internalBorderColor;
var r = root.radius;
var fadeLength = Math.max(1, r);
@@ -53,6 +53,8 @@ Singleton {
property color controlBgHover: '#57575B'
property color controlFg: "#FFFFFF"
property color accentUnfocused: "#848484"
property color link: "#235CCF"
property color inputBg: ColorUtils.transparentize(bg0, 0.4)
}
darkColors: QtObject {
id: darkColors
@@ -70,7 +72,7 @@ Singleton {
property color bg2: '#8a8a8a'
property color bg2Hover: '#b1b1b1'
property color bg2Active: '#919191'
property color bg2Border: '#c4c4c4'
property color bg2Border: '#bdbdbd'
property color subfg: "#CED1D7"
property color fg: "#FFFFFF"
property color fg1: "#D1D1D1"
@@ -80,6 +82,8 @@ Singleton {
property color controlBgHover: "#CFCED1"
property color controlFg: "#454545"
property color accentUnfocused: "#989898"
property color link: "#A7C9FC"
property color inputBg: ColorUtils.transparentize(darkColors.bg0, 0.5)
}
colors: QtObject {
id: colors
@@ -110,6 +114,8 @@ Singleton {
property color controlBg: root.dark ? root.darkColors.controlBg : root.lightColors.controlBg
property color controlBgHover: root.dark ? root.darkColors.controlBgHover : root.lightColors.controlBgHover
property color controlFg: root.dark ? root.darkColors.controlFg : root.lightColors.controlFg
property color inputBg: root.dark ? root.darkColors.inputBg : root.lightColors.inputBg
property color link: root.dark ? root.darkColors.link : root.lightColors.link
property color danger: "#C42B1C"
property color dangerActive: "#B62D1F"
property color warning: "#FF9900"
@@ -118,6 +124,7 @@ Singleton {
property color accentActive: Appearance.colors.colPrimaryActive
property color accentUnfocused: root.dark ? root.darkColors.accentUnfocused : root.lightColors.accentUnfocused
property color accentFg: ColorUtils.isDark(accent) ? "#FFFFFF" : "#000000"
property color selection: Appearance.colors.colPrimaryContainer
}
radius: QtObject {
@@ -2,7 +2,6 @@ import QtQuick
import org.kde.kirigami as Kirigami
import qs.services
import qs.modules.common
import qs.modules.waffle.looks
Kirigami.Icon {
id: root
@@ -53,10 +53,11 @@ Button {
// Hover stuff
signal hoverTimedOut
property bool shouldShowTooltip: false
ToolTip.delay: 400
property Timer hoverTimer: Timer {
id: hoverTimer
running: root.hovered
interval: 400
interval: root.ToolTip.delay
onTriggered: {
root.hoverTimedOut();
}
@@ -8,8 +8,11 @@ Text {
color: Looks.colors.fg
font {
hintingPreference: Font.PreferFullHinting
family: Looks.font.family.ui
pixelSize: Looks.font.pixelSize.normal
weight: Looks.font.weight.regular
}
linkColor: Looks.colors.link
}
@@ -0,0 +1,18 @@
import QtQuick
import QtQuick.Controls
TextInput {
id: root
renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter
color: Looks.colors.fg
font {
hintingPreference: Font.PreferFullHinting
family: Looks.font.family.ui
pixelSize: Looks.font.pixelSize.large
weight: Looks.font.weight.regular
}
selectionColor: Looks.colors.selection
}
@@ -20,6 +20,7 @@ WBarAttachedPanelContent {
property bool collapsed: false
contentItem: ColumnLayout {
id: contentLayout
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
@@ -41,9 +42,24 @@ WBarAttachedPanelContent {
}
contentItem: NotificationPaneContent {
implicitWidth: calendarColumnLayout.implicitWidth
implicitHeight: Notifications.list.length > 0 ? (notificationArea.height - notificationPane.borderWidth * 2) : 230
implicitHeight: {
if (Notifications.list.length > 0) {
return ((contentLayout.height - calendarPane.height - contentLayout.spacing) - notificationPane.borderWidth * 2)
}
return 230;
}
Timer {
id: enableTimer
interval: Config.options.hacks.arbitraryRaceConditionDelay
onTriggered: heightBehavior.enabled = true;
}
Behavior on implicitHeight {
id: heightBehavior
enabled: false
Component.onCompleted: {
enableTimer.restart();
}
animation: Looks.transition.enter.createObject(this)
}
}
@@ -51,9 +67,9 @@ WBarAttachedPanelContent {
}
WPane {
contentItem: ColumnLayout {
id: calendarPane
contentItem: WPanelPageColumn {
id: calendarColumnLayout
spacing: 0
DateHeader {
Layout.fillWidth: true
Synchronizer on collapsed {
@@ -8,18 +8,24 @@ import qs.modules.common.functions
import qs.modules.waffle.looks
WBorderlessButton {
id: headerButton
id: root
Layout.fillWidth: false
implicitWidth: 16
implicitHeight: 16
property real implicitSize: 16
implicitWidth: implicitSize
implicitHeight: implicitSize
color: "transparent"
colForeground: root.hovered && !root.pressed ? Looks.colors.fg : Looks.colors.fg1
Behavior on colForeground {
animation: Looks.transition.color.createObject(this)
}
contentItem: Item {
FluentIcon {
anchors.centerIn: parent
implicitSize: 16
icon: headerButton.icon.name
color: headerButton.hovered && !headerButton.pressed ? Looks.colors.fg : Looks.colors.fg1
implicitSize: root.implicitSize
icon: root.icon.name
color: root.colForeground
}
}
}
@@ -2,18 +2,27 @@ import QtQuick
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
SmallBorderedIconButton {
AcrylicButton {
id: root
property bool iconVisible: true
property string iconName: ""
property bool iconFilled: true
colBackground: Looks.colors.bg2
colBackgroundHover: Looks.colors.bg2Hover
colBackgroundActive: Looks.colors.bg2Active
property color colBorder: Looks.colors.bg2Border
property color colBorderToggled: Looks.colors.accent
border.color: checked ? colBorderToggled : colBorder
leftPadding: 12
rightPadding: 12
implicitWidth: focusButtonContent.implicitWidth + leftPadding + rightPadding
implicitHeight: 24
contentItem: Row {
id: focusButtonContent
@@ -12,6 +12,7 @@ MouseArea {
required property var notificationGroup
readonly property var notifications: notificationGroup?.notifications ?? []
property bool expanded: false
implicitWidth: contentLayout.implicitWidth
implicitHeight: contentLayout.implicitHeight
@@ -34,12 +35,23 @@ MouseArea {
interactive: false
spacing: 4
model: ScriptModel {
values: root.notifications.slice().reverse()
values: root.expanded ? root.notifications.slice().reverse() : root.notifications.slice(-1)
objectProp: "notificationId"
}
delegate: WSingleNotification {
required property int index
required property var modelData
width: ListView.view.width
notification: modelData
groupExpandControlMessage: {
if (root.notifications.length <= 1) return "";
if (!root.expanded) return Translation.tr("+%1 notifications").arg(root.notifications.length - 1);
if (index === root.notifications.length - 1) return Translation.tr("See fewer");
return "";
}
onGroupExpandToggle: {
root.expanded = !root.expanded;
}
}
}
}
@@ -1,3 +1,4 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
@@ -12,11 +13,18 @@ MouseArea {
id: root
required property var notification
property bool expanded: false
property bool expanded: notification.actions.length > 0
property string groupExpandControlMessage: ""
signal groupExpandToggle
hoverEnabled: true
implicitHeight: contentItem.implicitHeight
implicitWidth: contentItem.implicitWidth
Behavior on implicitHeight {
animation: Looks.transition.enter.createObject(this)
}
Rectangle {
id: contentItem
anchors.fill: parent
@@ -26,34 +34,205 @@ MouseArea {
implicitHeight: notificationContent.implicitHeight + padding * 2
implicitWidth: notificationContent.implicitWidth + padding * 2
border.width: 1
border.color: Looks.applyContentTransparency(Looks.colors.ambientShadow)
border.color: ColorUtils.applyAlpha(Looks.colors.ambientShadow, 0.1)
ColumnLayout {
id: notificationContent
anchors.fill: parent
anchors.margins: contentItem.padding
spacing: 19
RowLayout {
// Header
SingleNotificationHeader {
Layout.fillWidth: true
WText {
text: NotificationUtils.getFriendlyNotifTimeString(root.notification?.time)
}
// Content
Item {
id: actualContent
Layout.fillWidth: true
Layout.fillHeight: true
property real spacing: 16
implicitHeight: Math.max(contentColumn.implicitHeight, imageLoader.height)
implicitWidth: contentColumn.implicitWidth
Loader {
id: imageLoader
anchors {
top: parent.top
left: parent.left
}
active: root.notification.image != ""
sourceComponent: StyledImage {
readonly property int size: 48
width: size
height: size
sourceSize.width: size
sourceSize.height: size
source: root.notification.image
fillMode: Image.PreserveAspectFit
}
}
ColumnLayout {
id: contentColumn
anchors {
top: parent.top
left: parent.left
right: parent.right
}
spacing: 3
SummaryText {
id: summaryText
Layout.leftMargin: imageLoader.active ? imageLoader.width + actualContent.spacing : 0
}
BodyText {
Layout.leftMargin: imageLoader.active ? imageLoader.width + actualContent.spacing : 0
// onLineLaidOut: (line) => {
// if (!imageLoader.active) return;
// const dodgeDistance = imageLoader.width + actualContent.spacing;
// // print(line.y, dodgeDistance)
// if (summaryText.height + line.y > dodgeDistance) {
// line.x -= dodgeDistance;
// line.width += dodgeDistance;
// }
// }
}
}
}
ColumnLayout {
// Actions
ActionsRow {
Layout.fillWidth: true
WText {
Layout.fillWidth: true
elide: Text.ElideRight
text: root.notification.summary
}
WText {
Layout.fillWidth: true
elide: Text.ElideRight
}
// "+1 notifications" button
GroupExpandButton {
Layout.bottomMargin: 2
}
}
}
component SingleNotificationHeader: RowLayout {
ExpandButton {
Layout.topMargin: -2
}
Item {
Layout.fillWidth: true
}
NotificationHeaderButton {
Layout.rightMargin: 4
opacity: root.containsMouse ? 1 : 0
icon.name: "dismiss"
implicitSize: 12
onClicked: {
Qt.callLater(() => {
Notifications.discardNotification(root.notification?.notificationId);
});
}
}
}
component ActionsRow: RowLayout {
visible: root.expanded && root.notification.actions.length > 0
uniformCellSizes: true
Repeater {
id: actionRepeater
model: root.notification.actions
delegate: WBorderedButton {
id: actionButton
Layout.fillHeight: true
required property var modelData
Layout.fillWidth: true
verticalPadding: 16
horizontalPadding: 12
text: modelData.text
implicitHeight: actionButtonText.implicitHeight + verticalPadding * 2
contentItem: WText {
id: actionButtonText
text: actionButton.text
font.pixelSize: Looks.font.pixelSize.large
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
maximumLineCount: root.expanded ? 100 : 1
}
}
}
}
component SummaryText: WText {
Layout.fillWidth: true
elide: Text.ElideRight
text: root.notification?.summary
font.pixelSize: Looks.font.pixelSize.large
}
component BodyText: WText {
Layout.fillWidth: true
Layout.fillHeight: true
elide: Text.ElideRight
verticalAlignment: Text.AlignTop
wrapMode: Text.Wrap
maximumLineCount: root.expanded ? 100 : 1
text: {
if (root.expanded)
return `<style>img{max-width:${summaryText.width}px; align: right}</style>` + `${NotificationUtils.processNotificationBody(root.notification.body, root.notification.appName || root.notification.summary).replace(/\n/g, "<br/>")}`;
return NotificationUtils.processNotificationBody(root.notification.body, root.notification.appName || root.notification.summary).replace(/\n/g, "<br/>");
}
color: Looks.colors.subfg
textFormat: root.expanded ? Text.RichText : Text.StyledText
onLinkActivated: link => {
Qt.openUrlExternally(link);
GlobalStates.sidebarRightOpen = false;
}
}
component ExpandButton: NotificationHeaderButton {
id: expandButton
implicitWidth: expandButtonContent.implicitWidth
onClicked: root.expanded = !root.expanded
contentItem: Item {
id: expandButtonContent
implicitWidth: expandButtonRow.implicitWidth
implicitHeight: expandButtonRow.implicitHeight
RowLayout {
id: expandButtonRow
anchors.centerIn: parent
spacing: 8
WText {
color: expandButton.colForeground
text: NotificationUtils.getFriendlyNotifTimeString(root.notification?.time)
}
FluentIcon {
Layout.rightMargin: 12
icon: "chevron-down"
implicitSize: 18
rotation: root.expanded ? -180 : 0
color: expandButton.colForeground
Behavior on rotation {
animation: Looks.transition.rotate.createObject(this)
}
}
}
}
}
component GroupExpandButton: AcrylicButton {
id: groupExpandButton
visible: root.groupExpandControlMessage !== ""
horizontalPadding: 10
implicitHeight: 24
implicitWidth: expandButtonText.implicitWidth + horizontalPadding * 2
onClicked: root.groupExpandToggle()
contentItem: Item {
WText {
id: expandButtonText
anchors.centerIn: parent
text: root.groupExpandControlMessage
}
}
}
}
@@ -0,0 +1,84 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
FooterRectangle {
id: root
property bool searching: text.length > 0
property alias text: searchInput.text
Component.onCompleted: searchInput.forceActiveFocus()
focus: true
color: searching ? Looks.colors.bgPanelBody : Looks.colors.bgPanelFooter
implicitWidth: 832 // TODO: Make sizes naturally inferred
implicitHeight: 63
Rectangle {
id: outline
anchors {
fill: parent
leftMargin: 32
rightMargin: 32
topMargin: 16
bottomMargin: 15
}
color: "transparent"
radius: height / 2
border.width: 1
border.color: Looks.colors.bg2Border
}
Rectangle {
id: searchInputBg
anchors.fill: outline
anchors.margins: 1
radius: height / 2
color: Looks.colors.inputBg
RowLayout {
anchors.fill: parent
spacing: 11
WAppIcon {
Layout.leftMargin: 14
iconName: "system-search-checked"
separateLightDark: true
implicitSize: 18
}
WTextInput {
id: searchInput
focus: true
Layout.fillWidth: true
WText {
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
}
color: Looks.colors.accentUnfocused
text: Translation.tr("Search for apps") // should also have "", settings, and documents" but we don't have those
visible: searchInput.text.length === 0
font.pixelSize: Looks.font.pixelSize.large
}
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.IBeamCursor
acceptedButtons: Qt.NoButton
}
}
@@ -0,0 +1,16 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
BodyRectangle {
id: root
}
@@ -0,0 +1,39 @@
pragma ComponentBehavior: Bound
import Qt.labs.synchronizer
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
WBarAttachedPanelContent {
id: root
property bool searching: false
property string searchText: ""
contentItem: WPane {
contentItem: WPanelPageColumn {
SearchBar {
focus: true
Layout.fillWidth: true
Synchronizer on searching {
property alias target: root.searching
}
Synchronizer on text {
property alias source: root.searchText
}
}
Loader {
id: pageContentLoader
Layout.fillWidth: true
source: root.searching ? "SearchPageContent.qml" : "StartPageContent.qml"
}
}
}
}
@@ -0,0 +1,98 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Quickshell
import org.kde.kirigami as Kirigami
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.common.widgets
import qs.modules.waffle.looks
WPanelPageColumn {
id: root
WPanelSeparator {}
BodyRectangle {
implicitHeight: 736 // TODO: Make sizes naturally inferred
}
WPanelSeparator {}
StartFooter {
Layout.fillWidth: true
}
component StartFooter: FooterRectangle {
implicitHeight: 63
UserButton {
anchors {
left: parent.left
leftMargin: 52
bottom: parent.bottom
bottomMargin: 12
}
}
PowerButton {
anchors {
right: parent.right
rightMargin: 52
bottom: parent.bottom
bottomMargin: 12
}
}
}
component UserButton: WBorderlessButton {
id: userButton
implicitWidth: userButtonRow.implicitWidth + 12 * 2
implicitHeight: 40
contentItem: Item {
RowLayout {
id: userButtonRow
anchors.centerIn: parent
spacing: 12
StyledImage {
id: avatar
// Use this for free fallback because I'm lazy
Layout.alignment: Qt.AlignTop
sourceSize: Qt.size(32, 32)
source: Directories.userAvatarPathAccountsService
fallbacks: [Directories.userAvatarPathRicersAndWeirdSystems, Directories.userAvatarPathRicersAndWeirdSystems2]
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Circle {
diameter: avatar.height
}
}
}
WText {
Layout.alignment: Qt.AlignVCenter
text: SystemInfo.username
}
}
}
}
component PowerButton: WBorderlessButton {
implicitWidth: 40
implicitHeight: 40
contentItem: Item {
FluentIcon {
anchors.centerIn: parent
icon: "power"
implicitSize: 20
}
}
}
}
@@ -0,0 +1,119 @@
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Hyprland
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
Scope {
id: root
Connections {
target: GlobalStates
function onSearchOpenChanged() {
if (GlobalStates.searchOpen)
panelLoader.active = true;
}
}
Loader {
id: panelLoader
active: GlobalStates.searchOpen
sourceComponent: PanelWindow {
id: panelWindow
exclusiveZone: 0
WlrLayershell.namespace: "quickshell:wStartMenu"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
color: "transparent"
anchors {
bottom: Config.options.waffles.bar.bottom
top: !Config.options.waffles.bar.bottom
left: Config.options.waffles.bar.leftAlignApps
}
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
HyprlandFocusGrab {
id: focusGrab
active: true
windows: [panelWindow]
onCleared: content.close()
}
Connections {
target: GlobalStates
function onSearchOpenChanged() {
if (!GlobalStates.searchOpen)
content.close();
}
}
StartMenuContent {
id: content
anchors.fill: parent
focus: true
onClosed: {
GlobalStates.searchOpen = false;
panelLoader.active = false;
}
}
}
}
IpcHandler {
target: "search"
function toggle() {
GlobalStates.searchOpen = !GlobalStates.searchOpen;
}
function close() {
GlobalStates.searchOpen = false;
}
function open() {
GlobalStates.searchOpen = true;
}
function toggleReleaseInterrupt() {
GlobalStates.superReleaseMightTrigger = false;
}
}
GlobalShortcut {
name: "searchToggle"
description: "Toggles search on press"
onPressed: {
GlobalStates.searchOpen = !GlobalStates.searchOpen;
}
}
GlobalShortcut {
name: "searchToggleRelease"
description: "Toggles search on release"
onPressed: {
GlobalStates.superReleaseMightTrigger = true;
}
onReleased: {
if (!GlobalStates.superReleaseMightTrigger) {
GlobalStates.superReleaseMightTrigger = true;
return;
}
GlobalStates.searchOpen = !GlobalStates.searchOpen;
}
}
GlobalShortcut {
name: "searchToggleReleaseInterrupt"
description: "Interrupts possibility of search being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything."
onPressed: {
GlobalStates.superReleaseMightTrigger = false;
}
}
}
+4 -1
View File
@@ -33,6 +33,7 @@ import qs.modules.waffle.background
import qs.modules.waffle.bar
import qs.modules.waffle.notificationCenter
import qs.modules.waffle.onScreenDisplay
import qs.modules.waffle.startMenu
import QtQuick
import QtQuick.Window
@@ -77,11 +78,13 @@ ShellRoot {
PanelLoader { identifier: "iiSidebarRight"; component: SidebarRight {} }
PanelLoader { identifier: "iiVerticalBar"; extraCondition: Config.options.bar.vertical; component: VerticalBar {} }
PanelLoader { identifier: "iiWallpaperSelector"; component: WallpaperSelector {} }
PanelLoader { identifier: "wActionCenter"; component: WaffleActionCenter {} }
PanelLoader { identifier: "wBar"; component: WaffleBar {} }
PanelLoader { identifier: "wBackground"; component: WaffleBackground {} }
PanelLoader { identifier: "wNotificationCenter"; component: WaffleNotificationCenter {} }
PanelLoader { identifier: "wOnScreenDisplay"; component: WaffleOSD {} }
PanelLoader { identifier: "wStartMenu"; component: WaffleStartMenu {} }
ReloadPopup {}
component PanelLoader: LazyLoader {
@@ -94,7 +97,7 @@ ShellRoot {
property list<string> families: ["ii", "waffle"]
property var panelFamilies: ({
"ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"],
"waffle": ["wActionCenter", "wBar", "wBackground", "wNotificationCenter", "wOnScreenDisplay", "iiCheatsheet", "iiLock", "iiNotificationPopup", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiSessionScreen", "iiWallpaperSelector"],
"waffle": ["wActionCenter", "wBar", "wBackground", "wNotificationCenter", "wOnScreenDisplay", "wStartMenu", "iiCheatsheet", "iiLock", "iiNotificationPopup", "iiOnScreenKeyboard", "iiOverlay", "iiPolkit", "iiRegionSelector", "iiSessionScreen", "iiWallpaperSelector"],
})
function cyclePanelFamily() {
const currentIndex = families.indexOf(Config.options.panelFamily)
+3
View File
@@ -191,6 +191,9 @@ Tips:
- Used in Quickshell config.
- `wlogout`
- Used in Hyprland config.
- `libqalculate`
- Used in Quickshell config, providing math ability in searchbar.
- Note that `qalc` is the needed executable. In Arch Linux [libqalculate](https://archlinux.org/packages/extra/x86_64/libqalculate) provides it, but in Fedora [qalculate](https://packages.fedoraproject.org/pkgs/libqalculate/qalculate/fedora-43.html#files) does and [libqalculate](https://packages.fedoraproject.org/pkgs/libqalculate/libqalculate/fedora-43.html#files) does not.
# Actual packages
@@ -1,6 +1,6 @@
pkgname=illogical-impulse-widgets
pkgver=1.0
pkgrel=5
pkgrel=6
pkgdesc='Illogical Impulse Widget Dependencies'
arch=(any)
license=(None)
@@ -14,4 +14,5 @@ depends=(
songrec
translate-shell
wlogout
libqalculate
)
+3 -1
View File
@@ -181,6 +181,7 @@ packages = [
"hyprpicker",
"songrec",
"translate-shell",
"qalculate",
"wlogout"
]
@@ -191,4 +192,5 @@ packages = [
"plasma-systemmonitor",
"unzip"
]
install_opts = ["--setopt=install_weak_deps=False"]
install_opts = ["--setopt=install_weak_deps=False"]
+32 -2
View File
@@ -37,8 +37,38 @@ As [commented](https://github.com/end-4/dots-hyprland/issues/1061#issuecomment-3
See also [caelestia-dots/shell#668](https://github.com/caelestia-dots/shell/issues/668).
### NixGL
On non-NixOS distros, packages installed via home-manager have problem accessing GPU, especially Hyprland because it requires GPU acceleration to launch. `nixGL` should be used to address the problem.
### GPU
On non-NixOS distros, packages installed via home-manager have problem accessing GPU, especially Hyprland because it requires GPU acceleration to launch.
~~`nixGL` should be used to address the problem.~~
Since home-manager 25.11, for non-NixOS just set the following:
```nix
targets.genericLinux.enable = true;
```
Then during building, home-manager will show a message to tell you running a command manually to configure GPU, like:
```bash
sudo /nix/store/<HASH>-non-nixos-gpu/bin/non-nixos-gpu-setup
```
It runs a bash script with following content:
```
#!/nix/store/<HASH>-bash-<VERSION>/bin/bash
set -e
# Install the systemd service file and ensure that the store path won't be
# garbage-collected as long as it's installed.
unit_path=/etc/systemd/system/non-nixos-gpu.service
ln -sf /nix/store/<HASH>-non-nixos-gpu/resources/non-nixos-gpu.service "$unit_path"
ln -sf "$unit_path" "/nix/var/nix"/gcroots/non-nixos-gpu.service
systemctl daemon-reload
systemctl enable non-nixos-gpu.service
systemctl restart non-nixos-gpu.service
```
_Note: it uses `systemctl`, maybe won't work for OpenRC..._
See [gpu-non-nixos](https://nix-community.github.io/home-manager/index.xhtml#sec-usage-gpu-non-nixos).
# Handling dot files
## Status
+11 -8
View File
@@ -3,23 +3,24 @@
description = "illogical-impulse";
inputs = {
# Qt 6.10 is not yet available from released version of nixpkgs.
#nixpkgs.url = "nixpkgs/nixos-25.05";
nixpkgs.url = "nixpkgs/nixos-unstable";
nixpkgs.url = "nixpkgs/nixos-25.11";
#nixpkgs.url = "nixpkgs/nixos-unstable";
home-manager = {
#url = "github:nix-community/home-manager/release-25.05";
url = "github:nix-community/home-manager/master";
url = "github:nix-community/home-manager/release-25.11";
#url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
nixgl.url = "github:nix-community/nixGL";
#nixgl.url = "github:nix-community/nixGL";
quickshell = {
url = "github:quickshell-mirror/quickshell/db1777c20b936a86528c1095cbcb1ebd92801402";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { nixpkgs, home-manager, nixgl, quickshell, ... }:
outputs = { nixpkgs, home-manager,
#nixgl,
quickshell, ... }:
let
home_attrs = rec {
username = import ./username.nix;
@@ -36,7 +37,9 @@
homeConfigurations = {
illogical_impulse = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
extraSpecialArgs = { inherit home_attrs nixgl quickshell; };
extraSpecialArgs = { inherit home_attrs
#nixgl
quickshell; };
modules = [
./home.nix
];
+14 -5
View File
@@ -1,8 +1,13 @@
{ config, lib, pkgs, nixgl, quickshell, home_attrs, ... }:
{ config, lib, pkgs,
#nixgl,
quickshell, home_attrs, ... }:
{
programs.home-manager.enable = true;
nixGL.packages = nixgl.packages;
nixGL.defaultWrapper = "mesa";
# Necessary for non-NixOS to handle GPU (since home-manager version 25.11)
targets.genericLinux.enable = true;
#nixGL.packages = nixgl.packages;
#nixGL.defaultWrapper = "mesa";
xdg.portal = {
enable = true;
@@ -27,7 +32,8 @@
systemd.enable = false; plugins = []; settings = {}; extraConfig = "";
enable = true;
## Use NixGL
package = config.lib.nixGL.wrap pkgs.hyprland;
#package = config.lib.nixGL.wrap pkgs.hyprland;
package = pkgs.hyprland;
};
home = {
@@ -167,6 +173,7 @@
songrec #songrec
translate-shell #translate-shell
wlogout #wlogout
libqalculate #libqalculate
]
++ [
@@ -174,7 +181,9 @@
### illogical-impulse-quickshell-git
#(config.lib.nixGL.wrap quickshell.packages.x86_64-linux.default)
(import ./quickshell.nix { inherit pkgs quickshell; nixGLWrap = config.lib.nixGL.wrap; })
(import ./quickshell.nix { inherit pkgs quickshell;
#nixGLWrap = config.lib.nixGL.wrap;
})
];
}//home_attrs;
}
+7 -3
View File
@@ -1,10 +1,14 @@
{ pkgs, quickshell, nixGLWrap, ... }:
{ pkgs, quickshell,
#nixGLWrap,
... }:
let
qs = nixGLWrap quickshell.packages.x86_64-linux.default;
#qs = nixGLWrap quickshell.packages.x86_64-linux.default;
qs = quickshell.packages.x86_64-linux.default;
in pkgs.stdenv.mkDerivation {
name = "illogical-impulse-quickshell-wrapper";
meta = with pkgs.lib; {
description = "Quickshell wrapped with NixGL + bundled Qt deps for home-manager usage";
#description = "Quickshell wrapped with NixGL + bundled Qt deps for home-manager usage";
description = "Quickshell bundled Qt deps for home-manager usage";
license = licenses.gpl3Only;
};
+3 -2
View File
@@ -32,8 +32,8 @@ function install_home-manager(){
try source $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
command -v $cmd && return
x nix-channel --add https://nixos.org/channels/nixos-25.05 nixpkgs-home
x nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.05.tar.gz home-manager
x nix-channel --add https://nixos.org/channels/nixos-25.11 nixpkgs-home
x nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager
x nix-channel --update
x env NIX_PATH="nixpkgs=$HOME/.nix-defexpr/channels/nixpkgs-home" nix-shell '<home-manager>' -A install
@@ -56,6 +56,7 @@ function hm_deps(){
x home-manager switch --flake .#illogical_impulse \
--extra-experimental-features nix-command \
--extra-experimental-features flakes
x sudo /nix/store/*-non-nixos-gpu/bin/non-nixos-gpu-setup
cd $REPO_ROOT
x git rm -f "${SETUP_USERNAME_NIXFILE}"
}