diff --git a/lib/mk-types/default.nix b/lib/mk-types/default.nix
index abd74e61..fc397453 100644
--- a/lib/mk-types/default.nix
+++ b/lib/mk-types/default.nix
@@ -12,7 +12,7 @@ in
pname = "${pname}-types";
version = "0.0.0";
- npmDepsHash = "sha256-8De8tRUKzRhD1jyx0anYNPMhxZyIr2nI45HdK6nb8jI=";
+ npmDepsHash = "sha256-3ll4Xd5F8ZH/7q/gOF0jgerM6QRk71d93XIwtDssfxU=";
src = ./.;
dontNpmBuild = true;
@@ -22,8 +22,7 @@ in
${concatMapStringsSep "\n" (p: "-g ${p.package.dev}/share/gir-1.0 \\") withGirNames}
-g ${ts-for-gir-src}/girs \
--ignoreVersionConflicts \
- --package \
- -e gjs -o ./types
+ -o ./types
'';
installPhase = ''
diff --git a/lib/mk-types/package-lock.json b/lib/mk-types/package-lock.json
index 47c396a2..50c53818 100644
Binary files a/lib/mk-types/package-lock.json and b/lib/mk-types/package-lock.json differ
diff --git a/lib/mk-types/package.json b/lib/mk-types/package.json
index 3aaa4533..5027ded4 100644
--- a/lib/mk-types/package.json
+++ b/lib/mk-types/package.json
@@ -1,5 +1,5 @@
{
"dependencies": {
- "@ts-for-gir/cli": "^3.3.0"
+ "@ts-for-gir/cli": "4.0.0-beta.16"
}
}
diff --git a/nixosModules/ags/v2/widgets/bar/fullscreen.tsx b/nixosModules/ags/v2/widgets/bar/fullscreen.tsx
index 9ae89b65..a73603ca 100644
--- a/nixosModules/ags/v2/widgets/bar/fullscreen.tsx
+++ b/nixosModules/ags/v2/widgets/bar/fullscreen.tsx
@@ -51,7 +51,10 @@ export default ({
gdkmonitor = Gdk.Display.get_default()?.get_monitor(0) as Gdk.Monitor,
child,
...rest
-}: Widget.WindowProps) => {
+}: {
+ anchor: Astal.WindowAnchor
+ gdkmonitor?: Gdk.Monitor
+} & Widget.WindowProps) => {
const monitor = get_hyprland_monitor_desc(gdkmonitor);
const BarVisible = Variable(true);
@@ -143,7 +146,6 @@ export default ({
name={`bar-${monitor}`}
layer={Astal.Layer.OVERLAY}
gdkmonitor={gdkmonitor}
- margins={[-1, -1, -1, -1]}
anchor={anchor}
{...rest}
>
diff --git a/nixosModules/ags/v2/widgets/bar/items/battery.tsx b/nixosModules/ags/v2/widgets/bar/items/battery.tsx
index 2b8c84c8..883ca22d 100644
--- a/nixosModules/ags/v2/widgets/bar/items/battery.tsx
+++ b/nixosModules/ags/v2/widgets/bar/items/battery.tsx
@@ -1,4 +1,4 @@
-import { bind, Widget } from 'astal';
+import { bind } from 'astal';
import AstalBattery from 'gi://AstalBattery';
const Battery = AstalBattery.get_default();
@@ -7,12 +7,11 @@ import Separator from '../../misc/separator';
const LOW_BATT = 20;
-const SPACING = 8;
export default () => (
{
+ setup={(self) => {
const update = () => {
const percent = Math.round(Battery.get_percentage() * 100);
const level = Math.floor(percent / 10) * 10;
@@ -37,7 +36,7 @@ export default () => (
}}
/>
-
+
diff --git a/nixosModules/ags/v2/widgets/bar/items/current-client.tsx b/nixosModules/ags/v2/widgets/bar/items/current-client.tsx
index e355bee0..b25b6f45 100644
--- a/nixosModules/ags/v2/widgets/bar/items/current-client.tsx
+++ b/nixosModules/ags/v2/widgets/bar/items/current-client.tsx
@@ -1,6 +1,4 @@
-import { bind, Widget } from 'astal';
-
-import Pango from 'gi://Pango?version=1.0';
+import { bind } from 'astal';
import AstalApps from 'gi://AstalApps?version=0.1';
const Applications = AstalApps.Apps.new();
@@ -11,8 +9,6 @@ const Hyprland = AstalHyprland.get_default();
import Separator from '../../misc/separator';
-const SPACING = 8;
-
export default () => {
const focused = bind(Hyprland, 'focusedClient');
@@ -23,10 +19,10 @@ export default () => {
>
{
+ setup={(self) => {
self.hook(Hyprland, 'notify::focused-client', () => {
const app = Applications.query(
- Hyprland.get_focused_client().get_class(),
+ Hyprland.get_focused_client()?.get_class() ?? '',
false,
)[0];
@@ -35,12 +31,12 @@ export default () => {
}}
/>
-
+
{focused.as((client) => (client && (
)))}
diff --git a/nixosModules/ags/v2/widgets/bar/items/workspaces.tsx b/nixosModules/ags/v2/widgets/bar/items/workspaces.tsx
new file mode 100644
index 00000000..bc836908
--- /dev/null
+++ b/nixosModules/ags/v2/widgets/bar/items/workspaces.tsx
@@ -0,0 +1,167 @@
+import { Gtk, idle, timeout, Widget } from 'astal';
+
+import AstalHyprland from 'gi://AstalHyprland?version=0.1';
+const Hyprland = AstalHyprland.get_default();
+
+
+const URGENT_DURATION = 1000;
+
+const Workspace = ({ id = 0 }) => (
+
+ {
+ Hyprland.message_async(`dispatch workspace ${id}`, () => { /**/ });
+ }}
+ >
+ idle(() => {
+ const update = (
+ _: Widget.Box,
+ addr?: string,
+ ) => {
+ const workspace = Hyprland.get_workspace(id);
+ const occupied = workspace && workspace.get_clients().length > 0;
+
+ self.toggleClassName('occupied', occupied);
+
+ if (!addr) {
+ return;
+ }
+
+ // Deal with urgent windows
+ const client = Hyprland.get_client(addr);
+ const isThisUrgent = client &&
+ client.workspace.id === id;
+
+ if (isThisUrgent) {
+ self.toggleClassName('urgent', true);
+
+ // Only show for a sec when urgent is current workspace
+ if (Hyprland.get_focused_workspace().get_id() === id) {
+ timeout(URGENT_DURATION, () => {
+ self.toggleClassName('urgent', false);
+ });
+ }
+ }
+ };
+
+ self
+ .hook(Hyprland, 'event', update)
+
+ // Deal with urgent windows
+ .hook(Hyprland, 'urgent', update)
+
+ .hook(Hyprland, 'notify::focused-workspace', () => {
+ if (Hyprland.get_focused_workspace().get_id() === id) {
+ self.toggleClassName('urgent', false);
+ }
+ });
+ })}
+ />
+
+
+);
+
+export default () => {
+ const L_PADDING = 2;
+ const WS_WIDTH = 30;
+
+ const updateHighlight = (self: Widget.Box) => {
+ const currentId = Hyprland.get_focused_workspace().get_id().toString();
+
+ const indicators = ((self.get_parent() as Widget.Overlay)
+ .child as Widget.Box)
+ .children as Widget.Revealer[];
+
+ const currentIndex = indicators.findIndex((w) => w.name === currentId);
+
+ if (currentIndex >= 0) {
+ self.css = `margin-left: ${L_PADDING + (currentIndex * WS_WIDTH)}px`;
+ }
+ };
+
+ const highlight = (
+ {
+ self.hook(Hyprland, 'notify::focused-workspace', updateHighlight);
+ }}
+ />
+ ) as Widget.Box;
+
+ let workspaces: Widget.Revealer[] = [];
+
+ return (
+
+
+ {
+ const refresh = () => {
+ (self.children as Widget.Revealer[]).forEach((rev) => {
+ rev.reveal_child = false;
+ });
+
+ workspaces.forEach((ws) => {
+ ws.reveal_child = true;
+ });
+ };
+
+ const updateWorkspaces = () => {
+ Hyprland.get_workspaces().forEach((ws) => {
+ const currentWs = (self.children as Widget.Revealer[])
+ .find((ch) => ch.name === ws.id.toString());
+
+ if (!currentWs && ws.id > 0) {
+ self.add(Workspace({ id: ws.id }));
+ }
+ });
+
+ // Make sure the order is correct
+ workspaces.forEach((workspace, i) => {
+ (workspace.get_parent() as Widget.Box)
+ .reorder_child(workspace, i);
+ });
+ };
+
+ self.hook(Hyprland, 'event', () => {
+ workspaces = (self.children as Widget.Revealer[])
+ .filter((ch) => {
+ return Hyprland.get_workspaces().find((ws) => {
+ return ws.id.toString() === ch.name;
+ });
+ })
+ .sort((a, b) => parseInt(a.name ?? '0') - parseInt(b.name ?? '0'));
+
+ updateWorkspaces();
+ refresh();
+
+ // Make sure the highlight doesn't go too far
+ const TEMP_TIMEOUT = 100;
+
+ timeout(TEMP_TIMEOUT, () => updateHighlight(highlight));
+ });
+ }}
+ />
+
+
+ );
+};
diff --git a/nixosModules/ags/v2/widgets/bar/style.scss b/nixosModules/ags/v2/widgets/bar/style.scss
index 1c243a1b..59cb985e 100644
--- a/nixosModules/ags/v2/widgets/bar/style.scss
+++ b/nixosModules/ags/v2/widgets/bar/style.scss
@@ -4,7 +4,7 @@
border-radius: 7px;
background-color: darken($window_bg_color, 3%);
font-size: 20px;
- min-height: 30px;
+ min-height: 35px;
.battery icon {
&.charging {
@@ -15,5 +15,32 @@
color: red;
}
}
+
+ .workspaces {
+ .button {
+ margin: 0 2.5px;
+ min-height: 22px;
+ min-width: 22px;
+ border-radius: 100%;
+ border: 2px solid transparent;
+ }
+
+ .occupied {
+ border: 2px solid $window_bg_color;
+ background: $accent_color;
+ transition: background-color 0.6s ease-in-out;
+ }
+
+ .urgent {
+ border: 2px solid $window_bg_color;
+ background: red;
+ transition: background-color 0.6s ease-in-out;
+ }
+
+ .active {
+ border: 2px solid #50fa7b;
+ transition: margin-left 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
+ }
+ }
}
}
diff --git a/nixosModules/ags/v2/widgets/bar/wim.tsx b/nixosModules/ags/v2/widgets/bar/wim.tsx
index 75d79b27..2ad3c8b6 100644
--- a/nixosModules/ags/v2/widgets/bar/wim.tsx
+++ b/nixosModules/ags/v2/widgets/bar/wim.tsx
@@ -3,6 +3,7 @@ import { Astal, Gtk } from 'astal';
import Battery from './items/battery';
import Clock from './items/clock';
import CurrentClient from './items/current-client';
+import Workspaces from './items/workspaces';
import BarRevealer from './fullscreen';
import Separator from '../misc/separator';
@@ -20,6 +21,10 @@ export default () => (
+
+
+
+