mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-16 02:32:09 -04:00
(frame): QOL Control Center & Notification updates
This commit is contained in:
@@ -115,6 +115,32 @@ Singleton {
|
||||
return true;
|
||||
}
|
||||
|
||||
function setPopoutBody(claimId, bodyX, bodyY, bodyW, bodyH) {
|
||||
if (!hasPopoutOwner(claimId))
|
||||
return false;
|
||||
if (bodyX !== undefined) {
|
||||
const nextX = Number(bodyX);
|
||||
if (!isNaN(nextX) && popoutBodyX !== nextX)
|
||||
popoutBodyX = nextX;
|
||||
}
|
||||
if (bodyY !== undefined) {
|
||||
const nextY = Number(bodyY);
|
||||
if (!isNaN(nextY) && popoutBodyY !== nextY)
|
||||
popoutBodyY = nextY;
|
||||
}
|
||||
if (bodyW !== undefined) {
|
||||
const nextW = Number(bodyW);
|
||||
if (!isNaN(nextW) && popoutBodyW !== nextW)
|
||||
popoutBodyW = nextW;
|
||||
}
|
||||
if (bodyH !== undefined) {
|
||||
const nextH = Number(bodyH);
|
||||
if (!isNaN(nextH) && popoutBodyH !== nextH)
|
||||
popoutBodyH = nextH;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function _cloneDockStates() {
|
||||
const next = {};
|
||||
for (const screenName in dockStates)
|
||||
|
||||
@@ -37,7 +37,7 @@ Item {
|
||||
Loader {
|
||||
id: pluginDetailLoader
|
||||
width: parent.width
|
||||
height: parent.height - Theme.spacingS
|
||||
height: Math.max(0, parent.height - Theme.spacingS)
|
||||
y: Theme.spacingS
|
||||
active: false
|
||||
sourceComponent: null
|
||||
@@ -46,7 +46,7 @@ Item {
|
||||
Loader {
|
||||
id: coreDetailLoader
|
||||
width: parent.width
|
||||
height: parent.height - Theme.spacingS
|
||||
height: Math.max(0, parent.height - Theme.spacingS)
|
||||
y: Theme.spacingS
|
||||
active: false
|
||||
sourceComponent: null
|
||||
@@ -134,7 +134,7 @@ Item {
|
||||
}
|
||||
|
||||
pluginDetailLoader.sourceComponent = builtinInstance.ccDetailContent;
|
||||
pluginDetailLoader.active = parent.height > 0;
|
||||
pluginDetailLoader.active = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -155,19 +155,19 @@ Item {
|
||||
}
|
||||
|
||||
pluginDetailLoader.sourceComponent = pluginDetailInstance.ccDetailContent;
|
||||
pluginDetailLoader.active = parent.height > 0;
|
||||
pluginDetailLoader.active = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (root.expandedSection.startsWith("diskUsage_")) {
|
||||
coreDetailLoader.sourceComponent = diskUsageDetailComponent;
|
||||
coreDetailLoader.active = parent.height > 0;
|
||||
coreDetailLoader.active = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (root.expandedSection.startsWith("brightnessSlider_")) {
|
||||
coreDetailLoader.sourceComponent = brightnessDetailComponent;
|
||||
coreDetailLoader.active = parent.height > 0;
|
||||
coreDetailLoader.active = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ Item {
|
||||
return;
|
||||
}
|
||||
|
||||
coreDetailLoader.active = parent.height > 0;
|
||||
coreDetailLoader.active = true;
|
||||
}
|
||||
|
||||
Component {
|
||||
|
||||
@@ -51,6 +51,35 @@ Column {
|
||||
return Math.max(100, maxPopoutHeight - totalRowHeight - rowSpacing);
|
||||
}
|
||||
|
||||
readonly property real targetImplicitHeight: {
|
||||
const rows = layoutResult.rows;
|
||||
let totalHeight = 0;
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const widgets = rows[i] || [];
|
||||
const sliderOnly = widgets.length > 0 && widgets.every(w => {
|
||||
const id = w.id || "";
|
||||
return id === "volumeSlider" || id === "brightnessSlider" || id === "inputVolumeSlider";
|
||||
});
|
||||
totalHeight += sliderOnly ? (editMode ? 56 : 36) : 60;
|
||||
if (expandedSection !== "" && i === expandedRowIndex)
|
||||
totalHeight += detailHeightForSection(expandedSection) + Theme.spacingS;
|
||||
}
|
||||
totalHeight += Math.max(0, rows.length - 1) * spacing;
|
||||
return totalHeight;
|
||||
}
|
||||
|
||||
function detailHeightForSection(section) {
|
||||
if (!section)
|
||||
return 0;
|
||||
if (section === "wifi" || section === "bluetooth" || section === "builtin_vpn")
|
||||
return Math.min(350, _maxDetailHeight);
|
||||
if (section.startsWith("brightnessSlider_"))
|
||||
return Math.min(400, _maxDetailHeight);
|
||||
if (section.startsWith("plugin_"))
|
||||
return Math.min(250, _maxDetailHeight);
|
||||
return Math.min(250, _maxDetailHeight);
|
||||
}
|
||||
|
||||
function calculateRowsAndWidgets() {
|
||||
return LayoutUtils.calculateRowsAndWidgets(root, expandedSection, expandedWidgetIndex);
|
||||
}
|
||||
@@ -179,7 +208,10 @@ Column {
|
||||
id: detailHost
|
||||
width: parent.width
|
||||
maxAvailableHeight: root._maxDetailHeight
|
||||
height: active ? (getDetailHeight(root.expandedSection) + Theme.spacingS) : 0
|
||||
height: active ? (root.detailHeightForSection(root.expandedSection) + Theme.spacingS) : 0
|
||||
clip: true
|
||||
property string retainedSection: ""
|
||||
property var retainedWidgetData: null
|
||||
property bool active: {
|
||||
if (root.expandedSection === "")
|
||||
return false;
|
||||
@@ -196,14 +228,47 @@ Column {
|
||||
|
||||
return rowIndex === root.expandedRowIndex;
|
||||
}
|
||||
visible: active
|
||||
expandedSection: root.expandedSection
|
||||
expandedWidgetData: root.expandedWidgetData
|
||||
visible: active || height > 0.5
|
||||
expandedSection: active ? root.expandedSection : retainedSection
|
||||
expandedWidgetData: active ? root.expandedWidgetData : retainedWidgetData
|
||||
bluetoothCodecSelector: root.bluetoothCodecSelector
|
||||
widgetModel: root.model
|
||||
collapseCallback: root.requestCollapse
|
||||
screenName: root.screenName
|
||||
screenModel: root.screenModel
|
||||
|
||||
function retainActiveDetail() {
|
||||
if (!active || !root.expandedSection)
|
||||
return;
|
||||
retainedSection = root.expandedSection;
|
||||
retainedWidgetData = root.expandedWidgetData;
|
||||
}
|
||||
|
||||
onActiveChanged: retainActiveDetail()
|
||||
onHeightChanged: {
|
||||
if (!active && height <= 0.5) {
|
||||
retainedSection = "";
|
||||
retainedWidgetData = null;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onExpandedSectionChanged() {
|
||||
detailHost.retainActiveDetail();
|
||||
}
|
||||
function onExpandedWidgetDataChanged() {
|
||||
detailHost.retainActiveDetail();
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.variantDuration(Theme.popoutAnimationDuration, detailHost.active)
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: detailHost.active ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,19 +20,53 @@ DankPopout {
|
||||
property int expandedWidgetIndex: -1
|
||||
property var expandedWidgetData: null
|
||||
property bool powerMenuOpen: powerMenuModalLoader?.item?.shouldBeVisible ?? false
|
||||
property real targetPopupHeight: 400
|
||||
property bool _heightUpdatePending: false
|
||||
|
||||
signal lockRequested
|
||||
|
||||
function _maxPopupHeight() {
|
||||
const screenHeight = (triggerScreen?.height ?? 1080);
|
||||
return screenHeight - 100;
|
||||
}
|
||||
|
||||
function _contentTargetHeight() {
|
||||
const item = contentLoader.item;
|
||||
if (!item)
|
||||
return 400;
|
||||
const naturalHeight = item.targetImplicitHeight !== undefined ? item.targetImplicitHeight : item.implicitHeight;
|
||||
return Math.max(300, naturalHeight + 20);
|
||||
}
|
||||
|
||||
function updateTargetPopupHeight() {
|
||||
const target = Math.min(_maxPopupHeight(), _contentTargetHeight());
|
||||
if (Math.abs(targetPopupHeight - target) < 0.5)
|
||||
return;
|
||||
targetPopupHeight = target;
|
||||
}
|
||||
|
||||
function queueTargetPopupHeightUpdate() {
|
||||
if (_heightUpdatePending)
|
||||
return;
|
||||
_heightUpdatePending = true;
|
||||
Qt.callLater(() => {
|
||||
_heightUpdatePending = false;
|
||||
updateTargetPopupHeight();
|
||||
});
|
||||
}
|
||||
|
||||
function collapseAll() {
|
||||
expandedSection = "";
|
||||
expandedWidgetIndex = -1;
|
||||
expandedWidgetData = null;
|
||||
queueTargetPopupHeightUpdate();
|
||||
}
|
||||
|
||||
onEditModeChanged: {
|
||||
if (editMode) {
|
||||
collapseAll();
|
||||
}
|
||||
queueTargetPopupHeightUpdate();
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
@@ -52,12 +86,7 @@ DankPopout {
|
||||
}
|
||||
|
||||
popupWidth: 550
|
||||
popupHeight: {
|
||||
const screenHeight = (triggerScreen?.height ?? 1080);
|
||||
const maxHeight = screenHeight - 100;
|
||||
const contentHeight = contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400;
|
||||
return Math.min(maxHeight, contentHeight);
|
||||
}
|
||||
popupHeight: targetPopupHeight
|
||||
triggerWidth: 80
|
||||
positioning: ""
|
||||
screen: triggerScreen
|
||||
@@ -95,6 +124,7 @@ DankPopout {
|
||||
onShouldBeVisibleChanged: {
|
||||
if (shouldBeVisible) {
|
||||
collapseAll();
|
||||
queueTargetPopupHeightUpdate();
|
||||
Qt.callLater(() => {
|
||||
if (NetworkService.activeService)
|
||||
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled;
|
||||
@@ -111,6 +141,28 @@ DankPopout {
|
||||
}
|
||||
}
|
||||
|
||||
onExpandedSectionChanged: queueTargetPopupHeightUpdate()
|
||||
onExpandedWidgetIndexChanged: queueTargetPopupHeightUpdate()
|
||||
onTriggerScreenChanged: queueTargetPopupHeightUpdate()
|
||||
|
||||
Connections {
|
||||
target: contentLoader
|
||||
function onLoaded() {
|
||||
root.queueTargetPopupHeightUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: contentLoader.item
|
||||
ignoreUnknownSignals: true
|
||||
function onTargetImplicitHeightChanged() {
|
||||
root.queueTargetPopupHeightUpdate();
|
||||
}
|
||||
function onImplicitHeightChanged() {
|
||||
root.queueTargetPopupHeightUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
WidgetModel {
|
||||
id: widgetModel
|
||||
}
|
||||
@@ -122,7 +174,13 @@ DankPopout {
|
||||
LayoutMirroring.enabled: I18n.isRtl
|
||||
LayoutMirroring.childrenInherit: true
|
||||
|
||||
implicitHeight: mainColumn.implicitHeight + Theme.spacingM
|
||||
readonly property real targetImplicitHeight: {
|
||||
let total = headerPane.implicitHeight + Theme.spacingS + widgetGrid.targetImplicitHeight;
|
||||
if (editControls.visible)
|
||||
total += Theme.spacingS + editControls.height;
|
||||
return total + Theme.spacingM;
|
||||
}
|
||||
implicitHeight: targetImplicitHeight
|
||||
property alias bluetoothCodecSelector: bluetoothCodecSelector
|
||||
|
||||
color: "transparent"
|
||||
@@ -145,84 +203,94 @@ DankPopout {
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
width: parent.width - Theme.spacingL * 2
|
||||
x: Theme.spacingL
|
||||
y: Theme.spacingL
|
||||
spacing: Theme.spacingS
|
||||
DankFlickable {
|
||||
id: contentFlickable
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
contentWidth: width
|
||||
contentHeight: Math.max(height, mainColumn.implicitHeight + Theme.spacingM)
|
||||
interactive: contentHeight > height
|
||||
|
||||
HeaderPane {
|
||||
id: headerPane
|
||||
width: parent.width
|
||||
editMode: root.editMode
|
||||
onEditModeToggled: root.editMode = !root.editMode
|
||||
onPowerButtonClicked: {
|
||||
if (powerMenuModalLoader) {
|
||||
powerMenuModalLoader.active = true;
|
||||
if (powerMenuModalLoader.item) {
|
||||
const bounds = Qt.rect(root.alignedX, root.alignedY, root.popupWidth, root.popupHeight);
|
||||
powerMenuModalLoader.item.openFromControlCenter(bounds, root.screen);
|
||||
Column {
|
||||
id: mainColumn
|
||||
width: contentFlickable.width - Theme.spacingL * 2
|
||||
x: Theme.spacingL
|
||||
y: Theme.spacingL
|
||||
spacing: Theme.spacingS
|
||||
|
||||
HeaderPane {
|
||||
id: headerPane
|
||||
width: parent.width
|
||||
editMode: root.editMode
|
||||
onEditModeToggled: root.editMode = !root.editMode
|
||||
onPowerButtonClicked: {
|
||||
if (powerMenuModalLoader) {
|
||||
powerMenuModalLoader.active = true;
|
||||
if (powerMenuModalLoader.item) {
|
||||
const bounds = Qt.rect(root.alignedX, root.alignedY, root.popupWidth, root.popupHeight);
|
||||
powerMenuModalLoader.item.openFromControlCenter(bounds, root.screen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onLockRequested: {
|
||||
root.close();
|
||||
root.lockRequested();
|
||||
}
|
||||
onSettingsButtonClicked: {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
DragDropGrid {
|
||||
id: widgetGrid
|
||||
width: parent.width
|
||||
editMode: root.editMode
|
||||
maxPopoutHeight: {
|
||||
const screenHeight = (root.triggerScreen?.height ?? 1080);
|
||||
return screenHeight - 100 - Theme.spacingL - headerPane.height - Theme.spacingS;
|
||||
}
|
||||
expandedSection: root.expandedSection
|
||||
expandedWidgetIndex: root.expandedWidgetIndex
|
||||
expandedWidgetData: root.expandedWidgetData
|
||||
model: widgetModel
|
||||
bluetoothCodecSelector: bluetoothCodecSelector
|
||||
colorPickerModal: root.colorPickerModal
|
||||
screenName: root.triggerScreen?.name || ""
|
||||
screenModel: root.triggerScreen?.model || ""
|
||||
parentScreen: root.triggerScreen
|
||||
onExpandClicked: (widgetData, globalIndex) => {
|
||||
root.expandedWidgetIndex = globalIndex;
|
||||
root.expandedWidgetData = widgetData;
|
||||
if (widgetData.id === "diskUsage") {
|
||||
root.toggleSection("diskUsage_" + (widgetData.instanceId || "default"));
|
||||
} else if (widgetData.id === "brightnessSlider") {
|
||||
root.toggleSection("brightnessSlider_" + (widgetData.instanceId || "default"));
|
||||
} else {
|
||||
root.toggleSection(widgetData.id);
|
||||
onLockRequested: {
|
||||
root.close();
|
||||
root.lockRequested();
|
||||
}
|
||||
onSettingsButtonClicked: {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
onRemoveWidget: index => widgetModel.removeWidget(index)
|
||||
onMoveWidget: (fromIndex, toIndex) => widgetModel.moveWidget(fromIndex, toIndex)
|
||||
onToggleWidgetSize: index => widgetModel.toggleWidgetSize(index)
|
||||
onCollapseRequested: root.collapseAll()
|
||||
}
|
||||
|
||||
EditControls {
|
||||
width: parent.width
|
||||
visible: editMode
|
||||
popoutContent: controlContent
|
||||
availableWidgets: {
|
||||
if (!editMode)
|
||||
return [];
|
||||
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id);
|
||||
const allWidgets = widgetModel.baseWidgetDefinitions.concat(widgetModel.getPluginWidgets());
|
||||
return allWidgets.filter(w => w.allowMultiple || !existingIds.includes(w.id));
|
||||
DragDropGrid {
|
||||
id: widgetGrid
|
||||
width: parent.width
|
||||
editMode: root.editMode
|
||||
maxPopoutHeight: {
|
||||
const screenHeight = (root.triggerScreen?.height ?? 1080);
|
||||
return screenHeight - 100 - Theme.spacingL - headerPane.implicitHeight - Theme.spacingS;
|
||||
}
|
||||
expandedSection: root.expandedSection
|
||||
expandedWidgetIndex: root.expandedWidgetIndex
|
||||
expandedWidgetData: root.expandedWidgetData
|
||||
model: widgetModel
|
||||
bluetoothCodecSelector: bluetoothCodecSelector
|
||||
colorPickerModal: root.colorPickerModal
|
||||
screenName: root.triggerScreen?.name || ""
|
||||
screenModel: root.triggerScreen?.model || ""
|
||||
parentScreen: root.triggerScreen
|
||||
onExpandClicked: (widgetData, globalIndex) => {
|
||||
root.expandedWidgetIndex = globalIndex;
|
||||
root.expandedWidgetData = widgetData;
|
||||
if (widgetData.id === "diskUsage") {
|
||||
root.toggleSection("diskUsage_" + (widgetData.instanceId || "default"));
|
||||
} else if (widgetData.id === "brightnessSlider") {
|
||||
root.toggleSection("brightnessSlider_" + (widgetData.instanceId || "default"));
|
||||
} else {
|
||||
root.toggleSection(widgetData.id);
|
||||
}
|
||||
}
|
||||
onRemoveWidget: index => widgetModel.removeWidget(index)
|
||||
onMoveWidget: (fromIndex, toIndex) => widgetModel.moveWidget(fromIndex, toIndex)
|
||||
onToggleWidgetSize: index => widgetModel.toggleWidgetSize(index)
|
||||
onCollapseRequested: root.collapseAll()
|
||||
}
|
||||
|
||||
EditControls {
|
||||
id: editControls
|
||||
width: parent.width
|
||||
visible: editMode
|
||||
popoutContent: controlContent
|
||||
availableWidgets: {
|
||||
if (!editMode)
|
||||
return [];
|
||||
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id);
|
||||
const allWidgets = widgetModel.baseWidgetDefinitions.concat(widgetModel.getPluginWidgets());
|
||||
return allWidgets.filter(w => w.allowMultiple || !existingIds.includes(w.id));
|
||||
}
|
||||
onAddWidget: widgetId => widgetModel.addWidget(widgetId)
|
||||
onResetToDefault: () => widgetModel.resetToDefault()
|
||||
onClearAll: () => widgetModel.clearAll()
|
||||
}
|
||||
onAddWidget: widgetId => widgetModel.addWidget(widgetId)
|
||||
onResetToDefault: () => widgetModel.resetToDefault()
|
||||
onClearAll: () => widgetModel.clearAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ DankListView {
|
||||
property bool listInitialized: false
|
||||
property int swipingCardIndex: -1
|
||||
property real swipingCardOffset: 0
|
||||
property real __pendingStableHeight: 0
|
||||
property real __heightUpdateThreshold: 20
|
||||
property bool _stableHeightUpdatePending: false
|
||||
readonly property real shadowBlurPx: Theme.elevationEnabled ? ((Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined) ? Theme.elevationLevel1.blurPx : 4) : 0
|
||||
readonly property real shadowHorizontalGutter: Theme.snap(Math.max(Theme.spacingS, Math.min(32, shadowBlurPx * 1.5 + 6)), 1)
|
||||
readonly property real shadowVerticalGutter: Theme.snap(Math.max(Theme.spacingXS, 6), 1)
|
||||
@@ -27,51 +26,52 @@ DankListView {
|
||||
Qt.callLater(() => {
|
||||
if (listView) {
|
||||
listView.listInitialized = true;
|
||||
listView.stableContentHeight = listView.contentHeight;
|
||||
listView.syncStableContentHeight(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: heightUpdateDebounce
|
||||
interval: Theme.mediumDuration + 20
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (!listView.isAnimatingExpansion && Math.abs(listView.__pendingStableHeight - listView.stableContentHeight) > listView.__heightUpdateThreshold) {
|
||||
listView.stableContentHeight = listView.__pendingStableHeight;
|
||||
}
|
||||
function targetContentHeight() {
|
||||
if (count <= 0)
|
||||
return contentHeight;
|
||||
|
||||
let total = topMargin + bottomMargin + Math.max(0, count - 1) * spacing;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const item = itemAtIndex(i);
|
||||
if (!item || item.nonAnimHeight === undefined)
|
||||
return contentHeight;
|
||||
total += item.nonAnimHeight;
|
||||
}
|
||||
return Math.max(0, total);
|
||||
}
|
||||
|
||||
function syncStableContentHeight(useTarget) {
|
||||
const nextHeight = useTarget ? targetContentHeight() : contentHeight;
|
||||
if (Math.abs(nextHeight - stableContentHeight) <= 0.5)
|
||||
return;
|
||||
stableContentHeight = nextHeight;
|
||||
}
|
||||
|
||||
function queueStableContentHeightUpdate(useTarget) {
|
||||
if (_stableHeightUpdatePending)
|
||||
return;
|
||||
_stableHeightUpdatePending = true;
|
||||
Qt.callLater(() => {
|
||||
_stableHeightUpdatePending = false;
|
||||
syncStableContentHeight(useTarget || isAnimatingExpansion);
|
||||
});
|
||||
}
|
||||
|
||||
onContentHeightChanged: {
|
||||
if (!isAnimatingExpansion) {
|
||||
__pendingStableHeight = contentHeight;
|
||||
if (Math.abs(contentHeight - stableContentHeight) > __heightUpdateThreshold) {
|
||||
heightUpdateDebounce.restart();
|
||||
} else {
|
||||
stableContentHeight = contentHeight;
|
||||
}
|
||||
}
|
||||
if (!isAnimatingExpansion)
|
||||
queueStableContentHeightUpdate(false);
|
||||
}
|
||||
|
||||
onIsAnimatingExpansionChanged: {
|
||||
if (isAnimatingExpansion) {
|
||||
heightUpdateDebounce.stop();
|
||||
let delta = 0;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const item = itemAtIndex(i);
|
||||
if (item && item.children[0] && item.children[0].isAnimating) {
|
||||
const targetDelegateHeight = item.children[0].targetHeight + listView.delegateShadowGutter;
|
||||
delta += targetDelegateHeight - item.height;
|
||||
}
|
||||
}
|
||||
const targetHeight = contentHeight + delta;
|
||||
// During expansion, always update immediately without threshold check
|
||||
stableContentHeight = targetHeight;
|
||||
syncStableContentHeight(true);
|
||||
} else {
|
||||
__pendingStableHeight = contentHeight;
|
||||
heightUpdateDebounce.stop();
|
||||
stableContentHeight = __pendingStableHeight;
|
||||
queueStableContentHeightUpdate(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,11 +148,14 @@ DankListView {
|
||||
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(listView.swipingCardOffset) / width * 0.02 : 1.0
|
||||
readonly property real swipeFadeStartOffset: width * 0.75
|
||||
readonly property real swipeFadeDistance: Math.max(1, width - swipeFadeStartOffset)
|
||||
readonly property real nonAnimHeight: notificationCard.targetHeight + listView.delegateShadowGutter
|
||||
|
||||
Component.onCompleted: {
|
||||
Qt.callLater(() => {
|
||||
if (delegateRoot)
|
||||
if (delegateRoot) {
|
||||
delegateRoot.__delegateInitialized = true;
|
||||
listView.queueStableContentHeightUpdate(listView.isAnimatingExpansion);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -180,6 +183,7 @@ DankListView {
|
||||
onIsAnimatingChanged: {
|
||||
if (isAnimating) {
|
||||
listView.isAnimatingExpansion = true;
|
||||
listView.syncStableContentHeight(true);
|
||||
} else {
|
||||
Qt.callLater(() => {
|
||||
if (!notificationCard || !listView)
|
||||
@@ -197,6 +201,13 @@ DankListView {
|
||||
}
|
||||
}
|
||||
|
||||
onTargetHeightChanged: {
|
||||
if (isAnimating || listView.isAnimatingExpansion)
|
||||
listView.syncStableContentHeight(true);
|
||||
else
|
||||
listView.queueStableContentHeightUpdate(false);
|
||||
}
|
||||
|
||||
isGroupSelected: {
|
||||
if (!keyboardController || !keyboardController.keyboardNavigationActive || !listView.keyboardActive)
|
||||
return false;
|
||||
|
||||
@@ -16,6 +16,12 @@ Rectangle {
|
||||
property bool userInitiatedExpansion: false
|
||||
property bool isAnimating: false
|
||||
property bool animateExpansion: true
|
||||
property bool _retainedExpandedContent: false
|
||||
property bool _clipAnimatedContent: false
|
||||
property real expandedContentOpacity: expanded ? 1 : 0
|
||||
property real collapsedContentOpacity: expanded ? 0 : 1
|
||||
readonly property bool renderExpandedContent: expanded || _retainedExpandedContent
|
||||
readonly property bool renderCollapsedContent: !expanded
|
||||
|
||||
property bool isGroupSelected: false
|
||||
property int selectedNotificationIndex: -1
|
||||
@@ -57,6 +63,14 @@ Rectangle {
|
||||
});
|
||||
}
|
||||
|
||||
function expansionMotionDuration() {
|
||||
return root.connectedFrameMode ? Theme.variantDuration(Theme.popoutAnimationDuration, root.expanded) : (root.expanded ? Theme.notificationExpandDuration : Theme.notificationCollapseDuration);
|
||||
}
|
||||
|
||||
function expansionMotionCurve() {
|
||||
return root.connectedFrameMode ? (root.expanded ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve) : Theme.expressiveCurves.emphasized;
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
enabled: listLevelScaleAnimationsEnabled
|
||||
NumberAnimation {
|
||||
@@ -66,6 +80,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Behavior on shadowBlurPx {
|
||||
enabled: !root.connectedFrameMode
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
@@ -73,6 +88,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Behavior on shadowOffsetXPx {
|
||||
enabled: !root.connectedFrameMode
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
@@ -80,6 +96,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Behavior on shadowOffsetYPx {
|
||||
enabled: !root.connectedFrameMode
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
@@ -94,6 +111,24 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on expandedContentOpacity {
|
||||
enabled: root.__initialized && root.userInitiatedExpansion && root.animateExpansion
|
||||
NumberAnimation {
|
||||
duration: root.expansionMotionDuration()
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.expansionMotionCurve()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on collapsedContentOpacity {
|
||||
enabled: root.__initialized && root.userInitiatedExpansion && root.animateExpansion
|
||||
NumberAnimation {
|
||||
duration: root.expansionMotionDuration()
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.expansionMotionCurve()
|
||||
}
|
||||
}
|
||||
|
||||
color: {
|
||||
if (isGroupSelected && keyboardNavigationActive) {
|
||||
return Theme.primaryPressed;
|
||||
@@ -129,7 +164,31 @@ Rectangle {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
clip: false
|
||||
clip: connectedFrameMode && _clipAnimatedContent
|
||||
|
||||
onExpandedChanged: {
|
||||
if (connectedFrameMode && __initialized && userInitiatedExpansion && animateExpansion)
|
||||
_clipAnimatedContent = true;
|
||||
if (expanded) {
|
||||
_retainedExpandedContent = false;
|
||||
return;
|
||||
}
|
||||
if (connectedFrameMode && __initialized && userInitiatedExpansion && animateExpansion)
|
||||
_retainedExpandedContent = true;
|
||||
}
|
||||
|
||||
onHeightChanged: {
|
||||
if (Math.abs(height - targetHeight) > 0.5)
|
||||
return;
|
||||
_clipAnimatedContent = false;
|
||||
if (!expanded && _retainedExpandedContent)
|
||||
_retainedExpandedContent = false;
|
||||
}
|
||||
|
||||
onExpandedContentOpacityChanged: {
|
||||
if (!expanded && _retainedExpandedContent && expandedContentOpacity <= 0.01)
|
||||
_retainedExpandedContent = false;
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: cardHoverHandler
|
||||
@@ -149,7 +208,7 @@ Rectangle {
|
||||
shadowOffsetX: root.shadowOffsetXPx
|
||||
shadowOffsetY: root.shadowOffsetYPx
|
||||
shadowColor: root.shadowElevation ? Theme.elevationShadowColor(root.shadowElevation) : "transparent"
|
||||
shadowEnabled: root.shadowsAllowed
|
||||
shadowEnabled: root.shadowsAllowed && !root.connectedFrameMode
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -189,7 +248,8 @@ Rectangle {
|
||||
anchors.leftMargin: Theme.spacingL
|
||||
anchors.rightMargin: Theme.spacingL + Theme.notificationHoverRevealMargin
|
||||
height: collapsedContentHeight + extraHeight
|
||||
visible: !expanded
|
||||
visible: renderCollapsedContent
|
||||
opacity: root.collapsedContentOpacity
|
||||
|
||||
DankCircularImage {
|
||||
id: iconContainer
|
||||
@@ -388,7 +448,8 @@ Rectangle {
|
||||
anchors.leftMargin: Theme.spacingL
|
||||
anchors.rightMargin: Theme.spacingL
|
||||
spacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
||||
visible: expanded
|
||||
visible: renderExpandedContent
|
||||
opacity: root.expandedContentOpacity
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
@@ -831,7 +892,8 @@ Rectangle {
|
||||
}
|
||||
|
||||
Row {
|
||||
visible: !expanded
|
||||
visible: renderCollapsedContent
|
||||
opacity: root.collapsedContentOpacity
|
||||
anchors.right: clearButton.visible ? clearButton.left : parent.right
|
||||
anchors.rightMargin: clearButton.visible ? contentSpacing : Theme.spacingL
|
||||
anchors.top: collapsedContent.bottom
|
||||
@@ -887,7 +949,8 @@ Rectangle {
|
||||
property bool isHovered: false
|
||||
readonly property int actionCount: (notificationGroup?.latestNotification?.actions || []).length
|
||||
|
||||
visible: !expanded && actionCount < 3
|
||||
visible: renderCollapsedContent && actionCount < 3
|
||||
opacity: root.collapsedContentOpacity
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingL
|
||||
anchors.top: collapsedContent.bottom
|
||||
@@ -918,7 +981,7 @@ Rectangle {
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
visible: !expanded && (notificationGroup?.count || 0) > 1 && !descriptionExpanded
|
||||
visible: renderCollapsedContent && (notificationGroup?.count || 0) > 1 && !descriptionExpanded
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.userInitiatedExpansion = true;
|
||||
@@ -962,15 +1025,17 @@ Rectangle {
|
||||
Behavior on height {
|
||||
enabled: root.__initialized && root.userInitiatedExpansion && root.animateExpansion
|
||||
NumberAnimation {
|
||||
duration: root.connectedFrameMode ? Theme.variantDuration(Theme.popoutAnimationDuration, root.expanded) : (root.expanded ? Theme.notificationExpandDuration : Theme.notificationCollapseDuration)
|
||||
duration: root.expansionMotionDuration()
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.connectedFrameMode ? (root.expanded ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve) : Theme.expressiveCurves.emphasized
|
||||
easing.bezierCurve: root.expansionMotionCurve()
|
||||
onRunningChanged: {
|
||||
if (running) {
|
||||
root.isAnimating = true;
|
||||
} else {
|
||||
root.isAnimating = false;
|
||||
root.userInitiatedExpansion = false;
|
||||
root._retainedExpandedContent = false;
|
||||
root._clipAnimatedContent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ DankPopout {
|
||||
property real stablePopupHeight: 400
|
||||
property real _lastAlignedContentHeight: -1
|
||||
property bool _pendingSizedOpen: false
|
||||
property bool _heightUpdatePending: false
|
||||
|
||||
function updateStablePopupHeight() {
|
||||
const item = contentLoader.item;
|
||||
@@ -30,6 +31,16 @@ DankPopout {
|
||||
stablePopupHeight = target;
|
||||
}
|
||||
|
||||
function queueStablePopupHeightUpdate() {
|
||||
if (_heightUpdatePending)
|
||||
return;
|
||||
_heightUpdatePending = true;
|
||||
Qt.callLater(() => {
|
||||
_heightUpdatePending = false;
|
||||
updateStablePopupHeight();
|
||||
});
|
||||
}
|
||||
|
||||
NotificationKeyboardController {
|
||||
id: keyboardController
|
||||
listView: null
|
||||
@@ -128,7 +139,7 @@ DankPopout {
|
||||
Connections {
|
||||
target: contentLoader.item
|
||||
function onImplicitHeightChanged() {
|
||||
root.updateStablePopupHeight();
|
||||
root.queueStablePopupHeightUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -537,21 +537,21 @@ PanelWindow {
|
||||
|
||||
Behavior on shadowBlurPx {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
duration: win.descriptionExpanded ? Theme.notificationExpandDuration : Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on shadowOffsetX {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
duration: win.descriptionExpanded ? Theme.notificationExpandDuration : Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on shadowOffsetY {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
duration: win.descriptionExpanded ? Theme.notificationExpandDuration : Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
@@ -566,7 +566,7 @@ PanelWindow {
|
||||
shadowOffsetX: content.shadowOffsetX
|
||||
shadowOffsetY: content.shadowOffsetY
|
||||
shadowColor: content.shadowsAllowed && content.elevLevel ? Theme.elevationShadowColor(content.elevLevel) : "transparent"
|
||||
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed
|
||||
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed && !win.connectedFrameMode
|
||||
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||
|
||||
@@ -578,39 +578,39 @@ PanelWindow {
|
||||
sourceRect.radius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||
sourceRect.color: win.connectedFrameMode ? Theme.popupLayerColor(Theme.surfaceContainer) : Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
sourceRect.antialiasing: true
|
||||
sourceRect.layer.enabled: win.connectedFrameMode
|
||||
sourceRect.layer.smooth: true
|
||||
sourceRect.layer.textureSize: win.connectedFrameMode && win.dpr > 1 ? Qt.size(Math.ceil(sourceRect.width * win.dpr), Math.ceil(sourceRect.height * win.dpr)) : Qt.size(0, 0)
|
||||
sourceRect.layer.enabled: false
|
||||
sourceRect.layer.textureSize: Qt.size(0, 0)
|
||||
sourceRect.border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
||||
sourceRect.border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
x: bgShadowLayer.sourceRect.x
|
||||
y: bgShadowLayer.sourceRect.y
|
||||
width: bgShadowLayer.sourceRect.width
|
||||
height: bgShadowLayer.sourceRect.height
|
||||
radius: bgShadowLayer.sourceRect.radius
|
||||
visible: notificationData && notificationData.urgency === NotificationUrgency.Critical
|
||||
opacity: 1
|
||||
clip: true
|
||||
// Keep critical accent outside shadow rendering so connected mode still shows it.
|
||||
Rectangle {
|
||||
x: content.cardInset
|
||||
y: content.cardInset
|
||||
width: Math.max(0, content.width - content.cardInset * 2)
|
||||
height: Math.max(0, content.height - content.cardInset * 2)
|
||||
radius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||
visible: win.notificationData && win.notificationData.urgency === NotificationUrgency.Critical
|
||||
opacity: 1
|
||||
clip: true
|
||||
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: Theme.primary
|
||||
}
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: Theme.primary
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 0.02
|
||||
color: Theme.primary
|
||||
}
|
||||
GradientStop {
|
||||
position: 0.02
|
||||
color: Theme.primary
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 0.021
|
||||
color: "transparent"
|
||||
}
|
||||
GradientStop {
|
||||
position: 0.021
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ QtObject {
|
||||
property var pendingDestroys: []
|
||||
property int destroyDelayMs: 100
|
||||
property bool _chromeSyncPending: false
|
||||
property bool _syncingVisibleNotifications: false
|
||||
readonly property real chromeOpenProgressThreshold: 0.10
|
||||
readonly property real chromeReleaseTailStart: 0.90
|
||||
readonly property real chromeReleaseDropProgress: 0.995
|
||||
@@ -160,6 +161,7 @@ QtObject {
|
||||
|
||||
function _sync(newWrappers) {
|
||||
let needsReposition = false;
|
||||
_syncingVisibleNotifications = true;
|
||||
for (const p of popupWindows.slice()) {
|
||||
if (!_isValidWindow(p) || p.exiting)
|
||||
continue;
|
||||
@@ -171,10 +173,10 @@ QtObject {
|
||||
}
|
||||
for (const w of newWrappers) {
|
||||
if (w && !_hasWindowFor(w) && _isFocusedScreen()) {
|
||||
_insertAtTop(w);
|
||||
needsReposition = false;
|
||||
needsReposition = _insertAtTop(w, true) || needsReposition;
|
||||
}
|
||||
}
|
||||
_syncingVisibleNotifications = false;
|
||||
if (needsReposition)
|
||||
_repositionAll();
|
||||
}
|
||||
@@ -183,9 +185,9 @@ QtObject {
|
||||
return (p.alignedHeight || p.implicitHeight || (baseNotificationHeight - popupSpacing)) + popupSpacing;
|
||||
}
|
||||
|
||||
function _insertAtTop(wrapper) {
|
||||
function _insertAtTop(wrapper, deferReposition) {
|
||||
if (!wrapper)
|
||||
return;
|
||||
return false;
|
||||
const notificationId = wrapper?.notification ? wrapper.notification.id : "";
|
||||
const win = popupComponent.createObject(null, {
|
||||
"notificationData": wrapper,
|
||||
@@ -194,15 +196,17 @@ QtObject {
|
||||
"screen": manager.modelData
|
||||
});
|
||||
if (!win)
|
||||
return;
|
||||
return false;
|
||||
if (!win.hasValidData) {
|
||||
win.destroy();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
popupWindows.unshift(win);
|
||||
_repositionAll();
|
||||
if (!deferReposition)
|
||||
_repositionAll();
|
||||
if (!sweeper.running)
|
||||
sweeper.start();
|
||||
return true;
|
||||
}
|
||||
|
||||
function _repositionAll() {
|
||||
@@ -321,6 +325,10 @@ QtObject {
|
||||
if (!rect || p !== trailing || !p.popupChromeReleaseProgress)
|
||||
return rect;
|
||||
|
||||
// Keep maxed-stack chrome anchored while a replacement tail exits.
|
||||
if (p.exiting && p.notificationData?.removedByLimit && _layoutWindows().length > 0)
|
||||
return rect;
|
||||
|
||||
const progress = _chromeReleaseTailProgress(p.popupChromeReleaseProgress());
|
||||
if (progress <= 0)
|
||||
return rect;
|
||||
@@ -489,17 +497,34 @@ QtObject {
|
||||
_scheduleNotificationChromeSync();
|
||||
}
|
||||
|
||||
// Coalesce resize repositioning; exit-path moves remain immediate.
|
||||
property bool _repositionPending: false
|
||||
|
||||
function _queueReposition() {
|
||||
if (_repositionPending)
|
||||
return;
|
||||
_repositionPending = true;
|
||||
Qt.callLater(_flushReposition);
|
||||
}
|
||||
|
||||
function _flushReposition() {
|
||||
_repositionPending = false;
|
||||
_repositionAll();
|
||||
}
|
||||
|
||||
function _onPopupHeightChanged(p) {
|
||||
if (!p || p.exiting || p._isDestroying)
|
||||
return;
|
||||
if (popupWindows.indexOf(p) === -1)
|
||||
return;
|
||||
_repositionAll();
|
||||
_queueReposition();
|
||||
}
|
||||
|
||||
function _onPopupExitStarted(p) {
|
||||
if (!p || popupWindows.indexOf(p) === -1)
|
||||
return;
|
||||
if (_syncingVisibleNotifications)
|
||||
return;
|
||||
_repositionAll();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@ Item {
|
||||
property bool fullHeightSurface: false
|
||||
property bool _primeContent: false
|
||||
property bool _resizeActive: false
|
||||
property real _surfaceMarginLeft: 0
|
||||
property real _surfaceW: 0
|
||||
property string _chromeClaimId: ""
|
||||
property int _connectedChromeSerial: 0
|
||||
property real _chromeAnimTravelX: 1
|
||||
@@ -49,6 +47,8 @@ Item {
|
||||
"rightBar": 0
|
||||
})
|
||||
property var screen: null
|
||||
// Connected resize uses one full-screen surface; body-sized regions are masks.
|
||||
readonly property bool useBackgroundWindow: false
|
||||
|
||||
readonly property real effectiveBarThickness: {
|
||||
if (Theme.isConnectedEffect)
|
||||
@@ -118,12 +118,6 @@ Item {
|
||||
}
|
||||
readonly property string effectiveShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
|
||||
|
||||
// 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;
|
||||
@@ -181,7 +175,7 @@ Item {
|
||||
if (barSide !== "top" && barSide !== "bottom")
|
||||
return contentContainer.animY;
|
||||
|
||||
const extent = Math.max(0, root.alignedHeight);
|
||||
const extent = Math.max(0, root.renderedAlignedHeight);
|
||||
const progress = Math.min(1, Math.abs(contentContainer.animY) / Math.max(1, _chromeAnimTravelY));
|
||||
const offset = Theme.snap(extent * progress, root.dpr);
|
||||
return contentContainer.animY < 0 ? -offset : offset;
|
||||
@@ -193,9 +187,9 @@ Item {
|
||||
"visible": visible,
|
||||
"barSide": contentContainer.connectedBarSide,
|
||||
"bodyX": root.alignedX,
|
||||
"bodyY": root.alignedY,
|
||||
"bodyY": root.renderedAlignedY,
|
||||
"bodyW": root.alignedWidth,
|
||||
"bodyH": root.alignedHeight,
|
||||
"bodyH": root.renderedAlignedHeight,
|
||||
"animX": _connectedChromeAnimX(),
|
||||
"animY": _connectedChromeAnimY(),
|
||||
"screen": root.screen ? root.screen.name : "",
|
||||
@@ -258,16 +252,28 @@ Item {
|
||||
ConnectedModeState.setPopoutAnim(_chromeClaimId, syncX ? _connectedChromeAnimX() : undefined, syncY ? _connectedChromeAnimY() : undefined);
|
||||
}
|
||||
|
||||
function _syncPopoutBody() {
|
||||
if (!root.frameOwnsConnectedChrome || !_chromeClaimId)
|
||||
return;
|
||||
if (!contentWindow.visible && !shouldBeVisible)
|
||||
return;
|
||||
ConnectedModeState.setPopoutBody(_chromeClaimId, root.alignedX, root.renderedAlignedY, root.alignedWidth, root.renderedAlignedHeight);
|
||||
}
|
||||
|
||||
function _flushFullSync() {
|
||||
_fullSyncPending = false;
|
||||
_syncPopoutChromeState();
|
||||
if (root && typeof root._syncPopoutChromeState === "function")
|
||||
root._syncPopoutChromeState();
|
||||
}
|
||||
|
||||
function _queueFullSync() {
|
||||
if (_fullSyncPending)
|
||||
return;
|
||||
_fullSyncPending = true;
|
||||
Qt.callLater(root._flushFullSync);
|
||||
Qt.callLater(() => {
|
||||
if (root && typeof root._flushFullSync === "function")
|
||||
root._flushFullSync();
|
||||
});
|
||||
}
|
||||
|
||||
onAlignedXChanged: _queueFullSync()
|
||||
@@ -275,6 +281,8 @@ Item {
|
||||
onAlignedWidthChanged: _queueFullSync()
|
||||
onContentAnimXChanged: _syncPopoutAnim("x")
|
||||
onContentAnimYChanged: _syncPopoutAnim("y")
|
||||
onRenderedAlignedYChanged: _syncPopoutBody()
|
||||
onRenderedAlignedHeightChanged: _syncPopoutBody()
|
||||
onScreenChanged: _syncPopoutChromeState()
|
||||
onEffectiveBarPositionChanged: _syncPopoutChromeState()
|
||||
|
||||
@@ -306,18 +314,10 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
readonly property bool useBackgroundWindow: !CompositorService.isHyprland || CompositorService.useHyprlandFocusGrab
|
||||
readonly property bool frameOwnsConnectedChrome: SettingsData.connectedFrameModeActive
|
||||
&& !!root.screen
|
||||
&& SettingsData.isScreenInPreferences(root.screen, SettingsData.frameScreenPreferences)
|
||||
|
||||
function updateSurfacePosition() {
|
||||
if (useBackgroundWindow && shouldBeVisible) {
|
||||
_surfaceMarginLeft = alignedX - shadowBuffer;
|
||||
_surfaceW = alignedWidth + shadowBuffer * 2;
|
||||
}
|
||||
}
|
||||
|
||||
property bool animationsEnabled: true
|
||||
|
||||
function open() {
|
||||
@@ -328,16 +328,8 @@ Item {
|
||||
animationsEnabled = false;
|
||||
_primeContent = true;
|
||||
|
||||
// Snapshot mask geometry
|
||||
_frozenMaskX = maskX;
|
||||
_frozenMaskY = maskY;
|
||||
_frozenMaskWidth = maskWidth;
|
||||
_frozenMaskHeight = maskHeight;
|
||||
|
||||
if (_lastOpenedScreen !== null && _lastOpenedScreen !== screen) {
|
||||
contentWindow.visible = false;
|
||||
if (useBackgroundWindow)
|
||||
backgroundWindow.visible = false;
|
||||
}
|
||||
_lastOpenedScreen = screen;
|
||||
|
||||
@@ -355,19 +347,12 @@ Item {
|
||||
_chromeClaimId = "";
|
||||
}
|
||||
|
||||
if (useBackgroundWindow) {
|
||||
_surfaceMarginLeft = alignedX - shadowBuffer;
|
||||
_surfaceW = alignedWidth + shadowBuffer * 2;
|
||||
backgroundWindow.visible = true;
|
||||
}
|
||||
contentWindow.visible = true;
|
||||
|
||||
Qt.callLater(() => {
|
||||
animationsEnabled = true;
|
||||
shouldBeVisible = true;
|
||||
if (shouldBeVisible && screen) {
|
||||
if (useBackgroundWindow)
|
||||
backgroundWindow.visible = true;
|
||||
contentWindow.visible = true;
|
||||
PopoutManager.showPopout(root);
|
||||
opened();
|
||||
@@ -413,8 +398,6 @@ Item {
|
||||
if (!shouldBeVisible) {
|
||||
isClosing = false;
|
||||
contentWindow.visible = false;
|
||||
if (useBackgroundWindow)
|
||||
backgroundWindow.visible = false;
|
||||
PopoutManager.hidePopout(root);
|
||||
popoutClosed();
|
||||
}
|
||||
@@ -536,6 +519,27 @@ Item {
|
||||
readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
|
||||
readonly property real alignedWidth: Theme.px(popupWidth, dpr)
|
||||
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
||||
property real renderedAlignedY: alignedY
|
||||
property real renderedAlignedHeight: alignedHeight
|
||||
readonly property bool renderedGeometryGrowing: alignedHeight >= renderedAlignedHeight
|
||||
|
||||
Behavior on renderedAlignedY {
|
||||
enabled: root.animationsEnabled && contentWindow.visible && root.shouldBeVisible
|
||||
NumberAnimation {
|
||||
duration: Theme.variantDuration(root.animationDuration, root.renderedGeometryGrowing)
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.renderedGeometryGrowing ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on renderedAlignedHeight {
|
||||
enabled: root.animationsEnabled && contentWindow.visible && root.shouldBeVisible
|
||||
NumberAnimation {
|
||||
duration: Theme.variantDuration(root.animationDuration, root.renderedGeometryGrowing)
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.renderedGeometryGrowing ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
readonly property real connectedAnchorX: {
|
||||
if (!Theme.isConnectedEffect)
|
||||
return triggerX;
|
||||
@@ -572,7 +576,7 @@ Item {
|
||||
}
|
||||
|
||||
onAlignedHeightChanged: {
|
||||
_syncPopoutChromeState();
|
||||
_queueFullSync();
|
||||
if (!suspendShadowWhileResizing || !shouldBeVisible)
|
||||
return;
|
||||
_resizeActive = true;
|
||||
@@ -661,117 +665,6 @@ Item {
|
||||
return Math.max(100, screenHeight - maskY - bottomExclusion);
|
||||
}
|
||||
|
||||
PanelWindow {
|
||||
id: backgroundWindow
|
||||
screen: root.screen
|
||||
visible: false
|
||||
color: "transparent"
|
||||
Component.onCompleted: {
|
||||
if (typeof updatesEnabled !== "undefined" && !root.overlayContent)
|
||||
updatesEnabled = false;
|
||||
}
|
||||
|
||||
WlrLayershell.namespace: root.layerNamespace + ":background"
|
||||
WlrLayershell.layer: WlrLayershell.Top
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
mask: Region {
|
||||
item: maskRect
|
||||
Region {
|
||||
item: contentExclusionRect
|
||||
intersection: Intersection.Subtract
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: maskRect
|
||||
visible: false
|
||||
color: "transparent"
|
||||
x: root._frozenMaskX
|
||||
y: root._frozenMaskY
|
||||
width: (backgroundWindow.visible && backgroundInteractive) ? root._frozenMaskWidth : 0
|
||||
height: (backgroundWindow.visible && backgroundInteractive) ? root._frozenMaskHeight : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: contentExclusionRect
|
||||
visible: false
|
||||
x: root.alignedX
|
||||
y: root.alignedY
|
||||
width: root.alignedWidth
|
||||
height: root.alignedHeight
|
||||
}
|
||||
|
||||
Item {
|
||||
id: outsideClickCatcher
|
||||
x: root._frozenMaskX
|
||||
y: root._frozenMaskY
|
||||
width: root._frozenMaskWidth
|
||||
height: root._frozenMaskHeight
|
||||
enabled: root.shouldBeVisible && root.backgroundInteractive
|
||||
|
||||
readonly property real contentLeft: Math.max(0, root.alignedX - x)
|
||||
readonly property real contentTop: Math.max(0, root.alignedY - y)
|
||||
readonly property real contentRight: Math.min(width, contentLeft + root.alignedWidth)
|
||||
readonly property real contentBottom: Math.min(height, contentTop + root.alignedHeight)
|
||||
|
||||
MouseArea {
|
||||
x: 0
|
||||
y: 0
|
||||
width: outsideClickCatcher.width
|
||||
height: Math.max(0, outsideClickCatcher.contentTop)
|
||||
enabled: parent.enabled
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: root.backgroundClicked()
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
x: 0
|
||||
y: outsideClickCatcher.contentBottom
|
||||
width: outsideClickCatcher.width
|
||||
height: Math.max(0, outsideClickCatcher.height - outsideClickCatcher.contentBottom)
|
||||
enabled: parent.enabled
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: root.backgroundClicked()
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
x: 0
|
||||
y: outsideClickCatcher.contentTop
|
||||
width: Math.max(0, outsideClickCatcher.contentLeft)
|
||||
height: Math.max(0, outsideClickCatcher.contentBottom - outsideClickCatcher.contentTop)
|
||||
enabled: parent.enabled
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: root.backgroundClicked()
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
x: outsideClickCatcher.contentRight
|
||||
y: outsideClickCatcher.contentTop
|
||||
width: Math.max(0, outsideClickCatcher.width - outsideClickCatcher.contentRight)
|
||||
height: Math.max(0, outsideClickCatcher.contentBottom - outsideClickCatcher.contentTop)
|
||||
enabled: parent.enabled
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: root.backgroundClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: overlayLoader
|
||||
anchors.fill: parent
|
||||
active: root.overlayContent !== null && backgroundWindow.visible
|
||||
sourceComponent: root.overlayContent
|
||||
}
|
||||
}
|
||||
|
||||
PanelWindow {
|
||||
id: contentWindow
|
||||
screen: root.screen
|
||||
@@ -824,27 +717,37 @@ Item {
|
||||
return WlrKeyboardFocus.Exclusive;
|
||||
}
|
||||
|
||||
readonly property bool _fullHeight: useBackgroundWindow && root.fullHeightSurface
|
||||
readonly property bool _fullHeight: root.fullHeightSurface
|
||||
anchors {
|
||||
left: true
|
||||
top: true
|
||||
right: !useBackgroundWindow
|
||||
bottom: _fullHeight || !useBackgroundWindow
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
WlrLayershell.margins {
|
||||
left: useBackgroundWindow ? root._surfaceMarginLeft : 0
|
||||
top: (useBackgroundWindow && !_fullHeight) ? (root.alignedY - shadowBuffer) : 0
|
||||
left: 0
|
||||
top: 0
|
||||
}
|
||||
|
||||
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
|
||||
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
|
||||
implicitWidth: 0
|
||||
implicitHeight: 0
|
||||
|
||||
mask: useBackgroundWindow ? contentInputMask : null
|
||||
mask: contentInputMask
|
||||
|
||||
Region {
|
||||
id: contentInputMask
|
||||
item: contentMaskRect
|
||||
// Outside-click dismissal needs full-screen input only while interactive.
|
||||
item: (shouldBeVisible && backgroundInteractive) ? fullScreenMaskItem : contentMaskRect
|
||||
}
|
||||
|
||||
Item {
|
||||
id: fullScreenMaskItem
|
||||
visible: false
|
||||
x: 0
|
||||
y: 0
|
||||
width: 32767
|
||||
height: 32767
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -853,18 +756,18 @@ Item {
|
||||
x: contentContainer.x - contentContainer.horizontalConnectorExtent
|
||||
y: contentContainer.y - contentContainer.verticalConnectorExtent
|
||||
width: root.alignedWidth + contentContainer.horizontalConnectorExtent * 2
|
||||
height: root.alignedHeight + contentContainer.verticalConnectorExtent * 2
|
||||
height: root.renderedAlignedHeight + contentContainer.verticalConnectorExtent * 2
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: !useBackgroundWindow && shouldBeVisible && backgroundInteractive
|
||||
enabled: shouldBeVisible && backgroundInteractive
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
z: -1
|
||||
onClicked: mouse => {
|
||||
const clickX = mouse.x;
|
||||
const clickY = mouse.y;
|
||||
const outsideContent = clickX < root.alignedX || clickX > root.alignedX + root.alignedWidth || clickY < root.alignedY || clickY > root.alignedY + root.alignedHeight;
|
||||
const outsideContent = clickX < root.alignedX || clickX > root.alignedX + root.alignedWidth || clickY < root.renderedAlignedY || clickY > root.renderedAlignedY + root.renderedAlignedHeight;
|
||||
if (!outsideContent)
|
||||
return;
|
||||
backgroundClicked();
|
||||
@@ -873,10 +776,10 @@ Item {
|
||||
|
||||
Item {
|
||||
id: contentContainer
|
||||
x: useBackgroundWindow ? shadowBuffer : root.alignedX
|
||||
y: (useBackgroundWindow && !contentWindow._fullHeight) ? shadowBuffer : root.alignedY
|
||||
x: root.alignedX
|
||||
y: root.renderedAlignedY
|
||||
width: root.alignedWidth
|
||||
height: root.alignedHeight
|
||||
height: root.renderedAlignedHeight
|
||||
|
||||
readonly property bool barTop: effectiveBarPosition === SettingsData.Position.Top
|
||||
readonly property bool barBottom: effectiveBarPosition === SettingsData.Position.Bottom
|
||||
@@ -1082,154 +985,147 @@ Item {
|
||||
return parent.height + clipOversize * 2;
|
||||
}
|
||||
|
||||
// Roll-out clips a wrapper while content and shadow keep full-size geometry.
|
||||
Item {
|
||||
id: aligner
|
||||
id: rollOutAdjuster
|
||||
readonly property real baseWidth: contentContainer.width
|
||||
readonly property real baseHeight: contentContainer.height
|
||||
readonly property bool isRollOut: typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode === 2 && Theme.isDirectionalEffect
|
||||
|
||||
x: (directionalClipMask.x !== 0 ? -directionalClipMask.x : 0) + (isRollOut && contentContainer.barRight ? baseWidth * (1 - contentContainer.scaleValue) : 0)
|
||||
y: (directionalClipMask.y !== 0 ? -directionalClipMask.y : 0) + (isRollOut && contentContainer.barBottom ? baseHeight * (1 - contentContainer.scaleValue) : 0)
|
||||
x: directionalClipMask.x !== 0 ? -directionalClipMask.x : 0
|
||||
y: directionalClipMask.y !== 0 ? -directionalClipMask.y : 0
|
||||
width: isRollOut && (contentContainer.barLeft || contentContainer.barRight) ? Math.max(0, baseWidth * contentContainer.scaleValue) : baseWidth
|
||||
height: isRollOut && (contentContainer.barTop || contentContainer.barBottom) ? Math.max(0, baseHeight * contentContainer.scaleValue) : baseHeight
|
||||
|
||||
clip: isRollOut
|
||||
|
||||
ElevationShadow {
|
||||
id: shadowSource
|
||||
readonly property real connectorExtent: Theme.isConnectedEffect ? Theme.connectedCornerRadius : 0
|
||||
readonly property real extraLeft: Theme.isConnectedEffect && (contentContainer.barTop || contentContainer.barBottom) ? connectorExtent : 0
|
||||
readonly property real extraRight: Theme.isConnectedEffect && (contentContainer.barTop || contentContainer.barBottom) ? connectorExtent : 0
|
||||
readonly property real extraTop: Theme.isConnectedEffect && (contentContainer.barLeft || contentContainer.barRight) ? connectorExtent : 0
|
||||
readonly property real extraBottom: Theme.isConnectedEffect && (contentContainer.barLeft || contentContainer.barRight) ? connectorExtent : 0
|
||||
readonly property real bodyX: extraLeft
|
||||
readonly property real bodyY: extraTop
|
||||
readonly property real bodyWidth: rollOutAdjuster.baseWidth
|
||||
readonly property real bodyHeight: rollOutAdjuster.baseHeight
|
||||
|
||||
width: rollOutAdjuster.baseWidth + extraLeft + extraRight
|
||||
height: rollOutAdjuster.baseHeight + extraTop + extraBottom
|
||||
opacity: contentWrapper.opacity
|
||||
scale: contentWrapper.scale
|
||||
x: contentWrapper.x - extraLeft
|
||||
y: contentWrapper.y - extraTop
|
||||
level: root.shadowLevel
|
||||
direction: root.effectiveShadowDirection
|
||||
fallbackOffset: root.shadowFallbackOffset
|
||||
targetRadius: contentContainer.surfaceRadius
|
||||
topLeftRadius: contentContainer.surfaceTopLeftRadius
|
||||
topRightRadius: contentContainer.surfaceTopRightRadius
|
||||
bottomLeftRadius: contentContainer.surfaceBottomLeftRadius
|
||||
bottomRightRadius: contentContainer.surfaceBottomRightRadius
|
||||
targetColor: contentContainer.surfaceColor
|
||||
borderColor: contentContainer.surfaceBorderColor
|
||||
borderWidth: contentContainer.surfaceBorderWidth
|
||||
useCustomSource: Theme.isConnectedEffect
|
||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive) && !root.frameOwnsConnectedChrome
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
visible: Theme.isConnectedEffect && !root.frameOwnsConnectedChrome
|
||||
clip: false
|
||||
|
||||
Rectangle {
|
||||
x: shadowSource.bodyX
|
||||
y: shadowSource.bodyY
|
||||
width: shadowSource.bodyWidth
|
||||
height: shadowSource.bodyHeight
|
||||
topLeftRadius: contentContainer.surfaceTopLeftRadius
|
||||
topRightRadius: contentContainer.surfaceTopRightRadius
|
||||
bottomLeftRadius: contentContainer.surfaceBottomLeftRadius
|
||||
bottomRightRadius: contentContainer.surfaceBottomRightRadius
|
||||
color: contentContainer.surfaceColor
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
visible: Theme.isConnectedEffect
|
||||
barSide: contentContainer.connectedBarSide
|
||||
placement: "left"
|
||||
spacing: 0
|
||||
connectorRadius: Theme.connectedCornerRadius
|
||||
color: contentContainer.surfaceColor
|
||||
dpr: root.dpr
|
||||
x: Theme.snap(contentContainer.connectorX(shadowSource.bodyX, shadowSource.bodyWidth, placement, spacing), root.dpr)
|
||||
y: Theme.snap(contentContainer.connectorY(shadowSource.bodyY, shadowSource.bodyHeight, placement, spacing), root.dpr)
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
visible: Theme.isConnectedEffect
|
||||
barSide: contentContainer.connectedBarSide
|
||||
placement: "right"
|
||||
spacing: 0
|
||||
connectorRadius: Theme.connectedCornerRadius
|
||||
color: contentContainer.surfaceColor
|
||||
dpr: root.dpr
|
||||
x: Theme.snap(contentContainer.connectorX(shadowSource.bodyX, shadowSource.bodyWidth, placement, spacing), root.dpr)
|
||||
y: Theme.snap(contentContainer.connectorY(shadowSource.bodyY, shadowSource.bodyHeight, placement, spacing), root.dpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: unrollCounteract
|
||||
x: aligner.isRollOut && contentContainer.barRight ? -(aligner.baseWidth * (1 - contentContainer.scaleValue)) : 0
|
||||
y: aligner.isRollOut && contentContainer.barBottom ? -(aligner.baseHeight * (1 - contentContainer.scaleValue)) : 0
|
||||
width: aligner.baseWidth
|
||||
height: aligner.baseHeight
|
||||
id: contentWrapper
|
||||
width: rollOutAdjuster.baseWidth
|
||||
height: rollOutAdjuster.baseHeight
|
||||
opacity: Theme.isDirectionalEffect ? 1 : (shouldBeVisible ? 1 : 0)
|
||||
visible: opacity > 0
|
||||
|
||||
ElevationShadow {
|
||||
id: shadowSource
|
||||
readonly property real connectorExtent: Theme.isConnectedEffect ? Theme.connectedCornerRadius : 0
|
||||
readonly property real extraLeft: Theme.isConnectedEffect && (contentContainer.barTop || contentContainer.barBottom) ? connectorExtent : 0
|
||||
readonly property real extraRight: Theme.isConnectedEffect && (contentContainer.barTop || contentContainer.barBottom) ? connectorExtent : 0
|
||||
readonly property real extraTop: Theme.isConnectedEffect && (contentContainer.barLeft || contentContainer.barRight) ? connectorExtent : 0
|
||||
readonly property real extraBottom: Theme.isConnectedEffect && (contentContainer.barLeft || contentContainer.barRight) ? connectorExtent : 0
|
||||
readonly property real bodyX: extraLeft
|
||||
readonly property real bodyY: extraTop
|
||||
readonly property real bodyWidth: parent.width
|
||||
readonly property real bodyHeight: parent.height
|
||||
scale: rollOutAdjuster.isRollOut ? 1.0 : contentContainer.scaleValue
|
||||
x: Theme.snap(contentContainer.animX + (rollOutAdjuster.baseWidth - width) * (1 - scale) * 0.5, root.dpr)
|
||||
y: Theme.snap(contentContainer.animY + (rollOutAdjuster.baseHeight - height) * (1 - scale) * 0.5, root.dpr)
|
||||
|
||||
width: parent.width + extraLeft + extraRight
|
||||
height: parent.height + extraTop + extraBottom
|
||||
opacity: contentWrapper.opacity
|
||||
scale: contentWrapper.scale
|
||||
x: contentWrapper.x - extraLeft
|
||||
y: contentWrapper.y - extraTop
|
||||
level: root.shadowLevel
|
||||
direction: root.effectiveShadowDirection
|
||||
fallbackOffset: root.shadowFallbackOffset
|
||||
targetRadius: contentContainer.surfaceRadius
|
||||
topLeftRadius: contentContainer.surfaceTopLeftRadius
|
||||
topRightRadius: contentContainer.surfaceTopRightRadius
|
||||
bottomLeftRadius: contentContainer.surfaceBottomLeftRadius
|
||||
bottomRightRadius: contentContainer.surfaceBottomRightRadius
|
||||
targetColor: contentContainer.surfaceColor
|
||||
borderColor: contentContainer.surfaceBorderColor
|
||||
borderWidth: contentContainer.surfaceBorderWidth
|
||||
useCustomSource: Theme.isConnectedEffect
|
||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive) && !root.frameOwnsConnectedChrome
|
||||
layer.enabled: contentWrapper.opacity < 1
|
||||
layer.smooth: false
|
||||
layer.textureSize: root.dpr > 1 ? Qt.size(Math.ceil(width * root.dpr), Math.ceil(height * root.dpr)) : Qt.size(0, 0)
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
visible: Theme.isConnectedEffect && !root.frameOwnsConnectedChrome
|
||||
clip: false
|
||||
|
||||
Rectangle {
|
||||
x: shadowSource.bodyX
|
||||
y: shadowSource.bodyY
|
||||
width: shadowSource.bodyWidth
|
||||
height: shadowSource.bodyHeight
|
||||
topLeftRadius: contentContainer.surfaceTopLeftRadius
|
||||
topRightRadius: contentContainer.surfaceTopRightRadius
|
||||
bottomLeftRadius: contentContainer.surfaceBottomLeftRadius
|
||||
bottomRightRadius: contentContainer.surfaceBottomRightRadius
|
||||
color: contentContainer.surfaceColor
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
visible: Theme.isConnectedEffect
|
||||
barSide: contentContainer.connectedBarSide
|
||||
placement: "left"
|
||||
spacing: 0
|
||||
connectorRadius: Theme.connectedCornerRadius
|
||||
color: contentContainer.surfaceColor
|
||||
dpr: root.dpr
|
||||
x: Theme.snap(contentContainer.connectorX(shadowSource.bodyX, shadowSource.bodyWidth, placement, spacing), root.dpr)
|
||||
y: Theme.snap(contentContainer.connectorY(shadowSource.bodyY, shadowSource.bodyHeight, placement, spacing), root.dpr)
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
visible: Theme.isConnectedEffect
|
||||
barSide: contentContainer.connectedBarSide
|
||||
placement: "right"
|
||||
spacing: 0
|
||||
connectorRadius: Theme.connectedCornerRadius
|
||||
color: contentContainer.surfaceColor
|
||||
dpr: root.dpr
|
||||
x: Theme.snap(contentContainer.connectorX(shadowSource.bodyX, shadowSource.bodyWidth, placement, spacing), root.dpr)
|
||||
y: Theme.snap(contentContainer.connectorY(shadowSource.bodyY, shadowSource.bodyHeight, placement, spacing), root.dpr)
|
||||
}
|
||||
Behavior on opacity {
|
||||
enabled: !Theme.isDirectionalEffect
|
||||
NumberAnimation {
|
||||
duration: Math.round(Theme.variantDuration(animationDuration, shouldBeVisible) * Theme.variantOpacityDurationScale)
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: contentWrapper
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
opacity: Theme.isDirectionalEffect ? 1 : (shouldBeVisible ? 1 : 0)
|
||||
visible: opacity > 0
|
||||
anchors.fill: parent
|
||||
clip: false
|
||||
visible: !Theme.isConnectedEffect
|
||||
|
||||
scale: aligner.isRollOut ? 1.0 : contentContainer.scaleValue
|
||||
x: Theme.snap(contentContainer.animX + (parent.width - width) * (1 - scale) * 0.5, root.dpr)
|
||||
y: Theme.snap(contentContainer.animY + (parent.height - height) * (1 - scale) * 0.5, root.dpr)
|
||||
|
||||
layer.enabled: contentWrapper.opacity < 1
|
||||
layer.smooth: false
|
||||
layer.textureSize: root.dpr > 1 ? Qt.size(Math.ceil(width * root.dpr), Math.ceil(height * root.dpr)) : Qt.size(0, 0)
|
||||
|
||||
Behavior on opacity {
|
||||
enabled: !Theme.isDirectionalEffect
|
||||
NumberAnimation {
|
||||
duration: Math.round(Theme.variantDuration(animationDuration, shouldBeVisible) * Theme.variantOpacityDurationScale)
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
clip: false
|
||||
visible: !Theme.isConnectedEffect
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
antialiasing: true
|
||||
topLeftRadius: contentContainer.surfaceTopLeftRadius
|
||||
topRightRadius: contentContainer.surfaceTopRightRadius
|
||||
bottomLeftRadius: contentContainer.surfaceBottomLeftRadius
|
||||
bottomRightRadius: contentContainer.surfaceBottomRightRadius
|
||||
color: contentContainer.surfaceColor
|
||||
border.color: contentContainer.surfaceBorderColor
|
||||
border.width: contentContainer.surfaceBorderWidth
|
||||
}
|
||||
antialiasing: true
|
||||
topLeftRadius: contentContainer.surfaceTopLeftRadius
|
||||
topRightRadius: contentContainer.surfaceTopRightRadius
|
||||
bottomLeftRadius: contentContainer.surfaceBottomLeftRadius
|
||||
bottomRightRadius: contentContainer.surfaceBottomRightRadius
|
||||
color: contentContainer.surfaceColor
|
||||
border.color: contentContainer.surfaceBorderColor
|
||||
border.width: contentContainer.surfaceBorderWidth
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
anchors.fill: parent
|
||||
active: root._primeContent || shouldBeVisible || contentWindow.visible
|
||||
asynchronous: false
|
||||
}
|
||||
} // closes contentWrapper
|
||||
} // closes unrollCounteract
|
||||
} // closes aligner
|
||||
} // closes directionalClipMask
|
||||
} // closes contentContainer
|
||||
Loader {
|
||||
id: contentLoader
|
||||
anchors.fill: parent
|
||||
active: root._primeContent || shouldBeVisible || contentWindow.visible
|
||||
asynchronous: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusHelper
|
||||
@@ -1247,5 +1143,12 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: overlayLoader
|
||||
anchors.fill: parent
|
||||
active: root.overlayContent !== null && contentWindow.visible
|
||||
sourceComponent: root.overlayContent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user