From 1720cb6c9b799058edb5775066551bdd84e09043 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 8 Sep 2025 01:22:48 -0700 Subject: [PATCH] qs: normalize screenshot rect --- modules/overlay-pkgs/tws.nix | 172 ++++++++++++++++++ .../shell/screenshot/Controller.qml | 27 ++- 2 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 modules/overlay-pkgs/tws.nix diff --git a/modules/overlay-pkgs/tws.nix b/modules/overlay-pkgs/tws.nix new file mode 100644 index 0000000..29d7f9c --- /dev/null +++ b/modules/overlay-pkgs/tws.nix @@ -0,0 +1,172 @@ +{ # ref: https://git.sr.ht/~rhizomic/tws + lib, + fetchurl, + stdenv, + + gnused, + gnutar, + patchelf, + makeFontsCache, + + bash, + alsa-lib, + at-spi2-atk, + cairo, + cups, + dbus, + expat, + ffmpeg, + fontconfig, + freetype, + gdk-pixbuf, + glib, + gtk2, + gtk3, + javaPackages, + libdrm, + libGL, + libxkbcommon, + mesa, + nspr, + nss, + pango, + xorg, + zlib, +}: let + libPath = lib.makeLibraryPath [ + alsa-lib + at-spi2-atk + cairo + cups + dbus + expat + ffmpeg + fontconfig + freetype + gdk-pixbuf + glib + gtk2 + gtk3 + javaPackages.openjfx21 + libdrm + libGL + libxkbcommon + mesa + nspr + nss + pango + xorg.libXfixes + xorg.libXcomposite + xorg.libXdamage + xorg.libXext + xorg.libXrandr + xorg.libXrender + xorg.libXtst + xorg.libXi + xorg.libXxf86vm + xorg.libxcb + xorg.libX11 + zlib + ]; +in stdenv.mkDerivation { + pname = "ibkr-tws"; + version = "0"; + + src = fetchurl { + url = "https://download2.interactivebrokers.com/installers/tws/latest-standalone/tws-latest-standalone-linux-x64.sh"; + hash = "sha256-Wk7lRE5ypJeAQfvi5aEDZYfUF6fJ3ktueYYytHohIGU="; + }; + + nativeBuildInputs = [ + gnused + gnutar + patchelf + ]; + + unpackPhase = '' + tws_length=$(stat -c %s "$src") + sfx_length=$(sed -nE 's/^tail -c ([0-9]+).*/\1/p' "$src") + + mkdir install4j + tail --bytes $sfx_length "$src" > sfx_archive.tar.gz + tar -xf sfx_archive.tar.gz -C install4j 2> /dev/null + + mkdir jre + tar -xf install4j/jre.tar.gz -C jre + + zero_dat_length=$(sed -nE 's/^file\.size\.0=([0-9]+)/\1/p' install4j/stats.properties) + installer_length=$(($tws_length - $sfx_length - $zero_dat_length)) + + head --bytes $installer_length "$src" > install.sh + # || true masks broken pipe + (tail --bytes +$(($installer_length + 1)) "$src" 2> /dev/null || true) | head --bytes $zero_dat_length > install4j/0.dat + + echo $tws_length : $sfx_length : $zero_dat_length : $installer_length + stat install4j/0.dat + ''; + + buildPhase = '' + for file in jre/bin/*; do + patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$file" + done + + unpack () { + jar="`echo "$1" | awk '{ print substr($0,1,length($0)-5) }'`" + jre/bin/unpack200 -r "$1" "$jar" + chmod a+r "$jar" + } + + for jarpack in jre/lib/*.jar.pack; do + unpack $jarpack + done + + for jarpack in jre/lib/ext/*.jar.pack; do + unpack $jarpack + done + ''; + + installPhase = '' + install4j_installer=$(sed -nE 's/.*\$INSTALL4J_JAVA_PREFIX.*install4j\.Installer([0-9]+).*/\1/p' "$src" | head -n 1) + + (cd install4j && \ + LD_LIBRARY_PATH='${libPath}:$LD_LIBRARY_PATH' \ + FONTCONFIG_FILE='${makeFontsCache { fontDirectories = []; }}' \ + INSTALL4J_JAVA_HOME='../jre' \ + ../jre/bin/java \ + -DjtsConfigDir='/home/jts' \ + -classpath 'i4jruntime.jar:launcher0.jar' \ + "install4j.Installer$install4j_installer" '-q' '-dir' "$out") + + mv jre "$out/jre" + + mkdir "$out/bin" + cat < "$out/bin/tws" + #! ${lib.getExe bash} + + TWS_DIR="\$XDG_DATA_HOME/tws" + if [ ! -d "\$TWS_DIR" ]; then + mkdir -p "\$TWS_DIR" + fi + + LD_LIBRARY_PATH="${libPath}:\$LD_LIBRARY_PATH" \ + INSTALL4J_JAVA_HOME="$out/jre" \ + $out/tws -J-DjtsConfigDir="\$TWS_DIR" + EOF + + mkdir -p "$out/share/icons/hicolor/128x128" + mv "$out/.install4j/tws.png" "$out/share/icons/hicolor/128x128/tws.png" + + mkdir -p "$out/share/applications" + cat < "$out/share/applications/tws.desktop" + [Desktop Entry] + Type=Application + Name=Trader Workstation + Exec="$out/bin/tws" + Icon=tws + Categories=Application + StartupWMClass=install4j-jclient-LoginFrame + EOF + + chmod +x "$out/bin/tws" + ''; +} diff --git a/modules/user/modules/quickshell/shell/screenshot/Controller.qml b/modules/user/modules/quickshell/shell/screenshot/Controller.qml index ad864a8..e57c701 100644 --- a/modules/user/modules/quickshell/shell/screenshot/Controller.qml +++ b/modules/user/modules/quickshell/shell/screenshot/Controller.qml @@ -42,7 +42,7 @@ Scope { command: [ "magick", root.path, - "-crop", `${selection.w}x${selection.h}+${selection.x}+${selection.y}`, + "-crop", `${selection.normal.width}x${selection.normal.height}+${selection.normal.x}+${selection.normal.y}`, "-quality", "70", "-page", "0x0+0+0", // removes page size and shot position root.path, @@ -74,6 +74,16 @@ Scope { readonly property real y: Math.min(y1, y2) readonly property real w: Math.max(x1, x2) - x readonly property real h: Math.max(y1, y2) - y + readonly property rect normal: Qt.rect(x - topleft.x, y - topleft.y, w, h) + } + + readonly property point topleft: Quickshell.screens.reduce((point, screen) => { + return Qt.point(Math.min(point.x, screen.x), Math.min(point.y, screen.y)) + }, Qt.point(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY)) + + function normalizedScreenRect(screen: ShellScreen): rect { + const p = topleft; + return Qt.rect(screen.x - p.x, screen.y - p.y, screen.width, screen.height) } LazyLoader { @@ -93,6 +103,7 @@ Scope { } PanelWindow { + id: panel required property var modelData; screen: modelData visible: root.visible @@ -115,15 +126,15 @@ Scope { enabled: !selectionComplete onPressed: { - selection.x1 = mouseX + screen.x; + selection.x1 = mouseX + panel.screen.x; selection.x2 = selection.x1; - selection.y1 = mouseY + screen.y; + selection.y1 = mouseY + panel.screen.y; selection.y2 = selection.y1; } onPositionChanged: { - selection.x2 = mouseX + screen.x; - selection.y2 = mouseY + screen.y; + selection.x2 = mouseX + panel.screen.x; + selection.y2 = mouseY + panel.screen.y; } onReleased: { @@ -139,14 +150,14 @@ Scope { parent: area anchors.fill: parent source: root.visible ? root.path : "" - sourceClipRect: Qt.rect(screen.x, screen.y, screen.width, screen.height) + sourceClipRect: root.normalizedScreenRect(panel.screen) } CutoutRect { id: cutoutRect anchors.fill: parent - innerX: selection.x - screen.x - innerY: selection.y - screen.y + innerX: selection.x - panel.screen.x + innerY: selection.y - panel.screen.y innerW: selection.w innerH: selection.h