From 8d94117a69b832719dd9d130afc5edeadd3719bf Mon Sep 17 00:00:00 2001 From: purian23 Date: Fri, 12 Jun 2026 10:40:18 -0400 Subject: [PATCH] Cleanup --- quickshell/Common/ConnectedModeState.qml | 10 ------ quickshell/Common/ElevationShadow.qml | 3 -- quickshell/Common/Theme.qml | 3 -- quickshell/Modals/Common/DankModal.qml | 7 +--- .../Modals/Common/DankModalConnected.qml | 11 +----- .../DankLauncherV2ModalConnected.qml | 25 +------------ quickshell/Modules/Frame/FrameBorder.qml | 5 +-- quickshell/Modules/Frame/FrameWindow.qml | 36 +------------------ quickshell/Shaders/frag/connected_arc.frag | 15 +------- quickshell/Shaders/frag/connected_chrome.frag | 9 +---- quickshell/Shaders/frag/elevation_rect.frag | 8 +---- quickshell/Shaders/frag/frame_arc.frag | 4 +-- quickshell/Widgets/DankPopout.qml | 8 +---- quickshell/Widgets/DankPopoutConnected.qml | 36 ++----------------- quickshell/Widgets/DismissZone.qml | 1 - quickshell/Widgets/WindowBlur.qml | 5 +-- 16 files changed, 13 insertions(+), 173 deletions(-) diff --git a/quickshell/Common/ConnectedModeState.qml b/quickshell/Common/ConnectedModeState.qml index c5b9a6e3..1ef80f82 100644 --- a/quickshell/Common/ConnectedModeState.qml +++ b/quickshell/Common/ConnectedModeState.qml @@ -131,7 +131,6 @@ Singleton { "slideY": 0 }) - // Popout state (updated by DankPopout when connectedFrameModeActive) property string popoutOwnerId: "" property bool popoutVisible: false property string popoutBarSide: "top" @@ -145,14 +144,10 @@ Singleton { property bool popoutOmitStartConnector: false property bool popoutOmitEndConnector: false - // Dock state (updated by Dock when connectedFrameModeActive), keyed by screen.name property var dockStates: ({}) - // Dock slide offsets — hot-path updates separated from full geometry state property var dockSlides: ({}) - // Surfaces are keyed by screen.name. FrameWindow watches to refresh connected chrome - // after claim/release boundaries without tracking each animation frame property var surfaceRevisions: ({}) function _cloneDict(src) { @@ -353,7 +348,6 @@ Singleton { dockStates = next; _clearSurfaceDescriptor(screenName, "dock"); - // Also clear corresponding slide if (dockSlides[screenName]) { const nextSlides = _cloneDict(dockSlides); delete nextSlides[screenName]; @@ -454,7 +448,6 @@ Singleton { return true; } - // DankModal / DankLauncherV2Modal State readonly property var emptyModalState: ({ "visible": false, "barSide": "bottom", @@ -655,9 +648,6 @@ Singleton { return false; } - // Prune state for screens that are no longer connected. Stale entries - // accumulate across hotplug cycles otherwise — Frame's per-screen - // FrameInstance doesn't notice when its peer dicts go orphan. function _pruneToLiveScreens() { const live = {}; const screens = Quickshell.screens || []; diff --git a/quickshell/Common/ElevationShadow.qml b/quickshell/Common/ElevationShadow.qml index 9260f6e5..45ba3647 100644 --- a/quickshell/Common/ElevationShadow.qml +++ b/quickshell/Common/ElevationShadow.qml @@ -19,7 +19,6 @@ Item { property color borderColor: "transparent" property real borderWidth: 0 - // Rounded-rect geometry within the item; defaults fill the item. property real sourceX: 0 property real sourceY: 0 property real sourceWidth: width @@ -36,8 +35,6 @@ Item { readonly property var _ambient: Theme.elevationAmbient(level) readonly property real _pad: shadowEnabled ? Math.ceil(Math.max(shadowBlurPx + shadowSpreadPx + Math.max(Math.abs(shadowOffsetX), Math.abs(shadowOffsetY)), _ambient.blurPx + _ambient.spreadPx) + 2) : 0 - // Fill + border + key/ambient shadows drawn analytically on one oversized - // quad — no FBO, no blur passes. ShaderEffect { anchors.fill: parent anchors.margins: -root._pad diff --git a/quickshell/Common/Theme.qml b/quickshell/Common/Theme.qml index 22124e89..fd03fed8 100644 --- a/quickshell/Common/Theme.qml +++ b/quickshell/Common/Theme.qml @@ -911,9 +911,6 @@ Singleton { } return Qt.rgba(r, g, b, alpha); } - // Non-directional ambient layer of the M3 two-part shadow model (key + - // ambient). Derived from the key level so user intensity/opacity settings - // scale both layers together. function elevationAmbient(level) { const blur = (level && level.blurPx !== undefined) ? Math.max(0, level.blurPx) : 0; const alpha = ((level && level.alpha !== undefined) ? level.alpha : 0.3) * 0.5; diff --git a/quickshell/Modals/Common/DankModal.qml b/quickshell/Modals/Common/DankModal.qml index c5106143..820bb249 100644 --- a/quickshell/Modals/Common/DankModal.qml +++ b/quickshell/Modals/Common/DankModal.qml @@ -54,10 +54,7 @@ Item { anchors.fill: parent } - // One focus grab for every modal; on Hyprland this is what delivers - // keyboard focus to the OnDemand surface, identically in both modes. - // The full-surface content window receives outside clicks itself, so an - // outside click closes the modal instead of being consumed by the grab. + // Hyprland OnDemand grab delivers keyboard focus to the modal content surface. HyprlandFocusGrab { windows: root.contentWindow ? [root.contentWindow] : [] active: KeyboardFocus.wantsGrab(root.shouldHaveFocus, root.customKeyboardFocus) @@ -105,8 +102,6 @@ Item { } } - // Defer Loader source-component swap until impl is fully closed; avoids - // tearing down a modal mid-animation when frame mode is toggled. function _maybeResolveBackend() { if (_resolvedBackend === _desiredBackend) return; diff --git a/quickshell/Modals/Common/DankModalConnected.qml b/quickshell/Modals/Common/DankModalConnected.qml index 25f2a208..37e82dc0 100644 --- a/quickshell/Modals/Common/DankModalConnected.qml +++ b/quickshell/Modals/Common/DankModalConnected.qml @@ -31,7 +31,6 @@ Item { property bool closeOnBackgroundClick: true property string animationType: "scale" - // Opposite side from the launcher by default; subclasses may override property string preferredConnectedBarSide: SettingsData.frameModalEmergeSide readonly property bool frameConnectedMode: SettingsData.frameEnabled && Theme.isConnectedEffect && !!effectiveScreen && SettingsData.isScreenInPreferences(effectiveScreen, SettingsData.frameScreenPreferences) @@ -94,7 +93,6 @@ Item { signal dialogClosed signal backgroundClicked - // Coalesce per-channel dirty bits; one ConnectedModeState write per tick. Timer { id: _syncTimer interval: 0 @@ -342,7 +340,6 @@ Item { return SettingsData.frameEdgeInsetForSide(effectiveScreen, side); } - // frameEdgeInsetForSide is the full inset; do not add frameBarSize readonly property real _connectedAlignedX: { switch (resolvedConnectedBarSide) { case "top": @@ -471,12 +468,9 @@ Item { } } - // Reveal frame: when the frame owns the connected chrome, the content - // must only become visible inside the modal's final footprint so it - // emerges in step with the chrome growing from the bar edge (the old - // two-window layout got this for free from the window boundary). Item { id: connectedReveal + // Clip to final footprint while frame-owned chrome grows from the bar edge. x: root.alignedX y: root.alignedY width: root.alignedWidth @@ -512,7 +506,6 @@ Item { readonly property real customDistRight: root.screenWidth - customAnchorX readonly property real customDistTop: customAnchorY readonly property real customDistBottom: root.screenHeight - customAnchorY - // Connected emergence: travel from the resolved bar edge, matching DankPopout cadence. readonly property real connectedEmergenceTravelX: Math.max(root.animationOffset, root.alignedWidth + Theme.spacingL) readonly property real connectedEmergenceTravelY: Math.max(root.animationOffset, root.alignedHeight + Theme.spacingL) readonly property real offsetX: { @@ -580,7 +573,6 @@ Item { return directionalTravel; return 0; default: - // Default to sliding down from top when centered return -Math.max(directionalTravel, root.screenHeight * 0.24); } } @@ -603,7 +595,6 @@ Item { readonly property real computedScaleCollapsed: root.animationScaleCollapsed - // openProgress: 0 = closed (at frozenMotionOffset, scaleCollapsed), 1 = open (at 0, scale 1). QtObject { id: morph property real openProgress: root.shouldBeVisible ? 1 : 0 diff --git a/quickshell/Modals/DankLauncherV2/DankLauncherV2ModalConnected.qml b/quickshell/Modals/DankLauncherV2/DankLauncherV2ModalConnected.qml index 4d7a0b22..15a3b2bf 100644 --- a/quickshell/Modals/DankLauncherV2/DankLauncherV2ModalConnected.qml +++ b/quickshell/Modals/DankLauncherV2/DankLauncherV2ModalConnected.qml @@ -30,7 +30,6 @@ Item { property string _pendingMode: "" readonly property bool unloadContentOnClose: SettingsData.dankLauncherV2UnloadOnClose - // Animation state — matches DankPopout/DankModal pattern property bool animationsEnabled: true property bool _motionActive: false property real _frozenMotionX: 0 @@ -108,8 +107,6 @@ Item { return SettingsData.frameEdgeInsetForSide(effectiveScreen, side); } - // frameEdgeInsetForSide is the full inset; do not add frameBarSize. - // Positions the modal flush to the emerge side, centered on the cross axis. readonly property var _connectedModalPos: { const fallback = { "x": (screenWidth - modalWidth) / 2, @@ -175,8 +172,6 @@ Item { readonly property int effectiveBorderWidth: connectedSurfaceOverride ? 0 : borderWidth readonly property bool effectiveBlurEnabled: Theme.connectedSurfaceBlurEnabled - // Shadow padding for the content window (render padding only, no motion padding). - // Zeroed when frame owns the chrome and Wayland clips past the bar edge readonly property var shadowLevel: Theme.elevationLevel3 readonly property real shadowFallbackOffset: 6 readonly property real shadowRenderPadding: (!frameOwnsConnectedChrome && Theme.elevationEnabled && SettingsData.modalElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, Theme.elevationLightDirection, shadowFallbackOffset, 8, 16) : 0 @@ -203,13 +198,11 @@ Item { } readonly property real contentSurfaceHeight: launcherArcExtenderActive ? _connectedChromeHeight : alignedHeight - // Where the content container sits inside the full-surface content window (screen coordinates) readonly property real _ccX: _connectedChromeX readonly property real _ccY: _connectedChromeY signal dialogClosed - // Coalesce per-channel dirty bits; one ConnectedModeState write per tick. Timer { id: _syncTimer interval: 0 @@ -365,8 +358,6 @@ Item { return; contentVisible = true; spotlightContent.closeTransientUi?.(); - // NOTE: forceActiveFocus() is deliberately NOT called here. - // It is deferred to after animation starts to avoid compositor IPC stalls. if (spotlightContent.searchField) { spotlightContent.searchField.text = query; @@ -404,10 +395,8 @@ Item { isClosing = false; openedFromOverview = false; - // Disable animations so the snap is instant animationsEnabled = false; - // Freeze the collapsed offsets (they depend on height which could change) _frozenMotionX = contentContainer ? contentContainer.collapsedMotionX : 0; _frozenMotionY = contentContainer ? contentContainer.collapsedMotionY : (Theme.isDirectionalEffect ? Math.max(root.screenHeight - root._ccY + root.shadowPad, Theme.effectAnimOffset * 1.1) : -Theme.effectAnimOffset); @@ -416,24 +405,19 @@ Item { contentWindow.screen = focusedScreen; } - // _motionActive = false ensures motionX/Y snap to frozen collapsed position _motionActive = false; - // Make windows visible but do NOT request keyboard focus yet ModalManager.openModal(modalHandle); spotlightOpen = true; contentWindow.visible = true; - // Load content and initialize (but no forceActiveFocus — that's deferred) _ensureContentLoadedAndInitialize(query || "", mode || ""); - // Frame 1: enable animations and trigger enter motion + // Defer focus until after enter motion starts (avoids compositor IPC stalls). Qt.callLater(() => { root.animationsEnabled = true; root._motionActive = true; - // Frame 2: request keyboard focus + activate search field - // Double-deferred to avoid compositor IPC competing with animation frames Qt.callLater(() => { root.keyboardActive = true; if (root.spotlightContent && root.spotlightContent.searchField) @@ -456,11 +440,9 @@ Item { spotlightContent?.closeTransientUi?.(); openedFromOverview = false; isClosing = true; - // For directional effects, defer contentVisible=false so content stays rendered during exit slide if (!Theme.isDirectionalEffect) contentVisible = false; - // Trigger exit animation — Behaviors will animate motionX/Y to frozen collapsed position _motionActive = false; keyboardActive = false; @@ -612,8 +594,6 @@ Item { } } - // Dismissable area: everything except the bar/dock strips, so bar - // widgets stay clickable for widget-to-widget transfer. Item { id: dismissArea visible: false @@ -712,7 +692,6 @@ Item { return -Math.max((root.shadowPad || 0) + Theme.effectAnimOffset, 40); } - // openProgress: 0 = closed (at frozenMotion, scaleCollapsed), 1 = open (at 0, scale 1). QtObject { id: morph property real openProgress: root._motionActive ? 1 : 0 @@ -771,7 +750,6 @@ Item { width: contentContainer.width height: contentContainer.height - // Shadow mirrors contentWrapper position/scale/opacity ElevationShadow { id: launcherShadowLayer width: parent.width @@ -789,7 +767,6 @@ Item { shadowEnabled: !root.frameOwnsConnectedChrome && Theme.elevationEnabled && SettingsData.modalElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" } - // contentWrapper moves inside static contentContainer — DankPopout pattern Item { id: contentWrapper width: parent.width diff --git a/quickshell/Modules/Frame/FrameBorder.qml b/quickshell/Modules/Frame/FrameBorder.qml index 543654f0..976817ad 100644 --- a/quickshell/Modules/Frame/FrameBorder.qml +++ b/quickshell/Modules/Frame/FrameBorder.qml @@ -3,10 +3,7 @@ pragma ComponentBehavior: Bound import QtQuick import qs.Common -// Frame perimeter ring: the full window rectangle with a rounded-rectangle -// cutout, rendered as a signed-distance field with analytic antialiasing. -// One primitive: no full-output mask textures, no corner double-blend, crisp -// edges at any scale without an FBO. +// Frame perimeter ring with rounded cutout (SDF). Item { id: root diff --git a/quickshell/Modules/Frame/FrameWindow.qml b/quickshell/Modules/Frame/FrameWindow.qml index c9ea1823..880a266c 100644 --- a/quickshell/Modules/Frame/FrameWindow.qml +++ b/quickshell/Modules/Frame/FrameWindow.qml @@ -92,8 +92,6 @@ PanelWindow { readonly property real _notifStartUnderlapValue: win._notifDescriptor.omitStartConnector ? win._seamOverlap : 0 readonly property real _notifEndUnderlapValue: win._notifDescriptor.omitEndConnector ? win._seamOverlap : 0 - // Theme.snap rounds to integer pixel: equal rounded values suppress - // downstream Changed during sub-pixel morph jitter. readonly property var _popoutRadii: SurfaceGeometry.connectorRadii(win._popoutDescriptor, win._popoutBodyGeometry, win._ccr, win._surfaceRadius, win._dpr, false) readonly property real _effectivePopoutCcr: win._popoutRadii.near readonly property real _effectivePopoutFarCcr: win._popoutRadii.far @@ -125,12 +123,8 @@ PanelWindow { readonly property real _surfaceRadius: Theme.connectedSurfaceRadius readonly property real _seamOverlap: Theme.hairline(win._dpr) readonly property bool _disableLayer: Quickshell.env("DMS_DISABLE_LAYER") === "true" || Quickshell.env("DMS_DISABLE_LAYER") === "1" - // Both elevation states render through the SDF shader; this only toggles - // the shadow term inside it. readonly property bool _elevationShadow: win._connectedActive && Theme.elevationEnabled && !win._disableLayer - // Active surfaces packed into four fixed SDF-shader slots. Each near (bar) - // edge is clamped to the cutout edge so the smooth-min connector attaches - // there; the per-corner smin radius is that corner's junction fillet. + // Pack active connected surfaces into four fixed SDF slots (near edges clamp to cutout). readonly property var _sdfSlots: { const T = win.cutoutTopInset; const L = win.cutoutLeftInset; @@ -158,16 +152,7 @@ PanelWindow { const s = src[i]; const b = clampNear(s.side, s.body); const active = b.width > 0 && b.height > 0 ? 1 : 0; - // Map start/end (left/top, right/bottom) onto corners - // (tl,tr,br,bl): bar-side corners take their near connector - // fillet, far corners always take the far fillet so a body - // meeting a perpendicular border joins with an arc (smin is - // inert when nothing is within k). A bar-side corner is sharp - // where its connector is present; an omitted connector makes - // its far corner sharp instead (the far-cap join). const sc = s.radii.startCr, ec = s.radii.endCr; - // Clamp the far fillet to the body extent so it cannot flare - // back across a shallow body into the bar mid-animation. const extent = (s.side === "top" || s.side === "bottom") ? b.height : b.width; const fc = Math.min(s.radii.farCr, extent); const omitS = s.radii.farStartCr > 0; @@ -175,9 +160,6 @@ PanelWindow { const bodyR = s.radii.surfaceRadius; const nearS = omitS ? bodyR : 0, nearE = omitE ? bodyR : 0; const farS = omitS ? 0 : bodyR, farE = omitE ? 0 : bodyR; - // An omitted bar-side corner sits flush against the border, so - // it keeps a nonzero fillet (a zero k hard-joins the coincident - // edges and shows a half-coverage hairline along the seam). const kS = omitS ? fc : sc, kE = omitE ? fc : ec; let ks, cr; if (s.side === "top") { @@ -221,8 +203,6 @@ PanelWindow { return Math.max(0, Math.min(requested, maxRadius)); } - // Pins every surface blur region to zero while frame blur cannot be - // consumed, so animations stop dirtying the region tree. readonly property bool _blurSurfacesActive: BlurService.enabled && SettingsData.frameBlurEnabled && win._frameActive readonly property int _blurCutoutCompensation: SettingsData.frameOpacity <= 0.2 ? 1 : 0 readonly property int _blurCutoutLeft: Math.max(0, win.cutoutLeftInset - win._blurCutoutCompensation) @@ -235,9 +215,6 @@ PanelWindow { return Math.max(0, Math.min(requested, maxRadius)); } - // Blur regions bind rounded integer pixels directly: equal rounded values - // suppress Changed during sub-pixel motion, and inactive children pin to - // all-zero so the region build skips them. QtObject { id: _notifBodyBlurAnchor @@ -255,7 +232,6 @@ PanelWindow { width: win._windowRegionWidth height: win._windowRegionHeight - // Frame cutout (always active when frame is on) Region { id: _blurCutout intersection: Intersection.Subtract @@ -829,7 +805,6 @@ PanelWindow { } } - // Notif body scene rect, accounting for start/end/side underlaps per bar orientation. function _notifBodyScene() { const isHoriz = SurfaceGeometry.isHorizontal(win._notifDescriptor.barSide); const start = win._notifStartUnderlapValue; @@ -861,9 +836,6 @@ PanelWindow { return Math.max(0, Math.min(win._effectivePopoutMaxCcr, extent - win._surfaceRadius)); } - // Active connected surfaces fed to the unified silhouette path. Raw animated - // body rects (no seam/fill overlap); the builder anchors each to the cutout - // edge. Connector radii use the same per-surface helpers as the blur regions. function _unifiedSurfaces() { const arr = []; const p = win._popoutBodyGeometry; @@ -971,8 +943,6 @@ PanelWindow { } catch (e) {} } - // Coalesce bursts of settings-change signals into a single _buildBlur() call - // on the next event loop tick. DeferredAction { id: blurRebuildAction onTriggered: win._runBlurRebuild() @@ -1096,10 +1066,6 @@ PanelWindow { cutoutRadius: win.cutoutRadius } - // The entire connected silhouette (frame ring + every active chrome) as one - // SDF in a fragment shader. Analytic fwidth AA → crisp at any scale, no FBO; - // the smooth-min radius is the connector. The elevation shadow is derived - // from the same distance field, so elevation-on needs no grouping layer. ShaderEffect { anchors.fill: parent visible: win._connectedActive diff --git a/quickshell/Shaders/frag/connected_arc.frag b/quickshell/Shaders/frag/connected_arc.frag index 04c11586..be485683 100644 --- a/quickshell/Shaders/frag/connected_arc.frag +++ b/quickshell/Shaders/frag/connected_arc.frag @@ -1,11 +1,6 @@ #version 450 -// Connected Frame Mode silhouette as a signed-distance field: the frame ring -// (an inverted rounded rectangle) smooth-unioned with each active chrome -// (popout/modal, dock, notification). The smooth-min radius IS the connector -// fillet. Antialiasing is analytic via fwidth -> crisp at any scale, no FBO. -// The elevation shadow samples the same field at the light offset, so both -// elevation states render in this one pass. +// Connected frame silhouette: frame ring + chrome bodies as one SDF with elevation shadow. layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; @@ -53,7 +48,6 @@ float sdRoundBox(vec2 p, vec2 c, vec2 hs, float r) { return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - r; } -// Per-corner rounded box. r = (topLeft, topRight, bottomRight, bottomLeft). float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) { p -= c; float rr = (p.x >= 0.0) ? (p.y >= 0.0 ? r.z : r.y) : (p.y >= 0.0 ? r.w : r.x); @@ -62,7 +56,6 @@ float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) { return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - rr; } -// Circular smooth-min: blends two SDFs with a fillet of radius k. float smin(float a, float b, float k) { if (k <= 0.0) return min(a, b); @@ -74,14 +67,12 @@ float chromeDist(vec2 px, vec4 rect, vec4 corner) { return sdRoundBox4(px, c, rect.zw * 0.5, corner); } -// Per-corner junction fillet radius, selected by chrome-rect quadrant. float chromeK(vec2 px, vec4 rect, vec4 ks) { vec2 p = px - (rect.xy + rect.zw * 0.5); return (p.x >= 0.0) ? (p.y >= 0.0 ? ks.z : ks.y) : (p.y >= 0.0 ? ks.w : ks.x); } float sceneDist(vec2 px) { - // Frame ring: inside the screen rect AND outside the rounded cutout (hole). vec2 sc = vec2(ubuf.widthPx, ubuf.heightPx) * 0.5; float dOuter = sdBox(px, sc, sc); vec2 cutC = vec2((ubuf.cutout.x + ubuf.cutout.z) * 0.5, (ubuf.cutout.y + ubuf.cutout.w) * 0.5); @@ -89,7 +80,6 @@ float sceneDist(vec2 px) { float dCut = sdRoundBox(px, cutC, cutH, ubuf.cutoutRadius); float d = max(dOuter, -dCut); - // Smooth-union the active chrome surfaces; smin radius = junction fillet. if (ubuf.chromeParam0.x > 0.5) d = smin(d, chromeDist(px, ubuf.chromeRect0, ubuf.chromeCorner0), chromeK(px, ubuf.chromeRect0, ubuf.chromeK0)); if (ubuf.chromeParam1.x > 0.5) @@ -106,14 +96,11 @@ void main() { float d = sceneDist(px); float fw = max(fwidth(d), 1e-4); float cov = 1.0 - smoothstep(-fw, fw, d); - // Opaque silhouette over shadow, then the surface alpha applied to the - // whole result — matches the old flattened-FBO + group-opacity look. vec4 col = vec4(ubuf.surfaceColor.rgb, 1.0) * cov; if (ubuf.shadowColor.a > 0.0) { float dk = sceneDist(px - ubuf.shadowParam.zw) - ubuf.shadowParam.y; float bk = max(ubuf.shadowParam.x, fw); float covK = 1.0 - smoothstep(-bk, bk, dk); - // Ambient wrap reuses the field already computed for the silhouette. float ba = max(ubuf.ambientParam.x, fw); float covA = 1.0 - smoothstep(-ba, ba, d - ubuf.ambientParam.y); float sh = 1.0 - (1.0 - covK * ubuf.shadowColor.a) * (1.0 - covA * ubuf.ambientParam.z); diff --git a/quickshell/Shaders/frag/connected_chrome.frag b/quickshell/Shaders/frag/connected_chrome.frag index 5e8f63b7..c106972f 100644 --- a/quickshell/Shaders/frag/connected_chrome.frag +++ b/quickshell/Shaders/frag/connected_chrome.frag @@ -1,9 +1,6 @@ #version 450 -// Popout-local connected chrome as a signed-distance field: the body rounded -// rect smooth-unioned against the bar-edge half-plane, so the connector -// fillets form analytically. Key + ambient shadows sample the same field; -// shadow is masked outside the silhouette. +// Popout-local connected chrome body + bar-edge connector as one SDF. layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; @@ -22,7 +19,6 @@ layout(std140, binding = 0) uniform buf { vec4 edgeParam; // x = bar side (0 top, 1 bottom, 2 left, 3 right), y = fillet k } ubuf; -// Per-corner rounded box. r = (topLeft, topRight, bottomRight, bottomLeft). float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) { p -= c; float rr = (p.x >= 0.0) ? (p.y >= 0.0 ? r.z : r.y) : (p.y >= 0.0 ? r.w : r.x); @@ -31,7 +27,6 @@ float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) { return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - rr; } -// Circular smooth-min: blends two SDFs with a fillet of radius k. float smin(float a, float b, float k) { if (k <= 0.0) return min(a, b); @@ -39,8 +34,6 @@ float smin(float a, float b, float k) { } float sceneDist(vec2 px) { - // Bar edge as a half-plane whose interior lies off-item, on the bar's - // side; only its fillet contribution is visible. float side = ubuf.edgeParam.x; float dEdge = side < 0.5 ? px.y : side < 1.5 ? (ubuf.heightPx - px.y) diff --git a/quickshell/Shaders/frag/elevation_rect.frag b/quickshell/Shaders/frag/elevation_rect.frag index 883c7861..d211eaec 100644 --- a/quickshell/Shaders/frag/elevation_rect.frag +++ b/quickshell/Shaders/frag/elevation_rect.frag @@ -1,10 +1,6 @@ #version 450 -// Standalone elevation surface as a signed-distance field: one quad draws the -// rounded-rect fill, its border, and the M3 two-part shadow (directional key + -// non-directional ambient) analytically — no FBO, no blur passes. The shadow -// is masked to outside the silhouette, so translucent fills never get -// interior darkening. +// Standalone rounded rect with border and M3 elevation shadow as one SDF. layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; @@ -24,7 +20,6 @@ layout(std140, binding = 0) uniform buf { vec4 ambientParam; // ambient: x = blur px, y = spread px, z = alpha } ubuf; -// Per-corner rounded box. r = (topLeft, topRight, bottomRight, bottomLeft). float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) { p -= c; float rr = (p.x >= 0.0) ? (p.y >= 0.0 ? r.z : r.y) : (p.y >= 0.0 ? r.w : r.x); @@ -43,7 +38,6 @@ void main() { float d = rectDist(px); float fw = max(fwidth(d), 1e-4); float cov = 1.0 - smoothstep(-fw, fw, d); - // Qt Rectangle semantics: border band on the rim, fill inset inside it. float covInner = 1.0 - smoothstep(-fw, fw, d + ubuf.borderWidth); vec4 col = vec4(ubuf.fillColor.rgb, 1.0) * (ubuf.fillColor.a * covInner) + vec4(ubuf.borderColor.rgb, 1.0) * (ubuf.borderColor.a * max(0.0, cov - covInner)); diff --git a/quickshell/Shaders/frag/frame_arc.frag b/quickshell/Shaders/frag/frame_arc.frag index d7783b2f..b61975a0 100644 --- a/quickshell/Shaders/frag/frame_arc.frag +++ b/quickshell/Shaders/frag/frame_arc.frag @@ -1,8 +1,6 @@ #version 450 -// Frame perimeter ring as a signed-distance field: the window rectangle minus -// a rounded-rectangle cutout. Antialiasing is analytic via fwidth -> crisp at -// any scale, no FBO and no mask textures. +// Frame perimeter ring with rounded cutout as one SDF. layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; diff --git a/quickshell/Widgets/DankPopout.qml b/quickshell/Widgets/DankPopout.qml index 938e3fe3..1fc6c347 100644 --- a/quickshell/Widgets/DankPopout.qml +++ b/quickshell/Widgets/DankPopout.qml @@ -53,11 +53,7 @@ Item { readonly property var backgroundWindow: impl.item ? impl.item.backgroundWindow : null readonly property var contentWindow: impl.item ? impl.item.contentWindow : null - // On Hyprland the OnDemand content surface only receives keyboard focus - // through a grab; everywhere else Exclusive focus covers this. Both - // popout windows plus every bar are whitelisted so clicks on them are - // delivered normally (dismiss MouseAreas, widget-to-widget transfer) - // instead of being consumed clearing the grab. + // Hyprland OnDemand grab: whitelist popout surfaces and bars so dismiss clicks still land. HyprlandFocusGrab { windows: { const list = []; @@ -146,8 +142,6 @@ Item { return _usesConnectedBackendForScreen(targetScreen) ? connectedComp : standaloneComp; } - // Defer Loader source-component swap until impl is fully closed; avoids - // tearing down a popout mid-animation when frame mode is toggled. function _maybeResolveBackend() { _resolveBackendForScreen(screen); } diff --git a/quickshell/Widgets/DankPopoutConnected.qml b/quickshell/Widgets/DankPopoutConnected.qml index 624fd8f5..3d88a5ce 100644 --- a/quickshell/Widgets/DankPopoutConnected.qml +++ b/quickshell/Widgets/DankPopoutConnected.qml @@ -53,7 +53,6 @@ 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 var effectivePopoutLayer: LayerShell.fromEnv("DMS_POPOUT_LAYER", root.triggerUsesOverlayLayer ? WlrLayer.Overlay : WlrLayer.Top, { "allow": ["top", "overlay"], @@ -91,7 +90,6 @@ Item { signal popoutClosed signal backgroundClicked - // Coalesce per-channel dirty bits; one ConnectedModeState write per tick. Timer { id: _syncTimer interval: 0 @@ -278,11 +276,9 @@ Item { chromeLease.release(); } - // ─── Exposed animation state for ConnectedModeState ──────────────────── readonly property real contentAnimX: contentContainer.animX readonly property real contentAnimY: contentContainer.animY - // ─── ConnectedModeState sync ──────────────────────────────────────────── function _syncPopoutChromeState() { if (!root.frameOwnsConnectedChrome) { _releaseConnectedChromeState(); @@ -422,16 +418,12 @@ Item { const screenChanged = _lastOpenedScreen !== null && _lastOpenedScreen !== screen; if (screenChanged) { - // Hide on this tick so Qt actually tears down the wl_surface; the show - // gets deferred below so the unmap is processed before the remap. contentWindow.visible = false; } _lastOpenedScreen = screen; PopoutManager.showPopout(popoutHandle); if (contentContainer) { - // Snap morph closed only on a fresh open; on screen-change re-open we stay at 1 - // because shouldBeVisible doesn't change and won't drive morph back to 1. if (!shouldBeVisible) morph.openProgress = 0; _captureChromeAnimTravel(); @@ -445,11 +437,7 @@ Item { } if (screenChanged) { - // Defer the show one event-loop tick. Qt coalesces a synchronous - // false→true visibility flip into a no-op, leaving WindowBlur committed - // to the previous screen's wl_surface. Splitting the flip across ticks - // forces a real surface destroy+create so BackgroundEffect.surfaceCreated - // fires and the blur region republishes on the new surface. + // Unmap/remap wl_surface across ticks so blur republishes on the new screen. Qt.callLater(() => { if (!root.shouldBeVisible) return; @@ -568,9 +556,7 @@ Item { return Math.abs(value - bound) <= Math.max(1, Theme.hairline(root.dpr) * 2); } - // Snap a frame-perpendicular position flush to the frame bound when it - // lands within the connector radius: a gap smaller than the radius cannot - // form the close-gap arc and renders as a pinched wedge instead. + // Snap positions within connector radius flush to the frame edge (avoids pinched arcs). function _snapNearFrameBound(value, minBound, maxBound, minIsFrame, maxIsFrame) { if (!root.usesConnectedSurfaceChrome || !root.closeFrameGapsActive) return value; @@ -637,7 +623,6 @@ Item { property real renderedAlignedY: alignedY property real renderedAlignedHeight: alignedHeight readonly property bool renderedGeometryGrowing: alignedHeight >= renderedAlignedHeight - // Snap rendered geometry while the entrance morph runs so it doesn't ride a second animation (side-bar ramp). readonly property bool _settlingToOpen: fullHeightSurface && shouldBeVisible && morphAnim.running Behavior on renderedAlignedY { @@ -687,8 +672,6 @@ Item { return 0; if (!root.usesConnectedSurfaceChrome) return exclusion; - // In a shared frame corner, the adjacent connected bar already occupies - // one rounded-corner radius before the popout's own connector begins. return exclusion + Theme.connectedCornerRadius * 2; } @@ -721,10 +704,8 @@ Item { switch (effectiveBarPosition) { case SettingsData.Position.Left: - // bar on left: left side is bar-adjacent (popupGap), right side is frame-perpendicular (edgeGap) return Math.max(popupGap, Math.min(screenWidth - popupWidth - edgeGapRight, anchorX)); case SettingsData.Position.Right: - // bar on right: right side is bar-adjacent (popupGap), left side is frame-perpendicular (edgeGap) return Math.max(edgeGapLeft, Math.min(screenWidth - popupWidth - popupGap, anchorX - popupWidth)); default: const rawX = triggerX + (triggerWidth / 2) - (popupWidth / 2); @@ -744,10 +725,8 @@ Item { switch (effectiveBarPosition) { case SettingsData.Position.Bottom: - // bar on bottom: bottom side is bar-adjacent (popupGap), top side is frame-perpendicular (edgeGap) return Math.max(edgeGapTop, Math.min(screenHeight - popupHeight - popupGap, anchorY - popupHeight)); case SettingsData.Position.Top: - // bar on top: top side is bar-adjacent (popupGap), bottom side is frame-perpendicular (edgeGap) return Math.max(popupGap, Math.min(screenHeight - popupHeight - edgeGapBottom, anchorY)); default: const rawY = triggerY - (popupHeight / 2); @@ -790,8 +769,6 @@ Item { readonly property real s: Math.min(1, contentContainer.scaleValue) readonly property bool trackBlurFromBarEdge: root.usesConnectedSurfaceChrome - // Connected chrome clips to the bar edge, so its blur grows from - // that same edge instead of translating through the bar before settling. readonly property real _dyClamp: (contentContainer.barTop || contentContainer.barBottom) ? Math.max(-contentContainer.height, Math.min(contentContainer.animY, contentContainer.height)) : 0 readonly property real _dxClamp: (contentContainer.barLeft || contentContainer.barRight) ? Math.max(-contentContainer.width, Math.min(contentContainer.animX, contentContainer.width)) : 0 @@ -827,7 +804,6 @@ Item { Region { id: contentInputMask - // Use bar-aware mask so bar widget clicks pass through when a popout is open. item: (shouldBeVisible && backgroundInteractive) ? backgroundDismissalMask : contentMaskRect } @@ -938,7 +914,6 @@ Item { readonly property real computedScaleCollapsed: root.animationScaleCollapsed - // openProgress: 0 = closed (at offset, scaleCollapsed), 1 = open (at 0, scale 1). QtObject { id: morph property real openProgress: 0 @@ -985,7 +960,6 @@ Item { clip: shouldClip - // Bound the clipping strictly to the bar side, allowing massive overflow on the other 3 sides for shadows x: shouldClip ? (contentContainer.barLeft ? -connectedClipAllowance : -clipOversize) : 0 y: shouldClip ? (contentContainer.barTop ? -connectedClipAllowance : -clipOversize) : 0 @@ -1043,8 +1017,6 @@ Item { shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive) && !root.frameOwnsConnectedChrome } - // Local connected chrome (body + connector fillets joined to - // the bar edge) and its shadow as one SDF quad — no FBO. Item { id: localChrome visible: root.usesLocalConnectedSurfaceChrome @@ -1070,8 +1042,6 @@ Item { ShaderEffect { anchors.fill: parent - // Shadow overflow pads every side except the bar - // edge, where the silhouette must end flush. anchors.topMargin: contentContainer.barTop ? 0 : -localChrome.pad anchors.bottomMargin: contentContainer.barBottom ? 0 : -localChrome.pad anchors.leftMargin: contentContainer.barLeft ? 0 : -localChrome.pad @@ -1144,8 +1114,6 @@ Item { Connections { target: contentWindow function onVisibleChanged() { - // open() flips contentWindow.visible to rebind the layer surface to - // a new screen; don't deactivate the wrapper while still open. if (!contentWindow.visible && !root.shouldBeVisible) contentWrapper._renderActive = false; } diff --git a/quickshell/Widgets/DismissZone.qml b/quickshell/Widgets/DismissZone.qml index 24b81a0d..c463997f 100644 --- a/quickshell/Widgets/DismissZone.qml +++ b/quickshell/Widgets/DismissZone.qml @@ -1,7 +1,6 @@ import QtQuick import qs.Common -// Defines the screen area (excluding bars) that dismisses popouts QtObject { id: root diff --git a/quickshell/Widgets/WindowBlur.qml b/quickshell/Widgets/WindowBlur.qml index a879e649..f4420dbf 100644 --- a/quickshell/Widgets/WindowBlur.qml +++ b/quickshell/Widgets/WindowBlur.qml @@ -52,10 +52,7 @@ Item { targetWindow.BackgroundEffect.blurRegion = null; } - // Force BackgroundEffect to re-publish the blur region on the current wl_surface. - // Clearing first bypasses Quickshell's same-Region dedup in BackgroundEffect::setBlurRegion, - // setting pendingBlurRegion=true so the next polish actually ships the region — needed - // when the underlying surface has been remapped (e.g. PanelWindow.screen change). + // Re-publish blur region after wl_surface remaps (e.g. screen change). function kick() { if (!targetWindow) return;