popout positioning fixes

This commit is contained in:
Zacharias-Brohn
2025-11-27 19:15:35 +01:00
parent fb864da6fb
commit 67ad544359
17 changed files with 201 additions and 93 deletions
+2 -2
View File
@@ -9,14 +9,14 @@ Shape {
required property Item bar
anchors.fill: parent
anchors.margins: 8
// anchors.margins: 8
anchors.topMargin: bar.implicitHeight
preferredRendererType: Shape.CurveRenderer
Modules.Background {
wrapper: root.panels.popouts
startX: wrapper.x - rounding
startX: wrapper.x - 8
startY: wrapper.y
}
}
+2 -3
View File
@@ -13,7 +13,7 @@ Item {
readonly property alias popouts: popouts
anchors.fill: parent
anchors.margins: 8
// anchors.margins: 8
anchors.topMargin: bar.implicitHeight
Modules.Wrapper {
@@ -21,9 +21,8 @@ Item {
screen: root.screen
anchors.top: parent.top
x: {
const off = currentCenter - 8 - nonAnimWidth / 2;
const off = currentCenter - nonAnimWidth / 2;
const diff = root.width - Math.floor(off + nonAnimWidth);
if ( diff < 0 )
return off + diff;
+41 -1
View File
@@ -14,11 +14,15 @@ Singleton {
readonly property var workspaces: Hyprland.workspaces
readonly property var monitors: Hyprland.monitors
readonly property HyprlandToplevel activeToplevel: Hyprland.activeToplevel?.wayland?.activated ? Hyprland.activeToplevel : null
readonly property HyprlandToplevel activeToplevel: Hyprland.activeToplevel
readonly property HyprlandWorkspace focusedWorkspace: Hyprland.focusedWorkspace
readonly property HyprlandMonitor focusedMonitor: Hyprland.focusedMonitor
readonly property int activeWsId: focusedWorkspace?.id ?? 1
property string activeName
property string applicationDir: "/usr/share/applications/"
property string desktopName: ""
readonly property HyprKeyboard keyboard: extras.devices.keyboards.find(kb => kb.main) ?? null
readonly property bool capsLock: keyboard?.capsLock ?? false
readonly property bool numLock: keyboard?.numLock ?? false
@@ -49,6 +53,19 @@ Singleton {
Component.onCompleted: reloadDynamicConfs()
function updateActiveWindow(): void {
root.desktopName = root.applicationDir + root.activeToplevel?.lastIpcObject.class + ".desktop";
}
Connections {
target: Hyprland
function onRawEvent( event: HyprlandEvent ): void {
if ( event.name === "activewindow" ) {
}
}
}
Connections {
target: Hyprland
@@ -63,15 +80,38 @@ Singleton {
} else if (["workspace", "moveworkspace", "activespecial", "focusedmon"].includes(n)) {
Hyprland.refreshWorkspaces();
Hyprland.refreshMonitors();
Qt.callLater( root.updateActiveWindow );
} else if (["openwindow", "closewindow", "movewindow"].includes(n)) {
Hyprland.refreshToplevels();
Hyprland.refreshWorkspaces();
Qt.callLater( root.updateActiveWindow );
} else if (n.includes("mon")) {
Hyprland.refreshMonitors();
Qt.callLater( root.updateActiveWindow );
} else if (n.includes("workspace")) {
Hyprland.refreshWorkspaces();
Qt.callLater( root.updateActiveWindow );
} else if (n.includes("window") || n.includes("group") || ["pin", "fullscreen", "changefloatingmode", "minimize"].includes(n)) {
Hyprland.refreshToplevels();
Qt.callLater( root.updateActiveWindow );
}
}
}
FileView {
id: desktopEntryName
path: root.desktopName
onLoaded: {
const lines = text().split( "\n" );
for ( const line of lines ) {
if ( line.startsWith( "Name=" )) {
let name = line.replace( "Name=", "" );
let caseFix = name[ 0 ].toUpperCase() + name.slice( 1 );
root.activeName = caseFix;
break;
}
}
}
}
+10 -14
View File
@@ -1,22 +1,18 @@
pragma Singleton
import Quickshell.Io
import Quickshell
import Quickshell.Hyprland
import qs.Helpers
Singleton {
function getInitialTitle(callback) {
initialTitleProc.running = true
initialTitleProc.stdout.streamFinished.connect( function() {
let cleaned = initialTitleProc.stdout.text.trim().replace(/\"/g, "")
callback(cleaned === "null" ? "" : cleaned)
})
}
let activeWindow = Hypr.activeToplevel.title
let activeClass = Hypr.activeToplevel.lastIpcObject.class.toString()
let regex = new RegExp(activeClass, "i")
Process {
id: initialTitleProc
command: ["./scripts/initialTitle.sh"]
running: false
stdout: StdioCollector {
}
console.log("ActiveWindow", activeWindow, "ActiveClass", activeClass, "Regex", regex)
const evalTitle = activeWindow.match(regex)
callback(evalTitle)
}
}
+2 -1
View File
@@ -9,7 +9,8 @@ import qs.Components
Item {
id: root
implicitWidth: expanded ? 300 : 150
implicitHeight: 34
anchors.top: parent.top
anchors.bottom: parent.bottom
property bool expanded: false
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff"
+10 -20
View File
@@ -11,8 +11,6 @@ import qs.Daemons
RowLayout {
id: root
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
readonly property int vPadding: 6
required property Wrapper popouts
@@ -38,22 +36,18 @@ RowLayout {
popouts.hasCurrent = true;
} else if ( id === "resources" && Config.barConfig.popouts.resources ) {
popouts.currentName = "resources";
popouts.currentCenter = Qt.binding(() => item.mapToItem(root, itemWidth / 2 + 5, 0).x);
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
popouts.hasCurrent = true;
} else if ( id === "tray" && Config.barConfig.popouts.tray ) {
const index = Math.floor(((x - top - 6) / item.implicitWidth) * item.items.count);
const index = Math.floor((( x - top ) / item.implicitWidth ) * item.items.count );
const trayItem = item.items.itemAt( index );
if ( trayItem ) {
popouts.currentName = `traymenu${ index }`;
popouts.currentCenter = Qt.binding(() => trayItem.mapToItem(root, trayItem.implicitWidth / 2 + 4, 0).x);
popouts.currentCenter = Qt.binding( () => trayItem.mapToItem( root, trayItem.implicitWidth / 2, 0 ).x );
popouts.hasCurrent = true;
} else {
popouts.hasCurrent = false;
}
} else if (id === "activeWindow" && Config.barConfig.popouts.activeWindow) {
popouts.currentName = id.toLowerCase();
popouts.currentCenter = item.mapToItem(root, 0, itemHeight / 2).y;
popouts.hasCurrent = true;
}
}
@@ -107,17 +101,13 @@ RowLayout {
DelegateChoice {
roleValue: "notifBell"
delegate: WrappedLoader {
sourceComponent: NotifBell {
Layout.alignment: Qt.AlignHCenter
}
sourceComponent: NotifBell {}
}
}
DelegateChoice {
roleValue: "clock"
delegate: WrappedLoader {
sourceComponent: Clock {
Layout.alignment: Qt.AlignHCenter
}
sourceComponent: Clock {}
}
}
DelegateChoice {
@@ -134,6 +124,9 @@ RowLayout {
required property string id
required property int index
Layout.alignment: Qt.AlignVCenter
Layout.fillHeight: true
function findFirstEnabled(): Item {
const count = repeater.count;
for (let i = 0; i < count; i++) {
@@ -153,11 +146,8 @@ RowLayout {
return null;
}
Layout.alignment: Qt.AlignHCenter
// Cursed ahh thing to add padding to first and last enabled components
Layout.topMargin: findFirstEnabled() === this ? root.vPadding : 0
Layout.bottomMargin: findLastEnabled() === this ? root.vPadding : 0
Layout.leftMargin: findFirstEnabled() === this ? root.vPadding : 0
Layout.rightMargin: findLastEnabled() === this ? root.vPadding : 0
visible: enabled
active: enabled
+8 -1
View File
@@ -4,9 +4,16 @@ import qs.Modules
Item {
implicitWidth: timeText.contentWidth
implicitHeight: timeText.contentHeight
anchors.top: parent.top
anchors.bottom: parent.bottom
Text {
id: timeText
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: Time.time
color: Config.useDynamicColors ? DynamicColors.palette.m3tertiary : "white"
+3 -7
View File
@@ -12,16 +12,13 @@ Item {
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
readonly property Item current: currentPopout?.item ?? null
anchors.centerIn: parent
implicitWidth: (currentPopout?.implicitWidth ?? 0) + 10 * 2
implicitHeight: (currentPopout?.implicitHeight ?? 0) + 10 * 2
implicitWidth: (currentPopout?.implicitWidth ?? 0) + 5 * 2
implicitHeight: (currentPopout?.implicitHeight ?? 0) + 5 * 2
Item {
id: content
anchors.fill: parent
anchors.margins: 10
Popout {
name: "audio"
@@ -80,8 +77,7 @@ Item {
required property string name
readonly property bool shouldBeActive: root.wrapper.currentName === name
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.centerIn: parent
opacity: 0
scale: 0.8
+11 -1
View File
@@ -4,11 +4,21 @@ import qs.Helpers
import qs.Components
Item {
id: root
implicitWidth: 20
implicitHeight: 18
anchors.top: parent.top
anchors.bottom: parent.bottom
MaterialIcon {
id: notificationCenterIcon
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
property color iconColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "white"
text: HasNotifications.hasNotifications ? "\uf4fe" : "\ue7f4"
font.family: "Material Symbols Rounded"
font.pixelSize: 20
+2
View File
@@ -14,8 +14,10 @@ Item {
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
implicitHeight: 34
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff"
clip: true
Rectangle {
id: backgroundRect
anchors {
left: parent.left
right: parent.right
+6
View File
@@ -7,9 +7,15 @@ import Quickshell.Services.SystemTray
Row {
id: root
anchors.top: parent.top
anchors.bottom: parent.bottom
required property PanelWindow bar
readonly property alias items: repeater
spacing: 0
Repeater {
id: repeater
model: SystemTray.items
+7 -3
View File
@@ -6,12 +6,16 @@ import qs.Config
Item {
id: root
property int countUpdates: Updates.availableUpdates
implicitWidth: contentRow.childrenRect.width + 10
implicitHeight: 22
implicitWidth: textMetrics.width + contentRow.spacing + 30
anchors.top: parent.top
anchors.bottom: parent.bottom
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3tertiaryFixed : "#ffffff"
Rectangle {
anchors.fill: parent
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
implicitHeight: 22
radius: height / 2
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : "#40000000"
Behavior on color {
+13 -21
View File
@@ -3,10 +3,11 @@ import QtQuick.Layouts
import Quickshell.Hyprland
import qs.Helpers
import qs.Config
import qs.Components
Item {
id: root
property string currentTitle
property string currentTitle: Hypr.activeName
Layout.fillHeight: true
Layout.preferredWidth: Math.max( titleText1.implicitWidth, titleText2.implicitWidth ) + 10
clip: true
@@ -14,15 +15,15 @@ Item {
property bool showFirst: true
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3primary : "white"
Component.onCompleted: {
Hyprland.rawEvent.connect(( event ) => {
if (event.name === "activewindow") {
InitialTitle.getInitialTitle( function( initialTitle ) {
root.currentTitle = initialTitle
})
}
})
}
// Component.onCompleted: {
// Hyprland.rawEvent.connect(( event ) => {
// if (event.name === "activewindow") {
// InitialTitle.getInitialTitle( function( initialTitle ) {
// root.currentTitle = initialTitle
// })
// }
// })
// }
onCurrentTitleChanged: {
if (showFirst) {
@@ -34,14 +35,13 @@ Item {
}
}
Text {
CustomText {
id: titleText1
anchors.fill: parent
anchors.margins: 5
text: root.currentTitle
color: root.textColor
elide: Text.ElideRight
font.family: "Rubik"
font.pixelSize: 16
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
@@ -49,13 +49,9 @@ Item {
Behavior on opacity {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
Behavior on color {
CAnim {}
}
}
Text {
CustomText {
id: titleText2
anchors.fill: parent
anchors.margins: 5
@@ -68,9 +64,5 @@ Item {
Behavior on opacity {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
Behavior on color {
CAnim {}
}
}
}
+6 -3
View File
@@ -12,14 +12,17 @@ import qs.Components
Item {
id: itemRoot
required property PanelWindow bar
implicitHeight: 28
implicitWidth: root.implicitWidth
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: workspacesRow.implicitWidth + 10
Rectangle {
id: root
property HyprlandMonitor monitor: Hyprland.monitorFor( itemRoot.bar?.screen )
implicitWidth: workspacesRow.implicitWidth + 10
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
implicitHeight: 22
function shouldShow(monitor) {
-2
View File
@@ -71,8 +71,6 @@ Item {
shouldBeActive: root.hasCurrent
asynchronous: true
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
sourceComponent: Content {
wrapper: root
+70 -6
View File
@@ -1,14 +1,78 @@
import Quickshell
import QtQuick
import Quickshell.Hyprland
FloatingWindow {
id: root
title: "terminal"
minimumSize: Qt.size(400, 300)
Component.onCompleted: {
Hyprland.refreshToplevels()
console.log(Hyprland.toplevels.values)
Rectangle {
id: root
width: 480
height: 320
property int callsToUpdateMinimumWidth: 0
property bool optimize: true
property int currentTextModel: 0
property var columnTexts: [
["Click on either", "rectangle above", "and note how the counter", "below updates", "significantly faster using the", "regular (non-optimized)", "implementation"],
["The width", "of this column", "is", "no wider than the", "widest item"],
["Note how using Qt.callLater()", "the minimum width is", "calculated a bare-minimum", "number", "of times"]
]
Text {
x: 20; y: 280
text: "Times minimum width has been calculated: " + root.callsToUpdateMinimumWidth
}
Row {
y: 25; spacing: 30; anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
width: 200; height: 50; color: "lightgreen"
Text { text: "Optimized behavior\nusing Qt.callLater()"; anchors.centerIn: parent }
MouseArea { anchors.fill: parent; onClicked: { root.optimize = true; root.currentTextModel++ } }
}
Rectangle {
width: 200; height: 50; color: "lightblue"
Text { text: "Regular behavior"; anchors.centerIn: parent}
MouseArea { anchors.fill: parent; onClicked: { root.optimize = false; root.currentTextModel++ } }
}
}
Column {
id: column
anchors.centerIn: parent
onChildrenChanged: root.optimize ? Qt.callLater(updateMinimumWidth) : updateMinimumWidth()
property int widestChild
function updateMinimumWidth() {
root.callsToUpdateMinimumWidth++
var w = 0;
for (var i in children) {
var child = children[i];
if (child.implicitWidth > w) {
w = child.implicitWidth;
}
}
widestChild = w;
}
Repeater {
id: repeater
model: root.columnTexts[root.currentTextModel%3]
delegate: Text {
id: text
required property string modelData
required property int index
color: "white"
text: modelData
width: column.widestChild
horizontalAlignment: Text.Center
Rectangle { anchors.fill: parent; z: -1; color: text.index%2 ? "gray" : "darkgray" }
}
}
}
}
}