Descovered a but on Slint where if the reported sizes differ preferences would not rport. HOpefully fixed. This could probably affect more than just Slint, just happened to catch it there.
This commit is contained in:
1 parent
7591f65b58
commit
d0fdce7285
9 files changed
+90
No files matched your search
@@ -121,6 +121,7 @@ type Adapter struct {
|
||||
foregroundReader *xorg.ForegroundReader // GLib thread only
|
||||
foregroundProcesses map[int]bool // GLib thread; provider PID matches for current client
|
||||
foreground atomic.Pointer[ForegroundState]
|
||||
preferencesPID atomic.Int64 // Owned preferences helper; zero when closed.
|
||||
echoFocus atomic.Pointer[echoFocus]
|
||||
eventListener *C.AtspiEventListener // GLib owner; released with subscriptions.
|
||||
foregroundChanges chan struct{}
|
||||
|
||||
@@ -129,6 +129,14 @@ func (adapter *Adapter) matchForeground(window *C.AtspiAccessible, id ObjectID,
|
||||
}
|
||||
return false
|
||||
}
|
||||
// Tiling window managers can report GTK's frame and X11's client at
|
||||
// different origins and sizes. Our own active preferences child is known
|
||||
// by its launched PID; require X11 to confirm that process is foreground.
|
||||
if preferences_foreground_matches(state, pid, adapter.preferencesPID.Load()) {
|
||||
adapter.foregroundWindow = id
|
||||
adapter.foregroundRecovery = 0
|
||||
return true
|
||||
}
|
||||
component := C.atspi_accessible_get_component_iface(window)
|
||||
if component == nil {
|
||||
if check != nil {
|
||||
|
||||
@@ -26,6 +26,17 @@ type ForegroundState struct {
|
||||
Epoch uint64
|
||||
}
|
||||
|
||||
// SetPreferencesProcess scopes geometry-independent foreground matching to the
|
||||
// UI child launched by this reader. Clear it when that child exits.
|
||||
func (adapter *Adapter) SetPreferencesProcess(pid int) {
|
||||
adapter.preferencesPID.Store(int64(pid))
|
||||
}
|
||||
|
||||
func preferences_foreground_matches(client xorg.Foreground, pid int, preferencesPID int64) bool {
|
||||
return client.Known && client.Window != 0 && preferencesPID > 0 &&
|
||||
int64(pid) == preferencesPID && client.PID == pid
|
||||
}
|
||||
|
||||
func foregroundWindowMatches(client xorg.Foreground, pid int, bounds Rectangle) bool {
|
||||
if client.PID > 0 && pid > 0 && client.PID != pid {
|
||||
return false
|
||||
|
||||
@@ -44,6 +44,37 @@ func TestForegroundWindowCorrelationSteamBigPictureScale(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferencesForegroundIdentity(t *testing.T) {
|
||||
// Slint/i3 reports GTK's frame and the X11 client with different borders.
|
||||
client := xorg.Foreground{Known: true, Window: 45, PID: 123,
|
||||
X: 2, Y: 18, Width: 1912, Height: 974, OuterX: 2, OuterY: 18, OuterWidth: 1912, OuterHeight: 974}
|
||||
if foregroundWindowMatches(client, 123, Rectangle{Width: 1916, Height: 994}) {
|
||||
t.Fatal("fixture must reproduce the reported bounds mismatch")
|
||||
}
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
client xorg.Foreground
|
||||
pid int
|
||||
owned int64
|
||||
want bool
|
||||
}{
|
||||
{"owned foreground helper", client, 123, 123, true},
|
||||
{"helper closed", client, 123, 0, false},
|
||||
{"another reader's helper", client, 123, 124, false},
|
||||
{"other provider", client, 124, 123, false},
|
||||
{"helper in background", xorg.Foreground{Known: true, Window: 46, PID: 124}, 123, 123, false},
|
||||
{"missing foreground PID", xorg.Foreground{Known: true, Window: 45}, 123, 123, false},
|
||||
{"empty workspace", xorg.Foreground{Known: true, PID: 123}, 123, 123, false},
|
||||
{"unknown foreground", xorg.Foreground{Window: 45, PID: 123}, 123, 123, false},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if got := preferences_foreground_matches(test.client, test.pid, test.owned); got != test.want {
|
||||
t.Fatalf("match = %v, want %v", got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestForegroundMenuPopupCorrelation(t *testing.T) {
|
||||
client := xorg.Foreground{Known: true, Window: 45, PID: 123}
|
||||
main := NewObjectID(":1.40", "/main")
|
||||
|
||||
@@ -77,6 +77,8 @@ func TestNativePreferencesDropdownEscape(t *testing.T) {
|
||||
if err := command.Start(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
adapter.SetPreferencesProcess(command.Process.Pid)
|
||||
defer adapter.SetPreferencesProcess(0)
|
||||
helperDone := make(chan error, 1)
|
||||
go func() { helperDone <- command.Wait() }()
|
||||
helperJoined := false
|
||||
@@ -118,6 +120,9 @@ func TestNativePreferencesDropdownEscape(t *testing.T) {
|
||||
select {
|
||||
case event := <-adapter.Events():
|
||||
t.Logf("%s %s %q capture=%s", event.Type, event.Source.Role, event.Source.Name, event.SnapshotDuration)
|
||||
if (event.Type == WindowActivatedEvent || event.Type == FocusedStateEvent && event.Detail1 == 1) && event.ForegroundMismatch {
|
||||
t.Fatalf("owned preferences focus rejected: %+v", event)
|
||||
}
|
||||
if event.Type == FocusedStateEvent && event.Detail1 == 1 {
|
||||
// Match the running reader's browser-mode classification.
|
||||
// Without these fresh ancestry queries, stale cached focus
|
||||
|
||||
Reference in new issue
Block a user