// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package atspi import ( "context" "os" "os/exec" "strconv" "testing" "time" ) // The GTK provider publishes its host PID over AT-SPI, but its X11 property // deliberately contains a different PID, as with a Flatpak PID namespace. func TestNativeForegroundProcessIdentity(t *testing.T) { if os.Getenv("CTHULHU_FOREGROUND_PID") != "1" { t.Skip("requires isolated GTK/X11 process identity fixture") } pid, err := strconv.Atoi(os.Getenv("CTHULHU_TREE_PID")) if err != nil { t.Fatal(err) } ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() adapter := New() if err := adapter.Start(ctx); err != nil { t.Fatal(err) } defer adapter.Stop(context.Background()) if _, err := adapter.CaptureDesktop(ctx); err != nil { t.Fatal(err) } if foreground := adapter.Foreground(); foreground.Client.PID != pid { t.Fatalf("foreground PID = %d; want host provider PID %d (window property is 252)", foreground.Client.PID, pid) } if err := exec.CommandContext(ctx, "xdotool", "key", "F6").Run(); err != nil { t.Fatal(err) } for { select { case event := <-adapter.Events(): if event.Type != FocusedStateEvent || event.Detail1 == 0 || event.Source.Name != "Caret review probe" { continue } wantMismatch := os.Getenv("CTHULHU_FOREGROUND_PROXY_OTHER") == "1" if event.ForegroundMismatch != wantMismatch || event.Foreground.Client.PID != pid || !event.Window.Valid() { t.Fatalf("foreground mismatch = %v; want %v: %+v", event.ForegroundMismatch, wantMismatch, event) } if os.Getenv("CTHULHU_FOREGROUND_PROXY") == "1" && event.Source.ApplicationProcess != "xdg-dbus-proxy" { t.Fatalf("fixture did not use a separate D-Bus proxy: %q", event.Source.ApplicationProcess) } return case <-ctx.Done(): t.Fatal("foreground control focus event missing") } } }