func (c *Client) Close() { if strIndex("WM_DELETE_WINDOW", c.protocols) > -1 { wm_protocols, err := xprop.Atm(wm.X, "WM_PROTOCOLS") if err != nil { logger.Warning.Println(err) return } wm_del_win, err := xprop.Atm(wm.X, "WM_DELETE_WINDOW") if err != nil { logger.Warning.Println(err) return } cm, err := xevent.NewClientMessage(32, c.Id(), wm_protocols, int(wm_del_win)) if err != nil { logger.Warning.Println(err) return } err = xproto.SendEventChecked(wm.X.Conn(), false, c.Id(), 0, string(cm.Bytes())).Check() if err != nil { logger.Message.Printf("Could not send WM_DELETE_WINDOW "+ "ClientMessage because: %s", err) } } else { c.win.Kill() // HULK SMASH! } }
func Focus(c Client) { Remove(c) if c.CanFocus() || c.SendFocusNotify() { Clients = append(Clients, c) c.PrepareForFocus() c.Focused() } if c.CanFocus() { c.Win().Focus() } if c.SendFocusNotify() { protsAtm, err := xprop.Atm(X, "WM_PROTOCOLS") if err != nil { logger.Warning.Println(err) return } takeFocusAtm, err := xprop.Atm(X, "WM_TAKE_FOCUS") if err != nil { logger.Warning.Println(err) return } cm, err := xevent.NewClientMessage(32, c.Id(), protsAtm, int(takeFocusAtm), int(X.TimeGet())) if err != nil { logger.Warning.Println(err) return } xproto.SendEvent(X.Conn(), false, c.Id(), 0, string(cm.Bytes())) } }
// currentTime forcefully causes a PropertyNotify event to fire on the root // window, then scans the event queue and picks up the time. // // It is NOT SAFE to call this function in a place other than Wingo's // initialization. Namely, this function subverts xevent's queue and reads // events directly from X. func currentTime(X *xgbutil.XUtil) (xproto.Timestamp, error) { wmClassAtom, err := xprop.Atm(X, "WM_CLASS") if err != nil { return 0, err } stringAtom, err := xprop.Atm(X, "STRING") if err != nil { return 0, err } // Make sure we're listening to PropertyChange events on the root window. err = xwindow.New(X, X.RootWin()).Listen(xproto.EventMaskPropertyChange) if err != nil { return 0, fmt.Errorf( "Could not listen to Root window events (PropertyChange): %s", err) } // Do a zero-length append on a property as suggested by ICCCM 2.1. err = xproto.ChangePropertyChecked( X.Conn(), xproto.PropModeAppend, X.RootWin(), wmClassAtom, stringAtom, 8, 0, nil).Check() if err != nil { return 0, err } // Now look for the PropertyNotify generated by that zero-length append // and return the timestamp attached to that event. // Note that we do this outside of xgbutil/xevent, since ownership // is literally the first thing we do after connecting to X. // (i.e., we don't have our event handling system initialized yet.) timeout := time.After(3 * time.Second) for { select { case <-timeout: return 0, fmt.Errorf( "Expected a PropertyNotify event to get a valid timestamp, " + "but never received one.") default: ev, err := X.Conn().PollForEvent() if err != nil { continue } if propNotify, ok := ev.(xproto.PropertyNotifyEvent); ok { X.TimeSet(propNotify.Time) // why not? return propNotify.Time, nil } time.Sleep(100 * time.Millisecond) } } panic("unreachable") }
func (m *TrayManager) RequireManageTrayIcons() { mstype, err := xprop.Atm(TrayXU, "MANAGER") if err != nil { logger.Warning("Get MANAGER Failed") return } timeStamp, _ := ewmh.WmUserTimeGet(TrayXU, m.owner) cm, err := xevent.NewClientMessage( 32, TrayXU.RootWin(), mstype, int(timeStamp), int(_NET_SYSTEM_TRAY_S0), int(m.owner), ) if err != nil { logger.Warning("Send MANAGER Request failed:", err) return } // !!! ewmh.ClientEvent not use EventMaskStructureNotify. xevent.SendRootEvent(TrayXU, cm, uint32(xproto.EventMaskStructureNotify)) }
func newFullScreenWorkaround() *fullScreenWorkaround { XU, _ := xgbutil.NewConn() ACTIVE_WINDOW, _ := xprop.Atm(XU, "_NET_ACTIVE_WINDOW") w := &fullScreenWorkaround{ XU, []string{"libflash", "chrome", "mplayer", "operaplugin", "soffice", "wpp", "evince", "vlc", "totem"}, ACTIVE_WINDOW, false, } return w }
// _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) }
// announce sends a ClientMessage event to the root window to let everyone // know that Wingo is the boss. (As per ICCCM 2.8.) func announce(X *xgbutil.XUtil) { typAtom, err := xprop.Atm(X, "MANAGER") if err != nil { logger.Warning.Println(err) return } manSelAtom, err := managerAtom(X) if err != nil { logger.Warning.Println(err) return } cm, err := xevent.NewClientMessage(32, X.RootWin(), typAtom, int(X.TimeGet()), int(manSelAtom), int(X.Dummy())) xproto.SendEvent(X.Conn(), false, X.RootWin(), xproto.EventMaskStructureNotify, string(cm.Bytes())) }
// 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_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)) }
// managerAtom returns an xproto.Atom of the manager selection atom. // Usually it's "WM_S0", where "0" is the screen number. func managerAtom(X *xgbutil.XUtil) (xproto.Atom, error) { name := fmt.Sprintf("WM_S%d", X.Conn().DefaultScreen) return xprop.Atm(X, name) }
func initAtom() { _NET_SHOWING_DESKTOP, _ = xprop.Atm(XU, "_NET_SHOWING_DESKTOP") DEEPIN_SCREEN_VIEWPORT, _ = xprop.Atm(XU, "DEEPIN_SCREEN_VIEWPORT") _NET_CLIENT_LIST, _ = xprop.Atm(XU, "_NET_CLIENT_LIST") _NET_ACTIVE_WINDOW, _ = xprop.Atm(XU, "_NET_ACTIVE_WINDOW") ATOM_WINDOW_ICON, _ = xprop.Atm(XU, "_NET_WM_ICON") ATOM_WINDOW_NAME, _ = xprop.Atm(XU, "_NET_WM_NAME") ATOM_WINDOW_STATE, _ = xprop.Atm(XU, "_NET_WM_STATE") ATOM_WINDOW_TYPE, _ = xprop.Atm(XU, "_NET_WM_WINDOW_TYPE") ATOM_DOCK_APP_ID, _ = xprop.Atm(XU, "_DDE_DOCK_APP_ID") _NET_SYSTEM_TRAY_S0, _ = xprop.Atm(TrayXU, "_NET_SYSTEM_TRAY_S0") _NET_SYSTEM_TRAY_OPCODE, _ = xprop.Atm(TrayXU, "_NET_SYSTEM_TRAY_OPCODE") }