refactor(island): add island satellite hover option

fixes #3296
port 1.6

(cherry picked from commit 60675ecb39)
This commit is contained in:
purian23
2026-09-10 03:36:41 +00:00
committed by dms-ci[bot]
parent 06cd88e990
commit 12f7675950
4 changed files with 137 additions and 77 deletions
+2 -14
View File
@@ -1168,20 +1168,8 @@ Item {
HoverHandler {
id: hoverPopoutHandler
enabled: (barConfig?.hoverPopouts ?? false) && !barWindow.clickThroughEnabled
property real lastGlobalX: 0
property real lastGlobalY: 0
onPointChanged: {
const gp = barUnitInset.mapToItem(null, point.position.x, point.position.y);
lastGlobalX = gp.x;
lastGlobalY = gp.y;
topBarContent.queueHoverPopout(gp.x, gp.y);
}
onHoveredChanged: {
topBarContent.updateHoverBarHovered(hovered);
}
onPointChanged: topBarContent.queueHoverFromItem(barUnitInset, point)
onHoveredChanged: topBarContent.updateHoverBarHovered(hovered)
}
}
}
+64 -11
View File
@@ -19,6 +19,8 @@ Item {
property var leftWidgetsModel
property var centerWidgetsModel
property var rightWidgetsModel
property var widgetOwner: null
property var hoverSections: null
property bool _animateFrameInsets: false
readonly property real innerPadding: barConfig?.innerPadding ?? 4
@@ -85,6 +87,34 @@ Item {
property alias vCenterSection: vCenterSection
property alias vRightSection: vRightSection
readonly property var _defaultHoverSections: barWindow.isVertical ? [
{
section: vLeftSection,
name: "left"
},
{
section: vCenterSection,
name: "center"
},
{
section: vRightSection,
name: "right"
}
] : [
{
section: hLeftSection,
name: "left"
},
{
section: hCenterSection,
name: "center"
},
{
section: hRightSection,
name: "right"
}
]
anchors.fill: parent
anchors.leftMargin: _leftMargin
anchors.rightMargin: _rightMargin
@@ -413,12 +443,8 @@ Item {
barContent: topBarContent
barWindow: topBarContent.barWindow
barConfig: topBarContent.barConfig
hLeftSection: topBarContent.hLeftSection
hCenterSection: topBarContent.hCenterSection
hRightSection: topBarContent.hRightSection
vLeftSection: topBarContent.vLeftSection
vCenterSection: topBarContent.vCenterSection
vRightSection: topBarContent.vRightSection
widgetOwner: topBarContent.widgetOwner
sections: topBarContent.hoverSections || topBarContent._defaultHoverSections
leftWidgetsModel: topBarContent.leftWidgetsModel
centerWidgetsModel: topBarContent.centerWidgetsModel
rightWidgetsModel: topBarContent.rightWidgetsModel
@@ -427,6 +453,28 @@ Item {
readonly property string activeHoverTrigger: hoverController.activeHoverTrigger
readonly property bool hoverPopoutsEnabled: hoverController.hoverPopoutsEnabled
function mapItemToScreen(item, x, y) {
if (!item || typeof item.mapToItem !== "function")
return null;
try {
const raw = item.mapToItem(null, x ?? 0, y ?? 0);
if (!raw)
return null;
return Qt.point(raw.x + (barWindow?.hostOriginX ?? 0), raw.y + (barWindow?.hostOriginY ?? 0));
} catch (e) {
return null;
}
}
function queueHoverFromItem(item, point) {
if (!point)
return;
const gp = mapItemToScreen(item, point.position.x, point.position.y);
if (!gp)
return;
queueHoverPopout(gp.x, gp.y);
}
function queueHoverPopout(gx, gy) {
hoverController.queueHoverPoint(gx, gy);
}
@@ -447,6 +495,10 @@ Item {
hoverController.updateBarHovered(hovered);
}
function invalidateHoverCandidateCache() {
hoverController.invalidateCandidateCache();
}
function resetHoverForBarGeometryChange() {
hoverController.resetForBarGeometryChange();
}
@@ -465,14 +517,13 @@ Item {
const centerSection = barWindow.isVertical ? vCenterSection : hCenterSection;
if (centerSection) {
if (barWindow.isVertical) {
const centerY = centerSection.height / 2;
return {
triggerPos: centerSection.mapToItem(null, 0, centerY),
triggerPos: mapItemToScreen(centerSection, 0, centerSection.height / 2),
triggerWidth: centerSection.height
};
}
return {
triggerPos: centerSection.mapToItem(null, 0, 0),
triggerPos: mapItemToScreen(centerSection, 0, 0),
triggerWidth: centerSection.width
};
}
@@ -480,7 +531,7 @@ Item {
const ref = opts.visualItem || widgetItem.visualContent || widgetItem;
const w = opts.triggerWidth !== undefined ? opts.triggerWidth : (widgetItem.visualWidth !== undefined ? widgetItem.visualWidth : widgetItem.width);
return {
triggerPos: ref.mapToItem(null, 0, 0),
triggerPos: mapItemToScreen(ref, 0, 0),
triggerWidth: w
};
}
@@ -987,7 +1038,9 @@ Item {
if (loader.item.setBarContext)
loader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
if (loader.item.setTriggerPosition) {
const globalPos = launcherButton.visualContent.mapToItem(null, 0, 0);
const globalPos = topBarContent.mapItemToScreen(launcherButton.visualContent, 0, 0);
if (!globalPos)
return false;
const currentScreen = barWindow.screen;
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barWindow.effectiveBarThickness, launcherButton.visualWidth, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
loader.item.setTriggerPosition(pos.x, pos.y, pos.width, launcherButton.section, currentScreen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
@@ -10,12 +10,8 @@ Item {
required property var barContent
required property var barWindow
required property var barConfig
required property var hLeftSection
required property var hCenterSection
required property var hRightSection
required property var vLeftSection
required property var vCenterSection
required property var vRightSection
property var widgetOwner: null
property var sections: []
property var leftWidgetsModel
property var centerWidgetsModel
@@ -46,6 +42,7 @@ Item {
onLeftWidgetsModelChanged: invalidateCandidateCache()
onCenterWidgetsModelChanged: invalidateCandidateCache()
onRightWidgetsModelChanged: invalidateCandidateCache()
onSectionsChanged: invalidateCandidateCache()
onHoverPopoutsEnabledChanged: {
if (hoverPopoutsEnabled)
@@ -62,7 +59,7 @@ Item {
Component.onDestruction: _disconnectCandidateWatchers()
Connections {
target: root.barContent
target: root.widgetOwner || root.barContent
function onWidthChanged() {
root.invalidateCandidateCache();
@@ -227,41 +224,12 @@ Item {
}
function _getBarSections() {
if (barWindow.isVertical) {
return [
{
section: vLeftSection,
name: "left"
},
{
section: vCenterSection,
name: "center"
},
{
section: vRightSection,
name: "right"
}
];
}
return [
{
section: hLeftSection,
name: "left"
},
{
section: hCenterSection,
name: "center"
},
{
section: hRightSection,
name: "right"
}
];
return root.sections || [];
}
// The widget registry is keyed by (widgetId, screenName)
function _itemBelongsToThisBar(item) {
const owner = barContent;
const owner = root.widgetOwner || barContent;
if (!owner || !item)
return true;
let node = item;
@@ -489,17 +457,15 @@ Item {
}
function _globalItemBounds(item) {
try {
const topLeft = item.mapToItem(null, 0, 0);
return {
x: topLeft.x,
y: topLeft.y,
width: item.width,
height: item.height
};
} catch (e) {
const topLeft = barContent.mapItemToScreen(item, 0, 0);
if (!topLeft)
return null;
}
return {
x: topLeft.x,
y: topLeft.y,
width: item.width,
height: item.height
};
}
function _hitBoundsForWidget(widgetItem, wrapper) {
@@ -153,6 +153,9 @@ Item {
property bool hasAdjacentLeftBar: false
property bool hasAdjacentRightBar: false
property var hyprlandOverviewLoader: root.hyprlandOverviewLoader
property var hostWindow: root.hostWindow
readonly property int hostOriginX: hostWindow?.hostOriginX ?? 0
readonly property int hostOriginY: hostWindow?.hostOriginY ?? 0
property var controlCenterButtonRef: null
property var clockButtonRef: null
property var systemUpdateButtonRef: null
@@ -269,9 +272,16 @@ Item {
return;
blurRebuildTimer.restart();
blurTrailTimer.restart();
componentProvider.invalidateHoverCandidateCache();
}
}
function onSatelliteRowMoved() {
kickBlur();
if (!root.motionRunning)
componentProvider.invalidateHoverCandidateCache();
}
function kickBlur() {
if (root.motionRunning)
return;
@@ -412,11 +422,26 @@ Item {
barWindow: satelliteBarWindow
rootWindow: root.hostWindow
barConfig: root.satelliteConfig
widgetOwner: root
hoverSections: [
{
section: leadingWidgetSection,
name: "left"
},
{
section: trailingWidgetSection,
name: "right"
}
]
leftWidgetsModel: emptyWidgetsModel
centerWidgetsModel: emptyWidgetsModel
rightWidgetsModel: emptyWidgetsModel
}
readonly property bool satelliteHoverTracking: root.visible && componentProvider.hoverPopoutsEnabled && !root.controller.inputSuspended
readonly property bool satellitesHovered: satelliteHoverTracking && (leadingEnvelopeHoverHandler.hovered || trailingEnvelopeHoverHandler.hovered || leadingWidgetHoverHandler.hovered || trailingWidgetHoverHandler.hovered)
onSatellitesHoveredChanged: componentProvider.updateHoverBarHovered(satellitesHovered)
Item {
id: leadingInputEnvelope
@@ -429,6 +454,12 @@ Item {
y: root.isVertical ? alongPos : crossPos
width: root.isVertical ? crossSize : alongSize
height: root.isVertical ? alongSize : crossSize
HoverHandler {
id: leadingEnvelopeHoverHandler
enabled: root.satelliteHoverTracking
onPointChanged: componentProvider.queueHoverFromItem(leadingInputEnvelope, point)
}
}
Item {
@@ -444,6 +475,12 @@ Item {
y: root.isVertical ? alongPos : crossPos
width: root.isVertical ? crossSize : alongSize
height: root.isVertical ? alongSize : crossSize
HoverHandler {
id: trailingEnvelopeHoverHandler
enabled: root.satelliteHoverTracking
onPointChanged: componentProvider.queueHoverFromItem(trailingInputEnvelope, point)
}
}
IslandSatelliteChrome {
@@ -500,8 +537,10 @@ Item {
y: root.isVertical ? alongPos : root.rowCross
width: root.isVertical ? crossSize : alongSize
height: root.isVertical ? alongSize : crossSize
onAlongPosChanged: root.kickBlur()
onAlongSizeChanged: root.kickBlur()
onXChanged: root.onSatelliteRowMoved()
onYChanged: root.onSatelliteRowMoved()
onWidthChanged: root.onSatelliteRowMoved()
onHeightChanged: root.onSatelliteRowMoved()
LeftSection {
id: leadingWidgetSection
@@ -521,6 +560,12 @@ Item {
crossEdgeExtension: root.crossEdgeExtension
edgeIsScreenEdge: root.edgeAligned
}
HoverHandler {
id: leadingWidgetHoverHandler
enabled: root.satelliteHoverTracking
onPointChanged: componentProvider.queueHoverFromItem(leadingInput, point)
}
}
Item {
@@ -534,8 +579,10 @@ Item {
y: root.isVertical ? alongPos : root.rowCross
width: root.isVertical ? crossSize : alongSize
height: root.isVertical ? alongSize : crossSize
onAlongPosChanged: root.kickBlur()
onAlongSizeChanged: root.kickBlur()
onXChanged: root.onSatelliteRowMoved()
onYChanged: root.onSatelliteRowMoved()
onWidthChanged: root.onSatelliteRowMoved()
onHeightChanged: root.onSatelliteRowMoved()
RightSection {
id: trailingWidgetSection
@@ -555,5 +602,11 @@ Item {
crossEdgeExtension: root.crossEdgeExtension
edgeIsScreenEdge: root.edgeAligned
}
HoverHandler {
id: trailingWidgetHoverHandler
enabled: root.satelliteHoverTracking
onPointChanged: componentProvider.queueHoverFromItem(trailingInput, point)
}
}
}