From d9050fc4f46d626c1cc36490cb340bd189b11acc Mon Sep 17 00:00:00 2001 From: kbinani Date: Wed, 21 Aug 2024 01:01:02 +0900 Subject: [PATCH 1/2] Flatten project structure --- screenshot_darwin.go => darwin.go | 6 +- internal/dbus_unavailable.go | 11 --- internal/util.go | 22 ----- nix.go | 81 +++++++++++++++++++ ...dbus_available.go => nix_dbus_available.go | 5 +- nix_dbus_unavailable.go | 14 ++++ internal/wayland.go => nix_wayland.go | 10 +-- internal/xwindow.go => nix_xwindow.go | 73 +---------------- screenshot.go | 16 ++++ screenshot_supported.go | 26 ------ screenshot_unsupported.go => unsupported.go | 0 screenshot_windows.go => windows.go | 7 +- 12 files changed, 128 insertions(+), 143 deletions(-) rename screenshot_darwin.go => darwin.go (98%) delete mode 100644 internal/dbus_unavailable.go delete mode 100644 internal/util.go create mode 100644 nix.go rename internal/dbus_available.go => nix_dbus_available.go (59%) create mode 100644 nix_dbus_unavailable.go rename internal/wayland.go => nix_wayland.go (91%) rename internal/xwindow.go => nix_xwindow.go (70%) delete mode 100644 screenshot_supported.go rename screenshot_unsupported.go => unsupported.go (100%) rename screenshot_windows.go => windows.go (98%) diff --git a/screenshot_darwin.go b/darwin.go similarity index 98% rename from screenshot_darwin.go rename to darwin.go index 9a58f31..86319ec 100644 --- a/screenshot_darwin.go +++ b/darwin.go @@ -1,4 +1,4 @@ -//go:build cgo +//go:build cgo && darwin package screenshot @@ -71,8 +71,6 @@ import ( "errors" "image" "unsafe" - - "github.com/kbinani/screenshot/internal" ) func Capture(x, y, width, height int) (*image.RGBA, error) { @@ -81,7 +79,7 @@ func Capture(x, y, width, height int) (*image.RGBA, error) { } rect := image.Rect(0, 0, width, height) - img, err := internal.CreateImage(rect) + img, err := createImage(rect) if err != nil { return nil, err } diff --git a/internal/dbus_unavailable.go b/internal/dbus_unavailable.go deleted file mode 100644 index 8aa31e6..0000000 --- a/internal/dbus_unavailable.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build freebsd - -package internal - -import ( - "image" -) - -func Capture(x, y, width, height int) (img *image.RGBA, e error) { - return captureXinerama(x, y, width, height) -} diff --git a/internal/util.go b/internal/util.go deleted file mode 100644 index b4ee753..0000000 --- a/internal/util.go +++ /dev/null @@ -1,22 +0,0 @@ -package internal - -import ( - "errors" - "image" -) - -func CreateImage(rect image.Rectangle) (img *image.RGBA, e error) { - img = nil - e = errors.New("Cannot create image.RGBA") - - defer func() { - err := recover() - if err == nil { - e = nil - } - }() - // image.NewRGBA may panic if rect is too large. - img = image.NewRGBA(rect) - - return img, e -} diff --git a/nix.go b/nix.go new file mode 100644 index 0000000..7529118 --- /dev/null +++ b/nix.go @@ -0,0 +1,81 @@ +//go:build !s390x && !ppc64le && !darwin && !windows && (linux || freebsd || openbsd || netbsd) + +package screenshot + +import ( + "github.com/jezek/xgb" + "github.com/jezek/xgb/xinerama" + "image" +) + +// NumActiveDisplays returns the number of active displays. +func NumActiveDisplays() (num int) { + defer func() { + e := recover() + if e != nil { + num = 0 + } + }() + + c, err := xgb.NewConn() + if err != nil { + return 0 + } + defer c.Close() + + err = xinerama.Init(c) + if err != nil { + return 0 + } + + reply, err := xinerama.QueryScreens(c).Reply() + if err != nil { + return 0 + } + + num = int(reply.Number) + return num +} + +// GetDisplayBounds returns the bounds of displayIndex'th display. +// The main display is displayIndex = 0. +func GetDisplayBounds(displayIndex int) (rect image.Rectangle) { + defer func() { + e := recover() + if e != nil { + rect = image.Rectangle{} + } + }() + + c, err := xgb.NewConn() + if err != nil { + return image.Rectangle{} + } + defer c.Close() + + err = xinerama.Init(c) + if err != nil { + return image.Rectangle{} + } + + reply, err := xinerama.QueryScreens(c).Reply() + if err != nil { + return image.Rectangle{} + } + + if displayIndex >= int(reply.Number) { + return image.Rectangle{} + } + + primary := reply.ScreenInfo[0] + x0 := int(primary.XOrg) + y0 := int(primary.YOrg) + + screen := reply.ScreenInfo[displayIndex] + x := int(screen.XOrg) - x0 + y := int(screen.YOrg) - y0 + w := int(screen.Width) + h := int(screen.Height) + rect = image.Rect(x, y, x+w, y+h) + return rect +} diff --git a/internal/dbus_available.go b/nix_dbus_available.go similarity index 59% rename from internal/dbus_available.go rename to nix_dbus_available.go index f6c6998..265d2b8 100644 --- a/internal/dbus_available.go +++ b/nix_dbus_available.go @@ -1,12 +1,15 @@ //go:build !s390x && !ppc64le && !darwin && !windows && (linux || openbsd || netbsd) -package internal +package screenshot import ( "image" "os" ) +// Capture returns screen capture of specified desktop region. +// x and y represent distance from the upper-left corner of primary display. +// Y-axis is downward direction. This means coordinates system is similar to Windows OS. func Capture(x, y, width, height int) (img *image.RGBA, e error) { sessionType := os.Getenv("XDG_SESSION_TYPE") if sessionType == "wayland" { diff --git a/nix_dbus_unavailable.go b/nix_dbus_unavailable.go new file mode 100644 index 0000000..d01dcf1 --- /dev/null +++ b/nix_dbus_unavailable.go @@ -0,0 +1,14 @@ +//go:build freebsd + +package screenshot + +import ( + "image" +) + +// Capture returns screen capture of specified desktop region. +// x and y represent distance from the upper-left corner of primary display. +// Y-axis is downward direction. This means coordinates system is similar to Windows OS. +func Capture(x, y, width, height int) (img *image.RGBA, e error) { + return captureXinerama(x, y, width, height) +} diff --git a/internal/wayland.go b/nix_wayland.go similarity index 91% rename from internal/wayland.go rename to nix_wayland.go index b56415b..05a013d 100644 --- a/internal/wayland.go +++ b/nix_wayland.go @@ -1,6 +1,6 @@ //go:build !s390x && !ppc64le && !darwin && !windows && !freebsd && (linux || openbsd || netbsd) -package internal +package screenshot import ( "fmt" @@ -13,7 +13,7 @@ import ( "sync/atomic" ) -var gCounter uint64 = 0 +var gTokenCounter uint64 = 0 func captureDbus(x, y, width, height int) (img *image.RGBA, e error) { c, err := dbus.ConnectSessionBus() @@ -26,7 +26,7 @@ func captureDbus(x, y, width, height int) (img *image.RGBA, e error) { e = err } }(c) - token := atomic.AddUint64(&gCounter, 1) + token := atomic.AddUint64(&gTokenCounter, 1) options := map[string]dbus.Variant{ "modal": dbus.MakeVariant(false), "interactive": dbus.MakeVariant(false), @@ -85,9 +85,9 @@ func captureDbus(x, y, width, height int) (img *image.RGBA, e error) { if err != nil { return nil, fmt.Errorf("png.Decode(%s) failed: %v", path, err) } - canvas, err := CreateImage(image.Rect(0, 0, width, height)) + canvas, err := createImage(image.Rect(0, 0, width, height)) if err != nil { - return nil, fmt.Errorf("util.CreateImage(%v) failed: %v", path, err) + return nil, fmt.Errorf("createImage(%v) failed: %v", path, err) } draw.Draw(canvas, image.Rect(0, 0, width, height), img, image.Point{x, y}, draw.Src) return canvas, e diff --git a/internal/xwindow.go b/nix_xwindow.go similarity index 70% rename from internal/xwindow.go rename to nix_xwindow.go index aab2388..d52e422 100644 --- a/internal/xwindow.go +++ b/nix_xwindow.go @@ -1,6 +1,6 @@ //go:build !s390x && !ppc64le && !darwin && !windows && (linux || freebsd || openbsd || netbsd) -package internal +package screenshot import ( "fmt" @@ -53,7 +53,7 @@ func captureXinerama(x, y, width, height int) (img *image.RGBA, e error) { intersect := wholeScreenBounds.Intersect(targetBounds) rect := image.Rect(0, 0, width, height) - img, err = CreateImage(rect) + img, err = createImage(rect) if err != nil { return nil, err } @@ -132,72 +132,3 @@ func captureXinerama(x, y, width, height int) (img *image.RGBA, e error) { return img, e } - -func NumActiveDisplays() (num int) { - defer func() { - e := recover() - if e != nil { - num = 0 - } - }() - - c, err := xgb.NewConn() - if err != nil { - return 0 - } - defer c.Close() - - err = xinerama.Init(c) - if err != nil { - return 0 - } - - reply, err := xinerama.QueryScreens(c).Reply() - if err != nil { - return 0 - } - - num = int(reply.Number) - return num -} - -func GetDisplayBounds(displayIndex int) (rect image.Rectangle) { - defer func() { - e := recover() - if e != nil { - rect = image.Rectangle{} - } - }() - - c, err := xgb.NewConn() - if err != nil { - return image.Rectangle{} - } - defer c.Close() - - err = xinerama.Init(c) - if err != nil { - return image.Rectangle{} - } - - reply, err := xinerama.QueryScreens(c).Reply() - if err != nil { - return image.Rectangle{} - } - - if displayIndex >= int(reply.Number) { - return image.Rectangle{} - } - - primary := reply.ScreenInfo[0] - x0 := int(primary.XOrg) - y0 := int(primary.YOrg) - - screen := reply.ScreenInfo[displayIndex] - x := int(screen.XOrg) - x0 - y := int(screen.YOrg) - y0 - w := int(screen.Width) - h := int(screen.Height) - rect = image.Rect(x, y, x+w, y+h) - return rect -} diff --git a/screenshot.go b/screenshot.go index 79c7063..385fb98 100644 --- a/screenshot.go +++ b/screenshot.go @@ -21,3 +21,19 @@ func CaptureDisplay(displayIndex int) (*image.RGBA, error) { func CaptureRect(rect image.Rectangle) (*image.RGBA, error) { return Capture(rect.Min.X, rect.Min.Y, rect.Dx(), rect.Dy()) } + +func createImage(rect image.Rectangle) (img *image.RGBA, e error) { + img = nil + e = errors.New("Cannot create image.RGBA") + + defer func() { + err := recover() + if err == nil { + e = nil + } + }() + // image.NewRGBA may panic if rect is too large. + img = image.NewRGBA(rect) + + return img, e +} diff --git a/screenshot_supported.go b/screenshot_supported.go deleted file mode 100644 index 68ffc89..0000000 --- a/screenshot_supported.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build !s390x && !ppc64le && !darwin && !windows && (linux || freebsd || openbsd || netbsd) - -package screenshot - -import ( - "github.com/kbinani/screenshot/internal" - "image" -) - -// Capture returns screen capture of specified desktop region. -// x and y represent distance from the upper-left corner of primary display. -// Y-axis is downward direction. This means coordinates system is similar to Windows OS. -func Capture(x, y, width, height int) (*image.RGBA, error) { - return internal.Capture(x, y, width, height) -} - -// NumActiveDisplays returns the number of active displays. -func NumActiveDisplays() int { - return internal.NumActiveDisplays() -} - -// GetDisplayBounds returns the bounds of displayIndex'th display. -// The main display is displayIndex = 0. -func GetDisplayBounds(displayIndex int) image.Rectangle { - return internal.GetDisplayBounds(displayIndex) -} diff --git a/screenshot_unsupported.go b/unsupported.go similarity index 100% rename from screenshot_unsupported.go rename to unsupported.go diff --git a/screenshot_windows.go b/windows.go similarity index 98% rename from screenshot_windows.go rename to windows.go index 01a2888..36e604f 100644 --- a/screenshot_windows.go +++ b/windows.go @@ -1,9 +1,10 @@ +//go:build windows + package screenshot import ( "errors" - "github.com/kbinani/screenshot/internal" - win "github.com/lxn/win" + "github.com/lxn/win" "image" "syscall" "unsafe" @@ -19,7 +20,7 @@ var ( func Capture(x, y, width, height int) (*image.RGBA, error) { rect := image.Rect(0, 0, width, height) - img, err := internal.CreateImage(rect) + img, err := createImage(rect) if err != nil { return nil, err } From 406d4ef5c02068c07b8c3b086d08ab8cf07d9930 Mon Sep 17 00:00:00 2001 From: kbinani Date: Wed, 21 Aug 2024 01:06:34 +0900 Subject: [PATCH 2/2] Update deps --- go.mod | 8 ++++---- go.sum | 14 ++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index a5e3785..8520db0 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,14 @@ module github.com/kbinani/screenshot -go 1.17 +go 1.21 require ( - github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 - github.com/jezek/xgb v1.1.0 + github.com/gen2brain/shm v0.1.0 + github.com/jezek/xgb v1.1.1 github.com/lxn/win v0.0.0-20210218163916-a377121e959e ) require ( + golang.org/x/sys v0.24.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - golang.org/x/sys v0.11.0 // indirect ) diff --git a/go.sum b/go.sum index 2ac813d..f9306d7 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,11 @@ -github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 h1:VLEKvjGJYAMCXw0/32r9io61tEXnMWDRxMk+peyRVFc= -github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= -github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4= -github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/gen2brain/shm v0.1.0 h1:MwPeg+zJQXN0RM9o+HqaSFypNoNEcNpeoGp0BTSx2YY= +github.com/gen2brain/shm v0.1.0/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= -github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= +github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= +github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=