183 lines
5 KiB
TypeScript
183 lines
5 KiB
TypeScript
|
const Applications = await Service.import('applications');
|
||
|
const Hyprland = await Service.import('hyprland');
|
||
|
|
||
|
const { Box, Icon, Label, Scrollable, Stack } = Widget;
|
||
|
const { execAsync, timeout } = Utils;
|
||
|
|
||
|
import PopupWindow from '../misc/popup.ts';
|
||
|
import CursorBox from '../misc/cursorbox.ts';
|
||
|
import { Client } from 'types/service/hyprland';
|
||
|
|
||
|
|
||
|
const takeScreenshot = (selector: string, delay = 1000): void => {
|
||
|
App.closeWindow('win-screenshot');
|
||
|
timeout(delay, () => {
|
||
|
execAsync(['bash', '-c', `grim ${selector} - | satty -f -`])
|
||
|
.catch(console.error);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
export default () => {
|
||
|
const windowList = Box({
|
||
|
vertical: true,
|
||
|
});
|
||
|
|
||
|
const updateWindows = async() => {
|
||
|
if (!App.getWindow('win-screenshot')?.visible) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
windowList.children = (JSON.parse(
|
||
|
await Hyprland.messageAsync('j/clients'),
|
||
|
) as Client[])
|
||
|
.filter((client) => client.workspace.id === Hyprland.active.workspace.id)
|
||
|
.map((client) => CursorBox({
|
||
|
class_name: 'item-btn',
|
||
|
|
||
|
on_primary_click_release: () => {
|
||
|
takeScreenshot(`-w ${client.address}`);
|
||
|
},
|
||
|
|
||
|
child: Box({
|
||
|
hpack: 'center',
|
||
|
|
||
|
children: [
|
||
|
Icon(Applications
|
||
|
.query(client.class)[0]?.app.get_string('Icon') ?? ''),
|
||
|
|
||
|
Label({
|
||
|
label: client.title,
|
||
|
truncate: 'end',
|
||
|
max_width_chars: 50,
|
||
|
}),
|
||
|
],
|
||
|
}),
|
||
|
}));
|
||
|
};
|
||
|
|
||
|
|
||
|
const stack = Stack({
|
||
|
transition: 'slide_left_right',
|
||
|
|
||
|
children: {
|
||
|
monitors: Scrollable({
|
||
|
child: Box({
|
||
|
vertical: true,
|
||
|
}).hook(Hyprland, (self) => {
|
||
|
self.children = Hyprland.monitors.map((monitor) => CursorBox({
|
||
|
class_name: 'item-btn',
|
||
|
|
||
|
on_primary_click_release: () => {
|
||
|
takeScreenshot(`-o ${monitor.name}`);
|
||
|
},
|
||
|
|
||
|
child: Label({
|
||
|
label: `${monitor.name}: ${monitor.description}`,
|
||
|
truncate: 'end',
|
||
|
max_width_chars: 50,
|
||
|
}),
|
||
|
}));
|
||
|
}, 'notify::monitors'),
|
||
|
}),
|
||
|
|
||
|
windows: Scrollable({
|
||
|
child: windowList
|
||
|
.hook(Hyprland, updateWindows, 'notify::clients')
|
||
|
.hook(Hyprland.active.workspace, updateWindows),
|
||
|
}),
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const monitorsButton = CursorBox({
|
||
|
class_name: 'header-btn',
|
||
|
|
||
|
on_primary_click_release: () => {
|
||
|
stack.shown = 'monitors';
|
||
|
},
|
||
|
|
||
|
child: Box({
|
||
|
hpack: 'center',
|
||
|
|
||
|
children: [
|
||
|
Icon('display-symbolic'),
|
||
|
Label('monitors'),
|
||
|
],
|
||
|
}),
|
||
|
});
|
||
|
|
||
|
const windowsButton = CursorBox({
|
||
|
class_name: 'header-btn',
|
||
|
|
||
|
on_primary_click_release: () => {
|
||
|
stack.shown = 'windows';
|
||
|
},
|
||
|
|
||
|
child: Box({
|
||
|
hpack: 'center',
|
||
|
|
||
|
children: [
|
||
|
Icon('window-symbolic'),
|
||
|
Label('windows'),
|
||
|
],
|
||
|
}),
|
||
|
});
|
||
|
|
||
|
const regionButton = CursorBox({
|
||
|
class_name: 'header-btn',
|
||
|
|
||
|
on_primary_click_release: () => {
|
||
|
takeScreenshot('-g "$(slurp)"', 0);
|
||
|
},
|
||
|
|
||
|
child: Box({
|
||
|
hpack: 'center',
|
||
|
|
||
|
children: [
|
||
|
Icon('tool-pencil-symbolic'),
|
||
|
Label('region'),
|
||
|
],
|
||
|
}),
|
||
|
});
|
||
|
|
||
|
return PopupWindow({
|
||
|
name: 'screenshot',
|
||
|
on_open: () => {
|
||
|
updateWindows();
|
||
|
},
|
||
|
child: Box({
|
||
|
class_name: 'screenshot',
|
||
|
vertical: true,
|
||
|
|
||
|
children: [
|
||
|
Box({
|
||
|
class_name: 'header',
|
||
|
homogeneous: true,
|
||
|
|
||
|
children: [
|
||
|
monitorsButton,
|
||
|
windowsButton,
|
||
|
regionButton,
|
||
|
],
|
||
|
}).hook(stack, () => {
|
||
|
switch (stack.shown) {
|
||
|
case 'monitors':
|
||
|
monitorsButton.toggleClassName('active', true);
|
||
|
windowsButton.toggleClassName('active', false);
|
||
|
break;
|
||
|
|
||
|
case 'windows':
|
||
|
monitorsButton.toggleClassName('active', false);
|
||
|
windowsButton.toggleClassName('active', true);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}, 'notify::shown'),
|
||
|
|
||
|
stack,
|
||
|
],
|
||
|
}),
|
||
|
});
|
||
|
};
|