mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-30 00:12:50 -05:00
screenshot: use wlr-output-management on DWL for x/y offsets
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/proto/dwl_ipc"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/proto/dwl_ipc"
|
||||||
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/proto/wlr_output_management"
|
||||||
wlhelpers "github.com/AvengeMedia/DankMaterialShell/core/internal/wayland/client"
|
wlhelpers "github.com/AvengeMedia/DankMaterialShell/core/internal/wayland/client"
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
|
"github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
|
||||||
)
|
)
|
||||||
@@ -89,12 +90,14 @@ func SetCompositorDWL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WindowGeometry struct {
|
type WindowGeometry struct {
|
||||||
X int32
|
X int32
|
||||||
Y int32
|
Y int32
|
||||||
Width int32
|
Width int32
|
||||||
Height int32
|
Height int32
|
||||||
Output string
|
Output string
|
||||||
Scale float64
|
Scale float64
|
||||||
|
OutputX int32
|
||||||
|
OutputY int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetActiveWindow() (*WindowGeometry, error) {
|
func GetActiveWindow() (*WindowGeometry, error) {
|
||||||
@@ -382,6 +385,79 @@ func GetFocusedMonitor() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getOutputPosition(outputName string) (x, y int32, ok bool) {
|
||||||
|
display, err := client.Connect("")
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
ctx := display.Context()
|
||||||
|
defer ctx.Close()
|
||||||
|
|
||||||
|
registry, err := display.GetRegistry()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputManager *wlr_output_management.ZwlrOutputManagerV1
|
||||||
|
|
||||||
|
registry.SetGlobalHandler(func(e client.RegistryGlobalEvent) {
|
||||||
|
if e.Interface == wlr_output_management.ZwlrOutputManagerV1InterfaceName {
|
||||||
|
mgr := wlr_output_management.NewZwlrOutputManagerV1(ctx)
|
||||||
|
version := e.Version
|
||||||
|
if version > 4 {
|
||||||
|
version = 4
|
||||||
|
}
|
||||||
|
if err := registry.Bind(e.Name, e.Interface, version, mgr); err == nil {
|
||||||
|
outputManager = mgr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if outputManager == nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
type headState struct {
|
||||||
|
name string
|
||||||
|
x, y int32
|
||||||
|
}
|
||||||
|
heads := make(map[*wlr_output_management.ZwlrOutputHeadV1]*headState)
|
||||||
|
done := false
|
||||||
|
|
||||||
|
outputManager.SetHeadHandler(func(e wlr_output_management.ZwlrOutputManagerV1HeadEvent) {
|
||||||
|
state := &headState{}
|
||||||
|
heads[e.Head] = state
|
||||||
|
e.Head.SetNameHandler(func(ne wlr_output_management.ZwlrOutputHeadV1NameEvent) {
|
||||||
|
state.name = ne.Name
|
||||||
|
})
|
||||||
|
e.Head.SetPositionHandler(func(pe wlr_output_management.ZwlrOutputHeadV1PositionEvent) {
|
||||||
|
state.x = pe.X
|
||||||
|
state.y = pe.Y
|
||||||
|
})
|
||||||
|
})
|
||||||
|
outputManager.SetDoneHandler(func(e wlr_output_management.ZwlrOutputManagerV1DoneEvent) {
|
||||||
|
done = true
|
||||||
|
})
|
||||||
|
|
||||||
|
for !done {
|
||||||
|
if err := ctx.Dispatch(); err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, state := range heads {
|
||||||
|
if state.name == outputName {
|
||||||
|
return state.x, state.y, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
|
||||||
func getDWLActiveWindow() (*WindowGeometry, error) {
|
func getDWLActiveWindow() (*WindowGeometry, error) {
|
||||||
display, err := client.Connect("")
|
display, err := client.Connect("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -509,13 +585,21 @@ func getDWLActiveWindow() (*WindowGeometry, error) {
|
|||||||
if scale <= 0 {
|
if scale <= 0 {
|
||||||
scale = 1.0
|
scale = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var outputX, outputY int32
|
||||||
|
if ox, oy, ok := getOutputPosition(state.name); ok {
|
||||||
|
outputX, outputY = ox, oy
|
||||||
|
}
|
||||||
|
|
||||||
return &WindowGeometry{
|
return &WindowGeometry{
|
||||||
X: state.x,
|
X: state.x,
|
||||||
Y: state.y,
|
Y: state.y,
|
||||||
Width: state.w,
|
Width: state.w,
|
||||||
Height: state.h,
|
Height: state.h,
|
||||||
Output: state.name,
|
Output: state.name,
|
||||||
Scale: scale,
|
Scale: scale,
|
||||||
|
OutputX: outputX,
|
||||||
|
OutputY: outputY,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,51 +150,33 @@ func (s *Screenshoter) captureWindow() (*CaptureResult, error) {
|
|||||||
case CompositorHyprland:
|
case CompositorHyprland:
|
||||||
return s.captureAndCrop(output, region)
|
return s.captureAndCrop(output, region)
|
||||||
case CompositorDWL:
|
case CompositorDWL:
|
||||||
return s.captureDWLWindow(output, region, geom.Scale)
|
return s.captureDWLWindow(output, region, geom)
|
||||||
default:
|
default:
|
||||||
return s.captureRegionOnOutput(output, region)
|
return s.captureRegionOnOutput(output, region)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Screenshoter) captureDWLWindow(output *WaylandOutput, region Region, dwlScale float64) (*CaptureResult, error) {
|
func (s *Screenshoter) captureDWLWindow(output *WaylandOutput, region Region, geom *WindowGeometry) (*CaptureResult, error) {
|
||||||
result, err := s.captureWholeOutput(output)
|
result, err := s.captureWholeOutput(output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
scale := dwlScale
|
scale := geom.Scale
|
||||||
if scale <= 0 {
|
if scale <= 0 || scale == 1.0 {
|
||||||
scale = float64(result.Buffer.Width) / float64(output.width)
|
if output.fractionalScale > 1.0 {
|
||||||
|
scale = output.fractionalScale
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if scale <= 0 {
|
if scale <= 0 {
|
||||||
scale = 1.0
|
scale = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
localX := int(float64(region.X) * scale)
|
localX := int(float64(region.X-geom.OutputX) * scale)
|
||||||
localY := int(float64(region.Y) * scale)
|
localY := int(float64(region.Y-geom.OutputY) * scale)
|
||||||
if localX >= result.Buffer.Width {
|
|
||||||
localX = localX % result.Buffer.Width
|
|
||||||
}
|
|
||||||
if localY >= result.Buffer.Height {
|
|
||||||
localY = localY % result.Buffer.Height
|
|
||||||
}
|
|
||||||
|
|
||||||
w := int(float64(region.Width) * scale)
|
w := int(float64(region.Width) * scale)
|
||||||
h := int(float64(region.Height) * scale)
|
h := int(float64(region.Height) * scale)
|
||||||
|
|
||||||
if localY+h > result.Buffer.Height && h <= result.Buffer.Height {
|
|
||||||
localY = result.Buffer.Height - h
|
|
||||||
if localY < 0 {
|
|
||||||
localY = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if localX+w > result.Buffer.Width && w <= result.Buffer.Width {
|
|
||||||
localX = result.Buffer.Width - w
|
|
||||||
if localX < 0 {
|
|
||||||
localX = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if localX < 0 {
|
if localX < 0 {
|
||||||
w += localX
|
w += localX
|
||||||
localX = 0
|
localX = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user