Revert "perf(mainscreen): merging fix/damage-control"

This reverts commit 67a7f75c37, reversing
changes made to 8828d9d7be.
This commit is contained in:
Lemmy
2026-03-20 00:29:04 -04:00
parent 039ad4db9c
commit c8d8709c26
11 changed files with 248 additions and 154 deletions
+1
View File
@@ -25,6 +25,7 @@ PanelWindow {
mask: Region {}
// Wayland layer shell configuration
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "noctalia-bar-exclusion-" + (screen?.name || "unknown")
WlrLayershell.exclusionMode: ExclusionMode.Auto
+1
View File
@@ -774,6 +774,7 @@ Loader {
margins.left: peekCenterOffsetX
WlrLayershell.namespace: "noctalia-dock-indicator-" + (screen?.name || "unknown")
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
implicitHeight: isVertical ? peekEdgeLength : indicatorThickness
-14
View File
@@ -103,20 +103,6 @@ Variants {
}
}
// Screen corners - 4 small PanelWindows, one per corner
Repeater {
model: ["topLeft", "topRight", "bottomLeft", "bottomRight"]
delegate: Loader {
active: windowItem.windowLoaded && windowItem.shouldBeActive
asynchronous: false
sourceComponent: ScreenCornerWindow {
screen: windowItem.modelData
corner: modelData
}
}
}
// BarExclusionZone - created after MainScreen has fully loaded
// Note: Exclusion zone should NOT be affected by hideOnOverview setting.
// When bar is hidden during overview, the exclusion zone should remain to prevent
+1
View File
@@ -33,6 +33,7 @@ PanelWindow {
// Wayland layer configuration
WlrLayershell.namespace: "noctalia-bar-content-" + (barWindow.screen?.name || "unknown")
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.exclusionMode: ExclusionMode.Ignore // Don't reserve space - BarExclusionZone in MainScreen handles that
// Position and size to match bar location (per-screen)
+1
View File
@@ -37,6 +37,7 @@ PanelWindow {
mask: Region {}
// Wayland layer shell configuration
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "noctalia-bar-exclusion-" + edge + "-" + (screen?.name || "unknown")
// When auto-hide, non-exclusive mode is enabled, OR bar is explicitly hidden via IPC, don't reserve space
// Note: We check BarService.isVisible directly, NOT effectivelyVisible, because we want
+1
View File
@@ -26,6 +26,7 @@ PanelWindow {
focusable: false
WlrLayershell.namespace: "noctalia-bar-trigger-" + (screen?.name || "unknown")
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.exclusionMode: ExclusionMode.Ignore
// Anchor to bar's edge
+10 -32
View File
@@ -44,6 +44,9 @@ PanelWindow {
}
// Wayland
// As this is always rendered, putting it on the top layer
// would prevent direct scanout for other Wayland clients.
// WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "noctalia-background-" + (screen?.name || "unknown")
WlrLayershell.exclusionMode: ExclusionMode.Ignore // Don't reserve space - BarExclusionZone handles that
WlrLayershell.keyboardFocus: {
@@ -67,37 +70,18 @@ PanelWindow {
}
anchors {
top: isFramed || _needsFullscreen || _barPosition !== "bottom"
bottom: isFramed || _needsFullscreen || _barPosition !== "top"
left: isFramed || _needsFullscreen || _barPosition !== "right"
right: isFramed || _needsFullscreen || _barPosition !== "left"
top: true
bottom: true
left: true
right: true
}
// Implicit sizes control the non-anchored dimension when collapsed (3 anchors).
// Layout: [margin] [bar] [max(margin, shadow)] — screen-edge side uses margin, inner side uses whichever is larger.
// When fullscreen (4 anchors), compositor ignores these.
implicitWidth: Math.ceil(barPlaceholder.barMarginH + barPlaceholder.barHeight + _innerPaddingH)
implicitHeight: Math.ceil(barPlaceholder.barMarginV + barPlaceholder.barHeight + _innerPaddingV)
// Desktop dimming when panels are open
property real dimmerOpacity: Settings.data.general.dimmerOpacity ?? 0.8
property bool isPanelOpen: (PanelService.openedPanel !== null) && (PanelService.openedPanel.screen === screen)
property bool isPanelClosing: (PanelService.openedPanel !== null) && PanelService.openedPanel.isClosing
property bool isAnyPanelOpen: PanelService.openedPanel !== null
// Dynamic fullscreen management — collapse to bar-sized when idle to avoid fullscreen compositor damage
readonly property bool isFramed: Settings.data.bar.barType === "framed"
readonly property string _barPosition: Settings.getBarPositionForScreen(screen?.name)
readonly property bool _barIsVertical: _barPosition === "left" || _barPosition === "right"
property bool _needsFullscreen: isAnyPanelOpen || PanelService.closingPanel !== null || _dimmerAnimating
property bool _dimmerAnimating: false
// Shadow padding for collapsed window — shadow extends beyond bar into the screen
readonly property real _shadowPadding: (Settings.data.general.enableShadows && !PowerProfileService.noctaliaPerformanceMode) ? Style.shadowBlurMax + Math.max(Math.abs(Style.shadowHorizontalOffset), Math.abs(Style.shadowVerticalOffset)) : 0
// Inner padding: the side facing into the screen needs at least shadow clearance
readonly property real _innerPaddingH: Math.max(barPlaceholder.barMarginH, _shadowPadding)
readonly property real _innerPaddingV: Math.max(barPlaceholder.barMarginV, _shadowPadding)
color: {
if (dimmerOpacity > 0 && isPanelOpen && !isPanelClosing) {
return Qt.alpha(Color.mShadow, dimmerOpacity);
@@ -110,7 +94,6 @@ PanelWindow {
ColorAnimation {
duration: isPanelClosing ? Style.animationFaster : Style.animationNormal
easing.type: Easing.OutQuad
onRunningChanged: root._dimmerAnimating = running
}
}
@@ -480,11 +463,6 @@ PanelWindow {
// Expose bar dimensions directly on this Item for BarBackground
// Use screen dimensions directly
x: {
if (!root._needsFullscreen && !root.isFramed) {
// Collapsed: bar is at margin from screen edge, shadow extends inward.
// For right bar the window faces left (inner side first), so bar starts after shadow clearance.
return barPosition === "right" ? root._innerPaddingH : barMarginH;
}
if (barPosition === "right")
return (screen?.width ?? 0) - barHeight - barMarginH;
if (isFramed && !barIsVertical)
@@ -492,9 +470,6 @@ PanelWindow {
return barMarginH;
}
y: {
if (!root._needsFullscreen && !root.isFramed) {
return barPosition === "bottom" ? root._innerPaddingV : barMarginV;
}
if (barPosition === "bottom")
return (screen?.height ?? 0) - barHeight - barMarginV;
if (isFramed && barIsVertical)
@@ -572,6 +547,9 @@ PanelWindow {
}
}
// Screen Corners
ScreenCorners {}
// Blur behind the bar and open panels
// Helper object holding computed properties for blur regions
QtObject {
-87
View File
@@ -1,87 +0,0 @@
import QtQuick
import QtQuick.Shapes
import Quickshell
import Quickshell.Wayland
import qs.Commons
/**
* ScreenCornerWindow - Small PanelWindow that renders a single concave screen corner.
*/
PanelWindow {
id: root
required property string corner // "topLeft", "topRight", "bottomLeft", "bottomRight"
readonly property real s: Style.screenRadius
readonly property bool shouldShow: Settings.data.general.showScreenCorners && s > 0
visible: shouldShow
color: "transparent"
// Click-through
mask: Region {}
WlrLayershell.namespace: "noctalia-corner-" + corner + "-" + (screen?.name || "unknown")
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
anchors {
top: corner === "topLeft" || corner === "topRight"
bottom: corner === "bottomLeft" || corner === "bottomRight"
left: corner === "topLeft" || corner === "bottomLeft"
right: corner === "topRight" || corner === "bottomRight"
}
implicitWidth: Math.ceil(s)
implicitHeight: Math.ceil(s)
// Cache to texture to avoid continuous re-tessellation
Item {
anchors.fill: parent
layer.enabled: true
Shape {
anchors.fill: parent
preferredRendererType: Shape.CurveRenderer
asynchronous: true
enabled: false
visible: root.s > 0 && width > 0 && height > 0
ShapePath {
id: cornerPath
readonly property color cornerColor: Settings.data.general.forceBlackScreenCorners ? "black" : Color.mSurface
strokeWidth: -1
fillColor: root.shouldShow ? cornerColor : "transparent"
Behavior on fillColor {
enabled: !Color.isTransitioning
ColorAnimation {
duration: Style.animationFast
}
}
PathSvg {
path: {
var s = root.s;
if (s <= 0)
return "M -1 -1 L -1 0 L 0 0 Z";
switch (root.corner) {
case "topLeft":
return "M 0 0 L " + s + " 0 A " + s + " " + s + " 0 0 0 0 " + s + " Z";
case "topRight":
return "M 0 0 L " + s + " 0 L " + s + " " + s + " A " + s + " " + s + " 0 0 0 0 0 Z";
case "bottomLeft":
return "M 0 0 A " + s + " " + s + " 0 0 0 " + s + " " + s + " L 0 " + s + " Z";
case "bottomRight":
return "M " + s + " " + s + " L 0 " + s + " A " + s + " " + s + " 0 0 0 " + s + " 0 Z";
default:
return "M -1 -1 L -1 0 L 0 0 Z";
}
}
}
}
}
}
}
+231
View File
@@ -0,0 +1,231 @@
import QtQuick
import QtQuick.Shapes
import qs.Commons
/**
* ScreenCorners - Shape component for rendering screen corners
*
* Renders concave corners at the screen edges to create a rounded screen effect.
* Self-contained Shape component (no shadows).
*/
Item {
id: root
anchors.fill: parent
// Wrapper with layer caching to reduce GPU tessellation overhead
Item {
anchors.fill: parent
// Cache the Shape to a texture to prevent continuous re-tessellation
layer.enabled: true
Shape {
id: cornersShape
anchors.fill: parent
preferredRendererType: Shape.CurveRenderer
asynchronous: true
enabled: false // Disable mouse input
visible: cornersPath.cornerRadius > 0 && width > 0 && height > 0
ShapePath {
id: cornersPath
// Corner configuration
readonly property color cornerColor: Settings.data.general.forceBlackScreenCorners ? "black" : Color.mSurface
readonly property real cornerRadius: Style.screenRadius
readonly property real cornerSize: Style.screenRadius
// Determine margins based on bar position
readonly property real topMargin: 0
readonly property real bottomMargin: 0
readonly property real leftMargin: 0
readonly property real rightMargin: 0
// Screen dimensions
readonly property real screenWidth: cornersShape.width
readonly property real screenHeight: cornersShape.height
// Only show screen corners if enabled and appropriate conditions are met
readonly property bool shouldShow: Settings.data.general.showScreenCorners
// ShapePath configuration
strokeWidth: -1 // No stroke, fill only
fillColor: shouldShow ? cornerColor : "transparent"
// Smooth color animation (disabled during theme transitions to sync with Color.qml)
Behavior on fillColor {
enabled: !Color.isTransitioning
ColorAnimation {
duration: Style.animationFast
}
}
// ========== PATH DEFINITION ==========
// Draws 4 separate corner squares at screen edges
// Each corner square has a concave arc on the inner diagonal
// ========== TOP-LEFT CORNER ==========
// Arc is at the bottom-right of this square (inner diagonal)
// Start at top-left screen corner
startX: leftMargin
startY: topMargin
// Top edge (moving right)
PathLine {
relativeX: cornersPath.cornerSize
relativeY: 0
}
// Right edge (moving down toward arc)
PathLine {
relativeX: 0
relativeY: cornersPath.cornerSize - cornersPath.cornerRadius
}
// Concave arc (bottom-right corner of square, curving inward toward screen center)
PathArc {
relativeX: -cornersPath.cornerRadius
relativeY: cornersPath.cornerRadius
radiusX: cornersPath.cornerRadius
radiusY: cornersPath.cornerRadius
direction: PathArc.Counterclockwise
}
// Bottom edge (moving left)
PathLine {
relativeX: -(cornersPath.cornerSize - cornersPath.cornerRadius)
relativeY: 0
}
// Left edge (moving up) - closes back to start
PathLine {
relativeX: 0
relativeY: -cornersPath.cornerSize
}
// ========== TOP-RIGHT CORNER ==========
// Arc is at the bottom-left of this square (inner diagonal)
PathMove {
x: cornersPath.screenWidth - cornersPath.rightMargin - cornersPath.cornerSize
y: cornersPath.topMargin
}
// Top edge (moving right)
PathLine {
relativeX: cornersPath.cornerSize
relativeY: 0
}
// Right edge (moving down)
PathLine {
relativeX: 0
relativeY: cornersPath.cornerSize
}
// Bottom edge (moving left toward arc)
PathLine {
relativeX: -(cornersPath.cornerSize - cornersPath.cornerRadius)
relativeY: 0
}
// Concave arc (bottom-left corner of square, curving inward toward screen center)
PathArc {
relativeX: -cornersPath.cornerRadius
relativeY: -cornersPath.cornerRadius
radiusX: cornersPath.cornerRadius
radiusY: cornersPath.cornerRadius
direction: PathArc.Counterclockwise
}
// Left edge (moving up) - closes back to start
PathLine {
relativeX: 0
relativeY: -(cornersPath.cornerSize - cornersPath.cornerRadius)
}
// ========== BOTTOM-LEFT CORNER ==========
// Arc is at the top-right of this square (inner diagonal)
PathMove {
x: cornersPath.leftMargin
y: cornersPath.screenHeight - cornersPath.bottomMargin - cornersPath.cornerSize
}
// Top edge (moving right toward arc)
PathLine {
relativeX: cornersPath.cornerSize - cornersPath.cornerRadius
relativeY: 0
}
// Concave arc (top-right corner of square, curving inward toward screen center)
PathArc {
relativeX: cornersPath.cornerRadius
relativeY: cornersPath.cornerRadius
radiusX: cornersPath.cornerRadius
radiusY: cornersPath.cornerRadius
direction: PathArc.Counterclockwise
}
// Right edge (moving down)
PathLine {
relativeX: 0
relativeY: cornersPath.cornerSize - cornersPath.cornerRadius
}
// Bottom edge (moving left)
PathLine {
relativeX: -cornersPath.cornerSize
relativeY: 0
}
// Left edge (moving up) - closes back to start
PathLine {
relativeX: 0
relativeY: -cornersPath.cornerSize
}
// ========== BOTTOM-RIGHT CORNER ==========
// Arc is at the top-left of this square (inner diagonal)
// Start at bottom-right of square (different from other corners!)
PathMove {
x: cornersPath.screenWidth - cornersPath.rightMargin
y: cornersPath.screenHeight - cornersPath.bottomMargin
}
// Bottom edge (moving left)
PathLine {
relativeX: -cornersPath.cornerSize
relativeY: 0
}
// Left edge (moving up toward arc)
PathLine {
relativeX: 0
relativeY: -(cornersPath.cornerSize - cornersPath.cornerRadius)
}
// Concave arc (top-left corner of square, curving inward toward screen center)
PathArc {
relativeX: cornersPath.cornerRadius
relativeY: -cornersPath.cornerRadius
radiusX: cornersPath.cornerRadius
radiusY: cornersPath.cornerRadius
direction: PathArc.Counterclockwise
}
// Top edge (moving right)
PathLine {
relativeX: cornersPath.cornerSize - cornersPath.cornerRadius
relativeY: 0
}
// Right edge (moving down) - closes back to start
PathLine {
relativeX: 0
relativeY: cornersPath.cornerSize
}
}
}
}
}
+2 -12
View File
@@ -145,10 +145,8 @@ Item {
// Panel visibility and sizing
visible: isPanelVisible
// Always use screen dimensions for layout — MainScreen may be collapsed to bar-sized when idle,
// but panels must compute positions and sizes against the full screen.
width: screen?.width ?? (parent ? parent.width : 0)
height: screen?.height ?? (parent ? parent.height : 0)
width: parent ? parent.width : 0
height: parent ? parent.height : 0
// Panel control functions
function toggle(buttonItem, buttonName) {
@@ -292,11 +290,6 @@ Item {
PanelService.closedPanel(root);
closed();
// Flush pending double-buffered Wayland state (blur regions) that won't
// be committed otherwise — after an app launch the compositor may stop
// sending frame callbacks, leaving the render loop idle.
Window.window?.flushWaylandState();
Logger.d("SmartPanel", "Panel closed immediately", objectName);
}
@@ -323,9 +316,6 @@ Item {
PanelService.closedPanel(root);
closed();
// Flush pending double-buffered Wayland state (blur regions).
Window.window?.flushWaylandState();
Logger.d("SmartPanel", "Panel close finalized", objectName);
}
-9
View File
@@ -399,15 +399,6 @@ Singleton {
assignToSlot(1, null);
}
// Reset closedImmediately after the current event cycle so all Behaviors
// that check it have processed their snaps. Cannot rely on MainScreen's
// onColorChanged because the color may already be transparent (dimmerOpacity=0).
if (closedImmediately) {
Qt.callLater(() => {
closedImmediately = false;
});
}
// Reset keyboard init state
isInitializingKeyboard = false;
keyboardInitTimer.stop();