Files

88 lines
2.6 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package xorg
/*
#include "commands_native.h"
*/
import "C"
type steamFocusSample struct {
window, focus uint64
pid int
known, steam bool
innerFocus bool
}
// The command owner retains one verified Steam browser child. A foreground
// transition arms at most one repair during the next ten 100ms focus samples.
// Steam's own restoration wins; we never choose a child from its geometry.
type steamFocusRepair struct {
previousWindow, window, target uint64
pid int
checksLeft, outerSamples int
}
func (repair *steamFocusRepair) observe(sample steamFocusSample) uint64 {
if !sample.known {
return 0
}
if sample.window != repair.previousWindow {
repair.previousWindow = sample.window
repair.checksLeft, repair.outerSamples = 10, 0
}
if !sample.steam {
repair.checksLeft, repair.outerSamples = 0, 0
return 0
}
if sample.innerFocus {
repair.window, repair.pid, repair.target = sample.window, sample.pid, sample.focus
repair.outerSamples = 0
}
if repair.checksLeft == 0 {
return 0
}
repair.checksLeft--
if sample.focus != sample.window {
repair.outerSamples = 0
return 0
}
repair.outerSamples++
if repair.outerSamples < 2 || sample.window != repair.window || sample.pid != repair.pid {
return 0
}
return repair.target
}
func read_command_focus(display *C.Display, steamEnabled bool) (int, steamFocusSample) {
var enabled C.int
if steamEnabled {
enabled = 1
}
result := C.cthulhu_read_command_focus(display, enabled)
value := result.steam
return int(result.xterm), steamFocusSample{window: uint64(value.window), focus: uint64(value.focus), pid: int(value.pid),
known: value.known != 0, steam: value.steam != 0, innerFocus: value.innerFocus != 0}
}
func restore_steam_focus(display *C.Display, window uint64, pid int, target uint64) bool {
return C.cthulhu_restore_steam_focus(display, C.Window(window), C.int(pid), C.Window(target)) != 0
}
func (owner *commandOwner) check_steam_focus(sample steamFocusSample) {
if owner.listener.secure.Load() || owner.workerContext.Err() != nil {
owner.steamFocus.checksLeft = 0
return
}
target := owner.steamFocus.observe(sample)
if target == 0 || !owner.commandGrabsAllowed() || len(owner.held) != 0 || owner.device.active != 0 ||
owner.learnMode || owner.uiSession != 0 || owner.ocrReview || owner.ocrPending {
return
}
if restore_steam_focus(owner.device.display, sample.window, sample.pid, target) {
owner.steamFocus.checksLeft = 0
}
}