diff --git a/img/apps/browser.png b/img/apps/browser.png new file mode 100644 index 0000000..c3975c4 Binary files /dev/null and b/img/apps/browser.png differ diff --git a/img/apps/files.png b/img/apps/files.png new file mode 100644 index 0000000..dcc489a Binary files /dev/null and b/img/apps/files.png differ diff --git a/img/apps/mail.png b/img/apps/mail.png new file mode 100644 index 0000000..1c25f14 Binary files /dev/null and b/img/apps/mail.png differ diff --git a/img/apps/media.png b/img/apps/media.png new file mode 100644 index 0000000..8a09ac0 Binary files /dev/null and b/img/apps/media.png differ diff --git a/img/apps/music.png b/img/apps/music.png new file mode 100644 index 0000000..937a3e4 Binary files /dev/null and b/img/apps/music.png differ diff --git a/img/apps/nologs.png b/img/apps/nologs.png new file mode 100644 index 0000000..9a7def7 Binary files /dev/null and b/img/apps/nologs.png differ diff --git a/img/apps/terminal.png b/img/apps/terminal.png new file mode 100644 index 0000000..7b4f2eb Binary files /dev/null and b/img/apps/terminal.png differ diff --git a/img/launcher/nixos_black.png b/img/launcher/nixos_black.png new file mode 100644 index 0000000..cb352cd Binary files /dev/null and b/img/launcher/nixos_black.png differ diff --git a/img/launcher/nixos_emblem.png b/img/launcher/nixos_emblem.png new file mode 100644 index 0000000..7e765f5 Binary files /dev/null and b/img/launcher/nixos_emblem.png differ diff --git a/img/launcher/nixos_neon.png b/img/launcher/nixos_neon.png new file mode 100644 index 0000000..acbaad4 Binary files /dev/null and b/img/launcher/nixos_neon.png differ diff --git a/img/launcher/synthwave.jpg b/img/launcher/synthwave.jpg new file mode 100644 index 0000000..253b7fc Binary files /dev/null and b/img/launcher/synthwave.jpg differ diff --git a/img/launcher/synthwave.png b/img/launcher/synthwave.png new file mode 100644 index 0000000..d55b016 Binary files /dev/null and b/img/launcher/synthwave.png differ diff --git a/status_bar.lua b/status_bar.lua index 357b316..63ffe78 100644 --- a/status_bar.lua +++ b/status_bar.lua @@ -1,3 +1,5 @@ +hl.bind("SUPEr + A", hl.dsp.global("quickshell:show_active_title")) + return { start = function() hl.exec_cmd("waybar") diff --git a/theme/default-flavor b/theme/default-flavor new file mode 100644 index 0000000..623a638 --- /dev/null +++ b/theme/default-flavor @@ -0,0 +1 @@ +synthwave diff --git a/theme/flavors/synthwave/launcher.json b/theme/flavors/synthwave/launcher.json new file mode 100644 index 0000000..026238d --- /dev/null +++ b/theme/flavors/synthwave/launcher.json @@ -0,0 +1,61 @@ +{ + "name": "Synthwave", + + "radius": 48, + "appRadius": 34, + "orbitMultiplier": 2, + + "centerIcon": "img/center/synthwave.png", + + "colors": { + "overlay": "#090914cc", + "centerBackground": "#ff2bd6", + "centerBorder": "#00eaff", + "appBackground": "#16162acc", + "appBorder": "#ffcc00", + "appHoverBackground": "#302050ee" + }, + + "programs": [ + { + "name": "Chat", + "icon": "img/apps/chat.png", + "command": ["ssh -t nichkara.eu tmux new-session -A -t office"] + }, + { + "name": "Files", + "icon": "img/apps/files.png", + "command": ["nemo"] + }, + { + "name": "Media", + "icon": "img/apps/media.png", + "command": ["delfin"] + }, + { + "name": "Music", + "icon": "img/apps/music.png", + "command": ["finamp"] + }, + { + "name": "Terminal", + "icon": "img/apps/terminal.png", + "command": ["kitty"] + }, + { + "name": "No logs Browser", + "icon": "img/apps/nologs.png", + "command": ["firefox --private-window"] + }, + { + "name": "Browser", + "icon": "img/apps/browser.png", + "command": ["firefox"] + }, + { + "name": "E-Mail", + "icon": "img/apps/mail.png", + "command": ["thunderbird"] + } + ] +} diff --git a/widgets/launcher/RadialLauncher.qml b/widgets/launcher/RadialLauncher.qml new file mode 100644 index 0000000..4bb4024 --- /dev/null +++ b/widgets/launcher/RadialLauncher.qml @@ -0,0 +1,158 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Widgets + +PanelWindow { + id: launcher + + required property bool open + required property string repoRoot + required property string flavorName + + signal closeRequested() + + visible: open + focusable: true + aboveWindows: true + color: "transparent" + + anchors { + top: true + right: true + bottom: true + left: true + } + + FileView { + id: flavorFile + + path: launcher.repoRoot + "/theme/flavors/" + launcher.flavorName + "/launcher.json" + blockLoading: true + watchChanges: true + + onFileChanged: reload() + } + + readonly property var flavor: JSON.parse(flavorFile.text()) + + Process { + id: appProcess + } + + function fileUrl(path) { + if (!path || path.length === 0) + return "" + + if (path.startsWith("/")) + return "file://" + path + + return "file://" + launcher.repoRoot + "/" + path + } + + function launchProgram(program) { + launcher.closeRequested() + + appProcess.command = program.command + appProcess.startDetached() + } + + Rectangle { + anchors.fill: parent + color: launcher.flavor.colors.overlay + + MouseArea { + anchors.fill: parent + onClicked: launcher.closeRequested() + } + + Item { + id: dial + + property real r: launcher.flavor.radius + property real appR: launcher.flavor.appRadius + property real orbit: launcher.flavor.orbitMultiplier * r + + width: orbit * 2 + appR * 2 + height: orbit * 2 + appR * 2 + + anchors.centerIn: parent + + Rectangle { + id: center + + width: dial.r * 2 + height: dial.r * 2 + radius: dial.r + + anchors.centerIn: parent + + color: launcher.flavor.colors.centerBackground + border.color: launcher.flavor.colors.centerBorder + border.width: 2 + + clip: true + + Image { + anchors.fill: parent + anchors.margins: 6 + + source: launcher.fileUrl(launcher.flavor.centerIcon) + fillMode: Image.PreserveAspectFit + smooth: true + } + } + + Repeater { + model: launcher.flavor.programs + + delegate: Item { + id: appButton + + required property int index + required property var modelData + + property real angle: (index * 45 - 90) * Math.PI / 180 + + width: dial.appR * 2 + height: dial.appR * 2 + + x: dial.width / 2 + Math.cos(angle) * dial.orbit - width / 2 + y: dial.height / 2 + Math.sin(angle) * dial.orbit - height / 2 + + Rectangle { + anchors.fill: parent + radius: width / 2 + + color: mouse.containsMouse + ? launcher.flavor.colors.appHoverBackground + : launcher.flavor.colors.appBackground + + border.color: launcher.flavor.colors.appBorder + border.width: 2 + + clip: true + + Image { + anchors.fill: parent + anchors.margins: 7 + + source: launcher.fileUrl(appButton.modelData.icon) + fillMode: Image.PreserveAspectFit + smooth: true + } + + MouseArea { + id: mouse + + anchors.fill: parent + hoverEnabled: true + + onClicked: launcher.launchProgram(appButton.modelData) + } + } + } + } + } + } +} diff --git a/widgets/status_bar/shell.qml b/widgets/status_bar/shell.qml new file mode 100644 index 0000000..b0b1c5e --- /dev/null +++ b/widgets/status_bar/shell.qml @@ -0,0 +1,93 @@ +import Quickshell +import Quickshell.Wayland +import Quickshell.Hyprland +import QtQuick +import QtQuick.Layouts + +PanelWindow { + anchors.top: true + anchors.left: false + anchors.right: true + anchors.bottom: true + + property bool expanded: false + property int collapsedWidth: 48 + property int expandedWidth: 320 + + implicitWidth: expanded ? expandedWidth : collapsedWidth + + margins.top: 10 + margins.bottom: 10 + margins.right: 4 + + color: "transparent" + + Behavior on implicitWidth { + NumberAnimation { + duration: 220 + } + } + + Rectangle { + anchors.fill: parent + radius: 16 + color: "#77330077" + border.width: 1 + border.color: "#000000" + } + + Item { + width: 48 + height: 48 + + Image { + anchors.fill: parent + source: Quickshell.shellDir + "/../../img/launcher/nixos_black.png" + fillMode: Image.PreserveAspectFit + smooth: true + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + Quickshell.execDetached(["wofi", "--show", "drun"]) + } + } + } + + Text { + anchors.left: parent.left + anchors.leftMargin: 56 + anchors.verticalCenter: parent.verticalCenter + rightPadding: 12 + + visible: expanded + opacity: expanded ? 1.0 : 0.0 + Behavior on opacity { + NumberAnimation { + duration: 160 + } + } + + text: Hyprland.activeToplevel ? Hyprland.activeToplevel.title : "" + color: "white" + elide: Text.ElideRight + } + + GlobalShortcut { + name: "toggle_title_bar" + description: "Expand bar and show active window title" + onPressed: { + expanded = !expanded + } + } + + GlobalShortcut { + name: "show_active_title" + description: "Show the active window title" + onPressed: { + expanded = true + } + } +} diff --git a/workspaces.lua b/workspaces.lua index 3d5f75b..95c0183 100644 --- a/workspaces.lua +++ b/workspaces.lua @@ -1,4 +1,4 @@ -local mainMod = "ALT" +local mainMod = "SUPER" -- Move window in direction hl.bind(mainMod .. " + SHIFT + H", hl.dsp.window.move({ direction = "left" })) @@ -6,6 +6,11 @@ hl.bind(mainMod .. " + SHIFT + L", hl.dsp.window.move({ direction = "right" })) hl.bind(mainMod .. " + SHIFT + K", hl.dsp.window.move({ direction = "up" })) hl.bind(mainMod .. " + SHIFT + J", hl.dsp.window.move({ direction = "down" })) +hl.bind(mainMod .. " + H", hl.dsp.focus({ direction = "left" })) +hl.bind(mainMod .. " + J", hl.dsp.focus({ direction = "down" })) +hl.bind(mainMod .. " + K", hl.dsp.focus({ direction = "up" })) +hl.bind(mainMod .. " + L", hl.dsp.focus({ direction = "right" })) + -- Switch to numbered workspaces for i = 1, 10 do local key = i % 10 -- workspace 10 -> key 0 @@ -13,20 +18,20 @@ for i = 1, 10 do end -- Previous / next workspace -hl.bind("CTRL + ALT + H", hl.dsp.focus({ workspace = "-1" })) -hl.bind("CTRL + ALT + L", hl.dsp.focus({ workspace = "+1" })) -hl.bind("CTRL + ALT + LEFT", hl.dsp.focus({ workspace = "-1" })) -hl.bind("CTRL + ALT + RIGHT", hl.dsp.focus({ workspace = "+1" })) +hl.bind(mainMod .. " + ALT + H", hl.dsp.focus({ workspace = "-1" })) +hl.bind(mainMod .. " + ALT + L", hl.dsp.focus({ workspace = "+1" })) +-- hl.bind("CTRL + ALT + LEFT", hl.dsp.focus({ workspace = "-1" })) +-- hl.bind("CTRL + ALT + RIGHT", hl.dsp.focus({ workspace = "+1" })) -- Move window to previous / next workspace (follows the window) -hl.bind("CTRL + ALT + SHIFT + H", hl.dsp.window.move({ workspace = "-1" })) -hl.bind("CTRL + ALT + SHIFT + L", hl.dsp.window.move({ workspace = "+1" })) -hl.bind("CTRL + ALT + SHIFT + LEFT", hl.dsp.window.move({ workspace = "-1" })) -hl.bind("CTRL + ALT + SHIFT + RIGHT", hl.dsp.window.move({ workspace = "+1" })) +hl.bind(mainMod .. " + ALT + SHIFT + H", hl.dsp.window.move({ workspace = "-1" })) +hl.bind(mainMod .. " + ALT + SHIFT + L", hl.dsp.window.move({ workspace = "+1" })) +-- hl.bind("CTRL + ALT + SHIFT + LEFT", hl.dsp.window.move({ workspace = "-1" })) +-- hl.bind("CTRL + ALT + SHIFT + RIGHT", hl.dsp.window.move({ workspace = "+1" })) -- Move window to previous / next workspace silently -hl.bind(mainMod .. " + CTRL + SHIFT + H", hl.dsp.window.move({ workspace = "-1", follow = false })) -hl.bind(mainMod .. " + CTRL + SHIFT + L", hl.dsp.window.move({ workspace = "+1", follow = false })) +hl.bind(mainMod .. " + ALT + SHIFT + J", hl.dsp.window.move({ workspace = "-1", follow = false })) +hl.bind(mainMod .. " + ALT + SHIFT + K", hl.dsp.window.move({ workspace = "+1", follow = false })) -- hl.bind(mainMod .. " + CTRL + SHIFT + LEFT", hl.dsp.window.move({ workspace = "-1", follow = false })) -- hl.bind(mainMod .. " + CTRL + SHIFT + RIGHT", hl.dsp.window.move({ workspace = "+1", follow = false }))