2024-01-30 11:29:07 -05:00
|
|
|
const Hyprland = await Service.import('hyprland');
|
|
|
|
const { Box, EventBox, Revealer, Window } = Widget;
|
2023-11-16 00:48:50 -05:00
|
|
|
|
2024-06-19 12:54:01 -04:00
|
|
|
import Gdk from 'gi://Gdk?version=3.0';
|
|
|
|
|
|
|
|
import {
|
|
|
|
get_hyprland_monitor_desc,
|
|
|
|
get_monitor_desc_from_id,
|
|
|
|
} from '../lib.ts';
|
|
|
|
|
2024-01-29 18:54:07 -05:00
|
|
|
|
2024-03-21 21:45:07 -04:00
|
|
|
const FullscreenState = Variable({
|
2024-06-19 12:54:01 -04:00
|
|
|
monitors: [] as string[],
|
|
|
|
clientAddrs: new Map() as Map<string, string>,
|
2024-03-21 21:45:07 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
Hyprland.connect('event', (hyprObj) => {
|
|
|
|
const arrayEquals = (a1: unknown[], a2: unknown[]) =>
|
|
|
|
a1.sort().toString() === a2.sort().toString();
|
2024-03-22 02:15:48 -04:00
|
|
|
|
2024-06-19 12:54:01 -04:00
|
|
|
const mapEquals = (m1: Map<string, string>, m2: Map<string, string>) =>
|
2024-03-21 21:45:07 -04:00
|
|
|
m1.size === m2.size &&
|
|
|
|
Array.from(m1.keys()).every((key) => m1.get(key) === m2.get(key));
|
|
|
|
|
|
|
|
const fs = FullscreenState.value;
|
2024-03-22 02:15:48 -04:00
|
|
|
const fsClients = hyprObj.clients.filter((c) => {
|
|
|
|
const mon = Hyprland.getMonitor(c.monitor);
|
|
|
|
|
|
|
|
return c.fullscreen &&
|
|
|
|
c.workspace.id === mon?.activeWorkspace.id;
|
|
|
|
});
|
2024-03-21 21:45:07 -04:00
|
|
|
|
2024-06-19 12:54:01 -04:00
|
|
|
const monitors = fsClients.map((c) =>
|
|
|
|
get_monitor_desc_from_id(c.monitor));
|
|
|
|
|
|
|
|
const clientAddrs = new Map(fsClients.map((c) => [
|
|
|
|
get_monitor_desc_from_id(c.monitor),
|
|
|
|
c.address,
|
|
|
|
]));
|
2024-03-21 21:45:07 -04:00
|
|
|
|
2024-03-22 02:15:48 -04:00
|
|
|
const hasChanged =
|
2024-03-21 21:45:07 -04:00
|
|
|
!arrayEquals(monitors, fs.monitors) ||
|
|
|
|
!mapEquals(clientAddrs, fs.clientAddrs);
|
|
|
|
|
|
|
|
if (hasChanged) {
|
|
|
|
FullscreenState.setValue({
|
|
|
|
monitors,
|
|
|
|
clientAddrs,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-06-19 12:54:01 -04:00
|
|
|
export default ({
|
|
|
|
anchor,
|
|
|
|
bar,
|
|
|
|
gdkmonitor = Gdk.Display.get_default()?.get_primary_monitor() as Gdk.Monitor,
|
|
|
|
...rest
|
|
|
|
}) => {
|
|
|
|
const monitor = get_hyprland_monitor_desc(gdkmonitor);
|
2024-03-21 21:45:07 -04:00
|
|
|
const BarVisible = Variable(true);
|
|
|
|
|
|
|
|
FullscreenState.connect('changed', (v) => {
|
|
|
|
BarVisible.setValue(!v.value.monitors.includes(monitor));
|
|
|
|
});
|
2023-11-16 00:48:50 -05:00
|
|
|
|
2024-03-21 21:45:07 -04:00
|
|
|
const barCloser = Window({
|
|
|
|
name: `bar-${monitor}-closer`,
|
|
|
|
visible: false,
|
2024-06-19 12:54:01 -04:00
|
|
|
gdkmonitor,
|
2024-03-21 21:45:07 -04:00
|
|
|
anchor: ['top', 'bottom', 'left', 'right'],
|
|
|
|
layer: 'overlay',
|
2023-10-17 13:47:02 -04:00
|
|
|
|
2024-03-21 21:45:07 -04:00
|
|
|
child: EventBox({
|
2024-03-21 22:00:24 -04:00
|
|
|
on_hover: () => {
|
|
|
|
barCloser.set_visible(false);
|
2024-03-21 21:45:07 -04:00
|
|
|
BarVisible.setValue(false);
|
|
|
|
},
|
2023-11-21 01:29:46 -05:00
|
|
|
|
2024-03-21 21:45:07 -04:00
|
|
|
child: Box({
|
|
|
|
css: 'padding: 1px;',
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
});
|
2023-11-21 01:29:46 -05:00
|
|
|
|
2024-03-21 22:00:24 -04:00
|
|
|
// Hide bar instantly when out of focus
|
|
|
|
Hyprland.active.workspace.connect('changed', () => {
|
|
|
|
const addr = FullscreenState.value.clientAddrs.get(monitor);
|
|
|
|
|
|
|
|
if (addr) {
|
|
|
|
const client = Hyprland.getClient(addr);
|
|
|
|
|
|
|
|
if (client!.workspace.id !== Hyprland.active.workspace.id) {
|
|
|
|
BarVisible.setValue(false);
|
|
|
|
barCloser.visible = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-03-21 21:54:38 -04:00
|
|
|
const buffer = Box({
|
|
|
|
css: 'min-height: 10px',
|
|
|
|
visible: BarVisible.bind().as((v) => !v),
|
|
|
|
});
|
|
|
|
|
2024-04-07 14:29:12 -04:00
|
|
|
const vertical = anchor.includes('left') && anchor.includes('right');
|
|
|
|
const isBottomOrLeft = (
|
|
|
|
anchor.includes('left') && anchor.includes('right') && anchor.includes('bottom')
|
|
|
|
) || (
|
|
|
|
anchor.includes('top') && anchor.includes('bottom') && anchor.includes('left')
|
|
|
|
);
|
|
|
|
|
|
|
|
let transition: 'slide_up' | 'slide_down' | 'slide_left' | 'slide_right';
|
|
|
|
|
|
|
|
if (vertical) {
|
|
|
|
transition = isBottomOrLeft ? 'slide_up' : 'slide_down';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
transition = isBottomOrLeft ? 'slide_right' : 'slide_left';
|
|
|
|
}
|
|
|
|
|
|
|
|
const barWrap = Revealer({
|
2024-03-21 21:54:38 -04:00
|
|
|
reveal_child: BarVisible.bind(),
|
2024-04-07 14:29:12 -04:00
|
|
|
transition,
|
2024-03-21 21:54:38 -04:00
|
|
|
child: bar,
|
|
|
|
});
|
|
|
|
|
2024-03-21 21:45:07 -04:00
|
|
|
return Window({
|
|
|
|
name: `bar-${monitor}`,
|
|
|
|
layer: 'overlay',
|
2024-06-19 12:54:01 -04:00
|
|
|
gdkmonitor,
|
2024-03-21 21:45:07 -04:00
|
|
|
margins: [-1, -1, -1, -1],
|
2024-04-07 14:29:12 -04:00
|
|
|
anchor,
|
2024-03-21 21:45:07 -04:00
|
|
|
...rest,
|
2023-11-06 20:38:16 -05:00
|
|
|
|
2024-03-21 21:45:07 -04:00
|
|
|
attribute: {
|
|
|
|
barCloser,
|
|
|
|
},
|
2023-11-21 01:29:46 -05:00
|
|
|
|
2024-03-21 21:45:07 -04:00
|
|
|
child: EventBox({
|
|
|
|
child: Box({
|
|
|
|
css: 'min-height: 1px; padding: 1px;',
|
|
|
|
hexpand: true,
|
|
|
|
hpack: 'fill',
|
2024-04-07 14:29:12 -04:00
|
|
|
vertical,
|
2024-03-21 21:54:38 -04:00
|
|
|
|
2024-04-07 14:29:12 -04:00
|
|
|
children: isBottomOrLeft ?
|
|
|
|
[buffer, barWrap] :
|
|
|
|
[barWrap, buffer],
|
2023-10-20 23:11:21 -04:00
|
|
|
}),
|
2024-03-21 21:45:07 -04:00
|
|
|
}).on('enter-notify-event', () => {
|
|
|
|
if (!BarVisible.value) {
|
|
|
|
barCloser.visible = true;
|
|
|
|
BarVisible.setValue(true);
|
|
|
|
}
|
|
|
|
}),
|
2023-11-16 00:48:50 -05:00
|
|
|
});
|
|
|
|
};
|