2024-01-30 11:29:07 -05:00
|
|
|
import Gtk from 'gi://Gtk?version=3.0';
|
|
|
|
const Hyprland = await Service.import('hyprland');
|
2023-11-21 01:29:46 -05:00
|
|
|
|
2024-04-10 21:04:19 -04:00
|
|
|
/* Types */
|
2024-01-29 18:54:07 -05:00
|
|
|
import { Window } from 'resource:///com/github/Aylur/ags/widgets/window.js';
|
|
|
|
|
|
|
|
import {
|
|
|
|
CloseType,
|
2024-04-07 14:29:12 -04:00
|
|
|
HyprTransition,
|
2024-01-29 18:54:07 -05:00
|
|
|
PopupWindowProps,
|
|
|
|
} from 'global-types';
|
2023-12-18 23:20:32 -05:00
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
|
|
|
|
export class PopupWindow<
|
2024-01-30 11:29:07 -05:00
|
|
|
Child extends Gtk.Widget,
|
2024-01-29 18:54:07 -05:00
|
|
|
Attr,
|
|
|
|
> extends Window<Child, Attr> {
|
|
|
|
static {
|
2024-04-10 21:04:19 -04:00
|
|
|
Widget.register(this, {
|
2024-01-29 18:54:07 -05:00
|
|
|
properties: {
|
2024-04-10 21:04:19 -04:00
|
|
|
close_on_unfocus: ['string', 'rw'],
|
|
|
|
transition: ['string', 'rw'],
|
2024-01-29 18:54:07 -05:00
|
|
|
},
|
2024-01-02 18:37:12 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-04-15 09:31:52 -04:00
|
|
|
|
|
|
|
private _close_on_unfocus: CloseType;
|
2024-01-02 18:37:12 -05:00
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
get close_on_unfocus() {
|
2024-04-15 09:31:52 -04:00
|
|
|
return this._close_on_unfocus;
|
2024-01-29 18:54:07 -05:00
|
|
|
}
|
2024-01-02 18:37:12 -05:00
|
|
|
|
2024-04-07 14:29:12 -04:00
|
|
|
set close_on_unfocus(value: CloseType) {
|
2024-04-15 09:31:52 -04:00
|
|
|
this._close_on_unfocus = value;
|
2024-01-29 18:54:07 -05:00
|
|
|
}
|
2024-01-02 18:37:12 -05:00
|
|
|
|
2024-04-15 09:31:52 -04:00
|
|
|
|
|
|
|
private _transition = 'unset' as HyprTransition;
|
|
|
|
|
2024-04-07 14:29:12 -04:00
|
|
|
get transition() {
|
2024-04-15 09:31:52 -04:00
|
|
|
return this._transition;
|
2024-04-07 14:29:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
set transition(t: HyprTransition) {
|
2024-04-15 09:31:52 -04:00
|
|
|
Hyprland.messageAsync(
|
|
|
|
`keyword layerrule animation ${t}, ${this.name}`,
|
|
|
|
).catch(logError);
|
|
|
|
this._transition = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private _on_open: (self: PopupWindow<Child, Attr>) => void;
|
|
|
|
|
|
|
|
get on_open() {
|
|
|
|
return this._on_open;
|
|
|
|
}
|
|
|
|
|
|
|
|
set on_open(fun: (self: PopupWindow<Child, Attr>) => void) {
|
|
|
|
this._on_open = fun;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private _on_close: (self: PopupWindow<Child, Attr>) => void;
|
|
|
|
|
|
|
|
get on_close() {
|
|
|
|
return this._on_close;
|
|
|
|
}
|
|
|
|
|
|
|
|
set on_close(fun: (self: PopupWindow<Child, Attr>) => void) {
|
|
|
|
this._on_close = fun;
|
2024-04-07 14:29:12 -04:00
|
|
|
}
|
|
|
|
|
2024-04-15 09:31:52 -04:00
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
constructor({
|
2024-04-07 14:29:12 -04:00
|
|
|
transition = 'slide top',
|
2024-01-29 18:54:07 -05:00
|
|
|
on_open = () => {/**/},
|
|
|
|
on_close = () => {/**/},
|
2024-01-02 18:37:12 -05:00
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
// Window props
|
|
|
|
name,
|
|
|
|
visible = false,
|
|
|
|
anchor = [],
|
|
|
|
layer = 'overlay',
|
|
|
|
close_on_unfocus = 'released',
|
|
|
|
...rest
|
|
|
|
}: PopupWindowProps<Child, Attr>) {
|
|
|
|
super({
|
|
|
|
...rest,
|
2024-04-07 14:29:12 -04:00
|
|
|
name: `win-${name}`,
|
2024-01-29 18:54:07 -05:00
|
|
|
visible,
|
|
|
|
anchor,
|
|
|
|
layer,
|
|
|
|
setup: () => {
|
|
|
|
const id = App.connect('config-parsed', () => {
|
2024-02-05 10:37:56 -05:00
|
|
|
// Add way to make window open on startup
|
2024-01-29 18:54:07 -05:00
|
|
|
if (visible) {
|
2024-04-07 14:29:12 -04:00
|
|
|
App.openWindow(`win-${name}`);
|
2024-01-02 18:37:12 -05:00
|
|
|
}
|
2024-02-05 10:37:56 -05:00
|
|
|
|
|
|
|
// This connection should always run only once
|
2024-01-29 18:54:07 -05:00
|
|
|
App.disconnect(id);
|
|
|
|
});
|
2024-04-07 14:29:12 -04:00
|
|
|
},
|
|
|
|
});
|
2024-01-02 18:37:12 -05:00
|
|
|
|
2024-04-15 09:31:52 -04:00
|
|
|
this._close_on_unfocus = close_on_unfocus;
|
|
|
|
this._on_open = on_open;
|
|
|
|
this._on_close = on_close;
|
|
|
|
|
2024-04-07 14:29:12 -04:00
|
|
|
this.hook(App, (_, currentName, isOpen) => {
|
|
|
|
if (currentName === `win-${name}`) {
|
2024-04-16 08:14:58 -04:00
|
|
|
// Make sure we have the right animation
|
|
|
|
this.transition = transition;
|
|
|
|
|
2024-04-07 14:29:12 -04:00
|
|
|
if (isOpen) {
|
2024-04-15 09:31:52 -04:00
|
|
|
this.on_open(this);
|
2024-04-07 14:29:12 -04:00
|
|
|
}
|
|
|
|
else {
|
2024-04-15 09:31:52 -04:00
|
|
|
this.on_close(this);
|
2024-04-07 14:29:12 -04:00
|
|
|
}
|
|
|
|
}
|
2024-01-29 18:54:07 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
set_x_pos(
|
2024-01-30 11:29:07 -05:00
|
|
|
alloc: Gtk.Allocation,
|
2024-01-29 18:54:07 -05:00
|
|
|
side = 'right' as 'left' | 'right',
|
|
|
|
) {
|
|
|
|
const width = this.get_display()
|
|
|
|
.get_monitor_at_point(alloc.x, alloc.y)
|
|
|
|
.get_geometry().width;
|
|
|
|
|
|
|
|
this.margins = [
|
|
|
|
this.margins[0],
|
|
|
|
|
|
|
|
side === 'right' ?
|
|
|
|
(width - alloc.x - alloc.width) :
|
|
|
|
this.margins[1],
|
|
|
|
|
|
|
|
this.margins[2],
|
|
|
|
|
|
|
|
side === 'right' ?
|
|
|
|
this.margins[3] :
|
|
|
|
(alloc.x - alloc.width),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
2023-10-30 19:53:50 -04:00
|
|
|
|
2024-01-30 11:29:07 -05:00
|
|
|
export default <Child extends Gtk.Widget, Attr>(
|
2024-01-29 18:54:07 -05:00
|
|
|
props: PopupWindowProps<Child, Attr>,
|
|
|
|
) => new PopupWindow(props);
|