Merge settings window to main #23
+2
-1
@@ -160,7 +160,8 @@ Singleton {
|
||||
hoverRegionHeight: dock.hoverRegionHeight,
|
||||
hoverToReveal: dock.hoverToReveal,
|
||||
pinnedApps: dock.pinnedApps,
|
||||
pinnedOnStartup: dock.pinnedOnStartup
|
||||
pinnedOnStartup: dock.pinnedOnStartup,
|
||||
ignoredAppRegexes: dock.ignoredAppRegexes
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ JsonObject {
|
||||
property real height: 60
|
||||
property real hoverRegionHeight: 2
|
||||
property bool hoverToReveal: true
|
||||
property list<string> ignoredAppRegexes: []
|
||||
property list<string> pinnedApps: ["org.kde.dolphin", "kitty",]
|
||||
property bool pinnedOnStartup: false
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import qs.Modules.Launcher as Launcher
|
||||
import qs.Modules.Resources as Resources
|
||||
import qs.Modules.Drawing as Drawing
|
||||
import qs.Modules.Settings as Settings
|
||||
import qs.Modules.Dock as Dock
|
||||
|
||||
Shape {
|
||||
id: root
|
||||
@@ -24,6 +25,7 @@ Shape {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Config.barConfig.border
|
||||
anchors.topMargin: bar.implicitHeight
|
||||
asynchronous: true
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
|
||||
Drawing.Background {
|
||||
@@ -93,4 +95,12 @@ Shape {
|
||||
startY: 0
|
||||
wrapper: root.panels.settings
|
||||
}
|
||||
|
||||
Dock.Background {
|
||||
id: dock
|
||||
|
||||
startX: (root.width - wrapper.width) / 2 - rounding
|
||||
startY: root.height
|
||||
wrapper: root.panels.dock
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,9 @@ CustomMouseArea {
|
||||
}
|
||||
}
|
||||
|
||||
if (!visibilities.dock && !visibilities.launcher && inBottomPanel(panels.dock, x, y))
|
||||
visibilities.dock = true;
|
||||
|
||||
if (y < root.bar.implicitHeight) {
|
||||
root.bar.checkPopout(x);
|
||||
}
|
||||
@@ -145,6 +148,9 @@ CustomMouseArea {
|
||||
root.panels.osd.hovered = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (root.visibilities.launcher)
|
||||
root.visibilities.dock = false;
|
||||
}
|
||||
|
||||
function onOsdChanged() {
|
||||
|
||||
@@ -12,6 +12,7 @@ import qs.Modules.Launcher as Launcher
|
||||
import qs.Modules.Resources as Resources
|
||||
import qs.Modules.Settings as Settings
|
||||
import qs.Modules.Drawing as Drawing
|
||||
import qs.Modules.Dock as Dock
|
||||
import qs.Config
|
||||
|
||||
Item {
|
||||
@@ -19,6 +20,7 @@ Item {
|
||||
|
||||
required property Item bar
|
||||
readonly property alias dashboard: dashboard
|
||||
readonly property alias dock: dock
|
||||
readonly property alias drawing: drawing
|
||||
required property Canvas drawingItem
|
||||
readonly property alias launcher: launcher
|
||||
@@ -143,4 +145,14 @@ Item {
|
||||
panels: root
|
||||
visibilities: root.visibilities
|
||||
}
|
||||
|
||||
Dock.Wrapper {
|
||||
id: dock
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
panels: root
|
||||
screen: root.screen
|
||||
visibilities: root.visibilities
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -33,7 +33,7 @@ Variants {
|
||||
property var root: Quickshell.shellDir
|
||||
|
||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.resources ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
||||
WlrLayershell.keyboardFocus: visibilities.dock || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.resources ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
||||
color: "transparent"
|
||||
contentItem.focus: true
|
||||
mask: visibilities.isDrawing ? null : region
|
||||
@@ -94,7 +94,7 @@ Variants {
|
||||
HyprlandFocusGrab {
|
||||
id: focusGrab
|
||||
|
||||
active: visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu"))
|
||||
active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu"))
|
||||
windows: [win]
|
||||
|
||||
onCleared: {
|
||||
@@ -104,6 +104,7 @@ Variants {
|
||||
visibilities.osd = false;
|
||||
visibilities.settings = false;
|
||||
visibilities.resources = false;
|
||||
visibilities.dock = false;
|
||||
panels.popouts.hasCurrent = false;
|
||||
}
|
||||
}
|
||||
@@ -113,6 +114,7 @@ Variants {
|
||||
|
||||
property bool bar
|
||||
property bool dashboard
|
||||
property bool dock
|
||||
property bool isDrawing
|
||||
property bool launcher
|
||||
property bool notif: NotifServer.popups.length > 0
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Config
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property list<var> apps: {
|
||||
var map = new Map();
|
||||
|
||||
// Pinned apps
|
||||
const pinnedApps = Config.dock.pinnedApps ?? [];
|
||||
for (const appId of pinnedApps) {
|
||||
if (!map.has(appId.toLowerCase()))
|
||||
map.set(appId.toLowerCase(), ({
|
||||
pinned: true,
|
||||
toplevels: []
|
||||
}));
|
||||
}
|
||||
|
||||
// Separator
|
||||
if (pinnedApps.length > 0) {
|
||||
map.set("SEPARATOR", {
|
||||
pinned: false,
|
||||
toplevels: []
|
||||
});
|
||||
}
|
||||
|
||||
// Ignored apps
|
||||
const ignoredRegexStrings = Config.dock.ignoredAppRegexes ?? [];
|
||||
const ignoredRegexes = ignoredRegexStrings.map(pattern => new RegExp(pattern, "i"));
|
||||
// Open windows
|
||||
for (const toplevel of ToplevelManager.toplevels.values) {
|
||||
if (ignoredRegexes.some(re => re.test(toplevel.appId)))
|
||||
continue;
|
||||
if (!map.has(toplevel.appId.toLowerCase()))
|
||||
map.set(toplevel.appId.toLowerCase(), ({
|
||||
pinned: false,
|
||||
toplevels: []
|
||||
}));
|
||||
map.get(toplevel.appId.toLowerCase()).toplevels.push(toplevel);
|
||||
}
|
||||
|
||||
var values = [];
|
||||
|
||||
for (const [key, value] of map) {
|
||||
values.push(appEntryComp.createObject(null, {
|
||||
appId: key,
|
||||
toplevels: value.toplevels,
|
||||
pinned: value.pinned
|
||||
}));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function isPinned(appId) {
|
||||
return Config.dock.pinnedApps.indexOf(appId) !== -1;
|
||||
}
|
||||
|
||||
function togglePin(appId) {
|
||||
if (root.isPinned(appId)) {
|
||||
Config.dock.pinnedApps = Config.dock.pinnedApps.filter(id => id !== appId);
|
||||
} else {
|
||||
Config.dock.pinnedApps = Config.dock.pinnedApps.concat([appId]);
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: appEntryComp
|
||||
|
||||
TaskbarAppEntry {
|
||||
}
|
||||
}
|
||||
|
||||
component TaskbarAppEntry: QtObject {
|
||||
id: wrapper
|
||||
|
||||
required property string appId
|
||||
required property bool pinned
|
||||
required property list<var> toplevels
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import qs.Modules.Dock.Parts
|
||||
import qs.Components
|
||||
import qs.Helpers
|
||||
import qs.Config
|
||||
@@ -17,12 +18,29 @@ Item {
|
||||
implicitHeight: Config.dock.height + root.padding * 2
|
||||
implicitWidth: dockRow.implicitWidth + root.padding * 2
|
||||
|
||||
RowLayout {
|
||||
CustomListView {
|
||||
id: dockRow
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
spacing: Appearance.spacing.small
|
||||
anchors.centerIn: parent
|
||||
implicitHeight: Config.dock.height
|
||||
implicitWidth: contentWidth
|
||||
orientation: ListView.Horizontal
|
||||
spacing: Appearance.padding.smaller
|
||||
|
||||
delegate: DockAppButton {
|
||||
required property var modelData
|
||||
|
||||
appListRoot: root
|
||||
appToplevel: modelData
|
||||
visibilities: root.visibilities
|
||||
}
|
||||
Behavior on implicitWidth {
|
||||
Anim {
|
||||
}
|
||||
}
|
||||
model: ScriptModel {
|
||||
objectProp: "appId"
|
||||
values: TaskbarApps.apps
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import qs.Components
|
||||
import qs.Helpers
|
||||
import qs.Config
|
||||
|
||||
CustomRect {
|
||||
id: root
|
||||
|
||||
property bool appIsActive: appToplevel.toplevels.find(t => (t.activated == true)) !== undefined
|
||||
property var appListRoot
|
||||
property var appToplevel
|
||||
property real countDotHeight: 4
|
||||
property real countDotWidth: 10
|
||||
property var desktopEntry: DesktopEntries.heuristicLookup(appToplevel.appId)
|
||||
property real iconSize: implicitHeight - 20
|
||||
readonly property bool isSeparator: appToplevel.appId === "SEPARATOR"
|
||||
property int lastFocused: -1
|
||||
required property PersistentProperties visibilities
|
||||
|
||||
implicitHeight: Config.dock.height
|
||||
implicitWidth: isSeparator ? 1 : implicitHeight
|
||||
radius: Appearance.rounding.normal - Appearance.padding.small
|
||||
|
||||
Loader {
|
||||
active: !isSeparator
|
||||
anchors.centerIn: parent
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
IconImage {
|
||||
id: icon
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
implicitSize: root.iconSize
|
||||
source: Quickshell.iconPath(AppSearch.guessIcon(appToplevel.appId), "image-missing")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 3
|
||||
|
||||
Repeater {
|
||||
model: Math.min(appToplevel.toplevels.length, 3)
|
||||
|
||||
delegate: Rectangle {
|
||||
required property int index
|
||||
|
||||
color: appIsActive ? DynamicColors.palette.m3primary : DynamicColors.tPalette.m3primary
|
||||
implicitHeight: root.countDotHeight
|
||||
implicitWidth: (appToplevel.toplevels.length <= 3) ? root.countDotWidth : root.countDotHeight // Circles when too many
|
||||
radius: Appearance.rounding.full
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StateLayer {
|
||||
onClicked: {
|
||||
if (appToplevel.toplevels.length === 0) {
|
||||
root.desktopEntry?.execute();
|
||||
root.visibilities.dock = false;
|
||||
return;
|
||||
}
|
||||
lastFocused = (lastFocused + 1) % appToplevel.toplevels.length;
|
||||
appToplevel.toplevels[lastFocused].activate();
|
||||
root.visibilities.dock = false;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onApplicationsChanged() {
|
||||
root.desktopEntry = DesktopEntries.heuristicLookup(appToplevel.appId);
|
||||
}
|
||||
|
||||
target: DesktopEntries
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: isSeparator
|
||||
|
||||
sourceComponent: DockSeparator {
|
||||
}
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Components
|
||||
import qs.Config
|
||||
|
||||
CustomRect {
|
||||
Layout.bottomMargin: dockRow.padding + Appearance.rounding.normal
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: dockRow.padding + Appearance.rounding.normal
|
||||
color: DynamicColors.palette.m3outlineVariant
|
||||
implicitWidth: 1
|
||||
}
|
||||
Reference in New Issue
Block a user