Add quickshell screenshot
This commit is contained in:
parent
36ff76a601
commit
5a70b9493c
|
@ -384,11 +384,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1711618169,
|
||||
"narHash": "sha256-K5j+SlsGfyrJeBzcZVH02O8P4T+ep4UEFryVVBWFdAw=",
|
||||
"lastModified": 1711716099,
|
||||
"narHash": "sha256-j9j3O4iR0ovVZTgjUb2nyvyZ1fPNMrR0fm65E4kZcgo=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "439788fce09efff383768ac2403526f9e0fe5ddd",
|
||||
"revCount": 136,
|
||||
"rev": "83afce7f68f8ffc74f53642d2bac9e604bd64dfc",
|
||||
"revCount": 137,
|
||||
"type": "git",
|
||||
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||
},
|
||||
|
|
|
@ -109,6 +109,8 @@ layerrule = animation fade, shell:background
|
|||
layerrule = blur, shell:bar
|
||||
layerrule = ignorezero, shell:bar
|
||||
|
||||
layerrule = noanim, shell:screenshot
|
||||
|
||||
layerrule = blur, walker
|
||||
layerrule = ignorezero, walker
|
||||
layerrule = animation popin 90%, walker
|
||||
|
@ -136,8 +138,10 @@ bind = $mod+SHIFT, return, exec, alacritty --class AlacrittyFloating
|
|||
bind = $mod, grave, exec, $launcher
|
||||
bind = $mod+SHIFT, q, hy3:killactive
|
||||
|
||||
bind = $mod+SHIFT, s, exec, echo "screenshot" | nc -w 0 -U /run/user/1000/quickshell.sock
|
||||
bind = $mod, c, exec, echo "termselect:start" | nc -w 0 -U /run/user/1000/quickshell.sock
|
||||
bindr = $mod, c, exec, echo "termselect:stop" | nc -w 0 -U /run/user/1000/quickshell.sock
|
||||
bind = $mod, PERIOD, exec, quickshell -c lockscreen
|
||||
|
||||
bind = $mod, f, fullscreen, 1
|
||||
bind = $mod+SHIFT, f, fullscreen, 0
|
||||
|
@ -163,10 +167,6 @@ bind = ,XF86AudioStop, exec, playerctl -a stop
|
|||
bind = ,XF86AudioNext, exec, playerctl next
|
||||
bind = ,XF86AudioPrev, exec, playerctl previous
|
||||
|
||||
bind = $mod+SHIFT, s, exec, grim -g "$(slurp)" - | wl-copy
|
||||
|
||||
bind = $mod, PERIOD, exec, quickshell -c lockscreen
|
||||
|
||||
bind = $mod, h, hy3:movefocus, l
|
||||
bind = $mod, j, hy3:movefocus, d
|
||||
bind = $mod, k, hy3:movefocus, u
|
||||
|
|
|
@ -5,6 +5,7 @@ in {
|
|||
qt6.qtimageformats # amog
|
||||
quickshell.packages.${system}.default
|
||||
pamtester # lockscreen
|
||||
grim imagemagick # screenshot
|
||||
];
|
||||
|
||||
xdg.configFile."quickshell/manifest.conf".text = lib.generators.toKeyValue {} {
|
||||
|
|
|
@ -40,7 +40,6 @@ Item {
|
|||
yCurve.interpolate(p, collapsedLayerRect.y, expandedLayerRect.y),
|
||||
xCurve.interpolate(p, collapsedLayerRect.width, expandedLayerRect.width),
|
||||
yCurve.interpolate(p, collapsedLayerRect.height, expandedLayerRect.height),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import QtQuick
|
|||
import Quickshell
|
||||
|
||||
Singleton {
|
||||
readonly property string rtpath: "/run/user/1000/quickshell"
|
||||
|
||||
readonly property var colors: QtObject {
|
||||
readonly property var bar: "#30c0ffff";
|
||||
readonly property var barOutline: "#50ffffff";
|
||||
|
|
|
@ -5,6 +5,7 @@ import Quickshell.Io
|
|||
|
||||
Singleton {
|
||||
property bool termSelect: false;
|
||||
signal screenshot();
|
||||
|
||||
SocketServer {
|
||||
active: true
|
||||
|
@ -15,6 +16,9 @@ Singleton {
|
|||
onRead: message => {
|
||||
console.log(message)
|
||||
switch (message) {
|
||||
case "screenshot":
|
||||
screenshot();
|
||||
break;
|
||||
case "termselect:start":
|
||||
termSelect = true;
|
||||
break;
|
||||
|
|
206
modules/user/modules/quickshell/shell/screenshot/Controller.qml
Normal file
206
modules/user/modules/quickshell/shell/screenshot/Controller.qml
Normal file
|
@ -0,0 +1,206 @@
|
|||
// very bad code DO NOT COPY
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import ".."
|
||||
|
||||
Scope {
|
||||
id: root
|
||||
property bool shooting: false;
|
||||
property bool shootingComplete: false;
|
||||
property bool visible: false;
|
||||
readonly property string path: `${ShellGlobals.rtpath}/screenshot.png`;
|
||||
|
||||
onShootingChanged: {
|
||||
if (shooting) {
|
||||
grimProc.running = true
|
||||
} else {
|
||||
visible = false
|
||||
shootingComplete = false
|
||||
cleanupProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: grimProc
|
||||
command: ["grim", "-l", "0", path]
|
||||
onExited: code => {
|
||||
if (code == 0) {
|
||||
root.visible = true
|
||||
} else {
|
||||
console.log("screenshot failed")
|
||||
cleanupProc.running = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: magickProc
|
||||
command: [
|
||||
"magick",
|
||||
path,
|
||||
"-crop",
|
||||
`${selection.w}x${selection.h}+${selection.x}+${selection.y}`,
|
||||
"-quality",
|
||||
"70",
|
||||
path,
|
||||
]
|
||||
|
||||
onExited: wlCopy.running = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: wlCopy
|
||||
command: ["sh", "-c", `wl-copy < '${path}'`]
|
||||
|
||||
onExited: shootingComplete = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: cleanupProc
|
||||
command: ["rm", path]
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: selection
|
||||
property real x1;
|
||||
property real y1;
|
||||
property real x2;
|
||||
property real y2;
|
||||
|
||||
readonly property real x: Math.min(x1, x2)
|
||||
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
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
loading: root.shooting
|
||||
active: root.visible
|
||||
onLoadingChanged: console.log(`loading set to ${loading} at ${new Date()}`)
|
||||
onActiveChanged: console.log(`active set to ${active} at ${new Date()}`)
|
||||
|
||||
Variants {
|
||||
model: Quickshell.screens
|
||||
|
||||
property bool selectionComplete: false
|
||||
|
||||
Component.onCompleted: {
|
||||
selection.x1 = 0
|
||||
selection.y1 = 0
|
||||
selection.x2 = 0
|
||||
selection.y2 = 0
|
||||
}
|
||||
|
||||
PanelWindow {
|
||||
required property var modelData;
|
||||
screen: modelData
|
||||
visible: root.visible
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.namespace: "shell:screenshot"
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
right: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: area
|
||||
anchors.fill: parent
|
||||
cursorShape: selectionComplete ? Qt.WaitCursor : Qt.CrossCursor
|
||||
enabled: !selectionComplete
|
||||
|
||||
onPressed: {
|
||||
selection.x1 = mouseX + screen.x;
|
||||
selection.x2 = selection.x1;
|
||||
selection.y1 = mouseY + screen.y;
|
||||
selection.y2 = selection.y1;
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
selection.x2 = mouseX + screen.x;
|
||||
selection.y2 = mouseY + screen.y;
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
console.log(`area: ${selection.x} ${selection.y} ${selection.w} ${selection.h}`)
|
||||
|
||||
if (selection.w > 0 && selection.h > 0) {
|
||||
magickProc.running = true
|
||||
selectionComplete = true
|
||||
} else {
|
||||
root.shooting = false
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
parent: area
|
||||
anchors.fill: parent
|
||||
source: root.visible ? root.path : ""
|
||||
sourceClipRect: Qt.rect(screen.x, screen.y, screen.width, screen.height)
|
||||
}
|
||||
|
||||
CutoutRect {
|
||||
id: cutoutRect
|
||||
anchors.fill: parent
|
||||
innerX: selection.x - screen.x
|
||||
innerY: selection.y - screen.y
|
||||
innerW: selection.w
|
||||
innerH: selection.h
|
||||
|
||||
NumberAnimation {
|
||||
id: rectFlashIn
|
||||
target: cutoutRect
|
||||
property: "opacity"
|
||||
duration: 200
|
||||
easing.type: Easing.OutExpo
|
||||
from: 0.0
|
||||
to: 1.0
|
||||
}
|
||||
|
||||
PropertyAnimation {
|
||||
running: selectionComplete
|
||||
target: cutoutRect
|
||||
property: "innerBorderColor"
|
||||
duration: 200
|
||||
to: "#00ff20"
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
running: selectionComplete
|
||||
target: cutoutRect
|
||||
property: "backgroundOpacity"
|
||||
duration: 200
|
||||
to: 0.0
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
running: shootingComplete
|
||||
target: cutoutRect
|
||||
property: "opacity"
|
||||
easing.type: Easing.OutCubic
|
||||
duration: 150
|
||||
to: 0.0
|
||||
onStopped: root.shooting = false
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
|
||||
function onVisibleChanged() {
|
||||
if (root.visible) {
|
||||
rectFlashIn.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property color backgroundColor: "#20ffffff"
|
||||
property real backgroundOpacity: 1.0
|
||||
property alias innerBorderColor: center.border.color
|
||||
property alias innerX: center.x
|
||||
property alias innerY: center.y
|
||||
property alias innerW: center.width
|
||||
property alias innerH: center.height
|
||||
|
||||
Rectangle {
|
||||
id: center
|
||||
border.color: "white"
|
||||
border.width: 2
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: root.backgroundColor
|
||||
opacity: backgroundOpacity
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: center.top
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: root.backgroundColor
|
||||
opacity: backgroundOpacity
|
||||
|
||||
anchors {
|
||||
top: center.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: root.backgroundColor
|
||||
opacity: backgroundOpacity
|
||||
|
||||
anchors {
|
||||
top: center.top
|
||||
left: parent.left
|
||||
right: center.left
|
||||
bottom: center.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: root.backgroundColor
|
||||
opacity: backgroundOpacity
|
||||
|
||||
anchors {
|
||||
top: center.top
|
||||
left: center.right
|
||||
right: parent.right
|
||||
bottom: center.bottom
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,8 +4,30 @@ import Quickshell.Wayland
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ".."
|
||||
import "screenshot" as Screenshot
|
||||
|
||||
ShellRoot {
|
||||
Process {
|
||||
command: ["mkdir", "-p", ShellGlobals.rtpath]
|
||||
running: true
|
||||
}
|
||||
|
||||
LazyLoader {
|
||||
id: screenshot
|
||||
loading: true
|
||||
|
||||
Screenshot.Controller {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ShellIpc
|
||||
|
||||
function onScreenshot() {
|
||||
screenshot.item.shooting = true;
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: Quickshell.screens
|
||||
|
||||
|
|
Loading…
Reference in a new issue