70 lines
2.6 KiB
Go
70 lines
2.6 KiB
Go
// Cthulhu screen reader.
|
|
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation, either version 3 of the License, or (at your option)
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
// more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with
|
|
// this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
|
|
|
package atspi
|
|
|
|
import "math"
|
|
|
|
// Rectangle uses AT-SPI screen coordinates. Negative positions are valid on
|
|
// multi-monitor desktops. Edges use int64 arithmetic to avoid native gint
|
|
// overflow. Zero-sized rectangles cannot contribute a flat-review zone.
|
|
type Rectangle struct {
|
|
X, Y, Width, Height int32
|
|
}
|
|
|
|
func (rect Rectangle) Valid() bool {
|
|
return rect.Width > 0 && rect.Height > 0 && rect.X != math.MinInt32 && rect.Y != math.MinInt32
|
|
}
|
|
|
|
// Intersection clips a screen rectangle without wrapping at native integer
|
|
// limits. A disjoint, empty, or unavailable rectangle has no intersection.
|
|
func (rect Rectangle) Intersection(other Rectangle) (Rectangle, bool) {
|
|
if !rect.Valid() || !other.Valid() {
|
|
return Rectangle{}, false
|
|
}
|
|
left := max(int64(rect.X), int64(other.X))
|
|
top := max(int64(rect.Y), int64(other.Y))
|
|
right := min(int64(rect.X)+int64(rect.Width), int64(other.X)+int64(other.Width))
|
|
bottom := min(int64(rect.Y)+int64(rect.Height), int64(other.Y)+int64(other.Height))
|
|
if right <= left || bottom <= top {
|
|
return Rectangle{}, false
|
|
}
|
|
return Rectangle{int32(left), int32(top), int32(right - left), int32(bottom - top)}, true
|
|
}
|
|
|
|
// Geometry is owned capture-time component data, separate from focus snapshots.
|
|
// Bounds are meaningful only when visibility is known and the object is both
|
|
// visible and showing. Neither state establishes that another window does not
|
|
// obscure the object. Unsupported components retain unknown bounds.
|
|
type Geometry struct {
|
|
Bounds Rectangle
|
|
BoundsKnown bool
|
|
VisibilityKnown bool
|
|
Visible bool
|
|
Showing bool
|
|
}
|
|
|
|
func (geometry Geometry) valid() bool {
|
|
if !geometry.VisibilityKnown && (geometry.Visible || geometry.Showing) {
|
|
return false
|
|
}
|
|
if geometry.BoundsKnown {
|
|
return geometry.VisibilityKnown && geometry.Visible && geometry.Showing && geometry.Bounds.Valid()
|
|
}
|
|
return geometry.Bounds == (Rectangle{})
|
|
}
|