Initial commit

This commit is contained in:
Ceres 2026-01-11 23:23:04 +00:00
commit f94fd70f07
Signed by: ceres-sees-all
GPG key ID: 9814758436430045
151 changed files with 7650 additions and 0 deletions

View file

@ -0,0 +1,25 @@
pragma Singleton
import Quickshell
Singleton {
readonly property string foreground: "#FDF8F0"
readonly property string background: "#151313"
readonly property string colour0: "#3F3D3D"
readonly property string colour1: "#51494A"
readonly property string colour2: "#866F67"
readonly property string colour3: "#808578"
readonly property string colour4: "#897E6B"
readonly property string colour5: "#EEDA8D"
readonly property string colour6: "#F9ECD4"
readonly property string colour7: "#F4EDE1"
readonly property string colour8: "#ABA69D"
readonly property string colour9: "#51494A"
readonly property string colour10: "#866F67"
readonly property string colour11: "#808578"
readonly property string colour12: "#897E6B"
readonly property string colour13: "#EEDA8D"
readonly property string colour14: "#F9ECD4"
readonly property string colour15: "#F4EDE1"
}

View file

@ -0,0 +1,54 @@
import QtQuick
import Quickshell
import Quickshell.Services.Pam
Scope {
id: root
signal unlocked()
signal failed()
// These properties are in the context and not individual lock surfaces
// so all surfaces can share the same state.
property string currentText: ""
property bool unlockInProgress: false
property bool showFailure: false
// Clear the failure text once the user starts typing.
onCurrentTextChanged: showFailure = false;
function tryUnlock() {
if (currentText === "") return;
root.unlockInProgress = true;
pam.start();
}
PamContext {
id: pam
// Its best to have a custom pam config for quickshell, as the system one
// might not be what your interface expects, and break in some way.
// This particular example only supports passwords.
configDirectory: "pam"
config: "password.conf"
// pam_unix will ask for a response for the password prompt
onPamMessage: {
if (this.responseRequired) {
this.respond(root.currentText);
}
}
// pam_unix won't send any important messages so all we need is the completion status.
onCompleted: result => {
if (result == PamResult.Success) {
root.unlocked();
} else {
root.currentText = "";
root.showFailure = true;
}
root.unlockInProgress = false;
}
}
}

View file

@ -0,0 +1,118 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls.Fusion
import Quickshell.Wayland
import Quickshell.Services.UPower
Rectangle {
id: root
required property LockContext context
Image {
anchors.fill: parent
source: "/home/ceres/.local/state/niri/wallpaper"
}
Label {
id: clock
property var date: new Date()
font.family: "Departure Mono"
color: Colours.foreground
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 100
}
// The native font renderer tends to look nicer at large sizes.
renderType: Text.NativeRendering
font.pointSize: 80
// updates the clock every second
Timer {
running: true
repeat: true
interval: 1000
onTriggered: clock.date = new Date();
}
// updated when the date changes
text: {
const hours = this.date.getHours().toString().padStart(2, '0');
const minutes = this.date.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
}
}
Text {
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 250
}
renderType: Text.NativeRendering
font.pointSize: 30
font.family: "Departure Mono"
color: Colours.foreground
text: Math.floor(UPower.displayDevice.percentage * 100) + "% Battery"
}
ColumnLayout {
// Uncommenting this will make the password entry invisible except on the active monitor.
// visible: Window.active
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.verticalCenter
}
RowLayout {
TextField {
id: passwordBox
background: Rectangle {
color: Colours.background
opacity: 0.9
border.width: 4
border.color: Colours.colour2
radius: 20
}
implicitWidth: 400
padding: 10
color: Colours.foreground
horizontalAlignment: TextInput.AlignHCenter
focus: true
enabled: !root.context.unlockInProgress
echoMode: TextInput.Password
inputMethodHints: Qt.ImhSensitiveData
onTextChanged: root.context.currentText = this.text;
onAccepted: root.context.tryUnlock();
Connections {
target: root.context
function onCurrentTextChanged() {
passwordBox.text = root.context.currentText;
}
}
}
}
Label {
anchors.horizontalCenter: parent.horizontalCenter
visible: root.context.showFailure
text: "Incorrect password"
font.family: "Departure Mono"
color: Colours.foreground
}
}
}

