import { Astal, Gdk, Gtk } from "ags/gtk4"; import { BackgroundWindow } from "./BackgroundWindow"; import GObject from "gi://GObject?version=2.0"; import { Accessor, CCProps, createComputed } from "ags"; import { omitObjectKeys, WidgetNodeType } from "../scripts/utils"; type PopupWindowSpecificProps = { children?: WidgetNodeType; onDestroy?: (self: Astal.Window) => void; /** Stylesheet for the background of the popup-window */ cssBackgroundWindow?: string; class?: string | Accessor; actionClickedOutside?: (self: Astal.Window) => void; actionKeyPressed?: (self: Astal.Window, keyval: number, keycode: number) => void; }; export type PopupWindowProps = Pick>, "monitor" | "layer" | "exclusivity" | "marginLeft" | "marginTop" | "marginRight" | "marginBottom" | "cursor" | "canFocus" | "hasFocus" | "tooltipMarkup" | "namespace" | "widthRequest" | "heightRequest" | "halign" | "valign" | "vexpand" | "hexpand"> & PopupWindowSpecificProps; const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor; export function PopupWindow(props: PopupWindowProps): GObject.Object { props.layer ??= Astal.Layer.OVERLAY; const bgWindow = props.cssBackgroundWindow ? ( as Astal.Window) : undefined; const omittedProps = omitObjectKeys(props, [ "children", "actionKeyPressed", "actionClickedOutside", "cssBackgroundWindow", "marginTop", "marginLeft", "marginRight", "marginBottom" ]); return `popup-window ${clss} ${namespace}`) : props.class.as(clss => `popup-window ${clss} ${props.namespace ?? ""}`)) : `popup-window ${props.class ?? ""} ${props.namespace ?? ""}` } keymode={Astal.Keymode.EXCLUSIVE} anchor={TOP | LEFT | RIGHT | BOTTOM} exclusivity={props.exclusivity ?? Astal.Exclusivity.NORMAL} onDestroy={(self) => { bgWindow?.close(); props.onDestroy?.(self); }} $={(self) => { props.actionClickedOutside ??= self.close; const conns: Map = new Map(); const gestureClick = Gtk.GestureClick.new(); const keyController = Gtk.EventControllerKey.new(); const allocation = (self.get_child()! as Gtk.Box).get_first_child()!.get_allocation(); self.add_controller(gestureClick); self.add_controller(keyController); conns.set(gestureClick, gestureClick.connect("released", (_, __, x, y) => { if((x < allocation.x || x > (allocation.x + allocation.width)) || (y < allocation.y || y > (allocation.y + allocation.height))) { // Disconnect signals because window is being closed conns.forEach((id, obj) => { obj.disconnect(id); }); props.actionClickedOutside!(self); } })); conns.set(keyController, keyController.connect("key-pressed", (_, keyval, keycode) => { if(keyval === Gdk.KEY_Escape) { conns.forEach((id, obj) => { obj.disconnect(id); }); props.actionClickedOutside!(self); return; } props.actionKeyPressed?.(self, keyval, keycode); })); conns.set(self, self.connect("destroy", () => conns.forEach((id, obj) => obj.disconnect(id)))); }}> { const gestureClick = Gtk.GestureClick.new(); self.add_controller(gestureClick); }}> {props.children} ; }