quickshell: notification click/action jumps to the app's window
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
5aea7fab27
commit
3d5ecb7b98
1 changed files with 59 additions and 1 deletions
|
|
@ -1480,7 +1480,10 @@ in
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: { modelData.invoke(); _nc.actionInvoked(); }
|
// Invoking an action ("View", "Reply"…)
|
||||||
|
// makes the app want focus, but it can't
|
||||||
|
// take it itself — see focusNotifApp.
|
||||||
|
onClicked: { modelData.invoke(); bar.focusNotifApp(_nc.notif); _nc.actionInvoked(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3217,6 +3220,37 @@ in
|
||||||
if (a.startsWith("/")) return "file://" + a;
|
if (a.startsWith("/")) return "file://" + a;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
// Jump to the window that sent a notification. Toplevel.activate()
|
||||||
|
// goes over wlr-foreign-toplevel — the same path a taskbar uses —
|
||||||
|
// so Hyprland follows it across workspaces. The app raising
|
||||||
|
// itself does not work here: misc:focus_on_activate is off, so
|
||||||
|
// its own activation request is dropped on purpose.
|
||||||
|
function focusNotifApp(notif) {
|
||||||
|
if (!notif) return;
|
||||||
|
const want = [(notif.desktopEntry || "").replace(/\.desktop$/, ""), notif.appName]
|
||||||
|
.filter(s => s !== "").map(s => s.toLowerCase());
|
||||||
|
if (want.length === 0) return;
|
||||||
|
const tls = ToplevelManager.toplevels.values;
|
||||||
|
// Exact appId first: appName is a display name ("Vesktop"),
|
||||||
|
// appId the wayland id ("vesktop"), and they often differ by
|
||||||
|
// more than case, hence the substring pass.
|
||||||
|
for (const t of tls)
|
||||||
|
if (want.includes((t.appId || "").toLowerCase())) { t.activate(); return; }
|
||||||
|
for (const t of tls) {
|
||||||
|
const id = (t.appId || "").toLowerCase();
|
||||||
|
if (id !== "" && want.some(w => id.includes(w) || w.includes(id))) { t.activate(); return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clicking a notification body. Apps hide "open the right chat"
|
||||||
|
// behind the default action, so fire that too when they send one.
|
||||||
|
function activateNotif(notif) {
|
||||||
|
if (!notif) return;
|
||||||
|
for (const a of notif.actions)
|
||||||
|
if (a.identifier === "default") { a.invoke(); break; }
|
||||||
|
focusNotifApp(notif);
|
||||||
|
}
|
||||||
|
|
||||||
function toggleDropdown(dd, setupFn) {
|
function toggleDropdown(dd, setupFn) {
|
||||||
if (dd.visible && !dd.closing) {
|
if (dd.visible && !dd.closing) {
|
||||||
dd.animateClose();
|
dd.animateClose();
|
||||||
|
|
@ -6045,6 +6079,18 @@ in
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: Math.max(notifPreview.visible ? 48 : 0, ncBody.height)
|
height: Math.max(notifPreview.visible ? 48 : 0, ncBody.height)
|
||||||
|
|
||||||
|
// First child, so the action chips and the
|
||||||
|
// dismiss button still take their own clicks.
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
bar.activateNotif(notifItem.modelData);
|
||||||
|
notifItem.modelData.dismiss();
|
||||||
|
bar.closeAllDropdowns();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Image preview (album art, screenshot thumb…)
|
// Image preview (album art, screenshot thumb…)
|
||||||
ClippingRectangle {
|
ClippingRectangle {
|
||||||
id: notifPreview
|
id: notifPreview
|
||||||
|
|
@ -6325,6 +6371,18 @@ in
|
||||||
|
|
||||||
property string previewSource: bar.notifPreviewSource(toastItem.currentNotif)
|
property string previewSource: bar.notifPreviewSource(toastItem.currentNotif)
|
||||||
|
|
||||||
|
// First child, so the action chips and the dismiss
|
||||||
|
// button still take their own clicks.
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
bar.activateNotif(toastItem.currentNotif);
|
||||||
|
if (toastItem.currentNotif) toastItem.currentNotif.dismiss();
|
||||||
|
toastItem.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Image preview (screenshot thumb, album art…)
|
// Image preview (screenshot thumb, album art…)
|
||||||
ClippingRectangle {
|
ClippingRectangle {
|
||||||
id: toastPreview
|
id: toastPreview
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue