summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/launcher.tsx40
-rw-r--r--utils/widgets.tsx46
2 files changed, 48 insertions, 38 deletions
diff --git a/modules/launcher.tsx b/modules/launcher.tsx
index d9e842c..966cdfd 100644
--- a/modules/launcher.tsx
+++ b/modules/launcher.tsx
@@ -8,7 +8,7 @@ import { Apps } from "../services/apps";
import Math, { type HistoryItem } from "../services/math";
import { getAppCategoryIcon } from "../utils/icons";
import { launch } from "../utils/system";
-import { convertPopupWindowProps, setupCustomTooltip } from "../utils/widgets";
+import { PopupWindow, setupCustomTooltip } from "../utils/widgets";
type Mode = "apps" | "files" | "math";
@@ -346,7 +346,7 @@ const LauncherContent = ({
);
@register()
-export default class Launcher extends Widget.Window {
+export default class Launcher extends PopupWindow {
readonly mode: Variable<Mode>;
constructor() {
@@ -354,26 +354,24 @@ export default class Launcher extends Widget.Window {
const mode = Variable<Mode>("apps");
const showResults = Variable.derive([bind(entry, "textLength"), mode], (t, m) => t > 0 || m !== "apps");
- super(
- convertPopupWindowProps({
- name: "launcher",
- anchor: Astal.WindowAnchor.TOP,
- keymode: Astal.Keymode.EXCLUSIVE,
- onKeyPressEvent(_, event) {
- const keyval = event.get_keyval()[1];
- // Focus entry on typing
- if (!entry.isFocus && keyval >= 32 && keyval <= 126) {
- entry.text += String.fromCharCode(keyval);
- entry.grab_focus();
- entry.set_position(-1);
+ super({
+ name: "launcher",
+ anchor: Astal.WindowAnchor.TOP,
+ keymode: Astal.Keymode.EXCLUSIVE,
+ onKeyPressEvent(_, event) {
+ const keyval = event.get_keyval()[1];
+ // Focus entry on typing
+ if (!entry.isFocus && keyval >= 32 && keyval <= 126) {
+ entry.text += String.fromCharCode(keyval);
+ entry.grab_focus();
+ entry.set_position(-1);
- // Consume event, if not consumed it will duplicate character in entry
- return true;
- }
- },
- child: <LauncherContent mode={mode} showResults={showResults} entry={entry} />,
- })
- );
+ // Consume event, if not consumed it will duplicate character in entry
+ return true;
+ }
+ },
+ child: <LauncherContent mode={mode} showResults={showResults} entry={entry} />,
+ });
this.mode = mode;
diff --git a/utils/widgets.tsx b/utils/widgets.tsx
index 51986ec..7b16075 100644
--- a/utils/widgets.tsx
+++ b/utils/widgets.tsx
@@ -1,4 +1,4 @@
-import { Binding } from "astal";
+import { Binding, register } from "astal";
import { App, Astal, Gdk, Widget } from "astal/gtk3";
import AstalHyprland from "gi://AstalHyprland";
@@ -52,21 +52,33 @@ const extendProp = <T,>(
override: (prop: T | undefined) => T | undefined
) => prop && (prop instanceof Binding ? prop.as(override) : override(prop));
-export const convertPopupWindowProps = (props: Widget.WindowProps): Widget.WindowProps => ({
- 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();
+@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
-});
+ return props.onKeyPressEvent?.(self, event);
+ },
+ borderWidth: 20, // To allow shadow, cause if not it gets cut off
+ });
+ }
-export const PopupWindow = (props: Widget.WindowProps) => <window {...convertPopupWindowProps(props)} />;
+ 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();
+ }
+}