[Astal] Add mode indicator
This commit is contained in:
@@ -1,50 +1,59 @@
|
||||
import AstalTray from "gi://AstalTray";
|
||||
import { bind, GObject } from "astal";
|
||||
import AstalHyprland from "gi://AstalHyprland";
|
||||
import { Gtk } from "astal/gtk4";
|
||||
import Pango from "gi://Pango?version=1.0";
|
||||
import {
|
||||
GObject, bind,
|
||||
exec,
|
||||
readFile
|
||||
} from 'astal';
|
||||
import AstalHyprland from 'gi://AstalHyprland';
|
||||
import AstalTray from 'gi://AstalTray';
|
||||
import {
|
||||
Gtk
|
||||
} from 'astal/gtk4';
|
||||
import Pango from 'gi://Pango?version=1.0';
|
||||
|
||||
const hypr = AstalHyprland.get_default();
|
||||
const SYNC = GObject.BindingFlags.SYNC_CREATE;
|
||||
|
||||
const SysTray = () => {
|
||||
const trayBox = new Gtk.Box({ cssClasses: ["bar-button"] });
|
||||
const trayBox = new Gtk.Box( {
|
||||
'cssClasses': [ 'bar-button' ]
|
||||
} );
|
||||
const tray = AstalTray.get_default();
|
||||
|
||||
const trayItems = new Map<string, Gtk.MenuButton>();
|
||||
const trayAddedHandler = tray.connect("item-added", (_, id) => {
|
||||
const item = tray.get_item(id);
|
||||
const popover = Gtk.PopoverMenu.new_from_model(item.menu_model);
|
||||
const trayAddedHandler = tray.connect( 'item-added', ( _, id ) => {
|
||||
const item = tray.get_item( id );
|
||||
const popover = Gtk.PopoverMenu.new_from_model( item.menu_model );
|
||||
const icon = new Gtk.Image();
|
||||
const button = new Gtk.MenuButton({
|
||||
const button = new Gtk.MenuButton( {
|
||||
popover,
|
||||
child: icon,
|
||||
cssClasses: ["tray-item"],
|
||||
});
|
||||
'child': icon,
|
||||
'cssClasses': [ 'tray-item' ],
|
||||
} );
|
||||
|
||||
item.bind_property("gicon", icon, "gicon", SYNC);
|
||||
popover.insert_action_group("dbusmenu", item.action_group);
|
||||
item.connect("notify::action-group", () => {
|
||||
popover.insert_action_group("dbusmenu", item.action_group);
|
||||
});
|
||||
item.bind_property(
|
||||
'gicon', icon, 'gicon', SYNC
|
||||
);
|
||||
popover.insert_action_group( 'dbusmenu', item.action_group );
|
||||
item.connect( 'notify::action-group', () => {
|
||||
popover.insert_action_group( 'dbusmenu', item.action_group );
|
||||
} );
|
||||
|
||||
trayItems.set(id, button);
|
||||
trayBox.append(button);
|
||||
});
|
||||
trayItems.set( id, button );
|
||||
trayBox.append( button );
|
||||
} );
|
||||
const trayRemovedHandler = tray.connect( 'item-removed', ( _, id ) => {
|
||||
const button = trayItems.get( id );
|
||||
|
||||
const trayRemovedHandler = tray.connect("item-removed", (_, id) => {
|
||||
const button = trayItems.get(id);
|
||||
if (button) {
|
||||
trayBox.remove(button);
|
||||
if ( button ) {
|
||||
trayBox.remove( button );
|
||||
button.run_dispose();
|
||||
trayItems.delete(id);
|
||||
trayItems.delete( id );
|
||||
}
|
||||
});
|
||||
} );
|
||||
|
||||
trayBox.connect("destroy", () => {
|
||||
tray.disconnect(trayAddedHandler);
|
||||
tray.disconnect(trayRemovedHandler);
|
||||
});
|
||||
trayBox.connect( 'destroy', () => {
|
||||
tray.disconnect( trayAddedHandler );
|
||||
tray.disconnect( trayRemovedHandler );
|
||||
} );
|
||||
|
||||
return trayBox;
|
||||
};
|
||||
@@ -52,25 +61,21 @@ const SysTray = () => {
|
||||
const Workspace = () => {
|
||||
return (
|
||||
<box>
|
||||
{bind(hypr, "workspaces").as(wss =>
|
||||
wss
|
||||
.filter(ws => !(ws.id >= -99 && ws.id <= -2)) // filter out special workspaces
|
||||
.sort((a, b) => a.id - b.id)
|
||||
.map(ws => (
|
||||
<button
|
||||
cssClasses={bind(hypr, "focusedWorkspace").as(fw =>
|
||||
ws === fw
|
||||
? [
|
||||
"focused-workspace-button",
|
||||
"workspace-button",
|
||||
]
|
||||
: ["workspace-button"],
|
||||
)}
|
||||
onButtonPressed={() => ws.focus()}
|
||||
child={<label label={String(ws.id)}></label>}
|
||||
></button>
|
||||
)),
|
||||
)}
|
||||
{bind( hypr, 'workspaces' ).as( wss => wss
|
||||
.filter( ws => !( ws.id >= -99 && ws.id <= -2 ) ) // filter out special workspaces
|
||||
.sort( ( a, b ) => a.id - b.id )
|
||||
.map( ws => (
|
||||
<button
|
||||
cssClasses={bind( hypr, 'focusedWorkspace' ).as( fw => ws === fw
|
||||
? [
|
||||
'focused-workspace-button',
|
||||
'workspace-button',
|
||||
]
|
||||
: [ 'workspace-button' ], )}
|
||||
onButtonPressed={() => ws.focus()}
|
||||
child={<label label={String( ws.id )}></label>}
|
||||
></button>
|
||||
) ), )}
|
||||
</box>
|
||||
);
|
||||
};
|
||||
@@ -80,15 +85,15 @@ const Workspace = () => {
|
||||
* displaying all available clients
|
||||
*/
|
||||
const ActiveWindow = () => {
|
||||
const focused = bind(hypr, "focusedClient");
|
||||
const focused = bind( hypr, 'focusedClient' );
|
||||
|
||||
const WindowPopover = (): Gtk.Popover => {
|
||||
// Set up boxes + Popover
|
||||
const popover = new Gtk.Popover();
|
||||
|
||||
const popoverBox = WindowPopoverBox();
|
||||
|
||||
popover.set_child(popoverBox);
|
||||
popover.set_child( popoverBox );
|
||||
|
||||
return popover;
|
||||
};
|
||||
|
||||
@@ -98,65 +103,88 @@ const ActiveWindow = () => {
|
||||
// Return fully assembled HyprlandFocusedClient box
|
||||
// ───────────────────────────────────────────────────────────────────
|
||||
return (
|
||||
<box visible={focused.as(Boolean)}>
|
||||
<box visible={focused.as( Boolean )}>
|
||||
<button
|
||||
onClicked={() => windowPopover.popup()}
|
||||
cssClasses={["bar-button"]}
|
||||
cssClasses={[ 'bar-button' ]}
|
||||
child={
|
||||
focused.as(
|
||||
client =>
|
||||
client && (
|
||||
<label
|
||||
maxWidthChars={70}
|
||||
ellipsize={Pango.EllipsizeMode.END}
|
||||
label={bind(client, "title").as(String)} />
|
||||
),
|
||||
)
|
||||
focused.as( client => client && (
|
||||
<label
|
||||
maxWidthChars={70}
|
||||
ellipsize={Pango.EllipsizeMode.END}
|
||||
label={bind( client, 'title' ).as( String )} />
|
||||
), )
|
||||
}></button>
|
||||
{windowPopover}
|
||||
</box >
|
||||
);
|
||||
};
|
||||
|
||||
type submaps = 'device' | 'launch' | 'workspace' | 'windowing' | 'screenshotting' | 'notifications' | '';
|
||||
|
||||
const ModeStatus = () => {
|
||||
const label = new Gtk.Label();
|
||||
const map = {
|
||||
"device": "D",
|
||||
"launch": "L",
|
||||
"workspace": "W",
|
||||
"windowing": "M",
|
||||
"screenshotting": "S",
|
||||
"notifications": "N",
|
||||
let isUsingHyprmode = false;
|
||||
|
||||
try {
|
||||
const path = exec( 'bash -c "cd ~ && pwd"' ) + '/.config/hyprmode';
|
||||
|
||||
isUsingHyprmode = readFile( path ).trim() === 'y';
|
||||
} catch ( e ) {
|
||||
printerr( 'Failed to read hyprmode config', e );
|
||||
}
|
||||
|
||||
const label = new Gtk.Label();
|
||||
|
||||
if ( !isUsingHyprmode ) return label;
|
||||
|
||||
print( '==> Using hyprmode config' );
|
||||
|
||||
const map = {
|
||||
'device': 'D',
|
||||
'launch': 'L',
|
||||
'workspace': 'W',
|
||||
'windowing': 'M',
|
||||
'screenshotting': 'S',
|
||||
'notifications': 'N',
|
||||
'': 'N'
|
||||
};
|
||||
|
||||
label.label = 'N';
|
||||
label.cssClasses = [ 'mode-status' ];
|
||||
|
||||
// TODO: Possibly add popover to it that lists binds
|
||||
hypr.connect("submap", (name: string) => {
|
||||
hypr.connect( 'submap', ( _, name: submaps ) => {
|
||||
label.label = map[name];
|
||||
label.cssClasses = ["mode-status", name + '-mode']
|
||||
})
|
||||
return
|
||||
}
|
||||
label.cssClasses = [
|
||||
'mode-status',
|
||||
name + '-mode'
|
||||
];
|
||||
} );
|
||||
|
||||
return label;
|
||||
};
|
||||
|
||||
const WindowPopoverBox = () => {
|
||||
return <box vertical>
|
||||
<label label={"Available Windows"} cssClasses={['title-2']}></label>
|
||||
<label label={'Available Windows'} cssClasses={[ 'title-2' ]}></label>
|
||||
<Gtk.Separator marginTop={5} marginBottom={5}></Gtk.Separator>
|
||||
<box vertical>
|
||||
{bind(hypr, 'clients').as(clients => {
|
||||
return clients.map(client => {
|
||||
{bind( hypr, 'clients' ).as( clients => {
|
||||
return clients.map( client => {
|
||||
return <button child={
|
||||
<box>
|
||||
<label label={bind(client, 'workspace').as(w => `(WS ${w.name})`)}></label>
|
||||
<label label={bind(client, 'initialClass').as(c => `[${c}]`)}></label>
|
||||
<label label={bind(client, 'title')}></label>
|
||||
<label label={bind( client, 'workspace' ).as( w => `(WS ${ w.name })` )}></label>
|
||||
<label label={bind( client, 'initialClass' ).as( c => `[${ c }]` )}></label>
|
||||
<label label={bind( client, 'title' )}></label>
|
||||
</box>
|
||||
}
|
||||
onClicked={() => client.focus()}
|
||||
></button>
|
||||
})
|
||||
})}
|
||||
onClicked={() => client.focus()}
|
||||
></button>;
|
||||
} );
|
||||
} )}
|
||||
</box>
|
||||
</box>
|
||||
}
|
||||
</box>;
|
||||
};
|
||||
|
||||
export default {
|
||||
Workspace,
|
||||
|
||||
Reference in New Issue
Block a user