mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'main' of https://github.com/noctalia-dev/noctalia-shell
This commit is contained in:
@@ -49,9 +49,7 @@ Item {
|
||||
Connections {
|
||||
target: root
|
||||
function onTooltipTextChanged() {
|
||||
if (PanelService.tooltip.visible) {
|
||||
PanelService.tooltip.updateText(root.tooltipText)
|
||||
}
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +219,7 @@ Item {
|
||||
onEntered: {
|
||||
hovered = true
|
||||
root.entered()
|
||||
PanelService.tooltip.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||
TooltipService.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||
if (disableOpen || forceClose) {
|
||||
return
|
||||
}
|
||||
@@ -235,7 +233,7 @@ Item {
|
||||
if (!forceOpen && !forceClose) {
|
||||
hide()
|
||||
}
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
|
||||
@@ -61,9 +61,7 @@ Item {
|
||||
Connections {
|
||||
target: root
|
||||
function onTooltipTextChanged() {
|
||||
if (PanelService.tooltip.visible) {
|
||||
PanelService.tooltip.updateText(root.tooltipText)
|
||||
}
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +260,7 @@ Item {
|
||||
onEntered: {
|
||||
hovered = true
|
||||
root.entered()
|
||||
PanelService.tooltip.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||
TooltipService.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||
if (disableOpen || forceClose) {
|
||||
return
|
||||
}
|
||||
@@ -276,7 +274,7 @@ Item {
|
||||
if (!forceOpen && !forceClose) {
|
||||
hide()
|
||||
}
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
|
||||
@@ -329,11 +329,11 @@ Item {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onEntered: {
|
||||
if ((windowTitle !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
||||
PanelService.tooltip.show(root, windowTitle, BarService.getTooltipDirection())
|
||||
TooltipService.show(root, windowTitle, BarService.getTooltipDirection())
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,14 +114,14 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
if (!PanelService.getPanel("calendarPanel")?.active) {
|
||||
PanelService.tooltip.show(root, I18n.tr("clock.tooltip"), BarService.getTooltipDirection())
|
||||
TooltipService.show(root, I18n.tr("clock.tooltip"), BarService.getTooltipDirection())
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
onClicked: {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
PanelService.getPanel("calendarPanel")?.toggle(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,11 +376,11 @@ Item {
|
||||
|
||||
onEntered: {
|
||||
if ((tooltipText !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
||||
PanelService.tooltip.show(root, tooltipText, BarService.getTooltipDirection())
|
||||
TooltipService.show(root, tooltipText, BarService.getTooltipDirection())
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
onEntered: PanelService.tooltip.show(taskbarItem, taskbarItem.modelData.title || taskbarItem.modelData.appId || "Unknown app.", BarService.getTooltipDirection())
|
||||
onExited: PanelService.tooltip.hide()
|
||||
onEntered: TooltipService.show(taskbarItem, taskbarItem.modelData.title || taskbarItem.modelData.appId || "Unknown app.", BarService.getTooltipDirection())
|
||||
onExited: TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ Rectangle {
|
||||
|
||||
modelData.secondaryActivate && modelData.secondaryActivate()
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
trayTooltip.hide()
|
||||
TooltipService.hideImmediately()
|
||||
|
||||
// Close the menu if it was visible
|
||||
if (trayPanel && trayPanel.visible) {
|
||||
@@ -135,8 +135,11 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
onEntered: PanelService.tooltip.show(trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
|
||||
onExited: PanelService.tooltip.hide()
|
||||
onEntered: {
|
||||
trayPanel.close()
|
||||
TooltipService.show(trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
|
||||
}
|
||||
onExited: TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,7 +474,7 @@ Variants {
|
||||
anyAppHovered = true
|
||||
const appName = appButton.appTitle || appButton.appId || "Unknown"
|
||||
const tooltipText = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
|
||||
PanelService.tooltip.show(appButton, tooltipText, "top")
|
||||
TooltipService.show(appButton, tooltipText, "top")
|
||||
if (autoHide) {
|
||||
showTimer.stop()
|
||||
hideTimer.stop()
|
||||
@@ -484,7 +484,7 @@ Variants {
|
||||
|
||||
onExited: {
|
||||
anyAppHovered = false
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
if (autoHide && !dockHovered && !peekHovered && !menuHovered) {
|
||||
hideTimer.restart()
|
||||
}
|
||||
@@ -500,7 +500,7 @@ Variants {
|
||||
// Close any other existing context menu first
|
||||
root.closeAllContextMenus()
|
||||
// Hide tooltip when showing context menu
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
contextMenu.show(appButton, modelData.toplevel || modelData)
|
||||
return
|
||||
}
|
||||
|
||||
+90
-81
@@ -14,9 +14,12 @@ PopupWindow {
|
||||
property var toplevel: null
|
||||
property Item anchorItem: null
|
||||
property real scaling: 1.0
|
||||
property bool hovered: menuMouseArea.containsMouse || activateMouseArea.containsMouse || pinMouseArea.containsMouse || closeMouseArea.containsMouse
|
||||
property bool hovered: menuMouseArea.containsMouse
|
||||
property var onAppClosed: null // Callback function for when an app is closed
|
||||
|
||||
// Track which menu item is hovered
|
||||
property int hoveredItem: -1 // -1: none, 0: focus, 1: pin, 2: close
|
||||
|
||||
signal requestClose
|
||||
|
||||
implicitWidth: 140 * scaling
|
||||
@@ -70,25 +73,64 @@ PopupWindow {
|
||||
visible = false
|
||||
}
|
||||
|
||||
// Close menu when clicking on background, track hover for the whole menu area
|
||||
MouseArea {
|
||||
id: menuMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
root.hide() // Close on right-click
|
||||
} else {
|
||||
root.hide() // Close when clicking on the background (outside menu content)
|
||||
// Helper function to determine which menu item is under the mouse
|
||||
function getHoveredItem(mouseY) {
|
||||
const itemHeight = 32 * scaling
|
||||
const startY = Style.marginM * scaling
|
||||
const relativeY = mouseY - startY
|
||||
|
||||
if (relativeY < 0)
|
||||
return -1
|
||||
|
||||
const itemIndex = Math.floor(relativeY / itemHeight)
|
||||
return itemIndex >= 0 && itemIndex < 3 ? itemIndex : -1
|
||||
}
|
||||
|
||||
// Handle menu item clicks
|
||||
function handleItemClick(itemIndex) {
|
||||
switch (itemIndex) {
|
||||
case 0:
|
||||
// Focus
|
||||
if (root.toplevel?.activate) {
|
||||
root.toplevel.activate()
|
||||
}
|
||||
root.requestClose()
|
||||
break
|
||||
case 1:
|
||||
// Pin/Unpin
|
||||
if (root.toplevel?.appId) {
|
||||
root.toggleAppPin(root.toplevel.appId)
|
||||
}
|
||||
root.requestClose()
|
||||
break
|
||||
case 2:
|
||||
// Close
|
||||
// Check if toplevel is still valid before trying to close it
|
||||
const isValidToplevel = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel)
|
||||
|
||||
if (isValidToplevel && root.toplevel.close) {
|
||||
root.toplevel.close()
|
||||
// Trigger immediate dock update callback if provided
|
||||
if (root.onAppClosed && typeof root.onAppClosed === "function") {
|
||||
Qt.callLater(root.onAppClosed)
|
||||
}
|
||||
} else {
|
||||
Logger.warn("DockMenu", "Cannot close app - invalid toplevel reference")
|
||||
}
|
||||
root.hide()
|
||||
root.requestClose()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: ["Escape"]
|
||||
enabled: root.visible
|
||||
onActivated: root.hide()
|
||||
Timer {
|
||||
id: closeTimer
|
||||
interval: 500
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
root.hide()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -98,12 +140,32 @@ PopupWindow {
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
|
||||
// Prevent clicks inside the menu from closing it
|
||||
// Single MouseArea to handle both auto-close and menu interactions
|
||||
MouseArea {
|
||||
id: menuMouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
hoverEnabled: true
|
||||
cursorShape: root.hoveredItem >= 0 ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
|
||||
} // Do nothing, just consume the click
|
||||
onEntered: {
|
||||
closeTimer.stop()
|
||||
}
|
||||
|
||||
onExited: {
|
||||
root.hoveredItem = -1
|
||||
closeTimer.start()
|
||||
}
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
root.hoveredItem = root.getHoveredItem(mouse.y)
|
||||
}
|
||||
|
||||
onClicked: mouse => {
|
||||
const clickedItem = root.getHoveredItem(mouse.y)
|
||||
if (clickedItem >= 0) {
|
||||
root.handleItemClick(clickedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
@@ -116,7 +178,7 @@ PopupWindow {
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 32 * scaling
|
||||
color: activateMouseArea.containsMouse ? Color.mTertiary : Color.transparent
|
||||
color: root.hoveredItem === 0 ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusXS * scaling
|
||||
|
||||
Row {
|
||||
@@ -128,38 +190,24 @@ PopupWindow {
|
||||
NIcon {
|
||||
icon: "eye"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
color: activateMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("dock.menu.focus")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: activateMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: activateMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
if (root.toplevel?.activate) {
|
||||
root.toplevel.activate()
|
||||
}
|
||||
root.requestClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pin/Unpin item
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 32 * scaling
|
||||
color: pinMouseArea.containsMouse ? Color.mTertiary : Color.transparent
|
||||
color: root.hoveredItem === 1 ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusXS * scaling
|
||||
|
||||
Row {
|
||||
@@ -175,7 +223,7 @@ PopupWindow {
|
||||
return root.isAppPinned(root.toplevel.appId) ? "unpin" : "pin"
|
||||
}
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
color: pinMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
@@ -186,32 +234,17 @@ PopupWindow {
|
||||
return root.isAppPinned(root.toplevel.appId) ? I18n.tr("dock.menu.unpin") : I18n.tr("dock.menu.pin")
|
||||
}
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: pinMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: pinMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
if (root.toplevel?.appId) {
|
||||
root.toggleAppPin(root.toplevel.appId)
|
||||
}
|
||||
//root.hide()
|
||||
root.requestClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close item
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 32 * scaling
|
||||
color: closeMouseArea.containsMouse ? Color.mTertiary : Color.transparent
|
||||
color: root.hoveredItem === 2 ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusXS * scaling
|
||||
|
||||
Row {
|
||||
@@ -223,41 +256,17 @@ PopupWindow {
|
||||
NIcon {
|
||||
icon: "close"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
color: closeMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("dock.menu.close")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: closeMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
// Check if toplevel is still valid before trying to close it
|
||||
const isValidToplevel = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel)
|
||||
|
||||
if (isValidToplevel && root.toplevel.close) {
|
||||
root.toplevel.close()
|
||||
// Trigger immediate dock update callback if provided
|
||||
if (root.onAppClosed && typeof root.onAppClosed === "function") {
|
||||
Qt.callLater(root.onAppClosed)
|
||||
}
|
||||
} else {
|
||||
Logger.warn("DockMenu", "Cannot close app - invalid toplevel reference")
|
||||
}
|
||||
root.hide()
|
||||
root.requestClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -894,7 +894,7 @@ Loader {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Style.marginM * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
radius: Style.radiusS * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
@@ -905,7 +905,8 @@ Loader {
|
||||
anchors.margins: Style.marginM * scaling
|
||||
anchors.fill: parent
|
||||
text: I18n.tr("lock-screen.shut-down")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
@@ -945,7 +946,7 @@ Loader {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Style.marginM * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
radius: Style.radiusS * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
@@ -956,7 +957,8 @@ Loader {
|
||||
anchors.margins: Style.marginM * scaling
|
||||
anchors.fill: parent
|
||||
text: I18n.tr("lock-screen.restart")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
@@ -997,7 +999,7 @@ Loader {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Style.marginM * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
radius: Style.radiusS * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
@@ -1008,7 +1010,8 @@ Loader {
|
||||
anchors.margins: Style.marginM * scaling
|
||||
anchors.fill: parent
|
||||
text: I18n.tr("lock-screen.suspend")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ ColumnLayout {
|
||||
// AudioService Devices
|
||||
ColumnLayout {
|
||||
spacing: Style.marginS * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NHeader {
|
||||
label: I18n.tr("settings.audio.devices.section.label")
|
||||
@@ -175,14 +176,15 @@ ColumnLayout {
|
||||
Repeater {
|
||||
model: AudioService.sinks
|
||||
NRadioButton {
|
||||
required property PwNode modelData
|
||||
ButtonGroup.group: sinks
|
||||
required property PwNode modelData
|
||||
text: modelData.description
|
||||
checked: AudioService.sink?.id === modelData.id
|
||||
onClicked: {
|
||||
AudioService.setAudioSink(modelData)
|
||||
localVolume = AudioService.volume
|
||||
}
|
||||
text: modelData.description
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,12 +206,14 @@ ColumnLayout {
|
||||
|
||||
Repeater {
|
||||
model: AudioService.sources
|
||||
//Layout.fillWidth: true
|
||||
NRadioButton {
|
||||
required property PwNode modelData
|
||||
ButtonGroup.group: sources
|
||||
required property PwNode modelData
|
||||
text: modelData.description
|
||||
checked: AudioService.source?.id === modelData.id
|
||||
onClicked: AudioService.setAudioSource(modelData)
|
||||
text: modelData.description
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ PopupWindow {
|
||||
property int padding: Style.marginM
|
||||
property int delay: 0
|
||||
property int hideDelay: 0
|
||||
property int maxWidth: 340
|
||||
property int maxWidth: 320
|
||||
property real scaling: 1.0
|
||||
property int animationDuration: Style.animationFast
|
||||
property real animationScale: 0.85
|
||||
@@ -25,7 +25,7 @@ PopupWindow {
|
||||
property real anchorY: 0
|
||||
property bool isPositioned: false
|
||||
property bool pendingShow: false
|
||||
property bool animatingOut: false
|
||||
property bool animatingOut: true
|
||||
|
||||
visible: false
|
||||
color: Color.transparent
|
||||
@@ -110,11 +110,7 @@ PopupWindow {
|
||||
if (!target || !tipText || tipText === "")
|
||||
return
|
||||
|
||||
if (showDelay !== undefined) {
|
||||
delay = showDelay
|
||||
} else {
|
||||
delay = Style.tooltipDelay
|
||||
}
|
||||
delay = showDelay
|
||||
|
||||
// Stop any running timers and animations
|
||||
hideTimer.stop()
|
||||
@@ -144,8 +140,9 @@ PopupWindow {
|
||||
|
||||
// Function to position and display the tooltip
|
||||
function positionAndShow() {
|
||||
if (!targetItem || !pendingShow)
|
||||
if (!targetItem || !targetItem.parent || !pendingShow) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get screen dimensions - try multiple methods
|
||||
var screenWidth = Screen.width
|
||||
@@ -393,6 +390,8 @@ PopupWindow {
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.WordWrap
|
||||
width: root.maxWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@ Singleton {
|
||||
// This is not a panel...
|
||||
property var lockScreen: null
|
||||
|
||||
// A ref. to our global tooltip
|
||||
property var tooltip: null
|
||||
|
||||
// Panels
|
||||
property var registeredPanels: ({})
|
||||
property var openedPanel: null
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Modules.Tooltip
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property var activeTooltip: null
|
||||
property var pendingTooltip: null // Track tooltip being created
|
||||
|
||||
property Component tooltipComponent: Component {
|
||||
Tooltip {}
|
||||
}
|
||||
|
||||
function show(target, text, direction, delay) {
|
||||
// Don't create if no text
|
||||
if (!target || !text) {
|
||||
Logger.log("Tooltip", "No target or text")
|
||||
return
|
||||
}
|
||||
|
||||
// If we have a pending tooltip for a different target, cancel it
|
||||
if (pendingTooltip && pendingTooltip.targetItem !== target) {
|
||||
pendingTooltip.hideImmediately()
|
||||
pendingTooltip.destroy()
|
||||
pendingTooltip = null
|
||||
}
|
||||
|
||||
// If we have an active tooltip for a different target, hide it
|
||||
if (activeTooltip && activeTooltip.targetItem !== target) {
|
||||
activeTooltip.hideImmediately()
|
||||
// Don't destroy immediately - let it clean itself up
|
||||
activeTooltip = null
|
||||
}
|
||||
|
||||
// If we already have a tooltip for this target, just update it
|
||||
if (activeTooltip && activeTooltip.targetItem === target) {
|
||||
activeTooltip.updateText(text)
|
||||
return activeTooltip
|
||||
}
|
||||
|
||||
// Create new tooltip instance
|
||||
const newTooltip = tooltipComponent.createObject(null)
|
||||
|
||||
if (newTooltip) {
|
||||
// Track as pending until it's visible
|
||||
pendingTooltip = newTooltip
|
||||
|
||||
// Connect cleanup when tooltip hides
|
||||
newTooltip.visibleChanged.connect(() => {
|
||||
if (!newTooltip.visible) {
|
||||
// Clean up after a delay to avoid interfering with new tooltips
|
||||
Qt.callLater(() => {
|
||||
if (newTooltip && !newTooltip.visible) {
|
||||
if (activeTooltip === newTooltip) {
|
||||
activeTooltip = null
|
||||
}
|
||||
if (pendingTooltip === newTooltip) {
|
||||
pendingTooltip = null
|
||||
}
|
||||
newTooltip.destroy()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// Tooltip is now visible, move from pending to active
|
||||
if (pendingTooltip === newTooltip) {
|
||||
activeTooltip = newTooltip
|
||||
pendingTooltip = null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Show the tooltip
|
||||
newTooltip.show(target, text, direction || "auto", delay || Style.tooltipDelay)
|
||||
|
||||
return newTooltip
|
||||
} else {
|
||||
Logger.error("Tooltip", "Failed to create tooltip instance")
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function hide() {
|
||||
if (pendingTooltip) {
|
||||
pendingTooltip.hide()
|
||||
}
|
||||
if (activeTooltip) {
|
||||
activeTooltip.hide()
|
||||
}
|
||||
}
|
||||
|
||||
function hideImmediately() {
|
||||
if (pendingTooltip) {
|
||||
pendingTooltip.hideImmediately()
|
||||
pendingTooltip.destroy()
|
||||
pendingTooltip = null
|
||||
}
|
||||
if (activeTooltip) {
|
||||
activeTooltip.hideImmediately()
|
||||
activeTooltip.destroy()
|
||||
activeTooltip = null
|
||||
}
|
||||
}
|
||||
|
||||
function updateText(newText) {
|
||||
if (activeTooltip) {
|
||||
activeTooltip.updateText(newText)
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -139,18 +139,18 @@ Rectangle {
|
||||
onEntered: {
|
||||
root.hovered = true
|
||||
if (tooltipText) {
|
||||
PanelService.tooltip.show(root, root.tooltipText)
|
||||
TooltipService.show(root, root.tooltipText)
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
root.hovered = false
|
||||
if (tooltipText) {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
onPressed: mouse => {
|
||||
if (tooltipText) {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
root.clicked()
|
||||
@@ -164,7 +164,7 @@ Rectangle {
|
||||
onCanceled: {
|
||||
root.hovered = false
|
||||
if (tooltipText) {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,20 +73,20 @@ Rectangle {
|
||||
onEntered: {
|
||||
hovering = root.enabled ? true : false
|
||||
if (tooltipText) {
|
||||
PanelService.tooltip.show(parent, tooltipText, tooltipDirection)
|
||||
TooltipService.show(parent, tooltipText, tooltipDirection)
|
||||
}
|
||||
root.entered()
|
||||
}
|
||||
onExited: {
|
||||
hovering = false
|
||||
if (tooltipText) {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
root.exited()
|
||||
}
|
||||
onClicked: function (mouse) {
|
||||
if (tooltipText) {
|
||||
PanelService.tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
if (!root.enabled && !allowClickWhenDisabled) {
|
||||
return
|
||||
|
||||
@@ -44,6 +44,7 @@ RadioButton {
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: outerCircle.right
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.marginS * scaling
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,10 +51,6 @@ ShellRoot {
|
||||
Bar {}
|
||||
Dock {}
|
||||
|
||||
Tooltip {
|
||||
id: globalTooltip
|
||||
}
|
||||
|
||||
Notification {
|
||||
id: notification
|
||||
}
|
||||
@@ -120,7 +116,6 @@ ShellRoot {
|
||||
Component.onCompleted: {
|
||||
// Save a ref. to our lockScreen so we can access it easily
|
||||
PanelService.lockScreen = lockScreen
|
||||
PanelService.tooltip = globalTooltip
|
||||
|
||||
BarWidgetRegistry.init()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user