screenshot: stop re-rotating frames hyprland 0.57 already delivers upright

fixes #4014
port 2.0
This commit is contained in:
bbedward committed 2026-10-29 13:46:50 -04:00
1 parent b18fc38693
commit a26298d294
3 files changed
+55 -15

No files matched your search

+26
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"os/exec"
"sync"
"github.com/duxlabs-dev/dux-go/wayland/client"
"github.com/duxlabs-dev/dux-shell/core/internal/proto/wlr_output_management"
@@ -151,6 +152,31 @@ func GetHyprlandMonitorScale(name string) float64 {
return 0
}
// !TODO: remove with the frameInLogicalOrientation version fallback
var hyprlandVersion = sync.OnceValues(func() (int, int) {
output, err := exec.Command("hyprctl", "-j", "version").Output()
if err != nil {
return 0, 0
}
var info struct {
Version string `json:"version"`
}
if err := json.Unmarshal(output, &info); err != nil {
return 0, 0
}
var major, minor int
fmt.Sscanf(info.Version, "%d.%d", &major, &minor)
return major, minor
})
func hyprlandVersionAtLeast(major, minor int) bool {
haveMajor, haveMinor := hyprlandVersion()
if haveMajor != major {
return haveMajor > major
}
return haveMinor >= minor
}
func getHyprlandFocusedMonitor() string {
output, err := exec.Command("hyprctl", "-j", "monitors").Output()
if err != nil {
+6 -9
View File
@@ -609,15 +609,12 @@ func (r *RegionSelector) preCaptureOutput(output *WaylandOutput, pc *PreCapture,
pc.yInverted = false
}
if output.transform != TransformNormal {
invTransform := InverseTransform(output.transform)
transformed, err := capturedBuf.ApplyTransform(invTransform)
if err != nil {
log.Error("apply transform failed", "err", err)
} else if transformed != capturedBuf {
capturedBuf.Close()
capturedBuf = transformed
}
transformed, err := output.untransformFrame(capturedBuf)
if err != nil {
log.Error("apply transform failed", "err", err)
} else if transformed != capturedBuf {
capturedBuf.Close()
capturedBuf = transformed
}
if withCursor {
+23 -6
View File
@@ -49,6 +49,28 @@ func (o *WaylandOutput) effectiveScale() float64 {
return scale
}
// Hyprland renders screencopy frames in the output's logical orientation since
// 901881c9f (v0.57.0); wlroots and niri still hand back the native framebuffer.
// !TODO: drop the version fallback once every distro ships hyprland >= 0.57
func (o *WaylandOutput) frameInLogicalOrientation(frameW, frameH int) bool {
switch o.transform {
case TransformNormal:
return true
case Transform90, Transform270, TransformFlipped90, TransformFlipped270:
if o.width != o.height {
return frameW == int(o.height) && frameH == int(o.width)
}
}
return DetectCompositor() == CompositorHyprland && hyprlandVersionAtLeast(0, 57)
}
func (o *WaylandOutput) untransformFrame(buf *ShmBuffer) (*ShmBuffer, error) {
if o.frameInLogicalOrientation(buf.Width, buf.Height) {
return buf, nil
}
return buf.ApplyTransform(InverseTransform(o.transform))
}
func (o *WaylandOutput) bounds() Region {
x, y, w, h := o.x, o.y, o.width, o.height
if DetectCompositor() == CompositorHyprland {
@@ -677,12 +699,7 @@ func (s *Screenshoter) captureWholeOutput(output *WaylandOutput) (*CaptureResult
result.YInverted = false
}
if output.transform == TransformNormal {
return result, nil
}
invTransform := InverseTransform(output.transform)
transformed, err := result.Buffer.ApplyTransform(invTransform)
transformed, err := output.untransformFrame(result.Buffer)
if err != nil {
result.Buffer.Close()
return nil, fmt.Errorf("apply transform: %w", err)