mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-03 11:02:08 -04:00
Compare commits
3 Commits
546cbfb3ca
...
a97409dfd7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a97409dfd7 | ||
|
|
eaa6a664c8 | ||
|
|
d934b3b3b4 |
@@ -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
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user