1160 lines
30 KiB
Go
1160 lines
30 KiB
Go
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...)
|
|
}
|