diff --git a/ags/widget/BackgroundWindow.tsx b/ags/widget/BackgroundWindow.tsx index fb4a138..88fcf05 100644 --- a/ags/widget/BackgroundWindow.tsx +++ b/ags/widget/BackgroundWindow.tsx @@ -23,6 +23,10 @@ export type BackgroundWindowProps = { actionClickSecondary?: (window: Astal.Window) => void; keymode?: Astal.Keymode; exclusivity?: Astal.Exclusivity; + + /** attach this window as a background for another window + * background-window will close when the attached window triggers ::close-request) */ + attach?: Astal.Window; }; /** Creates a fullscreen GtkWindow that is used for making @@ -31,23 +35,21 @@ export type BackgroundWindowProps = { * * @param props Properties for background-window * - * @returns The generated background window + * @returns The generated background-window */ export function BackgroundWindow(props: BackgroundWindowProps): Astal.Window { const conns: Map = new Map(); - return conns.forEach((id, obj) => obj.disconnect(id))} + return { const gestureClick = Gtk.GestureClick.new(), eventControllerKey = Gtk.EventControllerKey.new(); + gestureClick.set_button(0); + self.add_controller(gestureClick); self.add_controller(eventControllerKey); @@ -75,6 +77,13 @@ export function BackgroundWindow(props: BackgroundWindowProps): Astal.Window { props.actionFired?.(self); })); - }} - /> as Astal.Window; + + props.attach && + conns.set(props.attach, (props.attach as Gtk.Widget).connect("close-request", () => + self.close() + )); + + conns.set(self, self.connect("destroy", () => conns.forEach((id, obj) => + obj.disconnect(id)))); + }} /> as Astal.Window; } diff --git a/ags/widget/PopupWindow.tsx b/ags/widget/PopupWindow.tsx index 36c60df..a08ffbe 100644 --- a/ags/widget/PopupWindow.tsx +++ b/ags/widget/PopupWindow.tsx @@ -1,18 +1,18 @@ import { Astal, Gdk, Gtk } from "ags/gtk4"; import { BackgroundWindow } from "./BackgroundWindow"; -import { Accessor, CCProps, createComputed } from "ags"; +import { Accessor, CCProps, createComputed, createRoot } from "ags"; import { omitObjectKeys, WidgetNodeType } from "../scripts/utils"; import GObject from "ags/gobject"; type PopupWindowSpecificProps = { - $?: (self: Astal.Window) => void; + $?: (self: Astal.Window, container: Gtk.Box) => void; children?: WidgetNodeType; - onDestroy?: (self: Astal.Window) => void; /** Stylesheet for the background of the popup-window */ cssBackgroundWindow?: string; class?: string | Accessor; + onCloseRequest?: (self: Astal.Window) => void|boolean; actionClickedOutside?: (self: Astal.Window) => void; actionKeyPressed?: (self: Astal.Window, keyval: number, keycode: number) => void; }; @@ -29,75 +29,82 @@ export type PopupWindowProps = Pick & PopupWindowSpecificProps; + const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor; export function PopupWindow(props: PopupWindowProps): GObject.Object { + props.visible ??= true; props.layer ??= Astal.Layer.OVERLAY; + props.actionClickedOutside ??= (self: Astal.Window) => self.close(); - const bgWindow = props.cssBackgroundWindow ? ( as Astal.Window) - : undefined; - - const omittedProps = omitObjectKeys(props, [ - "children", + let clickedInside: boolean = false; + + 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); - }} + } keymode={Astal.Keymode.EXCLUSIVE} exclusivity={props.exclusivity ?? Astal.Exclusivity.NORMAL} + anchor={TOP | LEFT | BOTTOM | RIGHT} visible={false} onCloseRequest={props.onCloseRequest} $={(self) => { - props.actionClickedOutside ??= (_: Astal.Window) => 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(); + const allocation = self.get_first_child()!.get_first_child()!.get_allocation(); self.add_controller(gestureClick); self.add_controller(keyController); + props.cssBackgroundWindow && createRoot(() => + + ); + + props.visible && self.show(); + 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); - }); + (y < allocation.y || y > (allocation.y + allocation.height))) { + if(clickedInside) { + clickedInside = false; + return; + } props.actionClickedOutside!(self); } })); - conns.set(keyController, keyController.connect("key-pressed", (_, keyval, keycode) => { + conns.set(keyController, keyController.connect("key-released", (_, keyval, keycode) => { if(keyval === Gdk.KEY_Escape) { conns.forEach((id, obj) => { obj.disconnect(id); @@ -110,32 +117,38 @@ export function PopupWindow(props: PopupWindowProps): GObject.Object { props.actionKeyPressed?.(self, keyval, keycode); })); - conns.set(self, self.connect("destroy", () => conns.forEach((id, obj) => + conns.set(self, self.connect("close-request", () => conns.forEach((id, obj) => obj.disconnect(id)))); - props.$?.(self); + props.$?.(self, self.get_first_child()!.get_first_child()!.get_first_child() as Gtk.Box); }}> - - - { - const gestureClick = Gtk.GestureClick.new(); - self.add_controller(gestureClick); + + { + const conns = new Map(), + gestureClick = Gtk.GestureClick.new(); - const clickConn = gestureClick.connect("released", () => true); - const destroyConn = self.connect("destroy", () => { - gestureClick.disconnect(clickConn); - self.disconnect(destroyConn); - }); + gestureClick.set_button(0); + + self.add_controller(gestureClick); + conns.set(gestureClick, gestureClick.connect("released", () => + clickedInside = true + )); + + conns.set(self, self.connect("destroy", () => conns.forEach((id, obj) => + obj.disconnect(id)))); }}> - {props.children} + + {props.children} + - ; + as Astal.Window; }