Files
cthulhu/internal/platform/xorg/commands_foreground.go

75 lines
2.7 KiB
Go

package xorg
/*
#cgo pkg-config: xres
#include "commands_native.h"
#include <X11/XKBlib.h>
*/
import "C"
func ActiveWindowIsXTerm() bool {
return C.cthulhu_active_window_is_xterm() != 0
}
// Foreground is an immutable X11 client identity and its screen rectangle.
// Known with Window == 0 means no foreground client, not missing metadata.
type Foreground struct {
Known bool
Window uint64
PID int
// PropertyPID retains _NET_WM_PID for diagnostics. PID uses the X server's
// local client identity when available, so Flatpak namespaces agree with AT-SPI.
PropertyPID int
X, Y, Width, Height int
OuterX, OuterY, OuterWidth, OuterHeight int
// Frame bounds come from the client's enclosing X11 window, independently
// of _NET_FRAME_EXTENTS. Zero dimensions mean no unambiguous frame exists.
FrameX, FrameY, FrameWidth, FrameHeight int
}
// ForegroundReader has no goroutine. Its native event-loop owner opens, reads,
// and closes it on that thread; no consumer performs X11 I/O.
type ForegroundReader struct {
display *C.Display
clientPIDs bool
pidWindow uint64
propertyPID, clientPID int
}
func OpenForegroundReader() *ForegroundReader {
display := C.XOpenDisplay(nil)
if display == nil {
return nil
}
return &ForegroundReader{display: display, clientPIDs: C.cthulhu_xres_client_pids_supported(display) != 0}
}
func (reader *ForegroundReader) Read() Foreground {
if reader == nil {
return Foreground{}
}
value := C.read_foreground(reader.display)
window, propertyPID := uint64(value.window), int(value.pid)
// The connection's owner also owns this one-client cache. Window departure
// (including no foreground) or a changed property discards the old identity.
// Resizing and ordinary input never trigger an extra server query.
if window != reader.pidWindow || propertyPID != reader.propertyPID {
reader.pidWindow, reader.propertyPID, reader.clientPID = window, propertyPID, 0
if window != 0 && reader.clientPIDs {
reader.clientPID = int(C.cthulhu_xres_client_pid(reader.display, C.Window(window)))
}
}
pid := propertyPID
if reader.clientPID > 0 {
pid = reader.clientPID
}
return Foreground{Known: value.known != 0, Window: window, PID: pid, PropertyPID: propertyPID,
X: int(value.x), Y: int(value.y), Width: int(value.width), Height: int(value.height), OuterX: int(value.outerX), OuterY: int(value.outerY), OuterWidth: int(value.outerWidth), OuterHeight: int(value.outerHeight),
FrameX: int(value.frameX), FrameY: int(value.frameY), FrameWidth: int(value.frameWidth), FrameHeight: int(value.frameHeight)}
}
func (reader *ForegroundReader) Close() {
if reader != nil {
C.XCloseDisplay(reader.display)
reader.display = nil
}
}