upd
This commit is contained in:
113
Shell/Notifications/NotificationLayer.qml
Normal file
113
Shell/Notifications/NotificationLayer.qml
Normal file
@@ -0,0 +1,113 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import ".."
|
||||
|
||||
PanelWindow {
|
||||
id: notificationLayer
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
right: true
|
||||
}
|
||||
|
||||
margins {
|
||||
top: 24
|
||||
right: 24
|
||||
}
|
||||
|
||||
// Top layer keeps notifications above normal windows while still usually
|
||||
// below fullscreen overlays. Overlay would be too aggressive here.
|
||||
WlrLayershell.layer: WlrLayer.Top
|
||||
WlrLayershell.focusable: false
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
WlrLayershell.namespace: "deltarune-quickshell-notifications"
|
||||
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
aboveWindows: true
|
||||
focusable: false
|
||||
visible: true
|
||||
color: "#00000000"
|
||||
|
||||
property int stackWidth: 420
|
||||
property int menuReservedHeight: 182
|
||||
|
||||
readonly property int screenHeight: screen ? screen.height : 1080
|
||||
readonly property bool topbarOpen: ShellStateManager.shellOpen
|
||||
readonly property int stackOffsetY: topbarOpen ? menuReservedHeight + 24 : 0
|
||||
readonly property int maxStackHeight: Math.max(120, screenHeight - 24 - stackOffsetY - 24)
|
||||
|
||||
implicitWidth: stackWidth
|
||||
implicitHeight: stackOffsetY + notificationViewport.height
|
||||
|
||||
// Input handling decision: the layer itself never grabs focus and is only
|
||||
// as large as the stack. This keeps the container effectively click-through
|
||||
// outside notification bounds and avoids any global pointer/keyboard grabs.
|
||||
mask: Region {
|
||||
item: notificationViewport
|
||||
}
|
||||
|
||||
NotificationModel {
|
||||
id: notificationModel
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: notificationViewport
|
||||
x: 0
|
||||
y: notificationLayer.stackOffsetY
|
||||
width: notificationLayer.stackWidth
|
||||
height: Math.min(notificationColumn.implicitHeight, notificationLayer.maxStackHeight)
|
||||
clip: true
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
contentWidth: width
|
||||
contentHeight: notificationColumn.implicitHeight
|
||||
interactive: contentHeight > height
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
|
||||
WheelHandler {
|
||||
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
|
||||
onWheel: function (event) {
|
||||
if (!notificationViewport.interactive)
|
||||
return;
|
||||
const step = event.angleDelta.y / 120 * 60;
|
||||
notificationViewport.contentY = Math.max(0, Math.min(notificationViewport.contentHeight - notificationViewport.height, notificationViewport.contentY - step));
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: notificationViewport.interactive ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
|
||||
width: 6
|
||||
}
|
||||
|
||||
Column {
|
||||
id: notificationColumn
|
||||
width: notificationViewport.width
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: notificationModel.notifications
|
||||
|
||||
NotificationCard {
|
||||
notificationId: rowNotificationId
|
||||
notifTitle: rowTitle
|
||||
notifBody: rowBody
|
||||
notifUrgency: rowUrgency
|
||||
notifAppName: rowAppName
|
||||
notifAppIcon: rowAppIcon
|
||||
notifImage: rowImage
|
||||
notifTimeoutMs: rowTimeoutMs
|
||||
notifCritical: rowCritical
|
||||
notifHints: rowHints
|
||||
|
||||
width: notificationLayer.stackWidth
|
||||
|
||||
onCloseFinished: function (closedNotificationId, reason) {
|
||||
notificationModel.closeById(closedNotificationId, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user