wm/vend/xgbutil/ewmh/ewmh.go

1160 lines
30 KiB
Go
Raw Permalink Normal View History

2023-06-11 14:21:08 +00:00
package ewmh
import (
"github.com/jezek/xgb/xproto"
"github.com/jezek/xgbutil"
"github.com/jezek/xgbutil/xevent"
"github.com/jezek/xgbutil/xprop"
)
// ClientEvent is a convenience function that sends ClientMessage events
// to the root window as specified by the EWMH spec.
func ClientEvent(xu *xgbutil.XUtil, window xproto.Window, messageType string,
data ...interface{}) error {
mstype, err := xprop.Atm(xu, messageType)
if err != nil {
return err
}
evMask := (xproto.EventMaskSubstructureNotify |
xproto.EventMaskSubstructureRedirect)
cm, err := xevent.NewClientMessage(32, window, mstype, data...)
if err != nil {
return err
}
return xevent.SendRootEvent(xu, cm, uint32(evMask))
}
// _NET_ACTIVE_WINDOW get
func ActiveWindowGet(xu *xgbutil.XUtil) (xproto.Window, error) {
return xprop.PropValWindow(xprop.GetProperty(xu, xu.RootWin(),
"_NET_ACTIVE_WINDOW"))
}
// _NET_ACTIVE_WINDOW set
func ActiveWindowSet(xu *xgbutil.XUtil, win xproto.Window) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_ACTIVE_WINDOW", "WINDOW",
uint(win))
}
// _NET_ACTIVE_WINDOW req
func ActiveWindowReq(xu *xgbutil.XUtil, win xproto.Window) error {
return ActiveWindowReqExtra(xu, win, 2, 0, 0)
}
// _NET_ACTIVE_WINDOW req extra
func ActiveWindowReqExtra(xu *xgbutil.XUtil, win xproto.Window, source int,
time xproto.Timestamp, currentActive xproto.Window) error {
return ClientEvent(xu, win, "_NET_ACTIVE_WINDOW", source, int(time),
int(currentActive))
}
// _NET_CLIENT_LIST get
func ClientListGet(xu *xgbutil.XUtil) ([]xproto.Window, error) {
return xprop.PropValWindows(xprop.GetProperty(xu, xu.RootWin(),
"_NET_CLIENT_LIST"))
}
// _NET_CLIENT_LIST set
func ClientListSet(xu *xgbutil.XUtil, wins []xproto.Window) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_CLIENT_LIST", "WINDOW",
xprop.WindowToInt(wins)...)
}
// _NET_CLIENT_LIST_STACKING get
func ClientListStackingGet(xu *xgbutil.XUtil) ([]xproto.Window, error) {
return xprop.PropValWindows(xprop.GetProperty(xu, xu.RootWin(),
"_NET_CLIENT_LIST_STACKING"))
}
// _NET_CLIENT_LIST_STACKING set
func ClientListStackingSet(xu *xgbutil.XUtil, wins []xproto.Window) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_CLIENT_LIST_STACKING",
"WINDOW", xprop.WindowToInt(wins)...)
}
// _NET_CLOSE_WINDOW req
func CloseWindow(xu *xgbutil.XUtil, win xproto.Window) error {
return CloseWindowExtra(xu, win, 0, 2)
}
// _NET_CLOSE_WINDOW req extra
func CloseWindowExtra(xu *xgbutil.XUtil, win xproto.Window,
time xproto.Timestamp, source int) error {
return ClientEvent(xu, win, "_NET_CLOSE_WINDOW", int(time), source)
}
// _NET_CURRENT_DESKTOP get
func CurrentDesktopGet(xu *xgbutil.XUtil) (uint, error) {
return xprop.PropValNum(xprop.GetProperty(xu, xu.RootWin(),
"_NET_CURRENT_DESKTOP"))
}
// _NET_CURRENT_DESKTOP set
func CurrentDesktopSet(xu *xgbutil.XUtil, desk uint) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_CURRENT_DESKTOP",
"CARDINAL", desk)
}
// _NET_CURRENT_DESKTOP req
func CurrentDesktopReq(xu *xgbutil.XUtil, desk int) error {
return CurrentDesktopReqExtra(xu, desk, 0)
}
// _NET_CURRENT_DESKTOP req extra
func CurrentDesktopReqExtra(xu *xgbutil.XUtil, desk int,
time xproto.Timestamp) error {
return ClientEvent(xu, xu.RootWin(), "_NET_CURRENT_DESKTOP", desk,
int(time))
}
// _NET_DESKTOP_NAMES get
func DesktopNamesGet(xu *xgbutil.XUtil) ([]string, error) {
return xprop.PropValStrs(xprop.GetProperty(xu, xu.RootWin(),
"_NET_DESKTOP_NAMES"))
}
// _NET_DESKTOP_NAMES set
func DesktopNamesSet(xu *xgbutil.XUtil, names []string) error {
nullterm := make([]byte, 0)
for _, name := range names {
nullterm = append(nullterm, name...)
nullterm = append(nullterm, 0)
}
return xprop.ChangeProp(xu, xu.RootWin(), 8, "_NET_DESKTOP_NAMES",
"UTF8_STRING", nullterm)
}
// DesktopGeometry is a struct that houses the width and height of a
// _NET_DESKTOP_GEOMETRY property reply.
type DesktopGeometry struct {
Width int
Height int
}
// _NET_DESKTOP_GEOMETRY get
func DesktopGeometryGet(xu *xgbutil.XUtil) (*DesktopGeometry, error) {
geom, err := xprop.PropValNums(xprop.GetProperty(xu, xu.RootWin(),
"_NET_DESKTOP_GEOMETRY"))
if err != nil {
return nil, err
}
return &DesktopGeometry{Width: int(geom[0]), Height: int(geom[1])}, nil
}
// _NET_DESKTOP_GEOMETRY set
func DesktopGeometrySet(xu *xgbutil.XUtil, dg *DesktopGeometry) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_DESKTOP_GEOMETRY",
"CARDINAL", uint(dg.Width), uint(dg.Height))
}
// _NET_DESKTOP_GEOMETRY req
func DesktopGeometryReq(xu *xgbutil.XUtil, dg *DesktopGeometry) error {
return ClientEvent(xu, xu.RootWin(), "_NET_DESKTOP_GEOMETRY", dg.Width,
dg.Height)
}
// DesktopLayout is a struct that organizes information pertaining to
// the _NET_DESKTOP_LAYOUT property. Namely, the orientation, the number
// of columns, the number of rows, and the starting corner.
type DesktopLayout struct {
Orientation int
Columns int
Rows int
StartingCorner int
}
// _NET_DESKTOP_LAYOUT constants for orientation
const (
OrientHorz = iota
OrientVert
)
// _NET_DESKTOP_LAYOUT constants for starting corner
const (
TopLeft = iota
TopRight
BottomRight
BottomLeft
)
// _NET_DESKTOP_LAYOUT get
func DesktopLayoutGet(xu *xgbutil.XUtil) (dl *DesktopLayout, err error) {
dlraw, err := xprop.PropValNums(xprop.GetProperty(xu, xu.RootWin(),
"_NET_DESKTOP_LAYOUT"))
if err != nil {
return nil, err
}
dl = &DesktopLayout{}
dl.Orientation = int(dlraw[0])
dl.Columns = int(dlraw[1])
dl.Rows = int(dlraw[2])
if len(dlraw) > 3 {
dl.StartingCorner = int(dlraw[3])
} else {
dl.StartingCorner = TopLeft
}
return dl, nil
}
// _NET_DESKTOP_LAYOUT set
func DesktopLayoutSet(xu *xgbutil.XUtil, orientation, columns, rows,
startingCorner uint) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_DESKTOP_LAYOUT",
"CARDINAL", orientation, columns, rows,
startingCorner)
}
// DesktopViewport is a struct that contains a pairing of x,y coordinates
// representing the top-left corner of each desktop. (There will typically
// be one struct here for each desktop in existence.)
type DesktopViewport struct {
X int
Y int
}
// _NET_DESKTOP_VIEWPORT get
func DesktopViewportGet(xu *xgbutil.XUtil) ([]DesktopViewport, error) {
coords, err := xprop.PropValNums(xprop.GetProperty(xu, xu.RootWin(),
"_NET_DESKTOP_VIEWPORT"))
if err != nil {
return nil, err
}
viewports := make([]DesktopViewport, len(coords)/2)
for i, _ := range viewports {
viewports[i] = DesktopViewport{
X: int(coords[i*2]),
Y: int(coords[i*2+1]),
}
}
return viewports, nil
}
// _NET_DESKTOP_VIEWPORT set
func DesktopViewportSet(xu *xgbutil.XUtil, viewports []DesktopViewport) error {
coords := make([]uint, len(viewports)*2)
for i, viewport := range viewports {
coords[i*2] = uint(viewport.X)
coords[i*2+1] = uint(viewport.Y)
}
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_DESKTOP_VIEWPORT",
"CARDINAL", coords...)
}
// _NET_DESKTOP_VIEWPORT req
func DesktopViewportReq(xu *xgbutil.XUtil, x, y int) error {
return ClientEvent(xu, xu.RootWin(), "_NET_DESKTOP_VIEWPORT", x, y)
}
// FrameExtents is a struct that organizes information associated with
// the _NET_FRAME_EXTENTS property. Namely, the left, right, top and bottom
// decoration sizes.
type FrameExtents struct {
Left int
Right int
Top int
Bottom int
}
// _NET_FRAME_EXTENTS get
func FrameExtentsGet(xu *xgbutil.XUtil,
win xproto.Window) (*FrameExtents, error) {
raw, err := xprop.PropValNums(xprop.GetProperty(xu, win,
"_NET_FRAME_EXTENTS"))
if err != nil {
return nil, err
}
return &FrameExtents{
Left: int(raw[0]),
Right: int(raw[1]),
Top: int(raw[2]),
Bottom: int(raw[3]),
}, nil
}
// _NET_FRAME_EXTENTS set
func FrameExtentsSet(xu *xgbutil.XUtil, win xproto.Window,
extents *FrameExtents) error {
raw := make([]uint, 4)
raw[0] = uint(extents.Left)
raw[1] = uint(extents.Right)
raw[2] = uint(extents.Top)
raw[3] = uint(extents.Bottom)
return xprop.ChangeProp32(xu, win, "_NET_FRAME_EXTENTS", "CARDINAL", raw...)
}
// _NET_MOVERESIZE_WINDOW req
// If 'w' or 'h' are 0, then they are not sent.
// If you need to resize a window without moving it, use the ReqExtra variant,
// or Resize.
func MoveresizeWindow(xu *xgbutil.XUtil, win xproto.Window,
x, y, w, h int) error {
return MoveresizeWindowExtra(xu, win, x, y, w, h, xproto.GravityBitForget,
2, true, true)
}
// _NET_MOVERESIZE_WINDOW req resize only
func ResizeWindow(xu *xgbutil.XUtil, win xproto.Window, w, h int) error {
return MoveresizeWindowExtra(xu, win, 0, 0, w, h, xproto.GravityBitForget,
2, false, false)
}
// _NET_MOVERESIZE_WINDOW req move only
func MoveWindow(xu *xgbutil.XUtil, win xproto.Window, x, y int) error {
return MoveresizeWindowExtra(xu, win, x, y, 0, 0, xproto.GravityBitForget,
2, true, true)
}
// _NET_MOVERESIZE_WINDOW req extra
// If 'w' or 'h' are 0, then they are not sent.
// To not set 'x' or 'y', 'usex' or 'usey' need to be set to false.
func MoveresizeWindowExtra(xu *xgbutil.XUtil, win xproto.Window, x, y, w, h,
gravity, source int, usex, usey bool) error {
flags := gravity
flags |= source << 12
if usex {
flags |= 1 << 8
}
if usey {
flags |= 1 << 9
}
if w > 0 {
flags |= 1 << 10
}
if h > 0 {
flags |= 1 << 11
}
return ClientEvent(xu, win, "_NET_MOVERESIZE_WINDOW", flags, x, y, w, h)
}
// _NET_NUMBER_OF_DESKTOPS get
func NumberOfDesktopsGet(xu *xgbutil.XUtil) (uint, error) {
return xprop.PropValNum(xprop.GetProperty(xu, xu.RootWin(),
"_NET_NUMBER_OF_DESKTOPS"))
}
// _NET_NUMBER_OF_DESKTOPS set
func NumberOfDesktopsSet(xu *xgbutil.XUtil, numDesks uint) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_NUMBER_OF_DESKTOPS",
"CARDINAL", numDesks)
}
// _NET_NUMBER_OF_DESKTOPS req
func NumberOfDesktopsReq(xu *xgbutil.XUtil, numDesks int) error {
return ClientEvent(xu, xu.RootWin(), "_NET_NUMBER_OF_DESKTOPS", numDesks)
}
// _NET_REQUEST_FRAME_EXTENTS req
func RequestFrameExtents(xu *xgbutil.XUtil, win xproto.Window) error {
return ClientEvent(xu, win, "_NET_REQUEST_FRAME_EXTENTS")
}
// _NET_RESTACK_WINDOW req
// The shortcut here is to just raise the window to the top of the window stack.
func RestackWindow(xu *xgbutil.XUtil, win xproto.Window) error {
return RestackWindowExtra(xu, win, xproto.StackModeAbove, 0, 2)
}
// _NET_RESTACK_WINDOW req extra
func RestackWindowExtra(xu *xgbutil.XUtil, win xproto.Window, stackMode int,
sibling xproto.Window, source int) error {
return ClientEvent(xu, win, "_NET_RESTACK_WINDOW", source, int(sibling),
stackMode)
}
// _NET_SHOWING_DESKTOP get
func ShowingDesktopGet(xu *xgbutil.XUtil) (bool, error) {
reply, err := xprop.GetProperty(xu, xu.RootWin(), "_NET_SHOWING_DESKTOP")
if err != nil {
return false, err
}
val, err := xprop.PropValNum(reply, nil)
if err != nil {
return false, err
}
return val == 1, nil
}
// _NET_SHOWING_DESKTOP set
func ShowingDesktopSet(xu *xgbutil.XUtil, show bool) error {
var showInt uint
if show {
showInt = 1
} else {
showInt = 0
}
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_SHOWING_DESKTOP",
"CARDINAL", showInt)
}
// _NET_SHOWING_DESKTOP req
func ShowingDesktopReq(xu *xgbutil.XUtil, show bool) error {
var showInt uint
if show {
showInt = 1
} else {
showInt = 0
}
return ClientEvent(xu, xu.RootWin(), "_NET_SHOWING_DESKTOP", showInt)
}
// _NET_SUPPORTED get
func SupportedGet(xu *xgbutil.XUtil) ([]string, error) {
reply, err := xprop.GetProperty(xu, xu.RootWin(), "_NET_SUPPORTED")
return xprop.PropValAtoms(xu, reply, err)
}
// _NET_SUPPORTED set
// This will create any atoms in the argument if they don't already exist.
func SupportedSet(xu *xgbutil.XUtil, atomNames []string) error {
atoms, err := xprop.StrToAtoms(xu, atomNames)
if err != nil {
return err
}
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_SUPPORTED", "ATOM",
atoms...)
}
// _NET_SUPPORTING_WM_CHECK get
func SupportingWmCheckGet(xu *xgbutil.XUtil,
win xproto.Window) (xproto.Window, error) {
return xprop.PropValWindow(xprop.GetProperty(xu, win,
"_NET_SUPPORTING_WM_CHECK"))
}
// _NET_SUPPORTING_WM_CHECK set
func SupportingWmCheckSet(xu *xgbutil.XUtil, win xproto.Window,
wmWin xproto.Window) error {
return xprop.ChangeProp32(xu, win, "_NET_SUPPORTING_WM_CHECK", "WINDOW",
uint(wmWin))
}
// _NET_VIRTUAL_ROOTS get
func VirtualRootsGet(xu *xgbutil.XUtil) ([]xproto.Window, error) {
return xprop.PropValWindows(xprop.GetProperty(xu, xu.RootWin(),
"_NET_VIRTUAL_ROOTS"))
}
// _NET_VIRTUAL_ROOTS set
func VirtualRootsSet(xu *xgbutil.XUtil, wins []xproto.Window) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_VIRTUAL_ROOTS", "WINDOW",
xprop.WindowToInt(wins)...)
}
// _NET_VISIBLE_DESKTOPS get
// This is not part of the EWMH spec, but is a property of my own creation.
// It allows the window manager to report that it has multiple desktops
// viewable at the same time. (This conflicts with other EWMH properties,
// so I don't think this will ever be added to the official spec.)
func VisibleDesktopsGet(xu *xgbutil.XUtil) ([]uint, error) {
return xprop.PropValNums(xprop.GetProperty(xu, xu.RootWin(),
"_NET_VISIBLE_DESKTOPS"))
}
// _NET_VISIBLE_DESKTOPS set
func VisibleDesktopsSet(xu *xgbutil.XUtil, desktops []uint) error {
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_VISIBLE_DESKTOPS",
"CARDINAL", desktops...)
}
// _NET_WM_ALLOWED_ACTIONS get
func WmAllowedActionsGet(xu *xgbutil.XUtil,
win xproto.Window) ([]string, error) {
raw, err := xprop.GetProperty(xu, win, "_NET_WM_ALLOWED_ACTIONS")
return xprop.PropValAtoms(xu, raw, err)
}
// _NET_WM_ALLOWED_ACTIONS set
func WmAllowedActionsSet(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, "_NET_WM_ALLOWED_ACTIONS", "ATOM",
atoms...)
}
// _NET_WM_DESKTOP get
func WmDesktopGet(xu *xgbutil.XUtil, win xproto.Window) (uint, error) {
return xprop.PropValNum(xprop.GetProperty(xu, win, "_NET_WM_DESKTOP"))
}
// _NET_WM_DESKTOP set
func WmDesktopSet(xu *xgbutil.XUtil, win xproto.Window, desk uint) error {
return xprop.ChangeProp32(xu, win, "_NET_WM_DESKTOP", "CARDINAL",
uint(desk))
}
// _NET_WM_DESKTOP req
func WmDesktopReq(xu *xgbutil.XUtil, win xproto.Window, desk uint) error {
return WmDesktopReqExtra(xu, win, desk, 2)
}
// _NET_WM_DESKTOP req extra
func WmDesktopReqExtra(xu *xgbutil.XUtil, win xproto.Window, desk uint,
source int) error {
return ClientEvent(xu, win, "_NET_WM_DESKTOP", desk, source)
}
// WmFullscreenMonitors is a struct that organizes information related to the
// _NET_WM_FULLSCREEN_MONITORS property. Namely, the top, bottom, left and
// right monitor edges for a particular window.
type WmFullscreenMonitors struct {
Top uint
Bottom uint
Left uint
Right uint
}
// _NET_WM_FULLSCREEN_MONITORS get
func WmFullscreenMonitorsGet(xu *xgbutil.XUtil,
win xproto.Window) (*WmFullscreenMonitors, error) {
raw, err := xprop.PropValNums(
xprop.GetProperty(xu, win, "_NET_WM_FULLSCREEN_MONITORS"))
if err != nil {
return nil, err
}
return &WmFullscreenMonitors{
Top: raw[0],
Bottom: raw[1],
Left: raw[2],
Right: raw[3],
}, nil
}
// _NET_WM_FULLSCREEN_MONITORS set
func WmFullscreenMonitorsSet(xu *xgbutil.XUtil, win xproto.Window,
edges *WmFullscreenMonitors) error {
raw := make([]uint, 4)
raw[0] = edges.Top
raw[1] = edges.Bottom
raw[2] = edges.Left
raw[3] = edges.Right
return xprop.ChangeProp32(xu, win, "_NET_WM_FULLSCREEN_MONITORS",
"CARDINAL", raw...)
}
// _NET_WM_FULLSCREEN_MONITORS req
func WmFullscreenMonitorsReq(xu *xgbutil.XUtil, win xproto.Window,
edges *WmFullscreenMonitors) error {
return WmFullscreenMonitorsReqExtra(xu, win, edges, 2)
}
// _NET_WM_FULLSCREEN_MONITORS req extra
func WmFullscreenMonitorsReqExtra(xu *xgbutil.XUtil, win xproto.Window,
edges *WmFullscreenMonitors, source int) error {
return ClientEvent(xu, win, "_NET_WM_FULLSCREEN_MONITORS",
edges.Top, edges.Bottom, edges.Left, edges.Right, source)
}
// _NET_WM_HANDLED_ICONS get
func WmHandledIconsGet(xu *xgbutil.XUtil, win xproto.Window) (bool, error) {
reply, err := xprop.GetProperty(xu, win, "_NET_WM_HANDLED_ICONS")
if err != nil {
return false, err
}
val, err := xprop.PropValNum(reply, nil)
if err != nil {
return false, err
}
return val == 1, nil
}
// _NET_WM_HANDLED_ICONS set
func WmHandledIconsSet(xu *xgbutil.XUtil, handle bool) error {
var handled uint
if handle {
handled = 1
} else {
handled = 0
}
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_WM_HANDLED_ICONS",
"CARDINAL", handled)
}
// WmIcon is a struct that contains data for a single icon.
// The WmIcon method will return a list of these, since a single
// client can specify multiple icons of varying sizes.
type WmIcon struct {
Width uint
Height uint
Data []uint
}
// _NET_WM_ICON get
func WmIconGet(xu *xgbutil.XUtil, win xproto.Window) ([]WmIcon, error) {
icon, err := xprop.PropValNums(xprop.GetProperty(xu, win, "_NET_WM_ICON"))
if err != nil {
return nil, err
}
wmicons := make([]WmIcon, 0)
start := uint(0)
for int(start) < len(icon) {
w, h := icon[start], icon[start+1]
upto := w * h
wmicon := WmIcon{
Width: w,
Height: h,
Data: icon[(start + 2):(start + upto + 2)],
}
wmicons = append(wmicons, wmicon)
start += upto + 2
}
return wmicons, nil
}
// _NET_WM_ICON set
func WmIconSet(xu *xgbutil.XUtil, win xproto.Window, icons []WmIcon) error {
raw := make([]uint, 0, 10000) // start big
for _, icon := range icons {
raw = append(raw, icon.Width, icon.Height)
raw = append(raw, icon.Data...)
}
return xprop.ChangeProp32(xu, win, "_NET_WM_ICON", "CARDINAL", raw...)
}
// WmIconGeometry struct organizes the information pertaining to the
// _NET_WM_ICON_GEOMETRY property. Namely, x, y, width and height.
type WmIconGeometry struct {
X int
Y int
Width uint
Height uint
}
// _NET_WM_ICON_GEOMETRY get
func WmIconGeometryGet(xu *xgbutil.XUtil,
win xproto.Window) (*WmIconGeometry, error) {
geom, err := xprop.PropValNums(xprop.GetProperty(xu, win,
"_NET_WM_ICON_GEOMETRY"))
if err != nil {
return nil, err
}
return &WmIconGeometry{
X: int(geom[0]),
Y: int(geom[1]),
Width: geom[2],
Height: geom[3],
}, nil
}
// _NET_WM_ICON_GEOMETRY set
func WmIconGeometrySet(xu *xgbutil.XUtil, win xproto.Window,
geom *WmIconGeometry) error {
rawGeom := make([]uint, 4)
rawGeom[0] = uint(geom.X)
rawGeom[1] = uint(geom.Y)
rawGeom[2] = geom.Width
rawGeom[3] = geom.Height
return xprop.ChangeProp32(xu, win, "_NET_WM_ICON_GEOMETRY", "CARDINAL",
rawGeom...)
}
// _NET_WM_ICON_NAME get
func WmIconNameGet(xu *xgbutil.XUtil, win xproto.Window) (string, error) {
return xprop.PropValStr(xprop.GetProperty(xu, win, "_NET_WM_ICON_NAME"))
}
// _NET_WM_ICON_NAME set
func WmIconNameSet(xu *xgbutil.XUtil, win xproto.Window, name string) error {
return xprop.ChangeProp(xu, win, 8, "_NET_WM_ICON_NAME", "UTF8_STRING",
[]byte(name))
}
// _NET_WM_MOVERESIZE constants
const (
SizeTopLeft = iota
SizeTop
SizeTopRight
SizeRight
SizeBottomRight
SizeBottom
SizeBottomLeft
SizeLeft
Move
SizeKeyboard
MoveKeyboard
Cancel
Infer // special for Wingo. DO NOT USE.
)
// _NET_WM_MOVERESIZE req
func WmMoveresize(xu *xgbutil.XUtil, win xproto.Window, direction int) error {
return WmMoveresizeExtra(xu, win, direction, 0, 0, 0, 2)
}
// _NET_WM_MOVERESIZE req extra
func WmMoveresizeExtra(xu *xgbutil.XUtil, win xproto.Window, direction,
xRoot, yRoot, button, source int) error {
return ClientEvent(xu, win, "_NET_WM_MOVERESIZE",
xRoot, yRoot, direction, button, source)
}
// _NET_WM_NAME get
func WmNameGet(xu *xgbutil.XUtil, win xproto.Window) (string, error) {
return xprop.PropValStr(xprop.GetProperty(xu, win, "_NET_WM_NAME"))
}
// _NET_WM_NAME set
func WmNameSet(xu *xgbutil.XUtil, win xproto.Window, name string) error {
return xprop.ChangeProp(xu, win, 8, "_NET_WM_NAME", "UTF8_STRING",
[]byte(name))
}
// WmOpaqueRegion organizes information related to the _NET_WM_OPAQUE_REGION
// property. Namely, the x, y, width and height of an opaque rectangle
// relative to the client window.
type WmOpaqueRegion struct {
X int
Y int
Width uint
Height uint
}
// _NET_WM_OPAQUE_REGION get
func WmOpaqueRegionGet(xu *xgbutil.XUtil,
win xproto.Window) ([]WmOpaqueRegion, error) {
raw, err := xprop.PropValNums(xprop.GetProperty(xu, win,
"_NET_WM_OPAQUE_REGION"))
if err != nil {
return nil, err
}
regions := make([]WmOpaqueRegion, len(raw)/4)
for i, _ := range regions {
regions[i] = WmOpaqueRegion{
X: int(raw[i*4+0]),
Y: int(raw[i*4+1]),
Width: raw[i*4+2],
Height: raw[i*4+3],
}
}
return regions, nil
}
// _NET_WM_OPAQUE_REGION set
func WmOpaqueRegionSet(xu *xgbutil.XUtil, win xproto.Window,
regions []WmOpaqueRegion) error {
raw := make([]uint, len(regions)*4)
for i, region := range regions {
raw[i*4+0] = uint(region.X)
raw[i*4+1] = uint(region.Y)
raw[i*4+2] = region.Width
raw[i*4+3] = region.Height
}
return xprop.ChangeProp32(xu, win, "_NET_WM_OPAQUE_REGION", "CARDINAL",
raw...)
}
// _NET_WM_PID get
func WmPidGet(xu *xgbutil.XUtil, win xproto.Window) (uint, error) {
return xprop.PropValNum(xprop.GetProperty(xu, win, "_NET_WM_PID"))
}
// _NET_WM_PID set
func WmPidSet(xu *xgbutil.XUtil, win xproto.Window, pid uint) error {
return xprop.ChangeProp32(xu, win, "_NET_WM_PID", "CARDINAL", pid)
}
// _NET_WM_PING req
func WmPing(xu *xgbutil.XUtil, win xproto.Window, response bool) error {
return WmPingExtra(xu, win, response, 0)
}
// _NET_WM_PING req extra
func WmPingExtra(xu *xgbutil.XUtil, win xproto.Window, response bool,
time xproto.Timestamp) error {
pingAtom, err := xprop.Atm(xu, "_NET_WM_PING")
if err != nil {
return err
}
var evWindow xproto.Window
if response {
evWindow = xu.RootWin()
} else {
evWindow = win
}
return ClientEvent(xu, evWindow, "WM_PROTOCOLS", int(pingAtom), int(time),
int(win))
}
// _NET_WM_STATE constants for state toggling
// These correspond to the "action" parameter.
const (
StateRemove = iota
StateAdd
StateToggle
)
// _NET_WM_STATE get
func WmStateGet(xu *xgbutil.XUtil, win xproto.Window) ([]string, error) {
raw, err := xprop.GetProperty(xu, win, "_NET_WM_STATE")
return xprop.PropValAtoms(xu, raw, err)
}
// _NET_WM_STATE set
func WmStateSet(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, "_NET_WM_STATE", "ATOM", atoms...)
}
// _NET_WM_STATE req
func WmStateReq(xu *xgbutil.XUtil, win xproto.Window, action int,
atomName string) error {
return WmStateReqExtra(xu, win, action, atomName, "", 2)
}
// _NET_WM_STATE req extra
func WmStateReqExtra(xu *xgbutil.XUtil, win xproto.Window, action int,
first string, second string, source int) (err error) {
var atom1, atom2 xproto.Atom
atom1, err = xprop.Atom(xu, first, false)
if err != nil {
return err
}
if len(second) > 0 {
atom2, err = xprop.Atom(xu, second, false)
if err != nil {
return err
}
} else {
atom2 = 0
}
return ClientEvent(xu, win, "_NET_WM_STATE", action, int(atom1), int(atom2),
source)
}
// WmStrut struct organizes information for the _NET_WM_STRUT property.
// Namely, it encapsulates its four values: left, right, top and bottom.
type WmStrut struct {
Left uint
Right uint
Top uint
Bottom uint
}
// _NET_WM_STRUT get
func WmStrutGet(xu *xgbutil.XUtil, win xproto.Window) (*WmStrut, error) {
struts, err := xprop.PropValNums(xprop.GetProperty(xu, win,
"_NET_WM_STRUT"))
if err != nil {
return nil, err
}
return &WmStrut{
Left: struts[0],
Right: struts[1],
Top: struts[2],
Bottom: struts[3],
}, nil
}
// _NET_WM_STRUT set
func WmStrutSet(xu *xgbutil.XUtil, win xproto.Window, struts *WmStrut) error {
rawStruts := make([]uint, 4)
rawStruts[0] = struts.Left
rawStruts[1] = struts.Right
rawStruts[2] = struts.Top
rawStruts[3] = struts.Bottom
return xprop.ChangeProp32(xu, win, "_NET_WM_STRUT", "CARDINAL",
rawStruts...)
}
// WmStrutPartial struct organizes information for the _NET_WM_STRUT_PARTIAL
// property. Namely, it encapsulates its twelve values: left, right, top,
// bottom, left_start_y, left_end_y, right_start_y, right_end_y,
// top_start_x, top_end_x, bottom_start_x, and bottom_end_x.
type WmStrutPartial struct {
Left, Right, Top, Bottom uint
LeftStartY, LeftEndY, RightStartY, RightEndY uint
TopStartX, TopEndX, BottomStartX, BottomEndX uint
}
// _NET_WM_STRUT_PARTIAL get
func WmStrutPartialGet(xu *xgbutil.XUtil,
win xproto.Window) (*WmStrutPartial, error) {
struts, err := xprop.PropValNums(xprop.GetProperty(xu, win,
"_NET_WM_STRUT_PARTIAL"))
if err != nil {
return nil, err
}
return &WmStrutPartial{
Left: struts[0], Right: struts[1], Top: struts[2], Bottom: struts[3],
LeftStartY: struts[4], LeftEndY: struts[5],
RightStartY: struts[6], RightEndY: struts[7],
TopStartX: struts[8], TopEndX: struts[9],
BottomStartX: struts[10], BottomEndX: struts[11],
}, nil
}
// _NET_WM_STRUT_PARTIAL set
func WmStrutPartialSet(xu *xgbutil.XUtil, win xproto.Window,
struts *WmStrutPartial) error {
rawStruts := make([]uint, 12)
rawStruts[0] = struts.Left
rawStruts[1] = struts.Right
rawStruts[2] = struts.Top
rawStruts[3] = struts.Bottom
rawStruts[4] = struts.LeftStartY
rawStruts[5] = struts.LeftEndY
rawStruts[6] = struts.RightStartY
rawStruts[7] = struts.RightEndY
rawStruts[8] = struts.TopStartX
rawStruts[9] = struts.TopEndX
rawStruts[10] = struts.BottomStartX
rawStruts[11] = struts.BottomEndX
return xprop.ChangeProp32(xu, win, "_NET_WM_STRUT_PARTIAL", "CARDINAL",
rawStruts...)
}
// _NET_WM_SYNC_REQUEST req
func WmSyncRequest(xu *xgbutil.XUtil, win xproto.Window, req_num uint64) error {
return WmSyncRequestExtra(xu, win, req_num, 0)
}
// _NET_WM_SYNC_REQUEST req extra
func WmSyncRequestExtra(xu *xgbutil.XUtil, win xproto.Window, reqNum uint64,
time xproto.Timestamp) error {
syncReq, err := xprop.Atm(xu, "_NET_WM_SYNC_REQUEST")
if err != nil {
return err
}
high := int(reqNum >> 32)
low := int(reqNum<<32 ^ reqNum)
return ClientEvent(xu, win, "WM_PROTOCOLS", int(syncReq), int(time),
low, high)
}
// _NET_WM_SYNC_REQUEST_COUNTER get
// I'm pretty sure this needs 64 bit integers, but I'm not quite sure
// how to go about that yet. Any ideas?
func WmSyncRequestCounter(xu *xgbutil.XUtil, win xproto.Window) (uint, error) {
return xprop.PropValNum(xprop.GetProperty(xu, win,
"_NET_WM_SYNC_REQUEST_COUNTER"))
}
// _NET_WM_SYNC_REQUEST_COUNTER set
// I'm pretty sure this needs 64 bit integers, but I'm not quite sure
// how to go about that yet. Any ideas?
func WmSyncRequestCounterSet(xu *xgbutil.XUtil, win xproto.Window,
counter uint) error {
return xprop.ChangeProp32(xu, win, "_NET_WM_SYNC_REQUEST_COUNTER",
"CARDINAL", counter)
}
// _NET_WM_USER_TIME get
func WmUserTimeGet(xu *xgbutil.XUtil, win xproto.Window) (uint, error) {
return xprop.PropValNum(xprop.GetProperty(xu, win, "_NET_WM_USER_TIME"))
}
// _NET_WM_USER_TIME set
func WmUserTimeSet(xu *xgbutil.XUtil, win xproto.Window, userTime uint) error {
return xprop.ChangeProp32(xu, win, "_NET_WM_USER_TIME", "CARDINAL",
userTime)
}
// _NET_WM_USER_TIME_WINDOW get
func WmUserTimeWindowGet(xu *xgbutil.XUtil,
win xproto.Window) (xproto.Window, error) {
return xprop.PropValWindow(xprop.GetProperty(xu, win,
"_NET_WM_USER_TIME_WINDOW"))
}
// _NET_WM_USER_TIME set
func WmUserTimeWindowSet(xu *xgbutil.XUtil, win xproto.Window,
timeWin xproto.Window) error {
return xprop.ChangeProp32(xu, win, "_NET_WM_USER_TIME_WINDOW", "CARDINAL",
uint(timeWin))
}
// _NET_WM_VISIBLE_ICON_NAME get
func WmVisibleIconNameGet(xu *xgbutil.XUtil,
win xproto.Window) (string, error) {
return xprop.PropValStr(xprop.GetProperty(xu, win,
"_NET_WM_VISIBLE_ICON_NAME"))
}
// _NET_WM_VISIBLE_ICON_NAME set
func WmVisibleIconNameSet(xu *xgbutil.XUtil, win xproto.Window,
name string) error {
return xprop.ChangeProp(xu, win, 8, "_NET_WM_VISIBLE_ICON_NAME",
"UTF8_STRING", []byte(name))
}
// _NET_WM_VISIBLE_NAME get
func WmVisibleNameGet(xu *xgbutil.XUtil, win xproto.Window) (string, error) {
return xprop.PropValStr(xprop.GetProperty(xu, win, "_NET_WM_VISIBLE_NAME"))
}
// _NET_WM_VISIBLE_NAME set
func WmVisibleNameSet(xu *xgbutil.XUtil, win xproto.Window, name string) error {
return xprop.ChangeProp(xu, win, 8, "_NET_WM_VISIBLE_NAME", "UTF8_STRING",
[]byte(name))
}
// _NET_WM_WINDOW_OPACITY get
// This isn't part of the EWMH spec, but is widely used by drop in
// compositing managers (i.e., xcompmgr, cairo-compmgr, etc.).
// This property is typically set not on a client window, but the *parent*
// of a client window in reparenting window managers.
// The float returned will be in the range [0.0, 1.0] where 0.0 is completely
// transparent and 1.0 is completely opaque.
func WmWindowOpacityGet(xu *xgbutil.XUtil, win xproto.Window) (float64, error) {
intOpacity, err := xprop.PropValNum(
xprop.GetProperty(xu, win, "_NET_WM_WINDOW_OPACITY"))
if err != nil {
return 0, err
}
return float64(uint(intOpacity)) / float64(0xffffffff), nil
}
// _NET_WM_WINDOW_OPACITY set
func WmWindowOpacitySet(xu *xgbutil.XUtil, win xproto.Window,
opacity float64) error {
return xprop.ChangeProp32(xu, win, "_NET_WM_WINDOW_OPACITY", "CARDINAL",
uint(opacity*0xffffffff))
}
// _NET_WM_WINDOW_TYPE get
func WmWindowTypeGet(xu *xgbutil.XUtil, win xproto.Window) ([]string, error) {
raw, err := xprop.GetProperty(xu, win, "_NET_WM_WINDOW_TYPE")
return xprop.PropValAtoms(xu, raw, err)
}
// _NET_WM_WINDOW_TYPE set
// This will create any atoms used in 'atomNames' if they don't already exist.
func WmWindowTypeSet(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, "_NET_WM_WINDOW_TYPE", "ATOM", atoms...)
}
// Workarea is a struct that represents a rectangle as a bounding box of
// a single desktop. So there should be as many Workarea structs as there
// are desktops.
type Workarea struct {
X int
Y int
Width uint
Height uint
}
// _NET_WORKAREA get
func WorkareaGet(xu *xgbutil.XUtil) ([]Workarea, error) {
rects, err := xprop.PropValNums(xprop.GetProperty(xu, xu.RootWin(),
"_NET_WORKAREA"))
if err != nil {
return nil, err
}
workareas := make([]Workarea, len(rects)/4)
for i, _ := range workareas {
workareas[i] = Workarea{
X: int(rects[i*4]),
Y: int(rects[i*4+1]),
Width: rects[i*4+2],
Height: rects[i*4+3],
}
}
return workareas, nil
}
// _NET_WORKAREA set
func WorkareaSet(xu *xgbutil.XUtil, workareas []Workarea) error {
rects := make([]uint, len(workareas)*4)
for i, workarea := range workareas {
rects[i*4+0] = uint(workarea.X)
rects[i*4+1] = uint(workarea.Y)
rects[i*4+2] = workarea.Width
rects[i*4+3] = workarea.Height
}
return xprop.ChangeProp32(xu, xu.RootWin(), "_NET_WORKAREA", "CARDINAL",
rects...)
}