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 }