refactor: move ts to src
Also move popupwindow to own file
This commit is contained in:
parent
476fbe69d3
commit
02fd2e97f2
20 changed files with 209 additions and 147 deletions
12
app.tsx
12
app.tsx
|
|
@ -1,11 +1,11 @@
|
||||||
import { execAsync, GLib, writeFileAsync } from "astal";
|
import { execAsync, GLib, writeFileAsync } from "astal";
|
||||||
import { App } from "astal/gtk3";
|
import { App } from "astal/gtk3";
|
||||||
import Bar from "./modules/bar";
|
import Bar from "./src/modules/bar";
|
||||||
import Launcher from "./modules/launcher";
|
import Launcher from "./src/modules/launcher";
|
||||||
import NotifPopups from "./modules/notifpopups";
|
import NotifPopups from "./src/modules/notifpopups";
|
||||||
import Osds from "./modules/osds";
|
import Osds from "./src/modules/osds";
|
||||||
import Monitors from "./services/monitors";
|
import Monitors from "./src/services/monitors";
|
||||||
import Players from "./services/players";
|
import Players from "./src/services/players";
|
||||||
|
|
||||||
const loadStyleAsync = async () => {
|
const loadStyleAsync = async () => {
|
||||||
if (!GLib.file_test(`${SRC}/scss/scheme/_index.scss`, GLib.FileTest.EXISTS))
|
if (!GLib.file_test(`${SRC}/scss/scheme/_index.scss`, GLib.FileTest.EXISTS))
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
padding-top: lib.s(10);
|
padding-top: lib.s(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup {
|
.notification {
|
||||||
@include lib.rounded(8, $tr: 0, $br: 0);
|
@include lib.rounded(8, $tr: 0, $br: 0);
|
||||||
@include lib.shadow;
|
@include lib.shadow;
|
||||||
@include font.main;
|
@include font.main;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import AstalNetwork from "gi://AstalNetwork";
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import AstalTray from "gi://AstalTray";
|
import AstalTray from "gi://AstalTray";
|
||||||
import AstalWp01 from "gi://AstalWp";
|
import AstalWp01 from "gi://AstalWp";
|
||||||
import { bar as config } from "../config";
|
import { bar as config } from "../../config";
|
||||||
import type { Monitor } from "../services/monitors";
|
import type { Monitor } from "../services/monitors";
|
||||||
import Players from "../services/players";
|
import Players from "../services/players";
|
||||||
import Updates from "../services/updates";
|
import Updates from "../services/updates";
|
||||||
|
|
@ -3,12 +3,13 @@ import { Astal, Gtk, Widget } from "astal/gtk3";
|
||||||
import fuzzysort from "fuzzysort";
|
import fuzzysort from "fuzzysort";
|
||||||
import type AstalApps from "gi://AstalApps";
|
import type AstalApps from "gi://AstalApps";
|
||||||
import AstalHyprland from "gi://AstalHyprland";
|
import AstalHyprland from "gi://AstalHyprland";
|
||||||
import { launcher as config } from "../config";
|
import { launcher as config } from "../../config";
|
||||||
import { Apps } from "../services/apps";
|
import { Apps } from "../services/apps";
|
||||||
import Math, { type HistoryItem } from "../services/math";
|
import Math, { type HistoryItem } from "../services/math";
|
||||||
import { getAppCategoryIcon } from "../utils/icons";
|
import { getAppCategoryIcon } from "../utils/icons";
|
||||||
import { launch } from "../utils/system";
|
import { launch } from "../utils/system";
|
||||||
import { PopupWindow, setupCustomTooltip } from "../utils/widgets";
|
import { setupCustomTooltip } from "../utils/widgets";
|
||||||
|
import PopupWindow from "../widgets/popupwindow";
|
||||||
|
|
||||||
type Mode = "apps" | "files" | "math";
|
type Mode = "apps" | "files" | "math";
|
||||||
|
|
||||||
57
src/modules/notifications.tsx
Normal file
57
src/modules/notifications.tsx
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { Gtk } from "astal/gtk3";
|
||||||
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
|
import { PopupWindow, setupChildClickthrough } from "../utils/widgets";
|
||||||
|
|
||||||
|
const List = () => (
|
||||||
|
<box
|
||||||
|
vertical
|
||||||
|
valign={Gtk.Align.START}
|
||||||
|
className="list"
|
||||||
|
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);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default class Notifications extends PopupWindow {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
name: "notifications",
|
||||||
|
child: (
|
||||||
|
<box>
|
||||||
|
<List />
|
||||||
|
</box>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
setupChildClickthrough(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/modules/notifpopups.tsx
Normal file
49
src/modules/notifpopups.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { Astal, Gtk } from "astal/gtk3";
|
||||||
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
|
import { notifpopups as config } from "../../config";
|
||||||
|
import { setupChildClickthrough } from "../utils/widgets";
|
||||||
|
import Notification from "../widgets/notification";
|
||||||
|
|
||||||
|
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, Notification>();
|
||||||
|
self.hook(notifd, "notified", (self, id) => {
|
||||||
|
const notification = notifd.get_notification(id);
|
||||||
|
|
||||||
|
const popup = (<Notification popup notification={notification} />) as Notification;
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
|
@ -5,9 +5,9 @@ import AstalWp from "gi://AstalWp";
|
||||||
import Cairo from "gi://cairo";
|
import Cairo from "gi://cairo";
|
||||||
import Pango from "gi://Pango";
|
import Pango from "gi://Pango";
|
||||||
import PangoCairo from "gi://PangoCairo";
|
import PangoCairo from "gi://PangoCairo";
|
||||||
import { osds as config } from "../config";
|
import { osds as config } from "../../config";
|
||||||
import Monitors, { type Monitor } from "../services/monitors";
|
import Monitors, { type Monitor } from "../services/monitors";
|
||||||
import { PopupWindow } from "../utils/widgets";
|
import PopupWindow from "../widgets/popupwindow";
|
||||||
|
|
||||||
const getStyle = (context: Gtk.StyleContext, prop: string) => context.get_property(prop, Gtk.StateFlags.NORMAL);
|
const getStyle = (context: Gtk.StyleContext, prop: string) => context.get_property(prop, Gtk.StateFlags.NORMAL);
|
||||||
const getNumStyle = (context: Gtk.StyleContext, prop: string) => getStyle(context, prop) as number;
|
const getNumStyle = (context: Gtk.StyleContext, prop: string) => getStyle(context, prop) as number;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { execAsync, GLib, GObject, property, readFileAsync, register, writeFileAsync } from "astal";
|
import { execAsync, GLib, GObject, property, readFileAsync, register, writeFileAsync } from "astal";
|
||||||
import { updates as config } from "../config";
|
import { updates as config } from "../../config";
|
||||||
|
|
||||||
interface Update {
|
interface Update {
|
||||||
name: string;
|
name: string;
|
||||||
45
src/utils/widgets.ts
Normal file
45
src/utils/widgets.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { Binding } from "astal";
|
||||||
|
import { Astal, Widget } from "astal/gtk3";
|
||||||
|
import AstalHyprland from "gi://AstalHyprland";
|
||||||
|
|
||||||
|
export const setupCustomTooltip = (self: any, text: string | Binding<string>) => {
|
||||||
|
if (!text) return null;
|
||||||
|
|
||||||
|
const window = new Widget.Window({
|
||||||
|
visible: false,
|
||||||
|
namespace: "caelestia-tooltip",
|
||||||
|
keymode: Astal.Keymode.NONE,
|
||||||
|
exclusivity: Astal.Exclusivity.IGNORE,
|
||||||
|
anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT,
|
||||||
|
child: new Widget.Label({ className: "tooltip", label: text }),
|
||||||
|
});
|
||||||
|
self.set_tooltip_window(window);
|
||||||
|
|
||||||
|
let dirty = true;
|
||||||
|
let lastX = 0;
|
||||||
|
self.connect("size-allocate", () => (dirty = true));
|
||||||
|
window.connect("size-allocate", () => {
|
||||||
|
window.marginLeft = lastX + (self.get_allocated_width() - window.get_preferred_width()[1]) / 2;
|
||||||
|
});
|
||||||
|
if (text instanceof Binding) self.hook(text, (_: any, v: string) => !v && window.hide());
|
||||||
|
|
||||||
|
self.connect("query-tooltip", (_: any, x: number, y: number) => {
|
||||||
|
if (text instanceof Binding && !text.get()) return false;
|
||||||
|
if (dirty) {
|
||||||
|
const { width, height } = self.get_allocation();
|
||||||
|
const { x: cx, y: cy } = AstalHyprland.get_default().get_cursor_position();
|
||||||
|
window.marginLeft = cx + ((width - window.get_preferred_width()[1]) / 2 - x);
|
||||||
|
window.marginTop = cy + (height - y);
|
||||||
|
lastX = cx - x;
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
self.connect("destroy", () => window.destroy());
|
||||||
|
|
||||||
|
return window;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setupChildClickthrough = (self: any) =>
|
||||||
|
self.connect("size-allocate", () => self.get_window()?.set_child_input_shapes());
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { GLib, register, timeout } from "astal";
|
import { GLib, register, timeout } from "astal";
|
||||||
import { Astal, Gtk, Widget } from "astal/gtk3";
|
import { Astal, Gtk, Widget } from "astal/gtk3";
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import { notifpopups as config } from "../config";
|
import { notifpopups as config } from "../../config";
|
||||||
import { desktopEntrySubs } from "../utils/icons";
|
import { desktopEntrySubs } from "../utils/icons";
|
||||||
import { setupChildClickthrough } from "../utils/widgets";
|
|
||||||
|
|
||||||
const urgencyToString = (urgency: AstalNotifd.Urgency) => {
|
const urgencyToString = (urgency: AstalNotifd.Urgency) => {
|
||||||
switch (urgency) {
|
switch (urgency) {
|
||||||
|
|
@ -53,17 +52,17 @@ const Image = ({ icon }: { icon: string }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
@register()
|
@register()
|
||||||
class NotifPopup extends Widget.Box {
|
export default class Notification extends Widget.Box {
|
||||||
readonly #revealer;
|
readonly #revealer;
|
||||||
#destroyed = false;
|
#destroyed = false;
|
||||||
|
|
||||||
constructor({ notification }: { notification: AstalNotifd.Notification }) {
|
constructor({ notification, popup }: { notification: AstalNotifd.Notification; popup?: boolean }) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.#revealer = (
|
this.#revealer = (
|
||||||
<revealer revealChild transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN} transitionDuration={150}>
|
<revealer revealChild transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN} transitionDuration={150}>
|
||||||
<box className="wrapper">
|
<box className="wrapper">
|
||||||
<box vertical className={`popup ${urgencyToString(notification.urgency)}`}>
|
<box vertical className={`notification ${urgencyToString(notification.urgency)}`}>
|
||||||
<box className="header">
|
<box className="header">
|
||||||
<AppIcon appIcon={notification.appIcon} desktopEntry={notification.appName} />
|
<AppIcon appIcon={notification.appIcon} desktopEntry={notification.appName} />
|
||||||
<label className="app-name" label={notification.appName ?? "Unknown"} />
|
<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
|
// Close popup after timeout if transient or expire enabled in config
|
||||||
if (config.expire || notification.transient)
|
if (popup && (config.expire || notification.transient))
|
||||||
timeout(
|
timeout(
|
||||||
notification.expireTimeout > 0
|
notification.expireTimeout > 0
|
||||||
? notification.expireTimeout
|
? 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>
|
|
||||||
);
|
|
||||||
39
src/widgets/popupwindow.ts
Normal file
39
src/widgets/popupwindow.ts
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
import { Binding, register } from "astal";
|
|
||||||
import { App, Astal, Gdk, Widget } from "astal/gtk3";
|
|
||||||
import AstalHyprland from "gi://AstalHyprland";
|
|
||||||
|
|
||||||
export const setupCustomTooltip = (self: any, text: string | Binding<string>) => {
|
|
||||||
if (!text) return null;
|
|
||||||
|
|
||||||
const window = (
|
|
||||||
<window
|
|
||||||
visible={false}
|
|
||||||
namespace="caelestia-tooltip"
|
|
||||||
keymode={Astal.Keymode.NONE}
|
|
||||||
exclusivity={Astal.Exclusivity.IGNORE}
|
|
||||||
anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT}
|
|
||||||
>
|
|
||||||
<label className="tooltip" label={text} />
|
|
||||||
</window>
|
|
||||||
) as Widget.Window;
|
|
||||||
self.set_tooltip_window(window);
|
|
||||||
|
|
||||||
let dirty = true;
|
|
||||||
let lastX = 0;
|
|
||||||
self.connect("size-allocate", () => (dirty = true));
|
|
||||||
window.connect("size-allocate", () => {
|
|
||||||
window.marginLeft = lastX + (self.get_allocated_width() - window.get_preferred_width()[1]) / 2;
|
|
||||||
});
|
|
||||||
if (text instanceof Binding) self.hook(text, (_: any, v: string) => !v && window.hide());
|
|
||||||
|
|
||||||
self.connect("query-tooltip", (_: any, x: number, y: number) => {
|
|
||||||
if (text instanceof Binding && !text.get()) return false;
|
|
||||||
if (dirty) {
|
|
||||||
const { width, height } = self.get_allocation();
|
|
||||||
const { x: cx, y: cy } = AstalHyprland.get_default().get_cursor_position();
|
|
||||||
window.marginLeft = cx + ((width - window.get_preferred_width()[1]) / 2 - x);
|
|
||||||
window.marginTop = cy + (height - y);
|
|
||||||
lastX = cx - x;
|
|
||||||
dirty = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
self.connect("destroy", () => window.destroy());
|
|
||||||
|
|
||||||
return window;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const setupChildClickthrough = (self: any) =>
|
|
||||||
self.connect("size-allocate", () => self.get_window()?.set_child_input_shapes());
|
|
||||||
|
|
||||||
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 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue