nosignal-shell/modules/drawers/Interactions.qml
M Matthew Hydock 468bab5e5b
launcher: allow show on hover (#498)
added `showOnHover` to launcher config, disabled by default to preserve
existing functionality. when enabled, drag-to-show is disabled.
2025-08-30 13:08:36 +10:00

243 lines
9 KiB
QML

import qs.components.controls
import qs.services
import qs.config
import qs.modules.bar.popouts as BarPopouts
import qs.modules.osd as Osd
import Quickshell
import QtQuick
CustomMouseArea {
id: root
required property ShellScreen screen
required property BarPopouts.Wrapper popouts
required property PersistentProperties visibilities
required property Panels panels
required property Item bar
property bool osdHovered
property point dragStart
property bool dashboardShortcutActive
property bool osdShortcutActive
property bool utilitiesShortcutActive
function withinPanelHeight(panel: Item, x: real, y: real): bool {
const panelY = Config.border.thickness + panel.y;
return y >= panelY - Config.border.rounding && y <= panelY + panel.height + Config.border.rounding;
}
function withinPanelWidth(panel: Item, x: real, y: real): bool {
const panelX = bar.implicitWidth + panel.x;
return x >= panelX - Config.border.rounding && x <= panelX + panel.width + Config.border.rounding;
}
function inLeftPanel(panel: Item, x: real, y: real): bool {
return x < bar.implicitWidth + panel.x + panel.width && withinPanelHeight(panel, x, y);
}
function inRightPanel(panel: Item, x: real, y: real): bool {
return x > bar.implicitWidth + panel.x && withinPanelHeight(panel, x, y);
}
function inTopPanel(panel: Item, x: real, y: real): bool {
return y < Config.border.thickness + panel.y + panel.height && withinPanelWidth(panel, x, y);
}
function inBottomPanel(panel: Item, x: real, y: real): bool {
return y > root.height - Config.border.thickness - panel.height - Config.border.rounding && withinPanelWidth(panel, x, y);
}
function onWheel(event: WheelEvent): void {
if (event.x < bar.implicitWidth) {
bar.handleWheel(event.y, event.angleDelta);
}
}
anchors.fill: parent
hoverEnabled: true
onPressed: event => dragStart = Qt.point(event.x, event.y)
onContainsMouseChanged: {
if (!containsMouse) {
// Only hide if not activated by shortcut
if (!osdShortcutActive) {
visibilities.osd = false;
osdHovered = false;
}
if (!dashboardShortcutActive)
visibilities.dashboard = false;
if (!utilitiesShortcutActive)
visibilities.utilities = false;
if (!popouts.currentName.startsWith("traymenu"))
popouts.hasCurrent = false;
if (Config.bar.showOnHover)
bar.isHovered = false;
}
}
onPositionChanged: event => {
if (popouts.isDetached)
return;
const x = event.x;
const y = event.y;
// Show bar in non-exclusive mode on hover
if (!visibilities.bar && Config.bar.showOnHover && x < bar.implicitWidth)
bar.isHovered = true;
// Show/hide bar on drag
if (pressed && dragStart.x < bar.implicitWidth) {
const dragX = x - dragStart.x;
if (dragX > Config.bar.dragThreshold)
visibilities.bar = true;
else if (dragX < -Config.bar.dragThreshold)
visibilities.bar = false;
}
// Show osd on hover
const showOsd = inRightPanel(panels.osd, x, y);
// Always update visibility based on hover if not in shortcut mode
if (!osdShortcutActive) {
visibilities.osd = showOsd;
osdHovered = showOsd;
} else if (showOsd) {
// If hovering over OSD area while in shortcut mode, transition to hover control
osdShortcutActive = false;
osdHovered = true;
}
// Show/hide session on drag
if (pressed && inRightPanel(panels.session, dragStart.x, dragStart.y) && withinPanelHeight(panels.session, x, y)) {
const dragX = x - dragStart.x;
if (dragX < -Config.session.dragThreshold)
visibilities.session = true;
else if (dragX > Config.session.dragThreshold)
visibilities.session = false;
}
// Show launcher on hover, or show/hide on drag if hover is disabled
if (Config.launcher.showOnHover) {
visibilities.launcher = inBottomPanel(panels.launcher, x, y);
} else if (pressed && inBottomPanel(panels.launcher, dragStart.x, dragStart.y) && withinPanelWidth(panels.launcher, x, y)) {
const dragY = y - dragStart.y;
if (dragY < -Config.launcher.dragThreshold)
visibilities.launcher = true;
else if (dragY > Config.launcher.dragThreshold)
visibilities.launcher = false;
}
// Show dashboard on hover
const showDashboard = Config.dashboard.showOnHover && inTopPanel(panels.dashboard, x, y);
// Always update visibility based on hover if not in shortcut mode
if (!dashboardShortcutActive) {
visibilities.dashboard = showDashboard;
} else if (showDashboard) {
// If hovering over dashboard area while in shortcut mode, transition to hover control
dashboardShortcutActive = false;
}
// Show/hide dashboard on drag (for touchscreen devices)
if (pressed && inTopPanel(panels.dashboard, dragStart.x, dragStart.y) && withinPanelWidth(panels.dashboard, x, y)) {
const dragY = y - dragStart.y;
if (dragY > Config.dashboard.dragThreshold)
visibilities.dashboard = true;
else if (dragY < -Config.dashboard.dragThreshold)
visibilities.dashboard = false;
}
// Show utilities on hover
const showUtilities = inBottomPanel(panels.utilities, x, y);
// Always update visibility based on hover if not in shortcut mode
if (!utilitiesShortcutActive) {
visibilities.utilities = showUtilities;
} else if (showUtilities) {
// If hovering over utilities area while in shortcut mode, transition to hover control
utilitiesShortcutActive = false;
}
// Show popouts on hover
if (x < bar.implicitWidth)
bar.checkPopout(y);
else if (!popouts.currentName.startsWith("traymenu") && !inLeftPanel(panels.popouts, x, y))
popouts.hasCurrent = false;
}
// Monitor individual visibility changes
Connections {
target: root.visibilities
function onLauncherChanged() {
// If launcher is hidden, clear shortcut flags for dashboard and OSD
if (!root.visibilities.launcher) {
root.dashboardShortcutActive = false;
root.osdShortcutActive = false;
root.utilitiesShortcutActive = false;
// Also hide dashboard and OSD if they're not being hovered
const inDashboardArea = root.inTopPanel(root.panels.dashboard, root.mouseX, root.mouseY);
const inOsdArea = root.inRightPanel(root.panels.osd, root.mouseX, root.mouseY);
if (!inDashboardArea) {
root.visibilities.dashboard = false;
}
if (!inOsdArea) {
root.visibilities.osd = false;
root.osdHovered = false;
}
}
}
function onDashboardChanged() {
if (root.visibilities.dashboard) {
// Dashboard became visible, immediately check if this should be shortcut mode
const inDashboardArea = root.inTopPanel(root.panels.dashboard, root.mouseX, root.mouseY);
if (!inDashboardArea) {
root.dashboardShortcutActive = true;
}
} else {
// Dashboard hidden, clear shortcut flag
root.dashboardShortcutActive = false;
}
}
function onOsdChanged() {
if (root.visibilities.osd) {
// OSD became visible, immediately check if this should be shortcut mode
const inOsdArea = root.inRightPanel(root.panels.osd, root.mouseX, root.mouseY);
if (!inOsdArea) {
root.osdShortcutActive = true;
}
} else {
// OSD hidden, clear shortcut flag
root.osdShortcutActive = false;
}
}
function onUtilitiesChanged() {
if (root.visibilities.utilities) {
// Utilities became visible, immediately check if this should be shortcut mode
const inUtilitiesArea = root.inBottomPanel(root.panels.utilities, root.mouseX, root.mouseY);
if (!inUtilitiesArea) {
root.utilitiesShortcutActive = true;
}
} else {
// Utilities hidden, clear shortcut flag
root.utilitiesShortcutActive = false;
}
}
}
Osd.Interactions {
screen: root.screen
visibilities: root.visibilities
hovered: root.osdHovered
}
}