wm/vend/xgbutil/icccm/icccm.go

359 lines
9.1 KiB
Go

package icccm
import (
"fmt"
"github.com/jezek/xgb/xproto"
"github.com/jezek/xgbutil"
"github.com/jezek/xgbutil/xprop"
)
const (
HintInput = (1 << iota)
HintState
HintIconPixmap
HintIconWindow
HintIconPosition
HintIconMask
HintWindowGroup
HintMessage
HintUrgency
)
const (
SizeHintUSPosition = (1 << iota)
SizeHintUSSize
SizeHintPPosition
SizeHintPSize
SizeHintPMinSize
SizeHintPMaxSize
SizeHintPResizeInc
SizeHintPAspect
SizeHintPBaseSize
SizeHintPWinGravity
)
const (
StateWithdrawn = iota
StateNormal
StateZoomed
StateIconic
StateInactive
)
// WM_NAME get
func WmNameGet(xu *xgbutil.XUtil, win xproto.Window) (string, error) {
return xprop.PropValStr(xprop.GetProperty(xu, win, "WM_NAME"))
}
// WM_NAME set
func WmNameSet(xu *xgbutil.XUtil, win xproto.Window, name string) error {
return xprop.ChangeProp(xu, win, 8, "WM_NAME", "STRING", ([]byte)(name))
}
// WM_ICON_NAME get
func WmIconNameGet(xu *xgbutil.XUtil, win xproto.Window) (string, error) {
return xprop.PropValStr(xprop.GetProperty(xu, win, "WM_ICON_NAME"))
}
// WM_ICON_NAME set
func WmIconNameSet(xu *xgbutil.XUtil, win xproto.Window, name string) error {
return xprop.ChangeProp(xu, win, 8, "WM_ICON_NAME", "STRING",
([]byte)(name))
}
// NormalHints is a struct that organizes the information related to the
// WM_NORMAL_HINTS property. Please see the ICCCM spec for more details.
type NormalHints struct {
Flags uint
X, Y int
Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight uint
WidthInc, HeightInc uint
MinAspectNum, MinAspectDen, MaxAspectNum, MaxAspectDen uint
BaseWidth, BaseHeight, WinGravity uint
}
// WM_NORMAL_HINTS get
func WmNormalHintsGet(xu *xgbutil.XUtil,
win xproto.Window) (nh *NormalHints, err error) {
lenExpect := 18
hints, err := xprop.PropValNums(xprop.GetProperty(xu, win,
"WM_NORMAL_HINTS"))
if err != nil {
return nil, err
}
if len(hints) != lenExpect {
return nil,
fmt.Errorf("WmNormalHint: There are %d fields in WM_NORMAL_HINTS, "+
"but xgbutil expects %d.", len(hints), lenExpect)
}
nh = &NormalHints{}
nh.Flags = hints[0]
nh.X = int(hints[1])
nh.Y = int(hints[2])
nh.Width = hints[3]
nh.Height = hints[4]
nh.MinWidth = hints[5]
nh.MinHeight = hints[6]
nh.MaxWidth = hints[7]
nh.MaxHeight = hints[8]
nh.WidthInc = hints[9]
nh.HeightInc = hints[10]
nh.MinAspectNum = hints[11]
nh.MinAspectDen = hints[12]
nh.MaxAspectNum = hints[13]
nh.MaxAspectDen = hints[14]
nh.BaseWidth = hints[15]
nh.BaseHeight = hints[16]
nh.WinGravity = hints[17]
if nh.WinGravity <= 0 {
nh.WinGravity = xproto.GravityNorthWest
}
return nh, nil
}
// WM_NORMAL_HINTS set
// Make sure to set the flags in the NormalHints struct correctly!
func WmNormalHintsSet(xu *xgbutil.XUtil, win xproto.Window,
nh *NormalHints) error {
raw := []uint{
nh.Flags,
uint(nh.X), uint(nh.Y), nh.Width, nh.Height,
nh.MinWidth, nh.MinHeight,
nh.MaxWidth, nh.MaxHeight,
nh.WidthInc, nh.HeightInc,
nh.MinAspectNum, nh.MinAspectDen,
nh.MaxAspectNum, nh.MaxAspectDen,
nh.BaseWidth, nh.BaseHeight,
nh.WinGravity,
}
return xprop.ChangeProp32(xu, win, "WM_NORMAL_HINTS", "WM_SIZE_HINTS",
raw...)
}
// Hints is a struct that organizes information related to the WM_HINTS
// property. Once again, I refer you to the ICCCM spec for documentation.
type Hints struct {
Flags uint
Input, InitialState uint
IconX, IconY int
IconPixmap, IconMask xproto.Pixmap
WindowGroup, IconWindow xproto.Window
}
// WM_HINTS get
func WmHintsGet(xu *xgbutil.XUtil,
win xproto.Window) (hints *Hints, err error) {
lenExpect := 9
raw, err := xprop.PropValNums(xprop.GetProperty(xu, win, "WM_HINTS"))
if err != nil {
return nil, err
}
if len(raw) != lenExpect {
return nil,
fmt.Errorf("WmHints: There are %d fields in "+
"WM_HINTS, but xgbutil expects %d.", len(raw), lenExpect)
}
hints = &Hints{}
hints.Flags = raw[0]
hints.Input = raw[1]
hints.InitialState = raw[2]
hints.IconPixmap = xproto.Pixmap(raw[3])
hints.IconWindow = xproto.Window(raw[4])
hints.IconX = int(raw[5])
hints.IconY = int(raw[6])
hints.IconMask = xproto.Pixmap(raw[7])
hints.WindowGroup = xproto.Window(raw[8])
return hints, nil
}
// WM_HINTS set
// Make sure to set the flags in the Hints struct correctly!
func WmHintsSet(xu *xgbutil.XUtil, win xproto.Window, hints *Hints) error {
raw := []uint{
hints.Flags, hints.Input, hints.InitialState,
uint(hints.IconPixmap), uint(hints.IconWindow),
uint(hints.IconX), uint(hints.IconY),
uint(hints.IconMask),
uint(hints.WindowGroup),
}
return xprop.ChangeProp32(xu, win, "WM_HINTS", "WM_HINTS", raw...)
}
// WmClass struct contains two data points:
// the instance and a class of a window.
type WmClass struct {
Instance, Class string
}
// WM_CLASS get
func WmClassGet(xu *xgbutil.XUtil, win xproto.Window) (*WmClass, error) {
raw, err := xprop.PropValStrs(xprop.GetProperty(xu, win, "WM_CLASS"))
if err != nil {
return nil, err
}
if len(raw) != 2 {
return nil,
fmt.Errorf("WmClass: Two string make up WM_CLASS, but "+
"xgbutil found %d in '%v'.", len(raw), raw)
}
return &WmClass{
Instance: raw[0],
Class: raw[1],
}, nil
}
// WM_CLASS set
func WmClassSet(xu *xgbutil.XUtil, win xproto.Window, class *WmClass) error {
raw := make([]byte, len(class.Instance)+len(class.Class)+2)
copy(raw, class.Instance)
copy(raw[(len(class.Instance)+1):], class.Class)
return xprop.ChangeProp(xu, win, 8, "WM_CLASS", "STRING", raw)
}
// WM_TRANSIENT_FOR get
func WmTransientForGet(xu *xgbutil.XUtil,
win xproto.Window) (xproto.Window, error) {
return xprop.PropValWindow(xprop.GetProperty(xu, win, "WM_TRANSIENT_FOR"))
}
// WM_TRANSIENT_FOR set
func WmTransientForSet(xu *xgbutil.XUtil, win xproto.Window,
transient xproto.Window) error {
return xprop.ChangeProp32(xu, win, "WM_TRANSIENT_FOR", "WINDOW",
uint(transient))
}
// WM_PROTOCOLS get
func WmProtocolsGet(xu *xgbutil.XUtil, win xproto.Window) ([]string, error) {
raw, err := xprop.GetProperty(xu, win, "WM_PROTOCOLS")
return xprop.PropValAtoms(xu, raw, err)
}
// WM_PROTOCOLS set
func WmProtocolsSet(xu *xgbutil.XUtil, win xproto.Window,
atomNames []string) error {
atoms, err := xprop.StrToAtoms(xu, atomNames)
if err != nil {
return err
}
return xprop.ChangeProp32(xu, win, "WM_PROTOCOLS", "ATOM", atoms...)
}
// WM_COLORMAP_WINDOWS get
func WmColormapWindowsGet(xu *xgbutil.XUtil,
win xproto.Window) ([]xproto.Window, error) {
return xprop.PropValWindows(xprop.GetProperty(xu, win,
"WM_COLORMAP_WINDOWS"))
}
// WM_COLORMAP_WINDOWS set
func WmColormapWindowsSet(xu *xgbutil.XUtil, win xproto.Window,
windows []xproto.Window) error {
return xprop.ChangeProp32(xu, win, "WM_COLORMAP_WINDOWS", "WINDOW",
xprop.WindowToInt(windows)...)
}
// WM_CLIENT_MACHINE get
func WmClientMachineGet(xu *xgbutil.XUtil, win xproto.Window) (string, error) {
return xprop.PropValStr(xprop.GetProperty(xu, win, "WM_CLIENT_MACHINE"))
}
// WM_CLIENT_MACHINE set
func WmClientMachineSet(xu *xgbutil.XUtil, win xproto.Window,
client string) error {
return xprop.ChangeProp(xu, win, 8, "WM_CLIENT_MACHINE", "STRING",
([]byte)(client))
}
// WmState is a struct that organizes information related to the WM_STATE
// property. Namely, the state (corresponding to a State* constant in this file)
// and the icon window (probably not used).
type WmState struct {
State uint
Icon xproto.Window
}
// WM_STATE get
func WmStateGet(xu *xgbutil.XUtil, win xproto.Window) (*WmState, error) {
raw, err := xprop.PropValNums(xprop.GetProperty(xu, win, "WM_STATE"))
if err != nil {
return nil, err
}
if len(raw) != 2 {
return nil,
fmt.Errorf("WmState: Expected two integers in WM_STATE property "+
"but xgbutil found %d in '%v'.", len(raw), raw)
}
return &WmState{
State: raw[0],
Icon: xproto.Window(raw[1]),
}, nil
}
// WM_STATE set
func WmStateSet(xu *xgbutil.XUtil, win xproto.Window, state *WmState) error {
raw := []uint{
state.State,
uint(state.Icon),
}
return xprop.ChangeProp32(xu, win, "WM_STATE", "WM_STATE", raw...)
}
// IconSize is a struct the organizes information related to the WM_ICON_SIZE
// property. Mostly info about its dimensions.
type IconSize struct {
MinWidth, MinHeight, MaxWidth, MaxHeight, WidthInc, HeightInc uint
}
// WM_ICON_SIZE get
func WmIconSizeGet(xu *xgbutil.XUtil, win xproto.Window) (*IconSize, error) {
raw, err := xprop.PropValNums(xprop.GetProperty(xu, win, "WM_ICON_SIZE"))
if err != nil {
return nil, err
}
if len(raw) != 6 {
return nil,
fmt.Errorf("WmIconSize: Expected six integers in WM_ICON_SIZE "+
"property, but xgbutil found "+"%d in '%v'.", len(raw), raw)
}
return &IconSize{
MinWidth: raw[0], MinHeight: raw[1],
MaxWidth: raw[2], MaxHeight: raw[3],
WidthInc: raw[4], HeightInc: raw[5],
}, nil
}
// WM_ICON_SIZE set
func WmIconSizeSet(xu *xgbutil.XUtil, win xproto.Window,
icondim *IconSize) error {
raw := []uint{
icondim.MinWidth, icondim.MinHeight,
icondim.MaxWidth, icondim.MaxHeight,
icondim.WidthInc, icondim.HeightInc,
}
return xprop.ChangeProp32(xu, win, "WM_ICON_SIZE", "WM_ICON_SIZE", raw...)
}