repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
quickshell/nuguland/niri.js
Raw// Niri 26.04: niri-ipc/src/{lib,state}.rs at
// https://github.com/niri-wm/niri/tree/8ed0da44d974c32c6877d2f4630c314da0717ecb
// Pure patches keep protocol validation/replays independent of QML process timing.
function object(value) {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function id(value) {
return Number.isSafeInteger(value) && value >= 0;
}
function optionalId(value) {
return value === null || id(value);
}
function optionalString(value) {
return value === null || typeof value === "string";
}
function pair(value) {
return Array.isArray(value) && value.length === 2 && value.every(Number.isFinite);
}
function timestamp(value) {
return value === null || object(value) && id(value.secs) && id(value.nanos) && value.nanos < 1000000000;
}
function layout(value) {
return object(value)
&& (value.pos_in_scrolling_layout === null || pair(value.pos_in_scrolling_layout) && value.pos_in_scrolling_layout.every(id))
&& pair(value.tile_size) && pair(value.window_size)
&& (value.tile_pos_in_workspace_view === null || pair(value.tile_pos_in_workspace_view))
&& pair(value.window_offset_in_tile);
}
function windowRecord(value) {
return object(value) && id(value.id) && optionalString(value.title) && optionalString(value.app_id)
&& (value.pid === null || Number.isInteger(value.pid)) && optionalId(value.workspace_id) && typeof value.is_focused === "boolean"
&& typeof value.is_floating === "boolean" && typeof value.is_urgent === "boolean"
&& layout(value.layout) && timestamp(value.focus_timestamp);
}
function workspaceRecord(value) {
return object(value) && id(value.id) && id(value.idx) && value.idx <= 255
&& optionalString(value.name) && optionalString(value.output)
&& typeof value.is_urgent === "boolean" && typeof value.is_active === "boolean"
&& typeof value.is_focused === "boolean" && optionalId(value.active_window_id);
}
function castRecord(value) {
if (!object(value) || !object(value.target) || Object.keys(value.target).length !== 1)
return false;
const name = Object.keys(value.target)[0];
const target = value.target[name];
return id(value.stream_id) && id(value.session_id) && ["PipeWire", "WlrScreencopy"].includes(value.kind)
&& typeof value.is_dynamic_target === "boolean" && typeof value.is_active === "boolean"
&& (value.pid === null || Number.isInteger(value.pid)) && optionalId(value.pw_node_id)
&& object(target) && (name === "Nothing" || name === "Output" && typeof target.name === "string"
|| name === "Window" && id(target.id));
}
function records(value, valid) {
return Array.isArray(value) && value.every(valid) && new Set(value.map(row => row.id)).size === value.length;
}
function requireValid(valid, name) {
if (!valid)
throw new Error("malformed niri " + name);
}
function replace(items, target, fields) {
return items.map(row => row.id === target ? Object.assign({}, row, fields) : row);
}
function windowPatch(windows) {
const focused = windows.find(row => row.is_focused);
return { windows: windows, focusedWindow: focused ? focused.id : null };
}
// null means ignored, never a successful state update. Unknown variants/fields
// are allowed by the IPC contract; known payloads must validate before mutation.
function reduce(state, event) {
requireValid(object(event) && Object.keys(event).length === 1, "event envelope");
const name = Object.keys(event)[0];
const data = event[name];
switch (name) {
case "WorkspacesChanged":
requireValid(object(data) && records(data.workspaces, workspaceRecord), name);
return { workspaces: data.workspaces, workspacesInitialized: true };
case "WorkspaceActivated": {
requireValid(object(data) && id(data.id) && typeof data.focused === "boolean", name);
const active = state.workspaces.find(row => row.id === data.id);
requireValid(!!active, name + " workspace");
return { workspaces: state.workspaces.map(row => Object.assign({}, row, {
is_active: row.output === active.output ? row.id === data.id : row.is_active,
is_focused: data.focused ? row.id === data.id : row.is_focused
})) };
}
case "WorkspaceActiveWindowChanged":
requireValid(object(data) && id(data.workspace_id) && optionalId(data.active_window_id), name);
requireValid(state.workspaces.some(row => row.id === data.workspace_id), name + " workspace");
// The window may not have arrived yet. Upstream does not require it here.
return { workspaces: replace(state.workspaces, data.workspace_id, { active_window_id: data.active_window_id }) };
case "WorkspaceUrgencyChanged":
requireValid(object(data) && id(data.id) && typeof data.urgent === "boolean", name);
return { workspaces: replace(state.workspaces, data.id, { is_urgent: data.urgent }) };
case "WindowsChanged":
requireValid(object(data) && records(data.windows, windowRecord), name);
return Object.assign(windowPatch(data.windows), { windowsInitialized: true });
case "WindowOpenedOrChanged": {
requireValid(object(data) && windowRecord(data.window), name);
const win = data.window;
const windows = state.windows.filter(row => row.id !== win.id).map(row =>
win.is_focused ? Object.assign({}, row, { is_focused: false }) : row);
windows.push(win);
return windowPatch(windows);
}
case "WindowClosed":
requireValid(object(data) && id(data.id), name);
requireValid(state.windows.some(row => row.id === data.id), name + " window");
return windowPatch(state.windows.filter(row => row.id !== data.id));
case "WindowFocusChanged":
requireValid(object(data) && optionalId(data.id), name);
return windowPatch(state.windows.map(row => Object.assign({}, row, { is_focused: row.id === data.id })));
case "WindowFocusTimestampChanged":
requireValid(object(data) && id(data.id) && timestamp(data.focus_timestamp), name);
return { windows: replace(state.windows, data.id, { focus_timestamp: data.focus_timestamp }) };
case "WindowUrgencyChanged":
requireValid(object(data) && id(data.id) && typeof data.urgent === "boolean", name);
return { windows: replace(state.windows, data.id, { is_urgent: data.urgent }) };
case "WindowLayoutsChanged": {
requireValid(object(data) && Array.isArray(data.changes) && data.changes.every(change =>
Array.isArray(change) && change.length === 2 && id(change[0]) && layout(change[1])
&& state.windows.some(row => row.id === change[0])), name);
let windows = state.windows;
for (const change of data.changes)
windows = replace(windows, change[0], { layout: change[1] });
return { windows: windows };
}
case "OverviewOpenedOrClosed":
requireValid(object(data) && typeof data.is_open === "boolean", name);
return { overviewState: data.is_open ? "open" : "closed" };
case "ScreenshotCaptured":
requireValid(object(data) && optionalString(data.path), name);
return { screenshotPath: data.path };
// These installed variants are not owned by Nuguland. Validate them without
// treating them as initialization or adding unused service state.
case "KeyboardLayoutsChanged":
requireValid(object(data) && object(data.keyboard_layouts)
&& Array.isArray(data.keyboard_layouts.names) && data.keyboard_layouts.names.every(value => typeof value === "string")
&& id(data.keyboard_layouts.current_idx) && data.keyboard_layouts.current_idx <= 255, name);
return null;
case "KeyboardLayoutSwitched":
requireValid(object(data) && id(data.idx) && data.idx <= 255, name);
return null;
case "ConfigLoaded":
requireValid(object(data) && typeof data.failed === "boolean", name);
return null;
case "CastsChanged":
requireValid(object(data) && Array.isArray(data.casts) && data.casts.every(castRecord), name);
return null;
case "CastStartedOrChanged":
requireValid(object(data) && castRecord(data.cast), name);
return null;
case "CastStopped":
requireValid(object(data) && id(data.stream_id), name);
return null;
default:
return null;
}
}
// Outputs are a separate request, never stream state. A failed/partial query
// must not replace the last inventory, including when stdout happens to be {}.
function parseOutputs(text, exitCode, exitStatus) {
requireValid(exitCode === 0 && exitStatus === 0, "outputs query exit");
const outputs = JSON.parse(text);
requireValid(object(outputs) && Object.keys(outputs).every(name => {
const row = outputs[name];
const logical = row && row.logical;
return object(row) && row.name === name && typeof row.make === "string" && typeof row.model === "string"
&& optionalString(row.serial) && Array.isArray(row.modes) && optionalId(row.current_mode)
&& (logical === null || object(logical) && [logical.x, logical.y, logical.width, logical.height, logical.scale].every(Number.isFinite));
}), "outputs inventory");
return outputs;
}