359 lines
9.1 KiB
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...)
|
||
|
}
|