View file

@ -0,0 +1,3 @@
auth required pam_unix.so
auth required pam_u2f.so cue authfile=/etc/u2f_mappings

31
quickshell/lock/shell.qml Normal file
View file

@ -0,0 +1,31 @@
import Quickshell
import Quickshell.Wayland
ShellRoot {
// This stores all the information shared between the lock surfaces on each screen.
LockContext {
id: lockContext
onUnlocked: {
// Unlock the screen before exiting, or the compositor will display a
// fallback lock you can't interact with.
lock.locked = false;
Qt.quit();
}
}
WlSessionLock {
id: lock
// Lock the session immediately when quickshell starts.
locked: true
WlSessionLockSurface {
LockSurface {
anchors.fill: parent
context: lockContext
}
}
}
}

View file

@ -0,0 +1,25 @@
pragma Singleton
import Quickshell
Singleton {
readonly property string foreground: "#FDF8F0"
readonly property string background: "#151313"
readonly property string colour0: "#3F3D3D"
readonly property string colour1: "#51494A"
readonly property string colour2: "#866F67"
readonly property string colour3: "#808578"
readonly property string colour4: "#897E6B"
readonly property string colour5: "#EEDA8D"
readonly property string colour6: "#F9ECD4"
readonly property string colour7: "#F4EDE1"
readonly property string colour8: "#ABA69D"
readonly property string colour9: "#51494A"
readonly property string colour10: "#866F67"
readonly property string colour11: "#808578"
readonly property string colour12: "#897E6B"
readonly property string colour13: "#EEDA8D"
readonly property string colour14: "#F9ECD4"
readonly property string colour15: "#F4EDE1"
}

View file

@ -0,0 +1,8 @@
pragma Singleton
import Quickshell
Singleton {
readonly property int launcherVisibleEntries: 5
readonly property real launcherOuterPadding: 10
}

View file

@ -0,0 +1,74 @@
//@ pragma IconTheme Adwaita
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Widgets
import Quickshell.Services.UPower
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../Config"
PanelWindow {
anchors {
bottom: true
right: true
}
width: text.width + 70
color: "transparent"
function getIcon() {
if (UPower.displayDevice.percentage > 0.9) {
if (UPower.onBattery == false) {
return "xfce4-battery-full-charging"
}
else {
return "xfce4-battery-full"
}
}
else if (0.5 < UPower.displayDevice.percentage) {
if (UPower.onBattery == false) {
return "xfce4-battery-ok-charging"
}
else {
return "xfce4-battery-ok"
}
}
else if (0.1 < UPower.displayDevice.percentage) {
if (UPower.onBattery == false) {
return "xfce4-battery-low-charging"
}
else {
return "xfce4-battery-low"
}
}
}
Rectangle {
anchors.fill: parent
topLeftRadius: 20
opacity: 0.95
color: Colours.colour1
Row {
anchors.verticalCenter: parent.verticalCenter
IconImage {
anchors.verticalCenter: parent.verticalCenter
width: 50
height: 50
source: Quickshell.iconPath(getIcon())
}
Text {
id: text
color: Colours.foreground
font.family: "Departure Mono"
font.pixelSize: 50
text: Math.floor(UPower.displayDevice.percentage * 100) + "%"
}
}
}
}

View file

@ -0,0 +1,56 @@
//@ pragma IconTheme Adwaita
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../Config"
PanelWindow {
anchors {
bottom: true
left: true
}
width: text.width + 20
color: "transparent"
Rectangle {
anchors.fill: parent
topRightRadius: 20
opacity: 0.95
color: Colours.colour1
Text {
id: text
anchors.centerIn: parent
color: Colours.foreground
font.family: "Departure Mono"
font.pixelSize: 50
Process {
id: dateProc
command: ["date"]
running: true
stdout: StdioCollector {
onStreamFinished: clock.text = this.text
}
}
Timer {
interval: 1000
running: true
repeat: true
onTriggered: text.text = Qt.formatDateTime(new Date(), "HH:mm")
}
}
}
}

View file

