1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-03 19:12:11 -04:00

Compare commits

..

3 Commits

Author SHA1 Message Date
bbedward
a97409dfd7 window: freeze mask geometry in popout 2026-02-02 16:29:59 -05:00
grokXcopilot
eaa6a664c8 feat(niri): Add drag-and-drop workspace reordering (#1569)
* feat(niri): Add drag-and-drop workspace reordering

Add interactive drag-and-drop reordering for Niri workspace indicators
with smooth animations matching the system tray behavior.

- Add moveWorkspaceToIndex() to NiriService for workspace reordering
- Implement drag detection with 5px threshold
- Add shift animation for items between source and target
- Clamp drag offset to stay within workspace row bounds
- Reset drag state when workspace list changes during drag
- Visual feedback: opacity change, border highlight on drag/drop target

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(settings): Add workspace drag reorder toggle

Add workspaceDragReorder setting to enable/disable workspace
drag-and-drop reordering. Enabled by default, only visible on Niri.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:58:05 -05:00
bbedward
d934b3b3b4 launcher v2: improve search result responsiveness, highlight matches 2026-02-02 12:49:20 -05:00
12 changed files with 394 additions and 73 deletions

View File

@@ -241,6 +241,7 @@ Singleton {
property bool showWorkspacePadding: false
property bool workspaceScrolling: false
property bool showWorkspaceApps: false
property bool workspaceDragReorder: true
property bool groupWorkspaceApps: true
property int maxWorkspaceIcons: 3
property int workspaceAppIconSizeOffset: 0

View File

@@ -98,6 +98,7 @@ var SPEC = {
showWorkspacePadding: { def: false },
workspaceScrolling: { def: false },
showWorkspaceApps: { def: false },
workspaceDragReorder: { def: true },
maxWorkspaceIcons: { def: 3 },
workspaceAppIconSizeOffset: { def: 0 },
groupWorkspaceApps: { def: true },

View File

@@ -26,6 +26,8 @@ Item {
property string activePluginId: ""
property var collapsedSections: ({})
property bool keyboardNavigationActive: false
property var _modeSectionsCache: ({})
property bool _queryDrivenSearch: false
property var sectionViewModes: ({})
property var pluginViewPreferences: ({})
property int gridColumns: SettingsData.appLauncherGridColumns
@@ -42,6 +44,14 @@ Item {
target: SettingsData
function onSortAppsAlphabeticallyChanged() {
AppSearchService.invalidateLauncherCache();
_clearModeCache();
}
}
Connections {
target: AppSearchService
function onCacheVersionChanged() {
_clearModeCache();
}
}
@@ -266,6 +276,7 @@ Item {
function setSearchQuery(query) {
_searchVersion++;
_queryDrivenSearch = true;
searchQuery = query;
searchDebounce.restart();
@@ -324,6 +335,8 @@ Item {
activePluginCategory = "";
pluginFilter = "";
collapsedSections = {};
_clearModeCache();
_queryDrivenSearch = false;
}
function loadPluginCategories(pluginId) {
@@ -369,7 +382,11 @@ Item {
return false;
}
function preserveSelectionAfterUpdate() {
function preserveSelectionAfterUpdate(forceFirst) {
if (forceFirst)
return function () {
return getFirstItemIndex();
};
var previousSelectedId = selectedItem?.id || "";
return function (newFlatModel) {
if (!previousSelectedId)
@@ -385,7 +402,9 @@ Item {
function performSearch() {
var currentVersion = _searchVersion;
isSearching = true;
var restoreSelection = preserveSelectionAfterUpdate();
var shouldResetSelection = _queryDrivenSearch;
_queryDrivenSearch = false;
var restoreSelection = preserveSelectionAfterUpdate(shouldResetSelection);
var cachedSections = AppSearchService.getCachedDefaultSections();
if (cachedSections && !searchQuery && searchMode === "all" && !pluginFilter) {
@@ -394,15 +413,22 @@ Item {
activePluginCategories = [];
activePluginCategory = "";
clearActivePluginViewPreference();
sections = cachedSections.map(function (s) {
var copy = Object.assign({}, s, {
items: s.items ? s.items.slice() : []
var modeCache = _getCachedModeData("all");
if (modeCache) {
sections = modeCache.sections;
flatModel = modeCache.flatModel;
} else {
sections = cachedSections.map(function (s) {
var copy = Object.assign({}, s, {
items: s.items ? s.items.slice() : []
});
if (collapsedSections[s.id] !== undefined)
copy.collapsed = collapsedSections[s.id];
return copy;
});
if (collapsedSections[s.id] !== undefined)
copy.collapsed = collapsedSections[s.id];
return copy;
});
flatModel = Scorer.flattenSections(sections);
flatModel = Scorer.flattenSections(sections);
_setCachedModeData("all", sections, flatModel);
}
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
@@ -475,18 +501,25 @@ Item {
if (searchMode === "apps") {
var cachedSections = AppSearchService.getCachedDefaultSections();
if (cachedSections && !searchQuery) {
var appSectionIds = ["favorites", "apps"];
sections = cachedSections.filter(function (s) {
return appSectionIds.indexOf(s.id) !== -1;
}).map(function (s) {
var copy = Object.assign({}, s, {
items: s.items ? s.items.slice() : []
var modeCache = _getCachedModeData("apps");
if (modeCache) {
sections = modeCache.sections;
flatModel = modeCache.flatModel;
} else {
var appSectionIds = ["favorites", "apps"];
sections = cachedSections.filter(function (s) {
return appSectionIds.indexOf(s.id) !== -1;
}).map(function (s) {
var copy = Object.assign({}, s, {
items: s.items ? s.items.slice() : []
});
if (collapsedSections[s.id] !== undefined)
copy.collapsed = collapsedSections[s.id];
return copy;
});
if (collapsedSections[s.id] !== undefined)
copy.collapsed = collapsedSections[s.id];
return copy;
});
flatModel = Scorer.flattenSections(sections);
flatModel = Scorer.flattenSections(sections);
_setCachedModeData("apps", sections, flatModel);
}
selectedFlatIndex = restoreSelection(flatModel);
updateSelectedItem();
isSearching = false;
@@ -1055,6 +1088,23 @@ Item {
return Nav.getFirstItemIndex(flatModel);
}
function _getCachedModeData(mode) {
return _modeSectionsCache[mode] || null;
}
function _setCachedModeData(mode, sectionsData, flatModelData) {
var cache = Object.assign({}, _modeSectionsCache);
cache[mode] = {
sections: sectionsData,
flatModel: flatModelData
};
_modeSectionsCache = cache;
}
function _clearModeCache() {
_modeSectionsCache = {};
}
function updateSelectedItem() {
if (selectedFlatIndex >= 0 && selectedFlatIndex < flatModel.length) {
var entry = flatModel[selectedFlatIndex];
@@ -1158,6 +1208,7 @@ Item {
}
function toggleSection(sectionId) {
_clearModeCache();
var newCollapsed = Object.assign({}, collapsedSections);
var currentState = newCollapsed[sectionId];

View File

@@ -90,6 +90,8 @@ Item {
spotlightContent.controller.activePluginName = "";
spotlightContent.controller.pluginFilter = "";
spotlightContent.controller.collapsedSections = {};
spotlightContent.controller.selectedFlatIndex = 0;
spotlightContent.controller.selectedItem = null;
if (query) {
spotlightContent.controller.setSearchQuery(query);
} else {

View File

@@ -35,6 +35,21 @@ Rectangle {
readonly property int computedIconSize: Math.min(48, Math.max(32, width * 0.45))
function highlightText(text, query, baseColor) {
if (!text || !query || query.length === 0)
return text;
var lowerText = text.toLowerCase();
var lowerQuery = query.toLowerCase();
var idx = lowerText.indexOf(lowerQuery);
if (idx === -1)
return text;
var before = text.substring(0, idx);
var match = text.substring(idx, idx + query.length);
var after = text.substring(idx + query.length);
var highlightColor = Theme.primary;
return '<span style="color:' + baseColor + '">' + before + '</span>' + '<span style="color:' + highlightColor + '; font-weight:600">' + match + '</span>' + '<span style="color:' + baseColor + '">' + after + '</span>';
}
radius: Theme.cornerRadius
color: isSelected ? Theme.primaryPressed : isHovered ? Theme.primaryHoverLight : "transparent"
@@ -55,11 +70,20 @@ Rectangle {
materialIconSizeAdjustment: root.computedIconSize * 0.3
}
StyledText {
Text {
width: parent.width
text: root.item?.name ?? ""
text: {
var query = root.controller?.searchQuery ?? "";
var name = root.item?.name ?? "";
var baseColor = root.isSelected ? Theme.primary : Theme.surfaceText;
if (!query)
return name;
return root.highlightText(name, query, baseColor);
}
textFormat: root.controller?.searchQuery ? Text.RichText : Text.PlainText
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
font.family: Theme.fontFamily
color: root.isSelected ? Theme.primary : Theme.surfaceText
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter

View File

@@ -33,6 +33,21 @@ Rectangle {
}
}
function highlightText(text, query, baseColor) {
if (!text || !query || query.length === 0)
return text;
var lowerText = text.toLowerCase();
var lowerQuery = query.toLowerCase();
var idx = lowerText.indexOf(lowerQuery);
if (idx === -1)
return text;
var before = text.substring(0, idx);
var match = text.substring(idx, idx + query.length);
var after = text.substring(idx + query.length);
var highlightColor = Theme.primary;
return '<span style="color:' + baseColor + '">' + before + '</span>' + '<span style="color:' + highlightColor + '; font-weight:600">' + match + '</span>' + '<span style="color:' + baseColor + '">' + after + '</span>';
}
width: parent?.width ?? 200
height: 52
color: isSelected ? Theme.primaryPressed : isHovered ? Theme.primaryHoverLight : "transparent"
@@ -82,23 +97,41 @@ Rectangle {
width: parent.width - 36 - Theme.spacingM * 3 - rightContent.width
spacing: 2
StyledText {
Text {
width: parent.width
text: root.item?.name ?? ""
text: {
var query = root.controller?.searchQuery ?? "";
var name = root.item?.name ?? "";
if (!query)
return name;
return root.highlightText(name, query, Theme.surfaceText);
}
textFormat: root.controller?.searchQuery ? Text.RichText : Text.PlainText
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
font.family: Theme.fontFamily
color: Theme.surfaceText
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
StyledText {
Text {
width: parent.width
text: root.item?.subtitle ?? ""
text: {
var query = root.controller?.searchQuery ?? "";
var subtitle = root.item?.subtitle ?? "";
if (!subtitle)
return "";
if (!query)
return subtitle;
return root.highlightText(subtitle, query, Theme.surfaceVariantText);
}
textFormat: root.controller?.searchQuery ? Text.RichText : Text.PlainText
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
color: Theme.surfaceVariantText
elide: Text.ElideRight
visible: text.length > 0
visible: (root.item?.subtitle ?? "").length > 0
horizontalAlignment: Text.AlignLeft
}
}

View File

@@ -23,6 +23,21 @@ Rectangle {
border.width: isSelected ? 2 : 0
border.color: Theme.primary
function highlightText(text, query, baseColor) {
if (!text || !query || query.length === 0)
return text;
var lowerText = text.toLowerCase();
var lowerQuery = query.toLowerCase();
var idx = lowerText.indexOf(lowerQuery);
if (idx === -1)
return text;
var before = text.substring(0, idx);
var match = text.substring(idx, idx + query.length);
var after = text.substring(idx + query.length);
var highlightColor = Theme.primary;
return '<span style="color:' + baseColor + '">' + before + '</span>' + '<span style="color:' + highlightColor + '; font-weight:600">' + match + '</span>' + '<span style="color:' + baseColor + '">' + after + '</span>';
}
readonly property string toplevelId: item?.data?.toplevelId ?? ""
readonly property var waylandToplevel: {
if (!toplevelId || !item?.pluginId)
@@ -108,12 +123,20 @@ Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, 0.85)
visible: root.item?.name?.length > 0
StyledText {
Text {
id: labelText
anchors.fill: parent
anchors.margins: Theme.spacingXS
text: root.item?.name ?? ""
text: {
var query = root.controller?.searchQuery ?? "";
var name = root.item?.name ?? "";
if (!query)
return name;
return root.highlightText(name, query, Theme.surfaceText);
}
textFormat: root.controller?.searchQuery ? Text.RichText : Text.PlainText
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
color: Theme.surfaceText
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter

View File

@@ -32,7 +32,7 @@ DankPopout {
}
popupWidth: 400
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 400
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 0
triggerWidth: 70
positioning: ""
screen: triggerScreen

View File

@@ -789,6 +789,18 @@ Item {
}
}
property int dragSourceIndex: -1
property int dragTargetIndex: -1
property bool suppressShiftAnimation: false
onWorkspaceListChanged: {
if (dragSourceIndex >= 0) {
dragSourceIndex = -1;
dragTargetIndex = -1;
suppressShiftAnimation = false;
}
}
Flow {
id: workspaceRow
@@ -798,6 +810,7 @@ Item {
flow: isVertical ? Flow.TopToBottom : Flow.LeftToRight
Repeater {
id: workspaceRepeater
model: ScriptModel {
values: root.workspaceList
}
@@ -805,6 +818,44 @@ Item {
Item {
id: delegateRoot
property bool isDropTarget: root.dragTargetIndex === index
z: dragHandler.dragging ? 1000 : 1
property real shiftOffset: {
if (root.dragSourceIndex < 0 || index === root.dragSourceIndex)
return 0;
const dragIdx = root.dragSourceIndex;
const dropIdx = root.dragTargetIndex;
if (dropIdx < 0)
return 0;
const shiftAmount = delegateRoot.width + Theme.spacingS;
if (dragIdx < dropIdx && index > dragIdx && index <= dropIdx)
return -shiftAmount;
if (dragIdx > dropIdx && index >= dropIdx && index < dragIdx)
return shiftAmount;
return 0;
}
transform: Translate {
x: root.isVertical ? 0 : delegateRoot.shiftOffset
y: root.isVertical ? delegateRoot.shiftOffset : 0
Behavior on x {
enabled: !root.suppressShiftAnimation
NumberAnimation {
duration: 150
easing.type: Easing.OutCubic
}
}
Behavior on y {
enabled: !root.suppressShiftAnimation
NumberAnimation {
duration: 150
easing.type: Easing.OutCubic
}
}
}
property bool isActive: {
if (root.useExtWorkspace)
return (modelData?.id || modelData?.name) === root.currentWorkspace;
@@ -1031,45 +1082,126 @@ Item {
readonly property color quickshellIconActiveColor: getContrastingIconColor(activeColor)
readonly property color quickshellIconInactiveColor: getContrastingIconColor(unfocusedColor)
Item {
id: dragHandler
anchors.fill: parent
property bool dragging: false
property point dragStartPos: Qt.point(0, 0)
property real dragAxisOffset: 0
Connections {
target: root
function onWorkspaceListChanged() {
if (dragHandler.dragging) {
dragHandler.dragging = false;
dragHandler.dragAxisOffset = 0;
mouseArea.mousePressed = false;
}
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: !isPlaceholder
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
cursorShape: isPlaceholder ? Qt.ArrowCursor : (dragHandler.dragging ? Qt.ClosedHandCursor : Qt.PointingHandCursor)
enabled: !isPlaceholder
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: mouse => {
if (isPlaceholder)
return;
const isRightClick = mouse.button === Qt.RightButton;
if (root.useExtWorkspace && (modelData?.id || modelData?.name)) {
ExtWorkspaceService.activateWorkspace(modelData.id || modelData.name, modelData.groupID || "");
} else if (CompositorService.isNiri) {
if (isRightClick) {
NiriService.toggleOverview();
} else if (modelData && modelData.idx !== undefined) {
NiriService.switchToWorkspace(modelData.idx);
property bool mousePressed: false
onPressed: mouse => {
if (mouse.button === Qt.LeftButton && CompositorService.isNiri && SettingsData.workspaceDragReorder && !isPlaceholder) {
mousePressed = true;
dragHandler.dragStartPos = Qt.point(mouse.x, mouse.y);
}
}
onPositionChanged: mouse => {
if (!mousePressed || !CompositorService.isNiri || !SettingsData.workspaceDragReorder || isPlaceholder)
return;
if (!dragHandler.dragging) {
const distance = root.isVertical
? Math.abs(mouse.y - dragHandler.dragStartPos.y)
: Math.abs(mouse.x - dragHandler.dragStartPos.x);
if (distance > 5) {
dragHandler.dragging = true;
root.dragSourceIndex = index;
root.dragTargetIndex = index;
}
} else if (CompositorService.isHyprland && modelData?.id) {
if (isRightClick && root.hyprlandOverviewLoader?.item) {
root.hyprlandOverviewLoader.item.overviewOpen = !root.hyprlandOverviewLoader.item.overviewOpen;
} else {
}
if (!dragHandler.dragging)
return;
const rawAxisOffset = root.isVertical
? (mouse.y - dragHandler.dragStartPos.y)
: (mouse.x - dragHandler.dragStartPos.x);
const itemSize = (root.isVertical ? delegateRoot.height : delegateRoot.width) + Theme.spacingS;
const maxOffsetPositive = (root.workspaceList.length - 1 - index) * itemSize;
const maxOffsetNegative = -index * itemSize;
const axisOffset = Math.max(maxOffsetNegative, Math.min(maxOffsetPositive, rawAxisOffset));
dragHandler.dragAxisOffset = axisOffset;
const slotOffset = Math.round(axisOffset / itemSize);
const newTargetIndex = Math.max(0, Math.min(root.workspaceList.length - 1, index + slotOffset));
if (newTargetIndex !== root.dragTargetIndex) {
root.dragTargetIndex = newTargetIndex;
}
}
onReleased: mouse => {
const wasDragging = dragHandler.dragging;
const didReorder = wasDragging && root.dragTargetIndex >= 0 && root.dragTargetIndex !== root.dragSourceIndex;
if (didReorder) {
const sourceWs = root.workspaceList[root.dragSourceIndex];
const targetWs = root.workspaceList[root.dragTargetIndex];
if (sourceWs && targetWs && sourceWs.idx !== undefined && targetWs.idx !== undefined) {
root.suppressShiftAnimation = true;
NiriService.moveWorkspaceToIndex(sourceWs.idx, targetWs.idx);
Qt.callLater(() => root.suppressShiftAnimation = false);
}
}
mousePressed = false;
dragHandler.dragging = false;
dragHandler.dragAxisOffset = 0;
root.dragSourceIndex = -1;
root.dragTargetIndex = -1;
if (wasDragging || isPlaceholder)
return;
if (mouse.button === Qt.LeftButton) {
if (root.useExtWorkspace && (modelData?.id || modelData?.name)) {
ExtWorkspaceService.activateWorkspace(modelData.id || modelData.name, modelData.groupID || "");
} else if (CompositorService.isNiri) {
if (modelData && modelData.idx !== undefined) {
NiriService.switchToWorkspace(modelData.idx);
}
} else if (CompositorService.isHyprland && modelData?.id) {
Hyprland.dispatch(`workspace ${modelData.id}`);
}
} else if (CompositorService.isDwl && modelData?.tag !== undefined) {
console.log("DWL click - tag:", modelData.tag, "rightClick:", isRightClick);
if (isRightClick) {
console.log("Calling toggleTag");
DwlService.toggleTag(root.screenName, modelData.tag);
} else {
console.log("Calling switchToTag");
} else if (CompositorService.isDwl && modelData?.tag !== undefined) {
DwlService.switchToTag(root.screenName, modelData.tag);
} else if ((CompositorService.isSway || CompositorService.isScroll) && modelData?.num) {
try {
I3.dispatch(`workspace number ${modelData.num}`);
} catch (_) {}
}
} else if (mouse.button === Qt.RightButton) {
if (CompositorService.isNiri) {
NiriService.toggleOverview();
} else if (CompositorService.isHyprland && root.hyprlandOverviewLoader?.item) {
root.hyprlandOverviewLoader.item.overviewOpen = !root.hyprlandOverviewLoader.item.overviewOpen;
} else if (CompositorService.isDwl && modelData?.tag !== undefined) {
DwlService.toggleTag(root.screenName, modelData.tag);
}
} else if ((CompositorService.isSway || CompositorService.isScroll) && modelData?.num) {
try {
I3.dispatch(`workspace number ${modelData.num}`);
} catch (_) {}
}
}
}
@@ -1203,9 +1335,22 @@ Item {
y: root.isVertical ? (parent.height - height) / 2 : (root.widgetHeight - height) / 2
radius: Theme.cornerRadius
color: isActive ? activeColor : isUrgent ? urgentColor : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.withAlpha(unfocusedColor, 0.7) : isOccupied ? occupiedColor : unfocusedColor
opacity: dragHandler.dragging ? 0.8 : 1.0
border.width: isUrgent ? 2 : 0
border.color: isUrgent ? urgentColor : "transparent"
border.width: dragHandler.dragging ? 2 : (isUrgent ? 2 : (isDropTarget ? 2 : 0))
border.color: dragHandler.dragging ? Theme.primary : (isUrgent ? urgentColor : (isDropTarget ? Theme.primary : "transparent"))
transform: Translate {
x: root.isVertical ? 0 : (dragHandler.dragging ? dragHandler.dragAxisOffset : 0)
y: root.isVertical ? (dragHandler.dragging ? dragHandler.dragAxisOffset : 0) : 0
}
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on width {
NumberAnimation {

View File

@@ -155,6 +155,16 @@ Item {
onToggled: checked => SettingsData.set("reverseScrolling", checked)
}
SettingsToggleRow {
settingKey: "workspaceDragReorder"
tags: ["workspace", "drag", "reorder", "sort", "move"]
text: I18n.tr("Drag to Reorder")
description: I18n.tr("Drag workspace indicators to reorder them")
checked: SettingsData.workspaceDragReorder
visible: CompositorService.isNiri
onToggled: checked => SettingsData.set("workspaceDragReorder", checked)
}
SettingsToggleRow {
settingKey: "dwlShowAllTags"
tags: ["dwl", "tags", "workspace"]

View File

@@ -1452,6 +1452,19 @@ Singleton {
});
}
function moveWorkspaceToIndex(workspaceIdx, targetIndex) {
return send({
"Action": {
"MoveWorkspaceToIndex": {
"index": targetIndex,
"reference": {
"Index": workspaceIdx
}
}
}
});
}
IpcHandler {
function screenshot(): string {
if (!CompositorService.isNiri) {

View File

@@ -74,6 +74,12 @@ Item {
property int effectiveBarPosition: 0
property real effectiveBarBottomGap: 0
// Snapshot mask geometry to prevent background damage on bar updates
property real _frozenMaskX: 0
property real _frozenMaskY: 0
property real _frozenMaskWidth: 0
property real _frozenMaskHeight: 0
function setBarContext(position, bottomGap) {
effectiveBarPosition = position !== undefined ? position : 0;
effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0;
@@ -104,6 +110,12 @@ Item {
return;
closeTimer.stop();
// Snapshot mask geometry
_frozenMaskX = maskX;
_frozenMaskY = maskY;
_frozenMaskWidth = maskWidth;
_frozenMaskHeight = maskHeight;
if (_lastOpenedScreen !== null && _lastOpenedScreen !== screen) {
contentWindow.visible = false;
if (useBackgroundWindow)
@@ -236,24 +248,30 @@ Item {
}
mask: Region {
item: Rectangle {
x: root.maskX
y: root.maskY
width: (shouldBeVisible && backgroundInteractive) ? root.maskWidth : 0
height: (shouldBeVisible && backgroundInteractive) ? root.maskHeight : 0
}
item: maskRect
}
Rectangle {
id: maskRect
visible: false
color: "transparent"
x: root._frozenMaskX
y: root._frozenMaskY
width: (shouldBeVisible && backgroundInteractive) ? root._frozenMaskWidth : 0
height: (shouldBeVisible && backgroundInteractive) ? root._frozenMaskHeight : 0
}
MouseArea {
x: root.maskX
y: root.maskY
width: root.maskWidth
height: root.maskHeight
x: root._frozenMaskX
y: root._frozenMaskY
width: root._frozenMaskWidth
height: root._frozenMaskHeight
hoverEnabled: false
enabled: shouldBeVisible && backgroundInteractive
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: mouse => {
const clickX = mouse.x + root.maskX;
const clickY = mouse.y + root.maskY;
const clickX = mouse.x + root._frozenMaskX;
const clickY = mouse.y + root._frozenMaskY;
const outsideContent = clickX < root.alignedX || clickX > root.alignedX + root.alignedWidth || clickY < root.alignedY || clickY > root.alignedY + root.alignedHeight;
if (!outsideContent)