mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-15 23:55:21 -04:00
Compare commits
1 Commits
1df7e478df
...
hover
| Author | SHA1 | Date | |
|---|---|---|---|
| fc72b6d779 |
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
|
|||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
@@ -16,8 +17,76 @@ Singleton {
|
|||||||
signal popoutOpening
|
signal popoutOpening
|
||||||
signal popoutChanged
|
signal popoutChanged
|
||||||
|
|
||||||
|
property real hoverCursorGlobalX: 0
|
||||||
|
property real hoverCursorGlobalY: 0
|
||||||
|
|
||||||
|
function updateHoverCursor(gx, gy) {
|
||||||
|
hoverCursorGlobalX = gx;
|
||||||
|
hoverCursorGlobalY = gy;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cursorOverBar(gx, gy, padding) {
|
||||||
|
const pad = padding !== undefined ? padding : 16;
|
||||||
|
const bars = KeyboardFocus.barWindows || [];
|
||||||
|
for (let i = 0; i < bars.length; i++) {
|
||||||
|
const w = bars[i];
|
||||||
|
if (!w?.visible)
|
||||||
|
continue;
|
||||||
|
if (typeof w.containsGlobalPoint === "function") {
|
||||||
|
if (w.containsGlobalPoint(gx, gy, pad))
|
||||||
|
return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const item = w.contentItem;
|
||||||
|
if (!item || typeof item.mapToItem !== "function")
|
||||||
|
continue;
|
||||||
|
const topLeft = item.mapToItem(null, 0, 0);
|
||||||
|
if (!topLeft)
|
||||||
|
continue;
|
||||||
|
if (gx >= topLeft.x - pad && gx < topLeft.x + item.width + pad && gy >= topLeft.y - pad && gy < topLeft.y + item.height + pad)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _isPopoutPresented(popout) {
|
||||||
|
if (!popout)
|
||||||
|
return false;
|
||||||
|
try {
|
||||||
|
if (popout.dashVisible !== undefined)
|
||||||
|
return !!popout.dashVisible;
|
||||||
|
if (popout.notificationHistoryVisible !== undefined)
|
||||||
|
return !!popout.notificationHistoryVisible;
|
||||||
|
return !!(popout.shouldBeVisible || popout.isClosing);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _openPopout(popout) {
|
||||||
|
if (popout.dashVisible !== undefined) {
|
||||||
|
if (popout.dashVisible && !popout.shouldBeVisible && !popout.isClosing)
|
||||||
|
popout.dashVisible = false;
|
||||||
|
popout.dashVisible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (popout.notificationHistoryVisible !== undefined) {
|
||||||
|
popout.notificationHistoryVisible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
popout.open();
|
||||||
|
}
|
||||||
|
|
||||||
function _closePopout(popout) {
|
function _closePopout(popout) {
|
||||||
try {
|
try {
|
||||||
|
if (popout?.hoverDismissEnabled) {
|
||||||
|
if (typeof popout.closeFromHoverDismiss === "function") {
|
||||||
|
popout.closeFromHoverDismiss();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (popout.hoverDismissEnabled !== undefined)
|
||||||
|
popout.hoverDismissEnabled = false;
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case popout.dashVisible !== undefined:
|
case popout.dashVisible !== undefined:
|
||||||
popout.dashVisible = false;
|
popout.dashVisible = false;
|
||||||
@@ -89,7 +158,26 @@ Singleton {
|
|||||||
continue;
|
continue;
|
||||||
_closePopout(popout);
|
_closePopout(popout);
|
||||||
}
|
}
|
||||||
currentPopoutsByScreen = {};
|
// Keep map entries until each popout's close animation finishes (hidePopout).
|
||||||
|
}
|
||||||
|
|
||||||
|
function closePopoutForScreen(screen) {
|
||||||
|
if (!screen)
|
||||||
|
return;
|
||||||
|
const screenName = screen.name;
|
||||||
|
const popout = currentPopoutsByScreen[screenName];
|
||||||
|
if (!popout || _isStale(popout)) {
|
||||||
|
currentPopoutsByScreen[screenName] = null;
|
||||||
|
currentPopoutTriggers[screenName] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_closePopout(popout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelHoverDismiss(screen) {
|
||||||
|
const popout = getActivePopout(screen);
|
||||||
|
if (popout?.cancelHoverDismiss)
|
||||||
|
popout.cancelHoverDismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActivePopout(screen) {
|
function getActivePopout(screen) {
|
||||||
@@ -106,6 +194,8 @@ Singleton {
|
|||||||
function requestPopout(popout, tabIndex, triggerSource) {
|
function requestPopout(popout, tabIndex, triggerSource) {
|
||||||
if (!popout || !popout.screen)
|
if (!popout || !popout.screen)
|
||||||
return;
|
return;
|
||||||
|
if (popout.hoverDismissEnabled !== undefined)
|
||||||
|
popout.hoverDismissEnabled = false;
|
||||||
screenshotActive = false;
|
screenshotActive = false;
|
||||||
const screenName = popout.screen.name;
|
const screenName = popout.screen.name;
|
||||||
const currentPopout = currentPopoutsByScreen[screenName];
|
const currentPopout = currentPopoutsByScreen[screenName];
|
||||||
@@ -181,16 +271,81 @@ Singleton {
|
|||||||
ModalManager.closeAllModalsExcept(null);
|
ModalManager.closeAllModalsExcept(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (movedFromOtherScreen) {
|
_openPopout(popout);
|
||||||
popout.open();
|
}
|
||||||
} else {
|
|
||||||
if (popout.dashVisible !== undefined) {
|
function requestHoverPopout(popout, tabIndex, triggerSource) {
|
||||||
popout.dashVisible = true;
|
if (!popout || !popout.screen)
|
||||||
} else if (popout.notificationHistoryVisible !== undefined) {
|
return;
|
||||||
popout.notificationHistoryVisible = true;
|
screenshotActive = false;
|
||||||
|
const screenName = popout.screen.name;
|
||||||
|
const currentPopout = currentPopoutsByScreen[screenName];
|
||||||
|
const triggerId = triggerSource !== undefined ? triggerSource : tabIndex;
|
||||||
|
|
||||||
|
const willOpen = !(currentPopout === popout && _isPopoutPresented(popout) && triggerId !== undefined && currentPopoutTriggers[screenName] === triggerId);
|
||||||
|
if (willOpen)
|
||||||
|
popoutOpening();
|
||||||
|
|
||||||
|
let movedFromOtherScreen = false;
|
||||||
|
for (const otherScreenName in currentPopoutsByScreen) {
|
||||||
|
if (otherScreenName === screenName)
|
||||||
|
continue;
|
||||||
|
const otherPopout = currentPopoutsByScreen[otherScreenName];
|
||||||
|
if (!otherPopout)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (_isStale(otherPopout)) {
|
||||||
|
currentPopoutsByScreen[otherScreenName] = null;
|
||||||
|
currentPopoutTriggers[otherScreenName] = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otherPopout === popout) {
|
||||||
|
movedFromOtherScreen = true;
|
||||||
|
currentPopoutsByScreen[otherScreenName] = null;
|
||||||
|
currentPopoutTriggers[otherScreenName] = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_closePopout(otherPopout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPopout && currentPopout !== popout) {
|
||||||
|
if (_isStale(currentPopout)) {
|
||||||
|
currentPopoutsByScreen[screenName] = null;
|
||||||
|
currentPopoutTriggers[screenName] = null;
|
||||||
} else {
|
} else {
|
||||||
popout.open();
|
_closePopout(currentPopout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentPopout === popout && _isPopoutPresented(popout) && !movedFromOtherScreen) {
|
||||||
|
if (triggerId !== undefined && currentPopoutTriggers[screenName] === triggerId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tabIndex !== undefined && popout.currentTabIndex !== undefined)
|
||||||
|
popout.currentTabIndex = tabIndex;
|
||||||
|
if (popout.updateSurfacePosition)
|
||||||
|
popout.updateSurfacePosition();
|
||||||
|
currentPopoutTriggers[screenName] = triggerId;
|
||||||
|
if (popout.hoverDismissEnabled !== undefined)
|
||||||
|
popout.hoverDismissEnabled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPopoutTriggers[screenName] = triggerId;
|
||||||
|
currentPopoutsByScreen[screenName] = popout;
|
||||||
|
popoutChanged();
|
||||||
|
|
||||||
|
if (tabIndex !== undefined && popout.currentTabIndex !== undefined)
|
||||||
|
popout.currentTabIndex = tabIndex;
|
||||||
|
|
||||||
|
if (currentPopout !== popout)
|
||||||
|
ModalManager.closeAllModalsExcept(null);
|
||||||
|
|
||||||
|
if (popout.hoverDismissEnabled !== undefined)
|
||||||
|
popout.hoverDismissEnabled = true;
|
||||||
|
|
||||||
|
_openPopout(popout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -810,7 +810,8 @@ Singleton {
|
|||||||
"shadowOpacity": 60,
|
"shadowOpacity": 60,
|
||||||
"shadowColorMode": "default",
|
"shadowColorMode": "default",
|
||||||
"shadowCustomColor": "#000000",
|
"shadowCustomColor": "#000000",
|
||||||
"clickThrough": false
|
"clickThrough": false,
|
||||||
|
"hoverPopouts": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -709,6 +709,14 @@ PanelWindow {
|
|||||||
readonly property var _rightSection: topBarContent ? (barWindow.isVertical ? topBarContent.vRightSection : topBarContent.hRightSection) : null
|
readonly property var _rightSection: topBarContent ? (barWindow.isVertical ? topBarContent.vRightSection : topBarContent.hRightSection) : null
|
||||||
readonly property real _revealProgress: topBarSlide.x + topBarSlide.y
|
readonly property real _revealProgress: topBarSlide.x + topBarSlide.y
|
||||||
|
|
||||||
|
function containsGlobalPoint(gx, gy, padding) {
|
||||||
|
const pad = padding !== undefined ? padding : 16;
|
||||||
|
if (!inputMask.showing)
|
||||||
|
return false;
|
||||||
|
const topLeft = inputMask.mapToItem(null, 0, 0);
|
||||||
|
return gx >= topLeft.x - pad && gx < topLeft.x + inputMask.width + pad && gy >= topLeft.y - pad && gy < topLeft.y + inputMask.height + pad;
|
||||||
|
}
|
||||||
|
|
||||||
function sectionRect(section, isCenter, _dep) {
|
function sectionRect(section, isCenter, _dep) {
|
||||||
if (!section)
|
if (!section)
|
||||||
return {
|
return {
|
||||||
@@ -1010,7 +1018,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onWheel: wheel => {
|
function processWheel(wheel) {
|
||||||
if (!(barConfig?.scrollEnabled ?? true) || actionInProgress) {
|
if (!(barConfig?.scrollEnabled ?? true) || actionInProgress) {
|
||||||
wheel.accepted = false;
|
wheel.accepted = false;
|
||||||
return;
|
return;
|
||||||
@@ -1079,6 +1087,8 @@ PanelWindow {
|
|||||||
|
|
||||||
wheel.accepted = false;
|
wheel.accepted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onWheel: wheel => processWheel(wheel)
|
||||||
}
|
}
|
||||||
|
|
||||||
DankBarContent {
|
DankBarContent {
|
||||||
@@ -1090,6 +1100,36 @@ PanelWindow {
|
|||||||
centerWidgetsModel: barWindow.centerWidgetsModel
|
centerWidgetsModel: barWindow.centerWidgetsModel
|
||||||
rightWidgetsModel: barWindow.rightWidgetsModel
|
rightWidgetsModel: barWindow.rightWidgetsModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: hoverPopoutArea
|
||||||
|
anchors.fill: parent
|
||||||
|
z: 1
|
||||||
|
hoverEnabled: barConfig?.hoverPopouts ?? false
|
||||||
|
enabled: hoverPopoutArea.hoverEnabled && !barWindow.clickThroughEnabled
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
propagateComposedEvents: true
|
||||||
|
|
||||||
|
property real lastGlobalX: 0
|
||||||
|
property real lastGlobalY: 0
|
||||||
|
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
const gp = mapToItem(null, mouse.x, mouse.y);
|
||||||
|
lastGlobalX = gp.x;
|
||||||
|
lastGlobalY = gp.y;
|
||||||
|
topBarContent.checkHoverPopout(gp.x, gp.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
onWheel: wheel => scrollArea.processWheel(wheel)
|
||||||
|
|
||||||
|
onContainsMouseChanged: {
|
||||||
|
if (containsMouse)
|
||||||
|
return;
|
||||||
|
if (topBarContent.cursorOverHoverChain(lastGlobalX, lastGlobalY))
|
||||||
|
return;
|
||||||
|
topBarContent.closeHoverSurfaces();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1922,4 +1922,53 @@ BasePill {
|
|||||||
return;
|
return;
|
||||||
currentTrayMenu.showForTrayItem(item, anchor, screen, atBottom, vertical ?? false, axisObj);
|
currentTrayMenu.showForTrayItem(item, anchor, screen, atBottom, vertical ?? false, axisObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _trayLayoutRoot() {
|
||||||
|
const contentChildren = root.visualContent?.children;
|
||||||
|
if (!contentChildren || contentChildren.length === 0)
|
||||||
|
return null;
|
||||||
|
const contentRoot = contentChildren[0];
|
||||||
|
return contentRoot?.layoutLoader?.item || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _trayHitAtGlobalPoint(gx, gy) {
|
||||||
|
if (!root.visible || root.width <= 0 || root.height <= 0)
|
||||||
|
return null;
|
||||||
|
const local = root.mapFromItem(null, gx, gy);
|
||||||
|
if (local.x < 0 || local.y < 0 || local.x > root.width || local.y > root.height)
|
||||||
|
return null;
|
||||||
|
const layout = _trayLayoutRoot();
|
||||||
|
if (!layout)
|
||||||
|
return null;
|
||||||
|
const layoutLocal = layout.mapFromItem(null, gx, gy);
|
||||||
|
const children = layout.children || [];
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
const child = children[i];
|
||||||
|
if (!child.visible || child.width <= 0 || child.height <= 0)
|
||||||
|
continue;
|
||||||
|
if (layoutLocal.x < child.x || layoutLocal.x >= child.x + child.width)
|
||||||
|
continue;
|
||||||
|
if (layoutLocal.y < child.y || layoutLocal.y >= child.y + child.height)
|
||||||
|
continue;
|
||||||
|
if (child.trayItem)
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hoverTriggerAtGlobalPoint(gx, gy) {
|
||||||
|
const hit = _trayHitAtGlobalPoint(gx, gy);
|
||||||
|
if (!hit?.trayItem?.hasMenu)
|
||||||
|
return "";
|
||||||
|
return "tray-" + (hit.trayItem.id || hit.itemKey || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function openHoverAtGlobalPoint(gx, gy) {
|
||||||
|
const hit = _trayHitAtGlobalPoint(gx, gy);
|
||||||
|
if (!hit?.trayItem?.hasMenu)
|
||||||
|
return false;
|
||||||
|
const anchor = hit.children?.length > 0 ? hit.children[0] : hit;
|
||||||
|
showForTrayItem(hit.trayItem, anchor, parentScreen, isAtBottom, isVerticalOrientation, axis);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -330,6 +330,24 @@ Item {
|
|||||||
pluginPopout.toggle();
|
pluginPopout.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function triggerHoverPopout(widgetHostId) {
|
||||||
|
if (pillClickAction) {
|
||||||
|
triggerPopout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hasPopout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const pill = isVertical ? verticalPill : horizontalPill;
|
||||||
|
const globalPos = pill.visualContent.mapToItem(null, 0, 0);
|
||||||
|
const currentScreen = parentScreen || Screen;
|
||||||
|
const barPosition = axis?.edge === "left" ? 2 : (axis?.edge === "right" ? 3 : (axis?.edge === "top" ? 0 : 1));
|
||||||
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, pill.visualWidth, barSpacing, barPosition, barConfig);
|
||||||
|
|
||||||
|
pluginPopout.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen, barPosition, barThickness, barSpacing, barConfig);
|
||||||
|
PopoutManager.requestHoverPopout(pluginPopout, undefined, widgetHostId || pluginId);
|
||||||
|
}
|
||||||
|
|
||||||
PluginPopout {
|
PluginPopout {
|
||||||
id: pluginPopout
|
id: pluginPopout
|
||||||
contentWidth: root.popoutWidth
|
contentWidth: root.popoutWidth
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ Item {
|
|||||||
scrollEnabled: defaultBar.scrollEnabled ?? true,
|
scrollEnabled: defaultBar.scrollEnabled ?? true,
|
||||||
scrollXBehavior: defaultBar.scrollXBehavior ?? "column",
|
scrollXBehavior: defaultBar.scrollXBehavior ?? "column",
|
||||||
scrollYBehavior: defaultBar.scrollYBehavior ?? "workspace",
|
scrollYBehavior: defaultBar.scrollYBehavior ?? "workspace",
|
||||||
|
hoverPopouts: defaultBar.hoverPopouts ?? false,
|
||||||
shadowIntensity: defaultBar.shadowIntensity ?? 0,
|
shadowIntensity: defaultBar.shadowIntensity ?? 0,
|
||||||
shadowOpacity: defaultBar.shadowOpacity ?? 60,
|
shadowOpacity: defaultBar.shadowOpacity ?? 60,
|
||||||
shadowDirectionMode: defaultBar.shadowDirectionMode ?? "inherit",
|
shadowDirectionMode: defaultBar.shadowDirectionMode ?? "inherit",
|
||||||
@@ -1741,6 +1742,19 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsToggleCard {
|
||||||
|
iconName: "touch_app"
|
||||||
|
title: I18n.tr("Hover Popouts")
|
||||||
|
description: I18n.tr("Open widget popouts by hovering over the bar. Moving to another widget switches the popout.")
|
||||||
|
visible: !dankBarTab.appearanceOnly && selectedBarConfig?.enabled
|
||||||
|
enabled: !(selectedBarConfig?.clickThrough ?? false)
|
||||||
|
opacity: (selectedBarConfig?.clickThrough ?? false) ? 0.5 : 1.0
|
||||||
|
checked: selectedBarConfig?.hoverPopouts ?? false
|
||||||
|
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
hoverPopouts: checked
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
SettingsToggleCard {
|
SettingsToggleCard {
|
||||||
iconName: "mouse"
|
iconName: "mouse"
|
||||||
title: I18n.tr("Scroll Wheel")
|
title: I18n.tr("Scroll Wheel")
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ Item {
|
|||||||
property list<real> animationExitCurve: Theme.variantPopoutExitCurve
|
property list<real> animationExitCurve: Theme.variantPopoutExitCurve
|
||||||
property bool suspendShadowWhileResizing: false
|
property bool suspendShadowWhileResizing: false
|
||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
|
property bool hoverDismissEnabled: false
|
||||||
property var customKeyboardFocus: null
|
property var customKeyboardFocus: null
|
||||||
property bool backgroundInteractive: true
|
property bool backgroundInteractive: true
|
||||||
property bool contentHandlesKeys: false
|
property bool contentHandlesKeys: false
|
||||||
@@ -82,6 +83,8 @@ Item {
|
|||||||
readonly property real alignedY: impl.item ? impl.item.alignedY : 0
|
readonly property real alignedY: impl.item ? impl.item.alignedY : 0
|
||||||
readonly property real alignedWidth: impl.item ? impl.item.alignedWidth : 0
|
readonly property real alignedWidth: impl.item ? impl.item.alignedWidth : 0
|
||||||
readonly property real alignedHeight: impl.item ? impl.item.alignedHeight : 0
|
readonly property real alignedHeight: impl.item ? impl.item.alignedHeight : 0
|
||||||
|
readonly property real renderedAlignedY: impl.item ? (impl.item.renderedAlignedY ?? impl.item.alignedY) : 0
|
||||||
|
readonly property real renderedAlignedHeight: impl.item ? (impl.item.renderedAlignedHeight ?? impl.item.alignedHeight) : 0
|
||||||
readonly property real maskX: impl.item ? impl.item.maskX : 0
|
readonly property real maskX: impl.item ? impl.item.maskX : 0
|
||||||
readonly property real maskY: impl.item ? impl.item.maskY : 0
|
readonly property real maskY: impl.item ? impl.item.maskY : 0
|
||||||
readonly property real maskWidth: impl.item ? impl.item.maskWidth : 0
|
readonly property real maskWidth: impl.item ? impl.item.maskWidth : 0
|
||||||
@@ -172,6 +175,32 @@ Item {
|
|||||||
impl.item.close();
|
impl.item.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cancelHoverDismiss() {
|
||||||
|
if (impl.item?.cancelHoverDismiss)
|
||||||
|
impl.item.cancelHoverDismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeFromHoverDismiss() {
|
||||||
|
hoverDismissEnabled = false;
|
||||||
|
if (impl.item) {
|
||||||
|
impl.item.animationsEnabled = true;
|
||||||
|
impl.item.animationDuration = Math.round(Theme.expressiveDurations.expressiveDefaultSpatial);
|
||||||
|
impl.item.animationExitCurve = Theme.expressiveCurves.expressiveDefaultSpatial;
|
||||||
|
}
|
||||||
|
if (dashVisible !== undefined) {
|
||||||
|
dashVisible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (notificationHistoryVisible !== undefined) {
|
||||||
|
notificationHistoryVisible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (impl.item)
|
||||||
|
impl.item.close();
|
||||||
|
else
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
(shouldBeVisible || _pendingOpen) ? close() : open();
|
(shouldBeVisible || _pendingOpen) ? close() : open();
|
||||||
}
|
}
|
||||||
@@ -210,6 +239,20 @@ Item {
|
|||||||
impl.item.updateSurfacePosition();
|
impl.item.updateSurfacePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function containsGlobalPoint(gx, gy) {
|
||||||
|
if (!screen)
|
||||||
|
return false;
|
||||||
|
const presented = shouldBeVisible || (impl.item?.isClosing ?? false);
|
||||||
|
if (!presented)
|
||||||
|
return false;
|
||||||
|
const padding = 24;
|
||||||
|
const x = alignedX - padding;
|
||||||
|
const y = renderedAlignedY - padding;
|
||||||
|
const w = alignedWidth + padding * 2;
|
||||||
|
const h = renderedAlignedHeight + padding * 2;
|
||||||
|
return gx >= x && gx <= x + w && gy >= y && gy <= y + h;
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: impl
|
id: impl
|
||||||
active: root.screen !== null
|
active: root.screen !== null
|
||||||
@@ -261,6 +304,7 @@ Item {
|
|||||||
it.screen = Qt.binding(() => root.screen);
|
it.screen = Qt.binding(() => root.screen);
|
||||||
it.effectiveBarPosition = Qt.binding(() => root.effectiveBarPosition);
|
it.effectiveBarPosition = Qt.binding(() => root.effectiveBarPosition);
|
||||||
it.effectiveBarBottomGap = Qt.binding(() => root.effectiveBarBottomGap);
|
it.effectiveBarBottomGap = Qt.binding(() => root.effectiveBarBottomGap);
|
||||||
|
it.hoverDismissEnabled = Qt.binding(() => root.hoverDismissEnabled);
|
||||||
|
|
||||||
it.shouldBeVisible = root.shouldBeVisible;
|
it.shouldBeVisible = root.shouldBeVisible;
|
||||||
if (root._primeContent && typeof it.primeContent === "function")
|
if (root._primeContent && typeof it.primeContent === "function")
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Quickshell
|
|||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -407,6 +408,20 @@ Item {
|
|||||||
onFrameOwnsConnectedChromeChanged: _syncPopoutChromeState()
|
onFrameOwnsConnectedChromeChanged: _syncPopoutChromeState()
|
||||||
|
|
||||||
property bool animationsEnabled: true
|
property bool animationsEnabled: true
|
||||||
|
property bool hoverDismissEnabled: false
|
||||||
|
|
||||||
|
function cancelHoverDismiss() {
|
||||||
|
hoverDismissTracker.cancelPending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeFromHoverDismiss() {
|
||||||
|
if (isClosing || !shouldBeVisible)
|
||||||
|
return;
|
||||||
|
if (popoutHandle?.closeFromHoverDismiss)
|
||||||
|
popoutHandle.closeFromHoverDismiss();
|
||||||
|
else
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
if (!screen)
|
if (!screen)
|
||||||
@@ -761,6 +776,27 @@ Item {
|
|||||||
visible: false
|
visible: false
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
z: -1
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
hoverEnabled: true
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
const gp = mapToItem(null, mouse.x, mouse.y);
|
||||||
|
PopoutManager.updateHoverCursor(gp.x, gp.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverDismissTracker {
|
||||||
|
id: hoverDismissTracker
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: root.hoverDismissEnabled && root.shouldBeVisible
|
||||||
|
shouldDismiss: function () {
|
||||||
|
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
||||||
|
}
|
||||||
|
onDismissRequested: root.closeFromHoverDismiss()
|
||||||
|
}
|
||||||
|
|
||||||
WindowBlur {
|
WindowBlur {
|
||||||
id: popoutBlur
|
id: popoutBlur
|
||||||
targetWindow: contentWindow
|
targetWindow: contentWindow
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Quickshell
|
|||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -35,6 +36,21 @@ Item {
|
|||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
property bool isClosing: false
|
property bool isClosing: false
|
||||||
property bool animationsEnabled: true
|
property bool animationsEnabled: true
|
||||||
|
property bool hoverDismissEnabled: false
|
||||||
|
|
||||||
|
function cancelHoverDismiss() {
|
||||||
|
hoverDismissTracker.cancelPending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeFromHoverDismiss() {
|
||||||
|
if (isClosing || !shouldBeVisible)
|
||||||
|
return;
|
||||||
|
if (popoutHandle?.closeFromHoverDismiss)
|
||||||
|
popoutHandle.closeFromHoverDismiss();
|
||||||
|
else
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
property var customKeyboardFocus: null
|
property var customKeyboardFocus: null
|
||||||
property bool backgroundInteractive: true
|
property bool backgroundInteractive: true
|
||||||
property bool contentHandlesKeys: false
|
property bool contentHandlesKeys: false
|
||||||
@@ -585,6 +601,27 @@ Item {
|
|||||||
color: "transparent"
|
color: "transparent"
|
||||||
readonly property bool closeVisualActive: root.shouldBeVisible || root.isClosing
|
readonly property bool closeVisualActive: root.shouldBeVisible || root.isClosing
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
z: -1
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
hoverEnabled: true
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
const gp = mapToItem(null, mouse.x, mouse.y);
|
||||||
|
PopoutManager.updateHoverCursor(gp.x, gp.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverDismissTracker {
|
||||||
|
id: hoverDismissTracker
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: root.hoverDismissEnabled && root.shouldBeVisible
|
||||||
|
shouldDismiss: function () {
|
||||||
|
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
||||||
|
}
|
||||||
|
onDismissRequested: root.closeFromHoverDismiss()
|
||||||
|
}
|
||||||
|
|
||||||
WindowBlur {
|
WindowBlur {
|
||||||
id: popoutBlur
|
id: popoutBlur
|
||||||
targetWindow: contentWindow
|
targetWindow: contentWindow
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ PanelWindow {
|
|||||||
WlrLayershell.namespace: layerNamespace
|
WlrLayershell.namespace: layerNamespace
|
||||||
|
|
||||||
property bool isVisible: false
|
property bool isVisible: false
|
||||||
|
property bool hoverDismissEnabled: false
|
||||||
property var targetScreen: null
|
property var targetScreen: null
|
||||||
property var modelData: null
|
property var modelData: null
|
||||||
property bool triggerUsesOverlayLayer: false
|
property bool triggerUsesOverlayLayer: false
|
||||||
@@ -39,6 +40,24 @@ PanelWindow {
|
|||||||
isVisible = false;
|
isVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hideFromHoverDismiss() {
|
||||||
|
hoverDismissEnabled = false;
|
||||||
|
slideAnimation.duration = Math.round(Theme.expressiveDurations.expressiveDefaultSpatial);
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelHoverDismiss() {
|
||||||
|
hoverDismissTracker.cancelPending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function containsGlobalPoint(gx, gy) {
|
||||||
|
if (!isVisible || !modelData)
|
||||||
|
return false;
|
||||||
|
const padding = 24;
|
||||||
|
const topLeft = slideContainer.mapToItem(null, 0, 0);
|
||||||
|
return gx >= topLeft.x - padding && gx < topLeft.x + slideContainer.width + padding && gy >= topLeft.y - padding && gy < topLeft.y + slideContainer.height + padding;
|
||||||
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
hide();
|
hide();
|
||||||
@@ -60,6 +79,27 @@ PanelWindow {
|
|||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
z: -1
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
hoverEnabled: true
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
const gp = mapToItem(null, mouse.x, mouse.y);
|
||||||
|
PopoutManager.updateHoverCursor(gp.x, gp.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverDismissTracker {
|
||||||
|
id: hoverDismissTracker
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: root.hoverDismissEnabled && root.isVisible
|
||||||
|
shouldDismiss: function () {
|
||||||
|
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
||||||
|
}
|
||||||
|
onDismissRequested: root.hideFromHoverDismiss()
|
||||||
|
}
|
||||||
|
|
||||||
readonly property bool slideoutBlurActive: root.visible && BlurService.enabled && Theme.connectedSurfaceBlurEnabled
|
readonly property bool slideoutBlurActive: root.visible && BlurService.enabled && Theme.connectedSurfaceBlurEnabled
|
||||||
|
|
||||||
WlrLayershell.layer: (triggerUsesOverlayLayer || CompositorService.framePeerSurfacesUseOverlayForScreen(modelData)) ? WlrLayershell.Overlay : WlrLayershell.Top
|
WlrLayershell.layer: (triggerUsesOverlayLayer || CompositorService.framePeerSurfacesUseOverlayForScreen(modelData)) ? WlrLayershell.Overlay : WlrLayershell.Top
|
||||||
@@ -104,8 +144,10 @@ PanelWindow {
|
|||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
|
|
||||||
onRunningChanged: {
|
onRunningChanged: {
|
||||||
if (!running && !root.isVisible) {
|
if (!running) {
|
||||||
root.mappedVisible = false;
|
if (!root.isVisible)
|
||||||
|
root.mappedVisible = false;
|
||||||
|
slideAnimation.duration = 450;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool enabled: false
|
||||||
|
property var shouldDismiss: null
|
||||||
|
|
||||||
|
signal dismissRequested
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
HoverHandler {
|
||||||
|
id: hoverHandler
|
||||||
|
enabled: root.enabled
|
||||||
|
onHoveredChanged: {
|
||||||
|
if (hoverHandler.hovered || !root.enabled)
|
||||||
|
return;
|
||||||
|
if (typeof root.shouldDismiss === "function" && !root.shouldDismiss())
|
||||||
|
return;
|
||||||
|
root.dismissRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelPending() {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user