💥 fix(popup-window): now it works as intended
This commit is contained in:
@@ -23,6 +23,10 @@ export type BackgroundWindowProps = {
|
|||||||
actionClickSecondary?: (window: Astal.Window) => void;
|
actionClickSecondary?: (window: Astal.Window) => void;
|
||||||
keymode?: Astal.Keymode;
|
keymode?: Astal.Keymode;
|
||||||
exclusivity?: Astal.Exclusivity;
|
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
|
/** Creates a fullscreen GtkWindow that is used for making
|
||||||
@@ -31,23 +35,21 @@ export type BackgroundWindowProps = {
|
|||||||
*
|
*
|
||||||
* @param props Properties for background-window
|
* @param props Properties for background-window
|
||||||
*
|
*
|
||||||
* @returns The generated background window
|
* @returns The generated background-window
|
||||||
*/
|
*/
|
||||||
export function BackgroundWindow(props: BackgroundWindowProps): Astal.Window {
|
export function BackgroundWindow(props: BackgroundWindowProps): Astal.Window {
|
||||||
const conns: Map<GObject.Object, number> = new Map();
|
const conns: Map<GObject.Object, number> = new Map();
|
||||||
|
|
||||||
return <Astal.Window namespace={"background-window"}
|
return <Astal.Window namespace={"background-window"} monitor={props.monitor} visible
|
||||||
css={props.css ?? "background: rgba(0, 0, 0, .2);"}
|
layer={props.layer ?? Astal.Layer.OVERLAY} keymode={props.keymode ?? Astal.Keymode.EXCLUSIVE}
|
||||||
monitor={props.monitor}
|
|
||||||
layer={props.layer ?? Astal.Layer.OVERLAY}
|
|
||||||
anchor={TOP | LEFT | BOTTOM | RIGHT}
|
|
||||||
keymode={props.keymode}
|
|
||||||
exclusivity={props.exclusivity ?? Astal.Exclusivity.IGNORE}
|
exclusivity={props.exclusivity ?? Astal.Exclusivity.IGNORE}
|
||||||
onDestroy={(_) => conns.forEach((id, obj) => obj.disconnect(id))}
|
anchor={TOP | LEFT | BOTTOM | RIGHT} css={props.css ?? "background: rgba(0, 0, 0, .2);"}
|
||||||
$={(self) => {
|
$={(self) => {
|
||||||
const gestureClick = Gtk.GestureClick.new(),
|
const gestureClick = Gtk.GestureClick.new(),
|
||||||
eventControllerKey = Gtk.EventControllerKey.new();
|
eventControllerKey = Gtk.EventControllerKey.new();
|
||||||
|
|
||||||
|
gestureClick.set_button(0);
|
||||||
|
|
||||||
self.add_controller(gestureClick);
|
self.add_controller(gestureClick);
|
||||||
self.add_controller(eventControllerKey);
|
self.add_controller(eventControllerKey);
|
||||||
|
|
||||||
@@ -75,6 +77,13 @@ export function BackgroundWindow(props: BackgroundWindowProps): Astal.Window {
|
|||||||
|
|
||||||
props.actionFired?.(self);
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-49
@@ -1,18 +1,18 @@
|
|||||||
import { Astal, Gdk, Gtk } from "ags/gtk4";
|
import { Astal, Gdk, Gtk } from "ags/gtk4";
|
||||||
import { BackgroundWindow } from "./BackgroundWindow";
|
import { BackgroundWindow } from "./BackgroundWindow";
|
||||||
import { Accessor, CCProps, createComputed } from "ags";
|
import { Accessor, CCProps, createComputed, createRoot } from "ags";
|
||||||
import { omitObjectKeys, WidgetNodeType } from "../scripts/utils";
|
import { omitObjectKeys, WidgetNodeType } from "../scripts/utils";
|
||||||
|
|
||||||
import GObject from "ags/gobject";
|
import GObject from "ags/gobject";
|
||||||
|
|
||||||
|
|
||||||
type PopupWindowSpecificProps = {
|
type PopupWindowSpecificProps = {
|
||||||
$?: (self: Astal.Window) => void;
|
$?: (self: Astal.Window, container: Gtk.Box) => void;
|
||||||
children?: WidgetNodeType;
|
children?: WidgetNodeType;
|
||||||
onDestroy?: (self: Astal.Window) => void;
|
|
||||||
/** Stylesheet for the background of the popup-window */
|
/** Stylesheet for the background of the popup-window */
|
||||||
cssBackgroundWindow?: string;
|
cssBackgroundWindow?: string;
|
||||||
class?: string | Accessor<string>;
|
class?: string | Accessor<string>;
|
||||||
|
onCloseRequest?: (self: Astal.Window) => void|boolean;
|
||||||
actionClickedOutside?: (self: Astal.Window) => void;
|
actionClickedOutside?: (self: Astal.Window) => void;
|
||||||
actionKeyPressed?: (self: Astal.Window, keyval: number, keycode: number) => void;
|
actionKeyPressed?: (self: Astal.Window, keyval: number, keycode: number) => void;
|
||||||
};
|
};
|
||||||
@@ -29,75 +29,82 @@ export type PopupWindowProps = Pick<Partial<CCProps<Astal.Window, Astal.Window.C
|
|||||||
| "canFocus"
|
| "canFocus"
|
||||||
| "hasFocus"
|
| "hasFocus"
|
||||||
| "tooltipMarkup"
|
| "tooltipMarkup"
|
||||||
|
| "tooltipText"
|
||||||
| "namespace"
|
| "namespace"
|
||||||
|
| "visible"
|
||||||
| "widthRequest"
|
| "widthRequest"
|
||||||
| "heightRequest"
|
| "heightRequest"
|
||||||
| "halign"
|
| "halign"
|
||||||
| "valign"
|
| "valign"
|
||||||
|
| "anchor"
|
||||||
| "vexpand"
|
| "vexpand"
|
||||||
| "hexpand"> & PopupWindowSpecificProps;
|
| "hexpand"> & PopupWindowSpecificProps;
|
||||||
|
|
||||||
|
|
||||||
const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor;
|
const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor;
|
||||||
|
|
||||||
export function PopupWindow(props: PopupWindowProps): GObject.Object {
|
export function PopupWindow(props: PopupWindowProps): GObject.Object {
|
||||||
|
props.visible ??= true;
|
||||||
props.layer ??= Astal.Layer.OVERLAY;
|
props.layer ??= Astal.Layer.OVERLAY;
|
||||||
|
props.actionClickedOutside ??= (self: Astal.Window) => self.close();
|
||||||
|
|
||||||
const bgWindow = props.cssBackgroundWindow ? (<BackgroundWindow
|
let clickedInside: boolean = false;
|
||||||
monitor={props.monitor ?? 0}
|
|
||||||
layer={props.layer}
|
|
||||||
css={props.cssBackgroundWindow} /> as Astal.Window)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const omittedProps = omitObjectKeys(props, [
|
return <Astal.Window {...omitObjectKeys(props, [
|
||||||
"children",
|
|
||||||
"actionKeyPressed",
|
"actionKeyPressed",
|
||||||
"actionClickedOutside",
|
"actionClickedOutside",
|
||||||
"cssBackgroundWindow",
|
"cssBackgroundWindow",
|
||||||
|
"anchor",
|
||||||
|
"halign",
|
||||||
|
"valign",
|
||||||
|
"namespace",
|
||||||
"marginTop",
|
"marginTop",
|
||||||
|
"widthRequest",
|
||||||
|
"heightRequest",
|
||||||
|
"visible",
|
||||||
"marginLeft",
|
"marginLeft",
|
||||||
"marginRight",
|
"marginRight",
|
||||||
"marginBottom"
|
"marginBottom"
|
||||||
]);
|
])} namespace={props.namespace ?? "popup-window"} class={
|
||||||
|
|
||||||
return <Astal.Window {...omittedProps} visible
|
|
||||||
namespace={props.namespace ?? "popup-window"} class={
|
|
||||||
(props.class instanceof Accessor) ?
|
(props.class instanceof Accessor) ?
|
||||||
((props.namespace instanceof Accessor) ?
|
((props.namespace instanceof Accessor) ?
|
||||||
createComputed([props.class, props.namespace], (clss, namespace) =>
|
createComputed([props.class, props.namespace], (clss, namespace) =>
|
||||||
`popup-window ${clss} ${namespace}`)
|
`popup-window ${clss} ${namespace}`)
|
||||||
: props.class.as(clss => `popup-window ${clss} ${props.namespace ?? ""}`))
|
: props.class.as(clss => `popup-window ${clss} ${props.namespace ?? ""}`))
|
||||||
: `popup-window ${props.class ?? ""} ${props.namespace ?? ""}`
|
: `popup-window ${props.class ?? ""} ${props.namespace ?? ""}`
|
||||||
} keymode={Astal.Keymode.EXCLUSIVE} anchor={TOP | LEFT | RIGHT | BOTTOM}
|
} keymode={Astal.Keymode.EXCLUSIVE} exclusivity={props.exclusivity ?? Astal.Exclusivity.NORMAL}
|
||||||
exclusivity={props.exclusivity ?? Astal.Exclusivity.NORMAL}
|
anchor={TOP | LEFT | BOTTOM | RIGHT} visible={false} onCloseRequest={props.onCloseRequest}
|
||||||
onDestroy={(self) => {
|
|
||||||
bgWindow?.close();
|
|
||||||
props.onDestroy?.(self);
|
|
||||||
}}
|
|
||||||
$={(self) => {
|
$={(self) => {
|
||||||
props.actionClickedOutside ??= (_: Astal.Window) => self.close();
|
|
||||||
|
|
||||||
const conns: Map<GObject.Object, number> = new Map();
|
const conns: Map<GObject.Object, number> = new Map();
|
||||||
const gestureClick = Gtk.GestureClick.new();
|
const gestureClick = Gtk.GestureClick.new();
|
||||||
const keyController = Gtk.EventControllerKey.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(gestureClick);
|
||||||
self.add_controller(keyController);
|
self.add_controller(keyController);
|
||||||
|
|
||||||
|
props.cssBackgroundWindow && createRoot(() =>
|
||||||
|
<BackgroundWindow monitor={props.monitor ?? 0}
|
||||||
|
layer={props.layer} css={props.cssBackgroundWindow}
|
||||||
|
keymode={Astal.Keymode.NONE} attach={self}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
props.visible && self.show();
|
||||||
|
|
||||||
conns.set(gestureClick, gestureClick.connect("released", (_, __, x, y) => {
|
conns.set(gestureClick, gestureClick.connect("released", (_, __, x, y) => {
|
||||||
if((x < allocation.x || x > (allocation.x + allocation.width)) ||
|
if((x < allocation.x || x > (allocation.x + allocation.width)) ||
|
||||||
(y < allocation.y || y > (allocation.y + allocation.height))) {
|
(y < allocation.y || y > (allocation.y + allocation.height))) {
|
||||||
|
if(clickedInside) {
|
||||||
// Disconnect signals because window is being closed
|
clickedInside = false;
|
||||||
conns.forEach((id, obj) => {
|
return;
|
||||||
obj.disconnect(id);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
props.actionClickedOutside!(self);
|
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) {
|
if(keyval === Gdk.KEY_Escape) {
|
||||||
conns.forEach((id, obj) => {
|
conns.forEach((id, obj) => {
|
||||||
obj.disconnect(id);
|
obj.disconnect(id);
|
||||||
@@ -110,32 +117,38 @@ export function PopupWindow(props: PopupWindowProps): GObject.Object {
|
|||||||
props.actionKeyPressed?.(self, keyval, keycode);
|
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))));
|
obj.disconnect(id))));
|
||||||
|
|
||||||
props.$?.(self);
|
props.$?.(self, self.get_first_child()!.get_first_child()!.get_first_child() as Gtk.Box);
|
||||||
}}>
|
}}>
|
||||||
<Gtk.Box halign={props.halign} valign={props.valign} hexpand vexpand css={`box {
|
<Gtk.Box hexpand={false} vexpand={false}>
|
||||||
margin-left: ${props.marginLeft ?? 0}px;
|
<Gtk.Box class={"popup-window-container"} halign={props.halign}
|
||||||
margin-right: ${props.marginRight ?? 0}px;
|
valign={props.valign} widthRequest={props.widthRequest}
|
||||||
margin-top: ${props.marginTop ?? 0}px;
|
hexpand={props.hexpand} vexpand={props.vexpand}
|
||||||
margin-bottom: ${props.marginBottom ?? 0}px;
|
heightRequest={props.heightRequest} css={`
|
||||||
}`
|
margin-left: ${props.marginLeft ?? 0}px;
|
||||||
}>
|
margin-right: ${props.marginRight ?? 0}px;
|
||||||
|
margin-top: ${props.marginTop ?? 0}px;
|
||||||
|
margin-bottom: ${props.marginBottom ?? 0}px;
|
||||||
|
`} $={(self) => {
|
||||||
|
const conns = new Map<GObject.Object, number>(),
|
||||||
|
gestureClick = Gtk.GestureClick.new();
|
||||||
|
|
||||||
|
gestureClick.set_button(0);
|
||||||
|
|
||||||
<Gtk.Box widthRequest={props.widthRequest} heightRequest={props.heightRequest}
|
|
||||||
$={(self) => {
|
|
||||||
const gestureClick = Gtk.GestureClick.new();
|
|
||||||
self.add_controller(gestureClick);
|
self.add_controller(gestureClick);
|
||||||
|
conns.set(gestureClick, gestureClick.connect("released", () =>
|
||||||
|
clickedInside = true
|
||||||
|
));
|
||||||
|
|
||||||
const clickConn = gestureClick.connect("released", () => true);
|
conns.set(self, self.connect("destroy", () => conns.forEach((id, obj) =>
|
||||||
const destroyConn = self.connect("destroy", () => {
|
obj.disconnect(id))));
|
||||||
gestureClick.disconnect(clickConn);
|
|
||||||
self.disconnect(destroyConn);
|
|
||||||
});
|
|
||||||
}}>
|
}}>
|
||||||
{props.children}
|
<Gtk.Box>
|
||||||
|
{props.children}
|
||||||
|
</Gtk.Box>
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Astal.Window>;
|
</Astal.Window> as Astal.Window;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user