ags: add brightness class, media widget on center-window and more

This commit is contained in:
retrozinndev
2025-02-15 08:24:00 -03:00
parent 2eb2f15db9
commit 6e9f2d4a7d
23 changed files with 441 additions and 268 deletions
+36 -2
View File
@@ -71,14 +71,47 @@ function handleVolumeArgs(args: Array<string>) {
if(!args[1])
return `Please specify what you want to do!\n\n${volumeHelp()}`
if(!/(sink|source)\-mute/.test(args[1]) && !args[2])
if(/^(sink|source)(\-increase|\-decrease|\-set)$/.test(args[1]) && !args[2])
return `You forgot to add a value to be set!`;
if(Number.isNaN(Number.parseFloat(args[2])) && Number.isSafeInteger(Number.parseFloat(args[2])))
return `Argument "${args[2]} is not a valid number! Please use integers"`;
const command: Array<string> = args[1].split('-');
if(/help/.test(args[1]))
return volumeHelp();
switch(command[1]) {
case "set":
command[0] === "sink" ?
Wireplumber.getDefault().setSinkVolume(Number.parseInt(args[2]))
:
Wireplumber.getDefault().setSourceVolume(Number.parseInt(args[2]))
return `Done! Set ${command[0]} volume to ${args[2]}`;
case "mute":
command[0] === "sink" ?
Wireplumber.getDefault().toggleMuteSink()
:
Wireplumber.getDefault().toggleMuteSource()
return `Done toggling mute!`;
case "increase":
command[0] === "sink" ?
Wireplumber.getDefault().increaseSinkVolume(Number.parseInt(args[2]))
:
Wireplumber.getDefault().increaseSourceVolume(Number.parseInt(args[2]))
return `Done increasing volume by ${args[2]}`;
case "decrease":
command[0] === "sink" ?
Wireplumber.getDefault().decreaseSinkVolume(Number.parseInt(args[2]))
:
Wireplumber.getDefault().decreaseSourceVolume(Number.parseInt(args[2]))
return `Done decreasing volume to ${args[2]}`;
}
return `Couldn't resolve arguments! "${args.join(' ').replace(new RegExp(`^${args[0]}`), "")}"`;
@@ -109,9 +142,10 @@ Options:
close [window_name]: sets specified window's visibility to false.
toggle [window_name]: toggles visibility of specified window.
reload: creates a new astal instance and removes this one.
volume: wireplumber volume controller, see "volume help".
help, -h, --help: shows this help message.
2024 (c) retrozinndev's Hyprland-Dots, licensed under the MIT License.
2025 (c) retrozinndev's Hyprland-Dots, licensed under the MIT License.
https://github.com/retrozinndev/Hyprland-Dots
`.trim();
}
+42
View File
@@ -0,0 +1,42 @@
import { exec, execAsync, GObject, monitorFile, Process, readFileAsync, register, signal } from "astal";
import { Connectable } from "astal/binding";
/** !!TODO!! Needs more work and testing
* I(retrozinndev) don't have a monitor that has software-controlled brightness
*/
@register({ GTypeName: "Brightness" })
class Brightness extends GObject.Object implements Connectable {
private readonly backlight: string|undefined;
private max: number;
private brightness: number;
@signal(Number)
declare brightnessChanged: (value: number) => void;
constructor(backlightDevice?: string) {
super();
this.backlight = backlightDevice || "";
this.max = Number.parseInt(exec(`brightnessctl -d ${backlightDevice} max`))
this.brightness = Number.parseInt(exec(`brightnessctl -d ${backlightDevice} get`))
readFileAsync(`/sys/class/backlight/${backlightDevice}/brightness`).catch(() => {
throw new Error(`Couldn't find backlight ${backlightDevice}`);
});
monitorFile(`/sys/class/backlight/${backlightDevice}/brightness`, async () => {
this.brightness = Number.parseInt(await execAsync(`brightnessctl -d ${backlightDevice} get`));
this.max = Number.parseInt(await execAsync(`brightnessctl -d ${backlightDevice} max`));
this.emit("brightness-changed", this.brightness);
});
}
public setBrightness(newBrightness: number): void {
execAsync(`brightnessctl -d ${this.backlight} set ${newBrightness || this.brightness}`).catch(() => {
throw new Error(`Couldn't set brightness of backlight ${this.backlight}`);
});
this.emit("brightness-changed", newBrightness);
}
}
+15 -10
View File
@@ -1,29 +1,32 @@
import AstalNotifd from "gi://AstalNotifd";
import { timeout } from "astal/time";
import { Connectable } from "astal/binding";
import { GObject, register, property, signal } from "astal";
import { GObject, register, signal } from "astal";
import { Windows } from "../windows";
@register()
class Notifications extends GObject.Object implements Connectable {
@register({ GTypeName: "Notifications" })
class NotificationsClass extends GObject.Object implements Connectable {
private static instance: Notifications;
private static instance: NotificationsClass;
private notifd: AstalNotifd.Notifd;
public notifications: Array<AstalNotifd.Notification> = [];
public notificationHistory: Array<AstalNotifd.Notification> = [];
@signal()
declare "notification-added": (notification: AstalNotifd.Notification) => void;
@signal(AstalNotifd.Notification)
declare notificationAdded: (added: AstalNotifd.Notification) => void;
@signal(Number)
declare notificationRemoved: (id: number) => void;
public static getDefault(): Notifications {
if(!Notifications.instance) {
Notifications.instance = new Notifications();
public static getDefault(): NotificationsClass {
if(!NotificationsClass.instance) {
NotificationsClass.instance = new NotificationsClass();
this.instance._init();
}
return Notifications.instance;
return NotificationsClass.instance;
}
constructor() {
@@ -95,3 +98,5 @@ class Notifications extends GObject.Object implements Connectable {
return this.notifd;
}
}
export const Notifications = new NotificationsClass();
+9 -8
View File
@@ -1,10 +1,11 @@
import { GObject } from "astal";
import { GObject, register } from "astal";
import AstalWp from "gi://AstalWp";
export const Wireplumber = GObject.registerClass({
GTypeName: "Wireplumber",
Signals: {}
}, class WireplumberClass extends GObject.Object {
export { WireplumberClass as Wireplumber };
@register({ GTypeName: "Wireplumber" })
class WireplumberClass extends GObject.Object {
private static astalWireplumber: (AstalWp.Wp|null) = AstalWp.get_default();
private static inst: WireplumberClass;
@@ -14,8 +15,8 @@ export const Wireplumber = GObject.registerClass({
private maxSinkVolume: number = 100;
private maxSourceVolume: number = 100;
_init(...props: any[]) {
super._init(props);
constructor() {
super();
if(!WireplumberClass.astalWireplumber)
throw new Error("Audio features will not work correctly! Please install wireplumber first", {
@@ -145,4 +146,4 @@ export const Wireplumber = GObject.registerClass({
return this.muteSource();
}
});
}
+1 -18
View File
@@ -112,27 +112,10 @@
& > button {
margin: 4px 1px;
border-radius: 4px;
label {
& label {
font-size: 8px;
}
&:hover {
background: colors.$bg-secondary;
}
&:first-child {
border-top-left-radius: 12px;
border-bottom-left-radius: 12px;
margin-left: 0;
}
&:last-child {
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
margin-right: 0;
}
}
}
+44 -7
View File
@@ -1,27 +1,63 @@
@use "sass:color";
@use "./wal";
@use "./functions" as funs; // Did you know that you can use the 'as' keyword? I just found out!
@use "./colors";
@use "./functions" as funs;
.center-window-container {
background: wal.$background;
background: colors.$bg-translucent;
border-radius: 18px;
padding: 12px;
& .left {
.top {
.time {
font-size: 22px;
& > .top {
padding-bottom: 10px;
& .time {
font-size: 28px;
font-weight: 800;
}
.date {
& .date {
font-size: 14px;
font-weight: 500;
color: funs.toRGB(color.adjust($color: wal.$foreground, $lightness: -15%));
color: colors.$fg-disabled;
}
}
& .big-media {
padding: 6px 16px;
& > box > .image {
background-size: cover;
background-position: center center;
border-radius: 10px;
}
& > .info {
padding: {
top: 4px;
bottom: 6px;
};
& .title {
font-size: 16px;
font-weight: 700;
}
& .artist {
font-size: 14px;
font-weight: 600;
color: colors.$fg-disabled;
}
}
& > .controls {
padding: 8px 0;
}
}
}
& .right {
& .calendar-box {
padding: 5px;
& calendar {
@@ -37,4 +73,5 @@
}
}
}
}
}
+6 -21
View File
@@ -1,9 +1,14 @@
@use "sass:color";
@use "./wal";
@use "./colors";
@use "./functions" as funs;
@use "./mixins";
.control-center-container {
background: rgba(wal.$background, .65);
@include mixins.reset-props;
@include mixins.default-styles;
background: colors.$bg-translucent;
border-radius: 24px;
padding: 20px 14px;
@@ -58,25 +63,5 @@
margin-right: 8px;
font-size: 15px;
}
trough {
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -20%));
border-radius: 8px;
}
trough highlight {
background: wal.$color1;
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
trough slider {
min-width: 1.2em;
min-height: 1.2em;
border-radius: 50%;
margin: -3px 0;
background: wal.$foreground;
margin-left: -1px;
}
}
}
+23 -1
View File
@@ -19,7 +19,7 @@
& > button {
background: colors.$bg-secondary;
margin: 0 1px;
padding: 0 6px;
padding: 4px 6px;
border-radius: 2px;
&:hover {
@@ -78,4 +78,26 @@
color: colors.$fg-primary;
}
}
& trough {
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -20%));
border-radius: 8px;
margin: 2px 0;
}
& trough highlight {
background: wal.$color1;
min-height: .9em;
border-top-left-radius: inherit;
border-bottom-left-radius: inherit;
}
& trough slider {
border-radius: 50%;
margin: -2px 0;
background: wal.$foreground;
margin-left: -1px;
min-width: 1.2em;
min-height: 1.2em;
}
}
+1 -1
View File
@@ -8,7 +8,7 @@
border-radius: 20px;
.icon {
margin-right: 14px;
margin-right: 10px;
font-size: 24px;
}
+18
View File
@@ -0,0 +1,18 @@
import { Astal, Gtk, Widget } from "astal/gtk3";
const { TOP, BOTTOM, LEFT, RIGHT }: typeof Astal.WindowAnchor = Astal.WindowAnchor;
/**
* Creates a screen-size window and opens the provided window after it.
* When clicking in the transparent background window, it closes(hides)
* the provided window.
* @param window the window to be rendered and closed when clicking outside of it
*/
export function PopupWindow(window: Gtk.Window) {
const bgWindow: Gtk.Window = new Widget.Window({
namespace: "popup-bg-window",
anchor: TOP | BOTTOM | LEFT | RIGHT,
} as Widget.WindowProps);
}
+4
View File
@@ -29,11 +29,15 @@ export function FocusedClient() {
new Widget.Label({
className: "class",
xalign: 0,
max_width_chars: 65,
truncate: false,
label: bind(focusedClient, "class")
} as Widget.LabelProps),
new Widget.Label({
className: "title",
xalign: 0,
max_width_chars: 48,
truncate: false,
label: bind(focusedClient, "title")
} as Widget.LabelProps)
] : []
+1
View File
@@ -54,6 +54,7 @@ export function Media(): Gtk.Widget {
new Widget.Button({
className: "next nf",
label: "󰒭",
tooltipText: "Next",
onClick: () => players[0].canGoNext && players[0].next()
} as Widget.ButtonProps)
] : new Widget.Label({
+111 -1
View File
@@ -1,6 +1,116 @@
import { AstalIO, bind, GLib, Process, timeout } from "astal";
import { Gtk, Widget } from "astal/gtk3";
import AstalMpris from "gi://AstalMpris";
let dragTimer: (AstalIO.Time|undefined);
export const BigMedia: Gtk.Widget = new Widget.Box({
className: "big-media",
//TODO
orientation: Gtk.Orientation.VERTICAL,
homogeneous: false,
children: bind(AstalMpris.get_default(), "players").as((players: Array<AstalMpris.Player>) =>
players[0] ? [
new Widget.Box({
halign: Gtk.Align.CENTER,
child: new Widget.Box({
className: "image",
hexpand: false,
orientation: Gtk.Orientation.VERTICAL,
visible: bind(players[0], "coverArt").as((coverArt: string) =>
coverArt !== ""),
css: bind(players[0], "coverArt").as((coverArt: string) =>
`.image { background-image: url('${coverArt}'); }`),
width_request: 132,
height_request: 128
} as Widget.BoxProps)
} as Widget.BoxProps),
new Widget.Box({
className: "info",
orientation: Gtk.Orientation.VERTICAL,
children: [
new Widget.Label({
className: "title",
tooltipText: bind(players[0], "title").as((title: string) => !title ? "No Title" : title),
label: bind(players[0], "title").as((title: string) => !title ? "No Title" : title),
truncate: true
} as Widget.LabelProps),
new Widget.Label({
className: "artist",
tooltipText: bind(players[0], "artist").as((artist: string) => !artist ? "No Artist" : artist),
label: bind(players[0], "artist").as((artist: string) => !artist ? "No Artist" : artist),
truncate: true
} as Widget.LabelProps)
]
} as Widget.BoxProps),
new Widget.Box({
className: "progress",
hexpand: true,
visible: bind(players[0], "canSeek"),
children: [
/*new Widget.Label({
className: "elapsed",
label: bind(players[0], "position").as((position: number) =>
Math.floor(position).toString())
}),*/
new Widget.Slider({
min: 0,
hexpand: true,
max: bind(players[0], "length").as((length: number) =>
Math.floor(length)),
value: bind(players[0], "position").as((position: number) =>
Math.floor(position)),
onDragged: (slider: Widget.Slider) => {
if(dragTimer === undefined)
dragTimer = timeout(600, () =>
players[0].set_position(Math.round(slider.value)));
else {
dragTimer.cancel();
dragTimer = timeout(600, () =>
players[0].set_position(Math.round(slider.value)));
}
}
})
]
}),
new Widget.Box({
className: "controls button-row",
hexpand: true,
halign: Gtk.Align.CENTER,
children: [
new Widget.Button({
className: "link nf",
label: "󰌹",
tooltipText: "Copy link to Clipboard",
visible: bind(players[0], "metadata").as((_metadata: GLib.HashTable) =>
players[0].get_meta("xesam:url") === null),
onClick: () => Process.exec(`wl-copy ${players[0].get_meta("xesam:url")?.get_string()[0]}`)
} as Widget.ButtonProps),
new Widget.Button({
className: "previous nf",
label: "󰒮",
tooltipText: "Previous",
onClick: () => players[0].canGoPrevious && players[0].previous()
} as Widget.ButtonProps),
new Widget.Button({
className: "pause nf",
tooltipText: bind(players[0], "playback_status").as((status: AstalMpris.PlaybackStatus) =>
status === AstalMpris.PlaybackStatus.PLAYING ? "Pause" : "Play"),
label: bind(players[0], "playbackStatus").as((status: AstalMpris.PlaybackStatus) =>
status === AstalMpris.PlaybackStatus.PLAYING ? "󰏤" : "󰐊"),
onClick: () => {
players[0].playbackStatus === AstalMpris.PlaybackStatus.PAUSED ?
players[0].play()
:
players[0].pause()
}
} as Widget.ButtonProps),
new Widget.Button({
className: "next nf",
label: "󰒭",
tooltipText: "Next",
onClick: () => players[0].canGoNext && players[0].next()
} as Widget.ButtonProps)
]
})
] : new Widget.Box({ className: "empty no-media" }))
} as Widget.BoxProps);
+18 -8
View File
@@ -1,12 +1,22 @@
import { Gtk, Widget } from "astal/gtk3";
export const tileList: Array<Gtk.Widget> = [
]
export const tileList: Array<Gtk.Widget> = [];
export const Tiles: Widget.Box = new Widget.Box({
child: new Gtk.Grid({
export function TilesWidget(): Gtk.Widget {
const tilesFlowBox: Gtk.FlowBox = new Gtk.FlowBox({
visible: true,
orientation: Gtk.Orientation.HORIZONTAL,
rowHomogeneous: true
} as Gtk.Grid.ConstructorProps)
} as Widget.BoxProps);
noShowAll: false,
orientation: Gtk.Orientation.HORIZONTAL
} as Gtk.Grid.ConstructorProps);
tileList.map((item: Gtk.Widget) =>
tilesFlowBox.insert(item, -1));
return new Widget.Box({
children: [
tilesFlowBox
]
} as Widget.BoxProps);
}
export const Tiles: Gtk.Widget = TilesWidget();
@@ -1,60 +0,0 @@
import { Binding } from "astal";
import { Gtk, Widget } from "astal/gtk3";
export interface MoreTileProps {
className?: string | Binding<string | undefined>;
iconName?: string | Binding<string | undefined>;
iconSize?: Gtk.IconSize;
title: string | Binding<string>;
description?: string | Binding<string | undefined>;
defaultToggleState?: boolean;
onToggledOn: Function;
onToggledOff: Function;
onClickMore: Function;
}
export function MoreTile(props: MoreTileProps): Gtk.Widget {
let toggleState: boolean = props?.defaultToggleState !== undefined ?
props.defaultToggleState : false;
const mainEventBox = new Widget.EventBox({
onClick: () => toggleState ? props.onToggledOff() : props.onToggledOn(),
expand: true,
child: new Widget.Box({
className: props?.className || "",
expand: true,
children: [
new Widget.Icon({
iconName: props?.iconName,
visible: props.iconName !== undefined,
iconSize: props.iconSize || Gtk.IconSize.BUTTON
}),
new Widget.Box({
className: "text",
orientation: Gtk.Orientation.VERTICAL,
children: [
new Widget.Label({
className: "title",
label: props.title
} as Widget.LabelProps),
new Widget.Label({
className: "description",
visible: props?.description !== undefined,
label: props?.description
} as Widget.LabelProps)
]
} as Widget.BoxProps),
new Widget.Button({
onClick: () => props.onClickMore(),
child: new Widget.Icon({
iconName: "go-next",
iconSize: Gtk.IconSize.BUTTON
} as Widget.IconProps),
} as Widget.ButtonProps)
]
} as Widget.BoxProps)
} as Widget.EventBoxProps);
return mainEventBox;
}
@@ -1,58 +0,0 @@
import { Binding, Variable } from "astal";
import { Gtk, Widget } from "astal/gtk3";
export interface NormalTileProps {
className?: string | Binding<string | undefined>;
iconName?: string | Binding<string | undefined>;
iconSize?: Gtk.IconSize;
title: string | Binding<string>;
description?: string | Binding<string | undefined>;
toggleState?: boolean | Binding<boolean | undefined>;
onToggledOn: Function;
onToggledOff: Function;
}
export function MoreTile(props: NormalTileProps): Gtk.Widget {
const mainEventBox = new Widget.EventBox({
onClick: () => toggleState ? props.onToggledOff() : props.onToggledOn(),
expand: true,
child: new Widget.Box({
className: props?.className || "",
expand: true,
children: [
new Widget.Icon({
iconName: props?.iconName,
visible: props.iconName !== undefined,
iconSize: props.iconSize || Gtk.IconSize.BUTTON
}),
new Widget.Box({
className: "text",
orientation: Gtk.Orientation.VERTICAL,
children: [
new Widget.Label({
className: "title",
label: props.title
} as Widget.LabelProps),
new Widget.Label({
className: "description",
visible: props?.description !== undefined,
label: props?.description
} as Widget.LabelProps)
]
} as Widget.BoxProps)
]
} as Widget.BoxProps)
} as Widget.EventBoxProps);
function toggleOn(): void {
mainEventBox.set_class_name(mainEventBox + "")
props.onToggledOn();
}
function toggleOff(): void {
props.onToggledOff();
}
return mainEventBox;
}
+39
View File
@@ -0,0 +1,39 @@
import { Binding } from "astal";
import { Gtk, Widget } from "astal/gtk3";
export type TileProps = {
className?: string | Binding<string | undefined>;
iconName?: string | Binding<string | undefined>;
visible?: boolean | Binding<boolean | undefined>;
iconSize?: number | Binding<number | undefined>;
title: string | Binding<string>;
description?: string | Binding<string | undefined>;
defaultToggleState?: boolean;
onToggledOn: () => void;
onToggledOff: () => void;
onClickMore?: () => void;
}
export function Tile(props: TileProps): Widget.Box {
const toggleButton = new Gtk.ToggleButton();
toggleButton.set_active(props.defaultToggleState || false);
const moreButton = new Widget.Button({
className: "more",
visible: props.onClickMore
});
return new Widget.Box({
className: (typeof Binding<string | undefined>) === (typeof props.className) ?
(props.className as Binding<string | undefined>).as((clsName: (string|undefined)) =>
`tile ${clsName || ""}`)
:
props.className,
visible: props.visible,
children: [
toggleButton,
moreButton
]
})
}
+2 -3
View File
@@ -1,4 +1,4 @@
import { Gdk, Astal, Gtk, Widget } from "astal/gtk3";
import { Astal, Gtk, Widget } from "astal/gtk3";
import { Clock } from "../widget/bar/Clock";
import { Logo } from "../widget/bar/Logo";
@@ -11,12 +11,11 @@ import { Media } from "../widget/bar/Media";
export const Bar: Widget.Window = new Widget.Window({
monitor: 0,
namespace: "top-bar",
anchor: Astal.WindowAnchor.TOP,
anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.RIGHT,
layer: Astal.Layer.TOP,
exclusivity: Astal.Exclusivity.EXCLUSIVE,
canFocus: false,
visible: true,
widthRequest: Gdk.Screen.get_default()?.get_monitor_geometry(0)?.width,
child: new Widget.Box({
className: "bar-container",
child: new Widget.CenterBox({
+3
View File
@@ -2,6 +2,7 @@ import { Astal, Gtk, Widget } from "astal/gtk3";
import { GLib } from "astal";
import { getDateTime } from "../scripts/time";
import { BigMedia } from "../widget/center-window/BigMedia";
export const CenterWindow: Widget.Window = new Widget.Window({
className: "center-window",
@@ -25,6 +26,7 @@ export const CenterWindow: Widget.Window = new Widget.Window({
new Widget.Box({
className: "top",
orientation: Gtk.Orientation.VERTICAL,
valign: Gtk.Align.START,
children: [
new Widget.Label({
className: "time",
@@ -38,6 +40,7 @@ export const CenterWindow: Widget.Window = new Widget.Window({
} as Widget.LabelProps)
]
} as Widget.BoxProps),
BigMedia
]
} as Widget.BoxProps),
new Widget.Box({
+22 -21
View File
@@ -3,23 +3,8 @@ import AstalNotifd from "gi://AstalNotifd";
import { bind } from "astal";
import { Notifications } from "../scripts/notification-handler";
export const FloatingNotifications: Widget.Window = new Widget.Window({
namespace: "floating-notifications",
canFocus: false,
anchor: Astal.WindowAnchor.RIGHT,
monitor: 0,
layer: Astal.Layer.OVERLAY,
visible: false,
width_request: 350,
exclusivity: Astal.Exclusivity.NORMAL,
child: new Widget.Box({
className: "floating-notifications-container",
orientation: Gtk.Orientation.VERTICAL,
homogeneous: false,
children: bind(Notifications, "notifications").as((notifications: Array<AstalNotifd.Notification>) => {
console.log("something changed!");
return notifications.map((notification: AstalNotifd.Notification) =>
new Widget.Box({
function NotificationWidget(notification: AstalNotifd.Notification): Gtk.Widget {
return new Widget.Box({
className: "notification",
homogeneous: false,
expand: false,
@@ -49,7 +34,7 @@ export const FloatingNotifications: Widget.Window = new Widget.Window({
new Widget.Box({
className: "image",
visible: notification.image !== "",
css: `.image { background-image: url('${notification.image}'); }`
css: `box.image { background-image: url('${notification.image}'); }`
} as Widget.BoxProps),
new Widget.Box({
className: "text",
@@ -70,8 +55,24 @@ export const FloatingNotifications: Widget.Window = new Widget.Window({
]
} as Widget.BoxProps)
]
} as Widget.BoxProps)
)
})
} as Widget.BoxProps);
}
export const FloatingNotifications: Widget.Window = new Widget.Window({
namespace: "floating-notifications",
canFocus: false,
anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.RIGHT,
monitor: 0,
layer: Astal.Layer.OVERLAY,
visible: false,
width_request: 350,
exclusivity: Astal.Exclusivity.NORMAL,
child: new Widget.Box({
className: "floating-notifications-container",
orientation: Gtk.Orientation.VERTICAL,
homogeneous: false,
children: bind(Notifications, "notifications").as((notifications: Array<AstalNotifd.Notification>) =>
notifications.map((notification: AstalNotifd.Notification) =>
NotificationWidget(notification)))
} as Widget.BoxProps)
} as Widget.WindowProps);
-2
View File
@@ -12,8 +12,6 @@ export const LogoutMenu: Widget.Window = new Widget.Window({
exclusivity: Astal.Exclusivity.IGNORE,
monitor: 0,
visible: false,
widthRequest: Gdk.Screen.get_default()?.get_monitor_geometry(0)?.width,
height_request: Gdk.Screen.get_default()?.get_monitor_geometry(0)?.height,
child: new Widget.EventBox({
className: "logout-menu",
onClick: () => Process.exec_async("astal close logout-menu", () => {}),
-1
View File
@@ -1,7 +1,6 @@
import { bind, Binding, Variable } from "astal";
import { Astal, Gtk, Widget } from "astal/gtk3";
import { Wireplumber } from "../scripts/volume";
import AstalWp from "gi://AstalWp?version=0.1";
export enum OSDModes {
SINK,