250 lines
5.9 KiB
QML
250 lines
5.9 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Hyprland
|
|
import "root:/"
|
|
|
|
Scope {
|
|
id: root
|
|
required property var bar;
|
|
|
|
property TooltipItem activeTooltip: null;
|
|
property TooltipItem activeMenu: null;
|
|
|
|
readonly property TooltipItem activeItem: activeMenu ?? activeTooltip;
|
|
property TooltipItem lastActiveItem: null;
|
|
readonly property TooltipItem shownItem: activeItem ?? lastActiveItem;
|
|
property real hangTime: lastActiveItem?.hangTime ?? 0;
|
|
|
|
property Item tooltipItem: null;
|
|
|
|
onActiveItemChanged: {
|
|
if (activeItem != null) {
|
|
hangTimer.stop();
|
|
activeItem.targetVisible = true;
|
|
|
|
if (tooltipItem) {
|
|
activeItem.parent = tooltipItem;
|
|
}
|
|
}
|
|
|
|
if (lastActiveItem != null && lastActiveItem != activeItem) {
|
|
if (activeItem != null) lastActiveItem.targetVisible = false;
|
|
else if (root.hangTime == 0) doLastHide();
|
|
else hangTimer.start();
|
|
}
|
|
|
|
if (activeItem != null) lastActiveItem = activeItem;
|
|
}
|
|
|
|
function setItem(item: TooltipItem) {
|
|
if (item.isMenu) {
|
|
activeMenu = item;
|
|
} else {
|
|
activeTooltip = item;
|
|
}
|
|
}
|
|
|
|
function removeItem(item: TooltipItem) {
|
|
if (item.isMenu && activeMenu == item) {
|
|
activeMenu = null
|
|
} else if (!item.isMenu && activeTooltip == item) {
|
|
activeTooltip = null
|
|
}
|
|
}
|
|
|
|
function doLastHide() {
|
|
lastActiveItem.targetVisible = false;
|
|
}
|
|
|
|
function onHidden(item: TooltipItem) {
|
|
if (item == lastActiveItem) {
|
|
lastActiveItem = null;
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: hangTimer
|
|
interval: root.hangTime
|
|
onTriggered: doLastHide();
|
|
}
|
|
|
|
property real scaleMul: lastActiveItem && lastActiveItem.targetVisible ? 1 : 0;
|
|
Behavior on scaleMul { SmoothedAnimation { velocity: 5 } }
|
|
|
|
LazyLoader {
|
|
id: popupLoader
|
|
activeAsync: shownItem != null
|
|
|
|
PopupWindow {
|
|
id: popup
|
|
|
|
anchor {
|
|
window: bar
|
|
rect.x: bar.tooltipXOffset
|
|
rect.y: tooltipItem.highestAnimY
|
|
adjustment: PopupAdjustment.None
|
|
}
|
|
|
|
HyprlandWindow.opacity: root.scaleMul
|
|
|
|
//height: bar.height
|
|
width: Math.max(700, tooltipItem.largestAnimWidth) // max due to qtwayland glitches
|
|
height: {
|
|
const h = tooltipItem.lowestAnimY - tooltipItem.highestAnimY
|
|
//console.log(`seth ${h} ${tooltipItem.highestAnimY} ${tooltipItem.lowestAnimY}; ${tooltipItem.y1} ${tooltipItem.y2}`)
|
|
return h
|
|
}
|
|
visible: true
|
|
color: "transparent"
|
|
//color: "#20000000"
|
|
|
|
mask: Region {
|
|
item: (shownItem?.hoverable ?? false) ? tooltipItem : null
|
|
}
|
|
|
|
HyprlandFocusGrab {
|
|
active: activeItem?.isMenu ?? false
|
|
windows: [ popup, bar, ...(activeItem?.grabWindows ?? []) ]
|
|
onActiveChanged: {
|
|
if (!active && activeItem?.isMenu) {
|
|
activeMenu.close()
|
|
}
|
|
}
|
|
}
|
|
|
|
/*Rectangle {
|
|
color: "#10ff0000"
|
|
//y: tooltipItem.highestAnimY
|
|
height: tooltipItem.lowestAnimY - tooltipItem.highestAnimY
|
|
width: parent.width
|
|
}
|
|
|
|
Rectangle {
|
|
color: "#1000ff00"
|
|
//y: tooltipItem.highestAnimY
|
|
height: popup.height
|
|
width: parent.width
|
|
}*/
|
|
|
|
Item {
|
|
id: tooltipItem
|
|
Component.onCompleted: {
|
|
root.tooltipItem = this;
|
|
if (root.shownItem) {
|
|
root.shownItem.parent = this;
|
|
}
|
|
|
|
//highestAnimY = targetY - targetHeight / 2;
|
|
//lowestAnimY = targetY + targetHeight / 2;
|
|
}
|
|
|
|
transform: Scale {
|
|
origin.x: 0
|
|
origin.y: tooltipItem.height / 2
|
|
xScale: 0.9 + scaleMul * 0.1
|
|
yScale: xScale
|
|
}
|
|
|
|
clip: width != targetWidth || height != targetHeight
|
|
|
|
// bkg
|
|
BarWidgetInner {
|
|
anchors.fill: parent
|
|
color: ShellGlobals.colors.bar
|
|
}
|
|
|
|
readonly property var targetWidth: shownItem?.implicitWidth ?? 0;
|
|
readonly property var targetHeight: shownItem?.implicitHeight ?? 0;
|
|
|
|
property var largestAnimWidth: 0;
|
|
property var highestAnimY: 0; // unused due to reposition timing issues
|
|
property var lowestAnimY: bar.height;
|
|
|
|
onTargetWidthChanged: {
|
|
if (targetWidth > largestAnimWidth) {
|
|
largestAnimWidth = targetWidth;
|
|
}
|
|
}
|
|
|
|
onTargetYChanged: updateYBounds();
|
|
onTargetHeightChanged: updateYBounds();
|
|
function updateYBounds() {
|
|
if (targetY - targetHeight / 2 < highestAnimY) {
|
|
//highestAnimY = targetY - targetHeight / 2
|
|
}
|
|
|
|
if (targetY + targetHeight / 2 > lowestAnimY) {
|
|
//lowestAnimY = targetY + targetHeight / 2
|
|
}
|
|
}
|
|
|
|
readonly property real targetY: {
|
|
if (shownItem == null) return 0;
|
|
const target = bar.contentItem.mapFromItem(shownItem.owner, 0, shownItem.targetRelativeY).y;
|
|
return bar.boundedY(target, shownItem.implicitHeight / 2);
|
|
}
|
|
|
|
property var w: -1
|
|
width: Math.max(1, w)
|
|
|
|
property var y1: -1
|
|
property var y2: -1
|
|
|
|
y: y1 - popup.anchor.rect.y
|
|
height: y2 - y1
|
|
|
|
readonly property bool anyAnimsRunning: y1Anim.running || y2Anim.running || widthAnim.running
|
|
|
|
onAnyAnimsRunningChanged: {
|
|
if (!anyAnimsRunning) {
|
|
largestAnimWidth = targetWidth
|
|
//highestAnimY = y1;
|
|
//lowestAnimY = y2;
|
|
}
|
|
}
|
|
|
|
SmoothedAnimation on y1 {
|
|
id: y1Anim
|
|
to: tooltipItem.targetY - tooltipItem.targetHeight / 2;
|
|
onToChanged: {
|
|
if (tooltipItem.y1 == -1 || !(shownItem?.animateSize ?? true)) {
|
|
stop();
|
|
tooltipItem.y1 = to;
|
|
} else {
|
|
velocity = (Math.max(tooltipItem.y1, to) - Math.min(tooltipItem.y1, to)) * 5;
|
|
restart();
|
|
}
|
|
}
|
|
}
|
|
|
|
SmoothedAnimation on y2 {
|
|
id: y2Anim
|
|
to: tooltipItem.targetY + tooltipItem.targetHeight / 2;
|
|
onToChanged: {
|
|
if (tooltipItem.y2 == -1 || !(shownItem?.animateSize ?? true)) {
|
|
stop();
|
|
tooltipItem.y2 = to;
|
|
} else {
|
|
velocity = (Math.max(tooltipItem.y2, to) - Math.min(tooltipItem.y2, to)) * 5;
|
|
restart();
|
|
}
|
|
}
|
|
}
|
|
|
|
SmoothedAnimation on w {
|
|
id: widthAnim
|
|
to: tooltipItem.targetWidth;
|
|
onToChanged: {
|
|
if (tooltipItem.w == -1 || !(shownItem?.animateSize ?? true)) {
|
|
stop();
|
|
tooltipItem.w = to;
|
|
} else {
|
|
velocity = (Math.max(tooltipItem.width, to) - Math.min(tooltipItem.width, to)) * 5;
|
|
restart();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|