func (p PositionChange) X() int {
	return p.x
}
X returns the pixel x-coordinate difference.
package mouse
type EventSource interface {
	PollMouseEvent() (Event, bool)
}
func New(source EventSource) *Mouse {
	if source == nil {
		panic("nil EventSource")
	}
	return &Mouse{
		source:       source,
		pressed:      map[Button]struct{}{},
		justPressed:  make(map[Button]bool),
		justReleased: make(map[Button]bool),
		position: Position{
			insideWindow: true,
		},
	}
}
type Mouse struct {
	source         EventSource
	pressed        map[Button]struct{}
	justPressed    map[Button]bool
	justReleased   map[Button]bool
	position       Position
	positionChange PositionChange
	scroll         Scroll
}
func (m *Mouse) Update() {
	m.clearJustPressed()
	m.clearJustReleased()
	lastPosition := m.position
	m.scroll = Scroll{}
	defer func() {
		m.positionChange = m.calculatePositionChange(lastPosition)
	}()
	for {
		event, ok := m.source.PollMouseEvent()
		if !ok {
			return
		}
		switch event.typ {
		case pressed:
			m.pressed[event.button] = struct{}{}
			m.justPressed[event.button] = true
		case released:
			delete(m.pressed, event.button)
			m.justReleased[event.button] = true
		case moved:
			m.position = event.position
		case scrolled:
			m.scroll = Scroll{
				x: event.scrollX + m.scroll.x,
				y: event.scrollY + m.scroll.y,
			}
		}
	}
}
func (m *Mouse) clearJustPressed() {
	for button := range m.justPressed {
		delete(m.justPressed, button)
	}
}
func (m *Mouse) clearJustReleased() {
	for button := range m.justReleased {
		delete(m.justReleased, button)
	}
}
func (m *Mouse) calculatePositionChange(lastPosition Position) PositionChange {
	if lastPosition == m.position {
		return PositionChange{}
	}
	windowLeft := false
	if !m.position.insideWindow && lastPosition.insideWindow {
		windowLeft = true
	}
	windowEntered := false
	if m.position.insideWindow && !lastPosition.insideWindow {
		windowEntered = true
	}
	return PositionChange{
		x:             m.position.x - lastPosition.x,
		y:             m.position.y - lastPosition.y,
		realX:         m.position.realX - lastPosition.realX,
		realY:         m.position.realY - lastPosition.realY,
		windowLeft:    windowLeft,
		windowEntered: windowEntered,
	}
}
func (m *Mouse) Pressed(button Button) bool {
	_, found := m.pressed[button]
	return found
}
func (m *Mouse) PressedButtons() []Button {
	var pressedButtons []Button
	for button := range m.pressed {
		pressedButtons = append(pressedButtons, button)
	}
	return pressedButtons
}
func (m *Mouse) JustPressed(button Button) bool {
	return m.justPressed[button]
}
func (m *Mouse) JustReleased(button Button) bool {
	return m.justReleased[button]
}
func (m *Mouse) Position() Position {
	return m.position
}
func (m *Mouse) PositionChange() PositionChange {
	return m.positionChange
}
func (m *Mouse) PositionChanged() bool {
	return m.positionChange != PositionChange{}
}
func (m *Mouse) Scroll() Scroll {
	return m.scroll
}
type Position struct {
	x, y         int
	realX, realY float64
	insideWindow bool
}
func (p Position) X() int {
	return p.x
}
func (p Position) Y() int {
	return p.y
}
func (p Position) RealX() float64 {
	return p.realX
}
func (p Position) RealY() float64 {
	return p.realY
}
func (p Position) InsideWindow() bool {
	return p.insideWindow
}
type PositionChange struct {
	x, y          int
	realX, realY  float64
	windowEntered bool
	windowLeft    bool
}