hyprland workspace client list not updated after move unless focused
Describe the bug Hyprland does not update workspace or clients bind on client move to another workspace. The only value which is updated is lastClient.
The comand in the hyprland config is movetoworkspacesilent, which does not move the focus to another workspace after moving the client. movetoworkspace works as expected, presumably because the focus is moved to where the client is moved.
Expected behavior To show the correct number of clients per workspace after moving a client to another workspace even when using movetoworkspacesilent to move client.
Additional context
Keybindings
bind = $mainMod SHIFT, 1, movetoworkspacesilent, 1 bind = $mainMod SHIFT, 2, movetoworkspacesilent, 2 bind = $mainMod SHIFT, 3, movetoworkspacesilent, 3 bind = $mainMod SHIFT, 4, movetoworkspacesilent, 4 bind = $mainMod SHIFT, 5, movetoworkspacesilent, 5 bind = $mainMod SHIFT, 6, movetoworkspacesilent, 6 bind = $mainMod SHIFT, 7, movetoworkspacesilent, 7 bind = $mainMod SHIFT, 8, movetoworkspacesilent, 8 bind = $mainMod SHIFT, 9, movetoworkspacesilent, 9 bind = $mainMod SHIFT, 0, movetoworkspacesilent, 10
Here is a sample code ` function verticalWidget(gdkMonitor: Gdk.Monitor): JSX.Element {
// Find correct monitor, or return empty if none found.
const currentHyprlandMonitor = hyprland.get_monitor_by_name(getMonitorName(gdkMonitor) ?? "");
if (!currentHyprlandMonitor) return <></>
print(`Monitor:${currentHyprlandMonitor.id} assigned a bar`)
return <box className="workspaces-widget-vertical" vertical={true}>
{Variable.derive([bind(hyprland, "workspaces"), bind(hyprland, "clients"), bind(hyprland,"focusedWorkspace"),bind(hyprland,"focusedClient")])().as((values) => {
let workspaces = values[0]; //only updates when switching workspace
let clients = values[1];
let focusedWorkspace = values[2];
// Sort
workspaces = showAllWorkspaces ? workspaces : workspaces.filter(val => val.monitor.id === currentHyprlandMonitor.id);
workspaces.sort((a, b) => a.id - b.id);
return workspaces.map((workspace) =>
<button
className={workspace === focusedWorkspace ? "focused" : ""}
onClicked={() => {
workspace.move_to(currentHyprlandMonitor);
workspace.focus();
}}
>
<box vertical={true}>
{`${workspace.id}:${workspace.clients.length} + ${clients.filter(val=>val.workspace===workspace).length}`}
</box>
</button>
);
})}
</box>
} `
I believe I have the same issue. When I move a client from one workspace to another using drag-and-drop (SUPER, mouse:272, movewindow), neither the workspaces nor the clients list updates.
To verify, I print out the list of workspaces every time it changes:
import { bind } from "astal"
import { Gtk } from "astal/gtk3"
import Hyprland from "gi://AstalHyprland"
import Clients from "./Clients"
const hyprland = Hyprland.get_default()
interface Props {
monitorId: number
}
export default function Workspaces({ monitorId }: Props) {
const workspaces = bind(hyprland, "workspaces").as((ws) =>
ws
//-------------------------------------------------------------------
.map((workspace) => {
print("workspace", workspace.name)
return workspace
})
//-------------------------------------------------------------------
.filter((workspace) => workspace.monitor.id === monitorId)
.sort((a, b) => a.id - b.id)
.map((workspace) => (
<button
halign={Gtk.Align.CENTER}
onClick={() =>
hyprland.dispatch("workspace", workspace.name)
}
>
<box orientation={Gtk.Orientation.HORIZONTAL} spacing={4}>
<label>
{workspace.name[workspace.name.length - 1]}
</label>
<Clients workspaceId={workspace.id} />
</box>
</button>
)),
)
return (
<box orientation={Gtk.Orientation.HORIZONTAL} halign={Gtk.Align.CENTER}>
{workspaces}
</box>
)
}
Expected Behavior:
When I move a client using drag-and-drop, the printed list of workspaces should update.
Actual Behavior:
- The workspace list does not update when moving a client via
movewindow. - However, when using
split-movetoworkspace, it correctly triggers updates (I currently use the split-monitor-workspaces plugin).
It seems like drag-and-drop moves are not firing the appropriate signal to AstalHyprland. Could this be a missing event, or does AstalHyprland need explicit handling for drag-and-drop workspace changes?
A simple workaround to just listen manually, not sure why client-moved is firing here but not when you bind to clients
const hypr = Hyprland.get_default();
const [clients, setClients] = createState(hypr.get_clients());
hypr.connect('client-added', (_, client) => {
setClients((c) => [...c, client]);
});
hypr.connect('client-removed', (_, address) => {
setClients((c) => c.filter((c) => c.address != address));
});
hypr.connect('client-moved', (hy, _) => {
setClients((_) => hy.get_clients());
});