Add multi-monitor support

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2025-02-14 20:24:25 +00:00
parent c4d8cc951d
commit ce96ec6bf7
7 changed files with 163 additions and 81 deletions

View File

@@ -3,12 +3,24 @@ import Launcher from './components/Launcher';
import Workspace from './components/Workspaces';
import Date from './components/Date';
import Systray from './components/Tray';
import Hyprland from "gi://AstalHyprland";
const anchor = Astal.WindowAnchor.TOP
| Astal.WindowAnchor.LEFT
| Astal.WindowAnchor.RIGHT;
export default (monitor: Gdk.Monitor) => <window
const hyprland = Hyprland.get_default();
function getHyprlandMonitor(gdkmonitor: Gdk.Monitor) {
const display = Gdk.Display.get_default()!;
const screen = display.get_default_screen();
for (let i = 0; i < display.get_n_monitors(); ++i) {
if (gdkmonitor === display.get_monitor(i))
return hyprland.get_monitor_by_name(screen.get_monitor_plug_name(i)!);
}
}
export default (monitor: Gdk.Monitor, index: number) => <window
className='bar'
gdkmonitor={monitor}
exclusivity={Astal.Exclusivity.EXCLUSIVE}
@@ -17,7 +29,7 @@ export default (monitor: Gdk.Monitor) => <window
<centerbox className='widgets'>
<box hexpand halign={Gtk.Align.START}>
<Launcher />
<Workspace />
<Workspace monitor={getHyprlandMonitor(monitor)!} />
</box>
<box hexpand halign={Gtk.Align.CENTER}>
<Date />

View File

@@ -1,28 +1,23 @@
import { bind, Binding, Variable } from "astal";
import { bind, Variable } from "astal";
import Hyprland from "gi://AstalHyprland";
import { range } from '../../lib';
const hyprland = Hyprland.get_default();
const Workspace = ({ id }: { id: number }) => {
const Workspace = ({ workspace }: { workspace: Hyprland.Workspace }) => {
const className = Variable.derive(
[bind(hyprland, "workspaces"), bind(hyprland, "focusedWorkspace")],
(workspaces, focused) => {
const workspace = workspaces.find((w) => w.id === id);
if (!workspace) return "button";
const occupied = workspace.get_clients().length > 0;
const active = focused.id === id;
return `button ${active ? "active" : occupied && "occupied"}`;
[bind(hyprland, "focusedWorkspace"), bind(workspace, "clients")],
(focused, clients) => {
if (focused.id == workspace.id) return "button active";
if (clients.length > 0) return "button occupied";
return "button";
},
);
return <box vertical>
<box vexpand />
<eventbox
onClickRelease={() => hyprland.dispatch("workspace", `${id}`)}
onClickRelease={() => hyprland.dispatch("workspace", `${workspace.id}`)}
>
<label
className={className()}
@@ -32,13 +27,17 @@ const Workspace = ({ id }: { id: number }) => {
</box>;
};
export default () => <eventbox
className="workspaces"
onScroll={(_, e) => {
hyprland.dispatch("workspace", e.delta_y > 0 ? "+1" : "-1");
}}
>
<box>
{range(10).map((i) => <Workspace id={i} />)}
</box>
</eventbox>
export default ({ monitor }: { monitor: Hyprland.Monitor }) => {
const workspaces = hyprland.get_workspaces().filter(w => w.monitor.id == monitor.id).sort((w1, w2) => w1.id - w2.id);
return <eventbox
className="workspaces"
onScroll={(_, e) => {
hyprland.dispatch("workspace", e.delta_y > 0 ? "m+1" : "m-1");
}}
>
<box>
{workspaces.map((w) => <Workspace workspace={w} />)}
</box>
</eventbox>;
};