all: misc
This commit is contained in:
parent
c6eef9f01c
commit
f22dee69f0
5 changed files with 375 additions and 230 deletions
|
|
@ -8,8 +8,7 @@ import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Hyprland
|
||||||
import ".."
|
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
PersistentProperties {
|
PersistentProperties {
|
||||||
|
|
@ -38,240 +37,37 @@ Singleton {
|
||||||
activeAsync: persist.launcherOpen
|
activeAsync: persist.launcherOpen
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
width: 450
|
id: launcherWindow
|
||||||
height: 7 + searchContainer.implicitHeight + list.topMargin * 2 + list.delegateHeight * 10
|
//anchors { left: true; right: true; top: true; bottom: true }
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
implicitWidth: content.width
|
||||||
|
implicitHeight: content.height
|
||||||
|
//color: "#20ff0000"
|
||||||
|
//WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
|
||||||
WlrLayershell.namespace: "shell:launcher"
|
WlrLayershell.namespace: "shell:launcher"
|
||||||
|
|
||||||
Rectangle {
|
/*HyprlandWindow.visibleMask: Region {
|
||||||
//anchors.fill: parent
|
item: content
|
||||||
height: 7 + searchContainer.implicitHeight + list.topMargin + list.bottomMargin + Math.min(list.contentHeight, list.delegateHeight * 10)
|
}*/
|
||||||
Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
|
||||||
width: 450
|
|
||||||
color: ShellGlobals.colors.bar
|
|
||||||
radius: 5
|
|
||||||
border.color: ShellGlobals.colors.barOutline
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
ColumnLayout {
|
HyprlandFocusGrab {
|
||||||
anchors.fill: parent
|
windows: [launcherWindow]
|
||||||
anchors.margins: 7
|
active: true
|
||||||
anchors.bottomMargin: 0
|
//onCleared: console.log("cleared")
|
||||||
spacing: 0
|
onCleared: persist.launcherOpen = false
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
MouseArea {
|
||||||
id: searchContainer
|
anchors.fill: parent
|
||||||
Layout.fillWidth: true
|
|
||||||
implicitHeight: searchbox.implicitHeight + 10
|
|
||||||
color: "#30c0ffff"
|
|
||||||
radius: 3
|
|
||||||
border.color: "#50ffffff"
|
|
||||||
|
|
||||||
RowLayout {
|
onPressed: persist.launcherOpen = false
|
||||||
id: searchbox
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 5
|
|
||||||
|
|
||||||
IconImage {
|
MouseArea {
|
||||||
implicitSize: parent.height
|
anchors.centerIn: parent
|
||||||
source: "root:icons/magnifying-glass.svg"
|
width: content.width
|
||||||
}
|
height: content.height
|
||||||
|
|
||||||
TextInput {
|
LaunchContent { id: content }
|
||||||
id: search
|
|
||||||
Layout.fillWidth: true
|
|
||||||
color: "white"
|
|
||||||
|
|
||||||
focus: true
|
|
||||||
Keys.forwardTo: [list]
|
|
||||||
Keys.onEscapePressed: persist.launcherOpen = false
|
|
||||||
|
|
||||||
Keys.onPressed: event => {
|
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
if (event.key == Qt.Key_J) {
|
|
||||||
list.currentIndex = list.currentIndex == list.count - 1 ? 0 : list.currentIndex + 1;
|
|
||||||
event.accepted = true;
|
|
||||||
} else if (event.key == Qt.Key_K) {
|
|
||||||
list.currentIndex = list.currentIndex == 0 ? list.count - 1 : list.currentIndex - 1;
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onAccepted: {
|
|
||||||
if (list.currentItem) {
|
|
||||||
list.currentItem.clicked(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
list.currentIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: list
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
clip: true
|
|
||||||
cacheBuffer: 0 // works around QTBUG-131106
|
|
||||||
//reuseItems: true
|
|
||||||
model: ScriptModel {
|
|
||||||
values: DesktopEntries.applications.values
|
|
||||||
.map(object => {
|
|
||||||
const stxt = search.text.toLowerCase();
|
|
||||||
const ntxt = object.name.toLowerCase();
|
|
||||||
let si = 0;
|
|
||||||
let ni = 0;
|
|
||||||
|
|
||||||
let matches = [];
|
|
||||||
let startMatch = -1;
|
|
||||||
|
|
||||||
for (let si = 0; si != stxt.length; ++si) {
|
|
||||||
const sc = stxt[si];
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// Drop any entries with letters that don't exist in order
|
|
||||||
if (ni == ntxt.length) return null;
|
|
||||||
|
|
||||||
const nc = ntxt[ni++];
|
|
||||||
|
|
||||||
if (nc == sc) {
|
|
||||||
if (startMatch == -1) startMatch = ni;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (startMatch != -1) {
|
|
||||||
matches.push({
|
|
||||||
index: startMatch,
|
|
||||||
length: ni - startMatch,
|
|
||||||
});
|
|
||||||
|
|
||||||
startMatch = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startMatch != -1) {
|
|
||||||
matches.push({
|
|
||||||
index: startMatch,
|
|
||||||
length: ni - startMatch + 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
object: object,
|
|
||||||
matches: matches,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.filter(entry => entry !== null)
|
|
||||||
.sort((a, b) => {
|
|
||||||
let ai = 0;
|
|
||||||
let bi = 0;
|
|
||||||
let s = 0;
|
|
||||||
|
|
||||||
while (ai != a.matches.length && bi != b.matches.length) {
|
|
||||||
const am = a.matches[ai];
|
|
||||||
const bm = b.matches[bi];
|
|
||||||
|
|
||||||
s = bm.length - am.length;
|
|
||||||
if (s != 0) return s;
|
|
||||||
|
|
||||||
s = am.index - bm.index;
|
|
||||||
if (s != 0) return s;
|
|
||||||
|
|
||||||
++ai;
|
|
||||||
++bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = a.matches.length - b.matches.length;
|
|
||||||
if (s != 0) return s;
|
|
||||||
|
|
||||||
s = a.object.name.length - b.object.name.length;
|
|
||||||
if (s != 0) return s;
|
|
||||||
|
|
||||||
return a.object.name.localeCompare(b.object.name);
|
|
||||||
})
|
|
||||||
.map(entry => entry.object);
|
|
||||||
|
|
||||||
onValuesChanged: list.currentIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
topMargin: 7
|
|
||||||
bottomMargin: list.count == 0 ? 0 : 7
|
|
||||||
|
|
||||||
add: Transition {
|
|
||||||
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 100 }
|
|
||||||
}
|
|
||||||
|
|
||||||
displaced: Transition {
|
|
||||||
NumberAnimation { property: "y"; duration: 200; easing.type: Easing.OutCubic }
|
|
||||||
NumberAnimation { property: "opacity"; to: 1; duration: 100 }
|
|
||||||
}
|
|
||||||
|
|
||||||
move: Transition {
|
|
||||||
NumberAnimation { property: "y"; duration: 200; easing.type: Easing.OutCubic }
|
|
||||||
NumberAnimation { property: "opacity"; to: 1; duration: 100 }
|
|
||||||
}
|
|
||||||
|
|
||||||
remove: Transition {
|
|
||||||
NumberAnimation { property: "y"; duration: 200; easing.type: Easing.OutCubic }
|
|
||||||
NumberAnimation { property: "opacity"; to: 0; duration: 100 }
|
|
||||||
}
|
|
||||||
|
|
||||||
highlight: Rectangle {
|
|
||||||
radius: 5
|
|
||||||
color: "#20e0ffff"
|
|
||||||
border.color: "#30ffffff"
|
|
||||||
border.width: 1
|
|
||||||
}
|
|
||||||
keyNavigationEnabled: true
|
|
||||||
keyNavigationWraps: true
|
|
||||||
highlightMoveVelocity: -1
|
|
||||||
highlightMoveDuration: 100
|
|
||||||
preferredHighlightBegin: list.topMargin
|
|
||||||
preferredHighlightEnd: list.height - list.bottomMargin
|
|
||||||
highlightRangeMode: ListView.ApplyRange
|
|
||||||
snapMode: ListView.SnapToItem
|
|
||||||
|
|
||||||
readonly property real delegateHeight: 44
|
|
||||||
|
|
||||||
delegate: MouseArea {
|
|
||||||
required property DesktopEntry modelData;
|
|
||||||
|
|
||||||
implicitHeight: list.delegateHeight
|
|
||||||
implicitWidth: ListView.view.width
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
modelData.execute();
|
|
||||||
persist.launcherOpen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: delegateLayout
|
|
||||||
anchors {
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: 5
|
|
||||||
}
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
asynchronous: true
|
|
||||||
implicitSize: 30
|
|
||||||
source: Quickshell.iconPath(modelData.icon)
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: modelData.name
|
|
||||||
color: "#f0f0f0"
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
331
modules/user/modules/quickshell/shell/launcher/LaunchContent.qml
Normal file
331
modules/user/modules/quickshell/shell/launcher/LaunchContent.qml
Normal file
|
|
@ -0,0 +1,331 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import qs
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
height: 7 + searchContainer.implicitHeight + list.topMargin * 2 + list.delegateHeight * 10;
|
||||||
|
width: 450
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: content
|
||||||
|
height: 7 + searchContainer.implicitHeight + list.topMargin + list.bottomMargin + Math.min(list.contentHeight, list.delegateHeight * 10)
|
||||||
|
Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||||
|
width: 450
|
||||||
|
color: ShellGlobals.colors.bar
|
||||||
|
radius: 5
|
||||||
|
border.color: ShellGlobals.colors.barOutline
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 7
|
||||||
|
anchors.bottomMargin: 0
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: searchContainer
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: searchbox.implicitHeight + 10
|
||||||
|
color: "#30c0ffff"
|
||||||
|
radius: 3
|
||||||
|
border.color: "#50ffffff"
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: searchbox
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 5
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
implicitSize: parent.height
|
||||||
|
source: "root:icons/magnifying-glass.svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
TextInput {
|
||||||
|
id: search
|
||||||
|
Layout.fillWidth: true
|
||||||
|
color: "white"
|
||||||
|
|
||||||
|
focus: true
|
||||||
|
Keys.forwardTo: [list]
|
||||||
|
Keys.onEscapePressed: persist.launcherOpen = false
|
||||||
|
|
||||||
|
Keys.onPressed: event => {
|
||||||
|
if (event.modifiers & Qt.ControlModifier) {
|
||||||
|
if (event.key == Qt.Key_J) {
|
||||||
|
list.currentIndex = list.currentIndex == list.count - 1 ? 0 : list.currentIndex + 1;
|
||||||
|
event.accepted = true;
|
||||||
|
} else if (event.key == Qt.Key_K) {
|
||||||
|
list.currentIndex = list.currentIndex == 0 ? list.count - 1 : list.currentIndex - 1;
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
if (list.currentItem) {
|
||||||
|
list.currentItem.clicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTextChanged: {
|
||||||
|
list.currentIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: list
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
clip: true
|
||||||
|
cacheBuffer: 0 // works around QTBUG-131106
|
||||||
|
//reuseItems: true
|
||||||
|
model: ScriptModel {
|
||||||
|
values: DesktopEntries.applications.values
|
||||||
|
.map(object => {
|
||||||
|
const stxt = search.text.toLowerCase();
|
||||||
|
const ntxt = object.name.toLowerCase();
|
||||||
|
let si = 0;
|
||||||
|
let ni = 0;
|
||||||
|
|
||||||
|
let matches = [];
|
||||||
|
let startMatch = -1;
|
||||||
|
|
||||||
|
for (let si = 0; si != stxt.length; ++si) {
|
||||||
|
const sc = stxt[si];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// Drop any entries with letters that don't exist in order
|
||||||
|
if (ni == ntxt.length) return null;
|
||||||
|
|
||||||
|
const nc = ntxt[ni++];
|
||||||
|
|
||||||
|
if (nc == sc) {
|
||||||
|
if (startMatch == -1) startMatch = ni;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (startMatch != -1) {
|
||||||
|
matches.push({
|
||||||
|
index: startMatch,
|
||||||
|
length: ni - startMatch,
|
||||||
|
});
|
||||||
|
|
||||||
|
startMatch = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startMatch != -1) {
|
||||||
|
matches.push({
|
||||||
|
index: startMatch,
|
||||||
|
length: ni - startMatch + 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
object: object,
|
||||||
|
matches: matches,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(entry => entry !== null)
|
||||||
|
.sort((a, b) => {
|
||||||
|
let ai = 0;
|
||||||
|
let bi = 0;
|
||||||
|
let s = 0;
|
||||||
|
|
||||||
|
while (ai != a.matches.length && bi != b.matches.length) {
|
||||||
|
const am = a.matches[ai];
|
||||||
|
const bm = b.matches[bi];
|
||||||
|
|
||||||
|
s = bm.length - am.length;
|
||||||
|
if (s != 0) return s;
|
||||||
|
|
||||||
|
s = am.index - bm.index;
|
||||||
|
if (s != 0) return s;
|
||||||
|
|
||||||
|
++ai;
|
||||||
|
++bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = a.matches.length - b.matches.length;
|
||||||
|
if (s != 0) return s;
|
||||||
|
|
||||||
|
s = a.object.name.length - b.object.name.length;
|
||||||
|
if (s != 0) return s;
|
||||||
|
|
||||||
|
return a.object.name.localeCompare(b.object.name);
|
||||||
|
})
|
||||||
|
.map(entry => entry.object);
|
||||||
|
|
||||||
|
onValuesChanged: list.currentIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
topMargin: 7
|
||||||
|
bottomMargin: list.count == 0 ? 0 : 7
|
||||||
|
|
||||||
|
add: Transition {
|
||||||
|
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 100 }
|
||||||
|
}
|
||||||
|
|
||||||
|
displaced: Transition {
|
||||||
|
NumberAnimation { property: "y"; duration: 200; easing.type: Easing.OutCubic }
|
||||||
|
NumberAnimation { property: "opacity"; to: 1; duration: 100 }
|
||||||
|
}
|
||||||
|
|
||||||
|
move: Transition {
|
||||||
|
NumberAnimation { property: "y"; duration: 200; easing.type: Easing.OutCubic }
|
||||||
|
NumberAnimation { property: "opacity"; to: 1; duration: 100 }
|
||||||
|
}
|
||||||
|
|
||||||
|
remove: Transition {
|
||||||
|
NumberAnimation { property: "y"; duration: 200; easing.type: Easing.OutCubic }
|
||||||
|
NumberAnimation { property: "opacity"; to: 0; duration: 100 }
|
||||||
|
}
|
||||||
|
|
||||||
|
highlight: Rectangle {
|
||||||
|
radius: 5
|
||||||
|
color: "#20e0ffff"
|
||||||
|
border.color: "#30ffffff"
|
||||||
|
border.width: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
keyNavigationEnabled: true
|
||||||
|
keyNavigationWraps: true
|
||||||
|
highlightMoveVelocity: -1
|
||||||
|
highlightMoveDuration: 100
|
||||||
|
preferredHighlightBegin: list.topMargin
|
||||||
|
preferredHighlightEnd: list.height - list.bottomMargin
|
||||||
|
highlightRangeMode: ListView.ApplyRange
|
||||||
|
snapMode: ListView.SnapToItem
|
||||||
|
|
||||||
|
readonly property real delegateHeight: 44
|
||||||
|
|
||||||
|
delegate: MouseArea {
|
||||||
|
required property DesktopEntry modelData;
|
||||||
|
|
||||||
|
implicitHeight: list.delegateHeight
|
||||||
|
implicitWidth: ListView.view.width
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
modelData.execute();
|
||||||
|
persist.launcherOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: delegateLayout
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
asynchronous: true
|
||||||
|
implicitSize: 30
|
||||||
|
source: Quickshell.iconPath(modelData.icon)
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: modelData.name
|
||||||
|
color: "#f0f0f0"
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: preview
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
left: content.right
|
||||||
|
leftMargin: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
property real listYOffset: 7 + searchContainer.implicitHeight
|
||||||
|
property real yCenter: list.contentY
|
||||||
|
y: listYOffset - yCenter - height / 2 + (list.currentItem?.y ?? 0) + list.delegateHeight / 2
|
||||||
|
|
||||||
|
implicitWidth: previewContent.implicitWidth + previewContent.anchors.margins * 2
|
||||||
|
implicitHeight: previewContent.implicitHeight + previewContent.anchors.margins * 2
|
||||||
|
|
||||||
|
color: ShellGlobals.colors.bar
|
||||||
|
radius: 5
|
||||||
|
border.color: ShellGlobals.colors.barOutline
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
property DesktopEntry entry: list.currentItem?.modelData ?? null
|
||||||
|
property var toplevels: !entry ? []: ToplevelManager.toplevels.values
|
||||||
|
.filter(toplevel => toplevel.appId.toLowerCase() == entry.id.toLowerCase())
|
||||||
|
|
||||||
|
// waits for hasContent before showing
|
||||||
|
// cant use visible because layout wont run
|
||||||
|
property real scaleMul: previewLayout.implicitWidth != 0 ? 1 : 0;
|
||||||
|
Behavior on scaleMul { SmoothedAnimation { velocity: 5 } }
|
||||||
|
|
||||||
|
opacity: scaleMul
|
||||||
|
|
||||||
|
transform: Scale {
|
||||||
|
origin.x: 0
|
||||||
|
origin.y: preview.height / 2
|
||||||
|
xScale: 0.9 + preview.scaleMul * 0.1
|
||||||
|
yScale: xScale
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: previewContent
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 10
|
||||||
|
implicitWidth: previewLayout.implicitWidth
|
||||||
|
implicitHeight: previewLayout.implicitHeight
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: previewLayout
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: preview.toplevels
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: delegate
|
||||||
|
required property Toplevel modelData;
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
visible: view.hasContent
|
||||||
|
implicitWidth: previewContent.implicitWidth
|
||||||
|
implicitHeight: previewContent.implicitHeight
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: previewContent
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 240
|
||||||
|
|
||||||
|
ScreencopyView {
|
||||||
|
id: view
|
||||||
|
implicitWidth: 240
|
||||||
|
implicitHeight: 200
|
||||||
|
captureSource: modelData
|
||||||
|
live: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: modelData.title
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real yCenter: 0
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,8 @@ import Quickshell.Wayland
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
|
id: root
|
||||||
|
|
||||||
WlrLayershell.namespace: "shell:notifications"
|
WlrLayershell.namespace: "shell:notifications"
|
||||||
exclusionMode: ExclusionMode.Ignore
|
exclusionMode: ExclusionMode.Ignore
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
@ -16,6 +18,9 @@ PanelWindow {
|
||||||
right: true
|
right: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property var bar: null
|
||||||
|
//property var fullscreen: Hyprland.monitorFor(root.screen)?.activeWorkspace?.hasFullscreen ?? false
|
||||||
|
|
||||||
property Component notifComponent: DaemonNotification {}
|
property Component notifComponent: DaemonNotification {}
|
||||||
|
|
||||||
NotificationDisplay {
|
NotificationDisplay {
|
||||||
|
|
@ -23,8 +28,8 @@ PanelWindow {
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
stack.y: 5 + 55//(NotificationManager.showTrayNotifs ? 55 : 0)
|
stack.y: root.bar.compactState * 10 + 50//5 + 55//(NotificationManager.showTrayNotifs ? 55 : 0)
|
||||||
stack.x: 72
|
stack.x: root.bar.leftMargin + root.bar.width - 10
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: display.stack.children.length != 0
|
visible: display.stack.children.length != 0
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
//@ pragma ShellId shell
|
//@ pragma ShellId shell
|
||||||
|
//@ pragma IgnoreSystemSettings
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
|
@ -13,6 +14,8 @@ import "launcher" as Launcher
|
||||||
import "background"
|
import "background"
|
||||||
|
|
||||||
ShellRoot {
|
ShellRoot {
|
||||||
|
id: root
|
||||||
|
|
||||||
Component.onCompleted: [Lock.Controller, Launcher.Controller.init()]
|
Component.onCompleted: [Lock.Controller, Launcher.Controller.init()]
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
|
|
@ -38,8 +41,11 @@ ShellRoot {
|
||||||
|
|
||||||
Notifs.NotificationOverlay {
|
Notifs.NotificationOverlay {
|
||||||
screen: Quickshell.screens.find(s => s.name == "DP-1")
|
screen: Quickshell.screens.find(s => s.name == "DP-1")
|
||||||
|
bar: root.bars.find(b => b.screen == screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property var bars: []
|
||||||
|
|
||||||
Variants {
|
Variants {
|
||||||
model: Quickshell.screens
|
model: Quickshell.screens
|
||||||
|
|
||||||
|
|
@ -48,6 +54,8 @@ ShellRoot {
|
||||||
|
|
||||||
Bar.Bar {
|
Bar.Bar {
|
||||||
screen: modelData
|
screen: modelData
|
||||||
|
Component.onCompleted: root.bars = [...root.bars, this]
|
||||||
|
Component.onDestruction: root.bars = root.bars.filter(b => b == this)
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue