feat(ags): add screenshot gui
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2024-05-05 22:43:03 -04:00
parent 63be8a848c
commit 551880cc24
20 changed files with 487 additions and 328 deletions

View file

@ -1,5 +1,10 @@
{nixpkgs-wayland, ...} @ inputs: [
{
grim-hyprland,
nixpkgs-wayland,
...
} @ inputs: [
(import ./dracula-theme inputs)
grim-hyprland.overlays.default
nixpkgs-wayland.overlay
]

View file

@ -1,110 +0,0 @@
{
config,
writeShellApplication,
stdenvNoCC,
jre,
fetchFromGitHub,
fetchurl,
makeWrapper,
makeDesktopItem,
rsync,
...
}:
stdenvNoCC.mkDerivation rec {
name = "rars-flatlaf";
src = fetchFromGitHub {
owner = "privat";
repo = "rars";
rev = "fd34014efd65b3cb5a52f1729c3b8240cae0c332";
hash = "sha256-D8X/cr+fnq/OOFYfMG9aPss95J8Z2yiROuF9kmHkK40=";
fetchSubmodules = true;
};
desktopItem = let
hyprland = config.home-manager.users.${config.vars.mainUser}.wayland.windowManager.hyprland.finalPackage;
execScript = writeShellApplication {
name = "execScript";
runtimeInputs = [hyprland];
text = "(sleep 1; hyprctl dispatch togglefloating) & ${name}";
};
in
makeDesktopItem {
name = "RARS";
desktopName = "RARS";
exec = "${execScript}/bin/execScript";
icon = name;
};
nativeBuildInputs = [makeWrapper rsync jre];
installPhase = let
flatlaf = fetchurl {
url = "https://repo1.maven.org/maven2/com/formdev/flatlaf/3.2/flatlaf-3.2.jar";
hash = "sha256-HAG+G9undDXWtySokKl7lkIUCFI7lEBduu+UgSVaxAA=";
};
icon = fetchurl {
url = "https://riscv.or.jp/wp-content/uploads/2019/06/cropped-RISC-V-logo-figonly-mod-2.png";
hash = "sha256-e1/iVmadVzyO77ikBr1cdXsJdDj8TiXh3Oyjek9GwqM=";
};
in
/*
bash
*/
''
# ./build-jar.sh
mkdir -p build
find src -name "*.java" | xargs javac --release 8 -d build
if [[ "$OSTYPE" == "darwin"* ]]; then
find src -type f -not -name "*.java" -exec rsync -R {} build \;
else
find src -type f -not -name "*.java" -exec cp --parents {} build \;
fi
cp -rf build/src/* build
rm -r build/src
cp README.md License.txt build
cd build
jar cfm ../rars.jar ./META-INF/MANIFEST.MF *
chmod +x ../rars.jar
cd ..
# ./build-jar-flatlaf.sh
mkdir -p build-flatlaf/
cd build-flatlaf/
cp ${flatlaf} ../flatlaf.jar
jar x < ../rars.jar
jar x < "../flatlaf.jar"
cat > META-INF/MANIFEST.MF <<EOF
Manifest-Version: 1.0
Implementation-Version: 3.1.1
Multi-Release: true
Main-Class: rars.Launch
EOF
jar cfm ../rars-flatlaf.jar META-INF/MANIFEST.MF *
chmod +x ../rars-flatlaf.jar
cd ..
# InstallPhase
runHook preInstall
cat > ./rars.desktop <<EOF
EOF
mkdir -p "$out/share/pixmaps"
cp "${icon}" "$out/share/pixmaps/${name}.png"
install -D $desktopItem/share/applications/* $out/share/applications/rars.desktop
export JAR=$out/share/java/${name}/${name}.jar
install -D ./${name}.jar $JAR
makeWrapper ${jre}/bin/java $out/bin/${name} \
--add-flags "-jar $JAR"
runHook postInstall
'';
}

View file

@ -424,6 +424,26 @@
"url": "https://repo.dec05eba.com/gpu-screen-recorder"
}
},
"grim-hyprland": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1713288659,
"narHash": "sha256-AWH3lJ2gLDMlc7N+ImQ8VCOa5Nj6Mjmnj4L2J910HR0=",
"owner": "eriedaberrie",
"repo": "grim-hyprland",
"rev": "d5e775f62717ece2ab352876d0136d9493f80cee",
"type": "github"
},
"original": {
"owner": "eriedaberrie",
"repo": "grim-hyprland",
"type": "github"
}
},
"gtk-session-lock": {
"inputs": {
"nixpkgs": [
@ -1693,6 +1713,7 @@
"firefox-gx-src": "firefox-gx-src",
"git-theme-src": "git-theme-src",
"gpu-screen-recorder-src": "gpu-screen-recorder-src",
"grim-hyprland": "grim-hyprland",
"gtk-session-lock": "gtk-session-lock",
"gtk-theme-src": "gtk-theme-src",
"headscale": "headscale",

View file

@ -278,6 +278,14 @@
inputs.hyprland.follows = "hyprland";
};
grim-hyprland = {
type = "github";
owner = "eriedaberrie";
repo = "grim-hyprland";
inputs.nixpkgs.follows = "nixpkgs";
};
##
## Wayland

View file

@ -8,6 +8,7 @@ import Clipboard from './ts/clipboard/main.ts';
import { NotifPopups, NotifCenter } from './ts/notifications/binto.ts';
import OSD from './ts/osd/main.ts';
import Powermenu from './ts/powermenu.ts';
import Screenshot from './ts/screenshot/main.ts';
// TODO: add workspace indicator
@ -28,6 +29,7 @@ App.config({
Clipboard(),
NotifCenter(),
Powermenu(),
Screenshot(),
Bar(),
NotifPopups(),

View file

@ -38,33 +38,6 @@
padding-bottom: 0;
min-width: 900px;
min-height: 650px;
scrollbar, scrollbar * {
all: unset;
}
scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
margin: 20px 0;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
}
slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
}
}
.placeholder {

View file

@ -38,33 +38,6 @@
padding-bottom: 0;
min-width: 900px;
min-height: 750px;
scrollbar, scrollbar * {
all: unset;
}
scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
margin: 20px 0;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
}
slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
}
}
.item {

View file

@ -0,0 +1,66 @@
.screenshot {
background-color: $bg;
color: $fg;
border: 2px solid $contrast-bg;
label {
font-size: 20pt;
}
.header {
border-bottom: 2px solid $contrast-bg;
.header-btn {
transition: 200ms;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
image {
-gtk-icon-shadow: 1px 1px $contrast-bg;
}
}
label {
margin: 10px;
font-weight: bold;
}
image {
font-size: 30px;
}
}
}
scrolledwindow {
min-height: 400px;
min-width: 800px;
padding: 0 10px;
box {
.item-btn {
transition: 200ms;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
}
}
label {
padding: 5px;
}
image {
font-size: 30px;
}
&:first-child label {
padding-top: 10px;
}
&:last-child label {
padding-bottom: 10px;
}
}
}
}

View file

@ -8,7 +8,7 @@ undershoot {
all: unset;
}
@import "./common";
@import './common';
@import './binto-widgets/applauncher';
@import './binto-widgets/bar';
@import './binto-widgets/notification';
@ -16,3 +16,4 @@ undershoot {
@import './binto-widgets/osd';
@import './binto-widgets/powermenu';
@import './binto-widgets/clipboard';
@import './binto-widgets/screenshot';

View file

@ -31,3 +31,33 @@ $yellow: #ecd3a0;
$accent: $blue;
$javacafe-magenta: #c296eb;
$javacafe-blue: #86aaec;
scrolledwindow {
scrollbar, scrollbar * {
all: unset;
}
scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
margin: 20px 0;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
}
slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
}
}

View file

@ -6,5 +6,5 @@ window {
.clock {
font-size: 80pt;
font-family: "Ubuntu Mono";
font-family: 'Ubuntu Mono';
}

View file

@ -39,33 +39,6 @@
padding-bottom: 0;
min-width: 700px;
min-height: 450px;
scrollbar, scrollbar * {
all: unset;
}
scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
margin: 20px 0;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
}
slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
}
}
.placeholder {

View file

@ -39,33 +39,6 @@
padding-bottom: 0;
min-width: 900px;
min-height: 750px;
scrollbar, scrollbar * {
all: unset;
}
scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
margin: 20px 0;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
}
slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
}
}
.item {

View file

@ -0,0 +1,75 @@
.screenshot {
background-color: $bg;
color: $fg;
border: 2px solid $contrast-bg;
border-radius: 25px;
label {
font-size: 20pt;
}
.header {
border-bottom: 2px solid $contrast-bg;
.header-btn {
transition: 200ms;
&:hover, &.active {
background-color: rgba(23, 23, 23, 0.7);
image {
-gtk-icon-shadow: 1px 1px $contrast-bg;
}
}
label {
margin: 10px;
font-weight: bold;
}
image {
font-size: 30px;
}
&:first-child {
border-top-left-radius: 25px;
}
&:last-child {
border-top-right-radius: 25px;
}
}
}
scrolledwindow {
min-height: 400px;
min-width: 800px;
padding: 0 10px;
box {
.item-btn {
transition: 200ms;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
}
}
label {
padding: 5px;
}
image {
font-size: 30px;
}
&:first-child label {
padding-top: 10px;
}
&:last-child label {
padding-bottom: 10px;
}
}
}
}

View file

@ -3,29 +3,29 @@
border-radius: 80px;
border: 2px solid $bg-secondary;
padding: 3px 12px;
}
.button {
margin: 0 2.5px;
min-height: 22px;
min-width: 22px;
border-radius: 100%;
border: 2px solid transparent;
}
.button {
margin: 0 2.5px;
min-height: 22px;
min-width: 22px;
border-radius: 100%;
border: 2px solid transparent;
}
.occupied {
border: 2px solid $bg;
background: $contrast-bg;
transition: background-color 0.6s ease-in-out;
}
.occupied {
border: 2px solid $bg;
background: $contrast-bg;
transition: background-color 0.6s ease-in-out;
}
.urgent {
border: 2px solid $bg;
background: red;
transition: background-color 0.6s ease-in-out;
}
.urgent {
border: 2px solid $bg;
background: red;
transition: background-color 0.6s ease-in-out;
}
.active {
border: 2px solid #50fa7b;
transition: margin-left 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
.active {
border: 2px solid #50fa7b;
transition: margin-left 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
}

View file

@ -8,17 +8,18 @@ undershoot {
all: unset;
}
@import "./common";
@import "./wim-widgets/powermenu";
@import "./wim-widgets/traybuttons";
@import "./wim-widgets/workspaces";
@import "./wim-widgets/systray";
@import "./wim-widgets/notification-center";
@import "./wim-widgets/notification";
@import "./wim-widgets/date";
@import "./wim-widgets/quick-settings";
@import "./wim-widgets/player";
@import "./wim-widgets/applauncher";
@import "./wim-widgets/osd";
@import "./wim-widgets/osk";
@import "./wim-widgets/clipboard";
@import './common';
@import './wim-widgets/powermenu';
@import './wim-widgets/traybuttons';
@import './wim-widgets/workspaces';
@import './wim-widgets/systray';
@import './wim-widgets/notification-center';
@import './wim-widgets/notification';
@import './wim-widgets/date';
@import './wim-widgets/quick-settings';
@import './wim-widgets/player';
@import './wim-widgets/applauncher';
@import './wim-widgets/osd';
@import './wim-widgets/osk';
@import './wim-widgets/clipboard';
@import './wim-widgets/screenshot';

View file

@ -0,0 +1,182 @@
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,
],
}),
});
};

View file

@ -10,6 +10,7 @@ import OSD from './ts/osd/main.ts';
import OSK from './ts/on-screen-keyboard/main.ts';
import Powermenu from './ts/powermenu.ts';
import QSettings from './ts/quick-settings/main.ts';
import Screenshot from './ts/screenshot/main.ts';
App.config({
@ -30,6 +31,7 @@ App.config({
OSK(),
Powermenu(),
QSettings(),
Screenshot(),
Bar(),
BgFade(),

View file

@ -146,15 +146,17 @@ in {
];
bind = [
"$mainMod SHIFT, E, exec, ags -t win-powermenu"
"$mainMod , D, exec, ags -t win-applauncher"
"$mainMod SHIFT, E , exec, ags -t win-powermenu"
"$mainMod , D , exec, ags -t win-applauncher"
"$mainMod , V , exec, ags -t win-clipboard"
" , Print, exec, ags -t win-screenshot"
];
binde = [
## Brightness control
", XF86MonBrightnessUp, exec, ags -r 'Brightness.screen += 0.05'"
", XF86MonBrightnessUp , exec, ags -r 'Brightness.screen += 0.05'"
", XF86MonBrightnessDown, exec, ags -r 'Brightness.screen -= 0.05'"
];
bindn = [" , Escape, exec, ags -r 'closeAll()'"];
bindn = [" , Escape , exec, ags -r 'closeAll()'"];
bindr = ["CAPS, Caps_Lock, exec, ags -r 'Brightness.fetchCapsState()'"];
};
};

View file

@ -6,6 +6,7 @@
}: let
inherit (lib) makeLibraryPath optionalString;
inherit (pkgs.writers) writeTOML;
inherit (config.vars) mainUser;
flakeDir = config.environment.variables.FLAKE;
in {
@ -46,71 +47,57 @@ in {
})
];
home.packages = with pkgs; [
# School
xournalpp
virt-manager
libreoffice-fresh # TODO: declarative conf?
hunspell
hunspellDicts.en_CA
config.customPkgs.rars-flatlaf
home.packages =
(with pkgs; [
# School
xournalpp
virt-manager
libreoffice-fresh # TODO: declarative conf?
hunspell
hunspellDicts.en_CA
# Apps
thunderbird # TODO: use programs.thunderbird
protonmail-bridge
spotifywm
photoqt
nextcloud-client
jellyfin-media-player
prismlauncher
# Apps
thunderbird # TODO: use programs.thunderbird
protonmail-bridge
spotifywm
photoqt
nextcloud-client
jellyfin-media-player
prismlauncher
# tools
wl-color-picker
wl-clipboard
cliphist
grim
slurp
satty
# TODO: make an ags widget to select windows, screens or a selection
(writeShellApplication {
name = "screenshot";
runtimeInputs = [
config.programs.hyprland.package
satty
grim
jq
];
text = ''
screen=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true).name')
exec grim -o "$screen" - | satty -f -
'';
})
/*
Discord themes for Vencord
https://markchan0225.github.io/RoundedDiscord/RoundedDiscord.theme.css
https://raw.githubusercontent.com/dracula/BetterDiscord/master/Dracula_Official.theme.css
*/
(symlinkJoin {
name = "discord";
paths = [
(discord.override {
withOpenASAR = true;
withVencord = true;
})
];
buildInputs = [makeWrapper];
postBuild = ''
wrapProgram $out/bin/Discord ${optionalString config.nvidia.enable
''--prefix LD_LIBRARY_PATH : "${makeLibraryPath [
addOpenGLRunpath.driverLink
libglvnd
]}"''} \
--add-flags "--enable-features=UseOzonePlatform,WebRTCPipeWireCapturer --ozone-platform=wayland"
'';
})
];
# tools
wl-color-picker
wl-clipboard
cliphist
grim-hyprland
slurp
satty
])
++ [
/*
Discord themes for Vencord
https://markchan0225.github.io/RoundedDiscord/RoundedDiscord.theme.css
https://raw.githubusercontent.com/dracula/BetterDiscord/master/Dracula_Official.theme.css
*/
(pkgs.symlinkJoin {
name = "discord";
paths = [
(pkgs.discord.override {
withOpenASAR = true;
withVencord = true;
})
];
buildInputs = [pkgs.makeWrapper];
postBuild = ''
wrapProgram $out/bin/Discord ${optionalString config.nvidia.enable
''--prefix LD_LIBRARY_PATH : "${makeLibraryPath [
pkgs.addOpenGLRunpath.driverLink
pkgs.libglvnd
]}"''} \
--add-flags "--enable-features=UseOzonePlatform,WebRTCPipeWireCapturer --ozone-platform=wayland"
'';
})
];
wayland.windowManager.hyprland = {
settings = {
@ -144,11 +131,6 @@ in {
bind = [
"$mainMod, Q, exec, foot"
# Clipboard History
"$mainMod, V, exec, ags -t win-clipboard"
" , Print, exec, screenshot"
"$mainMod, Print, exec, grim -g \"$(slurp)\" - | satty -f -"
"$mainMod SHIFT, C, exec, wl-color-picker"
"$mainMod, T, togglespecialworkspace, thunder"