summaryrefslogtreecommitdiff
path: root/src/widgets
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-01-16 16:35:37 +1100
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-01-16 16:35:37 +1100
commit02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38 (patch)
tree5e2a56becf6ba6961995e541ce9688224f704773 /src/widgets
parentpopupwindow: switch to class (diff)
downloadcaelestia-shell-02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38.tar.gz
caelestia-shell-02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38.tar.bz2
caelestia-shell-02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38.zip
refactor: move ts to src
Also move popupwindow to own file
Diffstat (limited to '')
-rw-r--r--src/widgets/notification.tsx (renamed from modules/notifpopups.tsx)55
-rw-r--r--src/widgets/popupwindow.ts39
2 files changed, 44 insertions, 50 deletions
diff --git a/modules/notifpopups.tsx b/src/widgets/notification.tsx
index c3441a9..0bef5ca 100644
--- a/modules/notifpopups.tsx
+++ b/src/widgets/notification.tsx
@@ -1,9 +1,8 @@
import { GLib, register, timeout } from "astal";
import { Astal, Gtk, Widget } from "astal/gtk3";
import AstalNotifd from "gi://AstalNotifd";
-import { notifpopups as config } from "../config";
+import { notifpopups as config } from "../../config";
import { desktopEntrySubs } from "../utils/icons";
-import { setupChildClickthrough } from "../utils/widgets";
const urgencyToString = (urgency: AstalNotifd.Urgency) => {
switch (urgency) {
@@ -53,17 +52,17 @@ const Image = ({ icon }: { icon: string }) => {
};
@register()
-class NotifPopup extends Widget.Box {
+export default class Notification extends Widget.Box {
readonly #revealer;
#destroyed = false;
- constructor({ notification }: { notification: AstalNotifd.Notification }) {
+ constructor({ notification, popup }: { notification: AstalNotifd.Notification; popup?: boolean }) {
super();
this.#revealer = (
<revealer revealChild transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN} transitionDuration={150}>
<box className="wrapper">
- <box vertical className={`popup ${urgencyToString(notification.urgency)}`}>
+ <box vertical className={`notification ${urgencyToString(notification.urgency)}`}>
<box className="header">
<AppIcon appIcon={notification.appIcon} desktopEntry={notification.appName} />
<label className="app-name" label={notification.appName ?? "Unknown"} />
@@ -106,7 +105,7 @@ class NotifPopup extends Widget.Box {
});
// Close popup after timeout if transient or expire enabled in config
- if (config.expire || notification.transient)
+ if (popup && (config.expire || notification.transient))
timeout(
notification.expireTimeout > 0
? notification.expireTimeout
@@ -131,47 +130,3 @@ class NotifPopup extends Widget.Box {
});
}
}
-
-export default () => (
- <window
- namespace="caelestia-notifpopups"
- anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.RIGHT | Astal.WindowAnchor.BOTTOM}
- >
- <box
- vertical
- valign={Gtk.Align.START}
- className="notifpopups"
- setup={self => {
- const notifd = AstalNotifd.get_default();
- const map = new Map<number, NotifPopup>();
- self.hook(notifd, "notified", (self, id) => {
- const notification = notifd.get_notification(id);
-
- const popup = (<NotifPopup notification={notification} />) as NotifPopup;
- popup.connect("destroy", () => map.get(notification.id) === popup && map.delete(notification.id));
- map.get(notification.id)?.destroyWithAnims();
- map.set(notification.id, popup);
-
- self.add(
- <eventbox
- // Dismiss on middle click
- onClick={(_, event) => event.button === Astal.MouseButton.MIDDLE && notification.dismiss()}
- // Close on hover lost
- onHoverLost={() => popup.destroyWithAnims()}
- >
- {popup}
- </eventbox>
- );
-
- // Limit number of popups
- if (config.maxPopups > 0 && self.children.length > config.maxPopups)
- map.values().next().value?.destroyWithAnims();
- });
- self.hook(notifd, "resolved", (_, id) => map.get(id)?.destroyWithAnims());
-
- // Change input region to child region so can click through empty space
- setupChildClickthrough(self);
- }}
- />
- </window>
-);
diff --git a/src/widgets/popupwindow.ts b/src/widgets/popupwindow.ts
new file mode 100644
index 0000000..67aa0ff
--- /dev/null
+++ b/src/widgets/popupwindow.ts
@@ -0,0 +1,39 @@
+import { Binding, register } from "astal";
+import { App, Astal, Gdk, Widget } from "astal/gtk3";
+import AstalHyprland from "gi://AstalHyprland?version=0.1";
+
+const extendProp = <T>(
+ prop: T | Binding<T | undefined> | undefined,
+ override: (prop: T | undefined) => T | undefined
+) => prop && (prop instanceof Binding ? prop.as(override) : override(prop));
+
+@register()
+export default class PopupWindow extends Widget.Window {
+ constructor(props: Widget.WindowProps) {
+ super({
+ keymode: Astal.Keymode.ON_DEMAND,
+ exclusivity: Astal.Exclusivity.IGNORE,
+ ...props,
+ visible: false,
+ application: App,
+ name: props.monitor ? extendProp(props.name, n => (n ? n + props.monitor : undefined)) : props.name,
+ namespace: extendProp(props.name, n => `caelestia-${n}`),
+ onKeyPressEvent: (self, event) => {
+ // Close window on escape
+ if (event.get_keyval()[1] === Gdk.KEY_Escape) self.hide();
+
+ return props.onKeyPressEvent?.(self, event);
+ },
+ borderWidth: 20, // To allow shadow, cause if not it gets cut off
+ });
+ }
+
+ popup_at_widget(widget: JSX.Element, event: Gdk.Event) {
+ const { width, height } = widget.get_allocation();
+ const [_, x, y] = event.get_coords();
+ const { x: cx, y: cy } = AstalHyprland.get_default().get_cursor_position();
+ this.marginLeft = cx + ((width - this.get_preferred_width()[1]) / 2 - x);
+ this.marginTop = cy + (height - y);
+ this.show();
+ }
+}