// Package platform is the seam between chirami and the desktop: it watches the
// selection, finds the pointer, and shows a pre-rendered popup image.
// Each OS backend lives in a subpackage and is picked by build tags in run_*.go.
package platform
import "image"
// Rect is in logical pixels (points on macOS).
type Rect struct{ X, Y, W, H float64 }
func (r Rect) Contains(x, y float64) bool {
return x >= r.X && y >= r.Y && x < r.X+r.W && y < r.Y+r.H
}
// Anchor is where the popup should appear.
type Anchor struct {
X, Y float64 // pointer position, logical px, in the same space as Screen
Screen Rect // usable bounds of the display under the pointer
Scale float64 // device px per logical px on that display
}
type EventKind int
const (
// Click is a primary-button release inside the popup.
Click EventKind = iota
// Motion is pointer movement inside the popup.
Motion
// Leave fires when the pointer leaves the popup after having entered it.
Leave
// Dismiss means the user wants it gone: Escape, or a click outside the
// popup where the backend can see one.
Dismiss
)
// Event coordinates are logical px relative to the popup image origin.
type Event struct {
Kind EventKind
X, Y float64
}
// Popup is a rendered card ready to show.
type Popup struct {
Image *image.RGBA // premultiplied RGBA, rendered at Anchor.Scale device px per logical px
X, Y float64 // top-left of Image in logical px, same space as Anchor
Hit Rect // the opaque card inside Image (excludes the shadow), logical px relative to Image origin
}
// Backend is implemented once per windowing system. All methods are safe to
// call from any goroutine.
type Backend interface {
// Selections delivers the selected text each time the selection settles:
// after it changes and, where the backend can tell, once the pointer
// button is released. The app debounces further.
Selections() <-chan string
// Locate reports where the pointer is now.
Locate() (Anchor, error)
// Pointer is a cheap current pointer position in Anchor space; ok is
// false where the platform cannot tell (Wayland).
Pointer() (x, y float64, ok bool)
// Show displays p without taking keyboard focus, replacing any popup
// already shown.
Show(p Popup) error
Hide()
Events() <-chan Event
}
// Screenshotter is implemented by backends that can tell when the user takes
// a screenshot with the desktop's own tool, as opposed to any image landing
// on the clipboard.
type Screenshotter interface {
// Screenshots delivers each screenshot the user takes, encoded as PNG.
Screenshots() <-chan []byte
}