@ -0,0 +1,178 @@
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../Config"
PanelWindow {
id: launcher
anchors.top: true
property var open: false
property int selectedIndex: 0
readonly property list<DesktopEntry> visibleEntries: Array.from(DesktopEntries.applications.values).sort((d1, d2) => d1.name.localeCompare(d2.name)).filter(application => application.name.toLowerCase().includes(search.text.toLowerCase()))
function genHeight() {
if (launcher.visibleEntries.length > Config.launcherVisibleEntries) {
return ((search.height * (Config.launcherVisibleEntries + 1) + Config.launcherOuterPadding))
}
else {
return (search.height * (launcher.visibleEntries.length + 1) + Config.launcherOuterPadding)
}
}
implicitHeight: open ? genHeight() : 0
implicitWidth: 500
color: "transparent"
visible: open ? true : false
Behavior on implicitHeight {
NumberAnimation {
duration: 80
easing.type: Easing.InOutQuad
easing.overshoot: 2
}
}
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
exclusionMode: ExclusionMode.Ignore
Rectangle {
id: rect
anchors.fill: parent
color: Colours.background
opacity: 0.9
bottomLeftRadius: 20
bottomRightRadius: 20
ColumnLayout {
id: content
anchors.fill: parent
Row{
Rectangle {
color: "transparent"
width: Config.launcherOuterPadding
height: search.height
}
Rectangle {
height: search.height
width: search.height
color: "transparent"
IconImage {
anchors.centerIn: parent
source: Quickshell.iconPath("search-icon")
height: search.height
width: search.height
}
}
Rectangle {
color: "transparent"
width: launcher.width - search.height - (2 * Config.launcherOuterPadding)
height: search.height
TextField {
id: search
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
focus: true
placeholderText: "Search..."
background: null
color: Colours.foreground
placeholderTextColor: Colours.colour0
Keys.onPressed: event => {
if (event.key == Qt.Key_Return) {
launcher.open = false;
launcher.visibleEntries[launcher.selectedIndex].execute();
}
if (event.key == Qt.Key_Down) {
if (list.currentIndex < (launcher.visibleEntries.length-1)) {
list.currentIndex++;
}
event.accepted = true;
}
if (event.key == Qt.Key_Up) {
if (list.currentIndex > 0) {
list.currentIndex--;
}
event.accepted = true;
}
if (event.key == Qt.Key_Escape) {
launcher.open = false;
event.accepted = true;
}
}
}
}
Rectangle {
color: "transparent"
width: Config.launcherOuterPadding
height: search.height
}
}
ListView {
id: list
model: launcher.visibleEntries
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
preferredHighlightBegin: 0
highlight: Rectangle { color: Colours.colour1; radius:20 }
currentIndex: 0
delegate: Row {
Rectangle {
color: "transparent"
width: Config.launcherOuterPadding
height: search.height
}
Rectangle {
color: "transparent"
height: search.height
width: search.height
IconImage {
source: Quickshell.iconPath(modelData.icon, true)
height:search.height
width: search.height
}
}
Rectangle {
color: "transparent"
height: search.height
width: launcher.width - search.height - Config.launcherOuterPadding
Text{
color: Colours.foreground
text: modelData.name
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}
IpcHandler {
target: "launcher"
function toggle() {
search.text = ""
launcher.open = !launcher.open
}
}
}

View file

@ -0,0 +1,237 @@
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Widgets
import QtQuick
import Qt.labs.folderlistmodel
import QtQuick.Layouts
import QtQuick.Controls
import "../Config"
PanelWindow {
id: pass
anchors.bottom: true
property var open: false
property int selectedIndex: 0
property string passLocation: ""
function genHeight() {
if (folderModel.count > 5) {
return 200
}
else {
return (search.height * (folderModel.count + 1)) + Config.launcherOuterPadding
}
}
Process {
id: passCopy
running: false
command: ["pass", "-c", passLocation]
}
Process {
id: userCopy
running: false
command: ["pass", "-c2", passLocation]
stdout: StdioCollector {
onStreamFinished: passCopy.running = true
}
}
function goBack() {
var lastSlash = list.currentItem.filePath.lastIndexOf('/')
var currentDir = list.currentItem.filePath.substring(0, lastSlash)
var lastSlash = currentDir.lastIndexOf('/')
var parentDir = currentDir.substring(0, lastSlash)
if (currentDir == "/home/ceres/.password-store") {
return;
}
else {
folderModel.folder = "file://" + parentDir
}
}
function copyPass() {
if(list.currentItem.fileIsDir==true) {
folderModel.folder = folderModel.folder+"/"+list.currentItem.fileBaseName
}
else {
passLocation = list.currentItem.filePath
passLocation = passLocation.replace("/home/ceres/.password-store/", "")
passLocation = passLocation.replace(".gpg", "")
userCopy.running = true
pass.open = false
search.text = ""
folderModel.folder = "file:///home/ceres/.password-store"
}
}
implicitHeight: open ? genHeight() : 0
implicitWidth: 500
color: "transparent"
visible: open ? true : false
Behavior on implicitHeight {
NumberAnimation {
duration: 80
easing.type: Easing.InOutQuad
easing.overshoot: 2
}
}
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
exclusionMode: ExclusionMode.Ignore
Rectangle {
id: rect
anchors.fill: parent
color: Colours.background
opacity: 0.9
topLeftRadius: 20
topRightRadius: 20
ColumnLayout {
id: content
anchors.fill: parent
Row{
Rectangle {
color: "transparent"
width: Config.launcherOuterPadding
height: search.height
}
Rectangle {
height: search.height
width: search.height
color: "transparent"
IconImage {
anchors.centerIn: parent
source: Quickshell.iconPath("search-icon")
height: search.height
width: search.height
}
}
Rectangle {
color: "transparent"
width: pass.width - search.height - (2 * Config.launcherOuterPadding)
height: search.height
TextField {
id: search
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
focus: true
placeholderText: "Search..."
background: null
color: Colours.foreground
placeholderTextColor: Colours.colour0
Keys.onPressed: event => {
if (event.key == Qt.Key_Return) {
copyPass();
event.accepted = true;
}
if (event.key == Qt.Key_Down) {
if(list.currentIndex<folderModel.count-1) {
list.currentIndex++;
}
event.accepted = true;
}
if (event.key == Qt.Key_Up) {
if (list.currentIndex > 0) {
list.currentIndex--;
}
event.accepted = true;
}
if (event.key == Qt.Key_Escape) {
pass.open = false;
list.currentIndex = 0
folderModel.folder = "file:///home/ceres/.password-store"
event.accepted = true;
}
if (event.key == Qt.Key_Tab) {
goBack();
event.accepted = true;
}
}
}
}
Rectangle {
color: "transparent"
width: Config.launcherOuterPadding
height: search.height
}
}
FolderListModel {
id: folderModel
folder: "file:///home/ceres/.password-store"
caseSensitive: false
showDirs: search.text === "" ? true : false
showDirsFirst: true
nameFilters: "*"+search.text+"*"
}
ListView {
id: list
model: folderModel
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
preferredHighlightBegin: 0
highlight: Rectangle { color: Colours.colour1; radius:20 }
currentIndex: 0
delegate: Row {
required property string fileBaseName
required property bool fileIsDir
required property string filePath
Rectangle {
color: "transparent"
width: Config.launcherOuterPadding
height: search.height
}
Rectangle {
color: "transparent"
height: search.height
width: pass.width - (2 * Config.launcherOuterPadding)
Text{
function genText() {
if(fileIsDir==true) {
return fileBaseName+"/"
}
else {
return fileBaseName
}
}
color: Colours.foreground
text: genText()
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}
IpcHandler {
target: "pass"
function toggle() {
search.text = ""
pass.open = !pass.open
}
}
}

View file

@ -0,0 +1,22 @@
import Quickshell
import QtQuick
import Quickshell.Wayland
PanelWindow {
id: background
anchors {
left: true
right: true
bottom: true
top: true
}
WlrLayershell.layer: WlrLayer.Background
Image {
width: background.width
height: background.height
source: "/home/ceres/.local/state/niri/wallpaper"
fillMode: Image.PreserveAspectCrop
}
}

View file

@ -0,0 +1,33 @@
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../Config"
ShellRoot{
id: widgets
property var open: false
Battery {
visible: open ? true : false
height: open ? 80 : 0
}
Clock {
visible: open ? true : false
height: open ? 80 : 0
}
IpcHandler {
target: "widgets"
function toggle() {
widgets.open = !widgets.open
}
}
}

View file

@ -0,0 +1,9 @@
import Quickshell
import "Modules"
ShellRoot {
Wallpaper {}
Launcher {}
Widgets {}
Pass {}
}