// create creates the window, initializes the keybind and mousebind packages // and sets up the window to act like a real top-level client. func (w *window) create() { keybind.Initialize(w.X) mousebind.Initialize(w.X) err := w.CreateChecked(w.X.RootWin(), 0, 0, flagWidth, flagHeight, xproto.CwBackPixel, 0xffffff) if err != nil { errLg.Fatalf("Could not create window: %s", err) } // Make the window close gracefully using the WM_DELETE_WINDOW protocol. w.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(w.X) }) // Set WM_STATE so it is interpreted as top-level and is mapped. err = icccm.WmStateSet(w.X, w.Id, &icccm.WmState{ State: icccm.StateNormal, }) if err != nil { // not a fatal error lg("Could not set WM_STATE: %s", err) } // _NET_WM_STATE = _NET_WM_STATE_NORMAL ewmh.WmStateSet(w.X, w.Id, []string{"_NET_WM_STATE_NORMAL"}) // Set the name to something. w.nameSet("Decoding all images...") w.Map() }
func (app *RuntimeApp) Activate(x, y int32) error { //TODO: handle multiple xids switch { case !contains(app.state, "_NET_WM_STATE_FOCUSED"): activateWindow(app.CurrentInfo.Xid) case contains(app.state, "_NET_WM_STATE_FOCUSED"): s, err := icccm.WmStateGet(XU, app.CurrentInfo.Xid) if err != nil { logger.Info("WmStateGetError:", s, err) return err } switch s.State { case icccm.StateIconic: s.State = icccm.StateNormal icccm.WmStateSet(XU, app.CurrentInfo.Xid, s) case icccm.StateNormal: activeXid, _ := ewmh.ActiveWindowGet(XU) logger.Debugf("%s, 0x%x(c), 0x%x(a), %v", app.Id, app.CurrentInfo.Xid, activeXid, app.state) if len(app.xids) == 1 { s.State = icccm.StateIconic iconifyWindow(app.CurrentInfo.Xid) } else { logger.Warningf("activeXid is 0x%x, current is 0x%x", activeXid, app.CurrentInfo.Xid) if activeXid == app.CurrentInfo.Xid { x := app.findNextLeader() ewmh.ActiveWindowReq(XU, x) } } } } return nil }
func (c *Client) unmanage() { wm.X.Grab() defer wm.X.Ungrab() go func() { c.frames.destroy() c.prompts.destroy() }() logger.Message.Printf("Unmanaging client: %s", c) c.frame.Unmap() c.win.Detach() icccm.WmStateSet(wm.X, c.Id(), &icccm.WmState{State: icccm.StateWithdrawn}) focus.Remove(c) wm.FocusFallback() stack.Remove(c) c.workspace.Remove(c) wm.RemoveClient(c) c.attnStop() xproto.ChangeSaveSetChecked( wm.X.Conn(), xproto.SetModeDelete, c.Id()).Check() if c.hadStruts { wm.Heads.ApplyStruts(wm.Clients) } }
func (c *Client) Map() { if c.IsMapped() { return } c.win.Map() c.frame.Map() icccm.WmStateSet(wm.X, c.Id(), &icccm.WmState{State: icccm.StateNormal}) }
func (c *Client) Unmap() { if !c.IsMapped() { return } c.unmapIgnore++ c.frame.Unmap() c.win.Unmap() icccm.WmStateSet(wm.X, c.Id(), &icccm.WmState{State: icccm.StateIconic}) }
func main() { X, _ := xgbutil.NewConn() active, err := ewmh.ActiveWindowGet(X) wmName, err := icccm.WmNameGet(X, active) showTest("WM_NAME get", wmName, err) err = icccm.WmNameSet(X, active, "hooblah") wmName, _ = icccm.WmNameGet(X, active) showTest("WM_NAME set", wmName, err) wmNormHints, err := icccm.WmNormalHintsGet(X, active) showTest("WM_NORMAL_HINTS get", wmNormHints, err) wmNormHints.Width += 5 err = icccm.WmNormalHintsSet(X, active, wmNormHints) showTest("WM_NORMAL_HINTS set", wmNormHints, err) wmHints, err := icccm.WmHintsGet(X, active) showTest("WM_HINTS get", wmHints, err) wmHints.InitialState = icccm.StateNormal err = icccm.WmHintsSet(X, active, wmHints) showTest("WM_NORMAL_HINTS set", wmHints, err) wmClass, err := icccm.WmClassGet(X, active) showTest("WM_CLASS get", wmClass, err) wmClass.Instance = "hoopdy hoop" err = icccm.WmClassSet(X, active, wmClass) showTest("WM_CLASS set", wmClass, err) wmTrans, err := icccm.WmTransientForGet(X, active) showTest("WM_TRANSIENT_FOR get", wmTrans, err) wmProts, err := icccm.WmProtocolsGet(X, active) showTest("WM_PROTOCOLS get", wmProts, err) wmClient, err := icccm.WmClientMachineGet(X, active) showTest("WM_CLIENT_MACHINE get", wmClient, err) err = icccm.WmClientMachineSet(X, active, "Leopard") wmClient, _ = icccm.WmClientMachineGet(X, active) showTest("WM_CLIENT_MACHINE set", wmClient, err) wmState, err := icccm.WmStateGet(X, active) showTest("WM_STATE get", wmState, err) wmState.Icon = xproto.Window(8365538) wmState.State = icccm.StateNormal err = icccm.WmStateSet(X, active, wmState) wmState, _ = icccm.WmStateGet(X, active) showTest("WM_STATE set", wmState, err) }
// This is a slightly modified version of xgraphics.XShowExtra that does // not set any resize constraints on the window (so that it can go // fullscreen). func showImage(im *xgraphics.Image, name string, quit bool) *xwindow.Window { if len(name) == 0 { name = "xgbutil Image Window" } w, h := im.Rect.Dx(), im.Rect.Dy() win, err := xwindow.Generate(im.X) if err != nil { xgbutil.Logger.Printf("Could not generate new window id: %s", err) return nil } // Create a very simple window with dimensions equal to the image. win.Create(im.X.RootWin(), 0, 0, w, h, 0) // Make this window close gracefully. win.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() if quit { xevent.Quit(w.X) } }) // Set WM_STATE so it is interpreted as a top-level window. err = icccm.WmStateSet(im.X, win.Id, &icccm.WmState{ State: icccm.StateNormal, }) if err != nil { // not a fatal error xgbutil.Logger.Printf("Could not set WM_STATE: %s", err) } // Set _NET_WM_NAME so it looks nice. err = ewmh.WmNameSet(im.X, win.Id, name) if err != nil { // not a fatal error xgbutil.Logger.Printf("Could not set _NET_WM_NAME: %s", err) } // Paint our image before mapping. im.XSurfaceSet(win.Id) im.XDraw() im.XPaint(win.Id) // Now we can map, since we've set all our properties. // (The initial map is when the window manager starts managing.) win.Map() return win }
func (c *client) unmanage() { X.Grab() defer X.Ungrab() c.win.Detach() icccm.WmStateSet(c.X, c.Id(), &icccm.WmState{State: icccm.StateWithdrawn}) c.Unmap() c.workspace.Remove(c) c.frames.destroy() c.prompts.destroy() focus.Remove(c) stack.Remove(c) wingo.remove(c) wingo.focusFallback() }
// newWindow creates the window, initializes the keybind and mousebind packages // and sets up the window to act like a real top-level client. func newWindow(X *xgbutil.XUtil) *Window { w, err := xwindow.Generate(X) if err != nil { errLg.Fatalf("Could not create window: %s", err) } keybind.Initialize(w.X) mousebind.Initialize(w.X) err = w.CreateChecked(w.X.RootWin(), 0, 0, 600, 600, xproto.CwBackPixel, 0xffffff) if err != nil { errLg.Fatalf("Could not create window: %s", err) } // Make the window close gracefully using the WM_DELETE_WINDOW protocol. w.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(w.X) }) // Set WM_STATE so it is interpreted as top-level and is mapped. err = icccm.WmStateSet(w.X, w.Id, &icccm.WmState{State: icccm.StateNormal}) if err != nil { lg("Could not set WM_STATE: %s", err) } // _NET_WM_STATE = _NET_WM_STATE_NORMAL // not needed because we we set FS later anyway? //ewmh.WmStateSet(w.X, w.Id, []string{"_NET_WM_STATE_NORMAL"}) w.Map() err = ewmh.WmStateReq(w.X, w.Id, ewmh.StateToggle, "_NET_WM_STATE_FULLSCREEN") if err != nil { lg("Failed to go FullScreen:", err) } return &Window{w} }
func (c *Client) unmanage() { wm.X.Grab() defer wm.X.Ungrab() go func() { c.frames.destroy() c.prompts.destroy() }() logger.Message.Printf("Unmanaging client: %s", c) infoWorkspace := c.workspace.String() infoClass := c.Class().Class infoInstance := c.Class().Instance infoName := c.Name() c.frame.Unmap() c.win.Detach() icccm.WmStateSet(wm.X, c.Id(), &icccm.WmState{State: icccm.StateWithdrawn}) focus.Remove(c) wm.FocusFallback() stack.Remove(c) c.workspace.Remove(c) wm.RemoveClient(c) c.attnStop() xproto.ChangeSaveSetChecked( wm.X.Conn(), xproto.SetModeDelete, c.Id()).Check() if c.hadStruts { wm.Heads.ApplyStruts(wm.Clients) } event.Notify(event.UnmanagedClient{ Id: c.Id(), Name: infoName, Workspace: infoWorkspace, Class: infoClass, Instance: infoInstance, }) }
func NewWindow() *Window { win, err := xwindow.Generate(X) if err != nil { log.Fatal("cannot generate window %v\n", err) return nil } width, height := 800, 600 win.Create(X.RootWin(), 0, 0, width, height, xproto.CwBackPixel, 0x0) win.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(w.X) }) icccm.WmStateSet(X, win.Id, &icccm.WmState{ State: icccm.StateNormal, }) win.Listen(xproto.EventMaskKeyPress) win.Clear(0, 0, 0, 0) win.Map() self := &Window{ win, nil, false, nil, } self.bindKeys() return self }
func makeWindow(ximage *xgraphics.Image) (*xwindow.Window, *bool) { w, h := ximage.Rect.Dx(), ximage.Rect.Dy() window, err := xwindow.Generate(ximage.X) if err != nil { xgbutil.Logger.Printf("Could not generate new window id: %s", err) return nil, nil } window.Create(ximage.X.RootWin(), 0, 0, w, h, xproto.CwBackPixel, 0x00000000) window.Listen(xproto.EventMaskExposure, xproto.EventMaskKeyPress, xproto.EventMaskStructureNotify, xproto.EventMaskVisibilityChange) window.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(w.X) }) err = icccm.WmStateSet(ximage.X, window.Id, &icccm.WmState{ State: icccm.StateNormal, }) if err != nil { xgbutil.Logger.Printf("Could not set WM_STATE: %s", err) } err = ewmh.WmNameSet(ximage.X, window.Id, "Computer System Monitor") if err != nil { xgbutil.Logger.Printf("Could not set _NET_WM_NAME: %s", err) } err = keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { err := ewmh.WmStateReq(ximage.X, window.Id, ewmh.StateToggle, "_NET_WM_STATE_FULLSCREEN") if err != nil { log.Fatal(err) } }).Connect(ximage.X, window.Id, "f", false) if err != nil { log.Fatal(err) } xevent.ExposeFun( func(xu *xgbutil.XUtil, event xevent.ExposeEvent) { ximage.XExpPaint(window.Id, 0, 0) }).Connect(ximage.X, window.Id) obscured := false xevent.VisibilityNotifyFun( func(xu *xgbutil.XUtil, event xevent.VisibilityNotifyEvent) { obscured = event.State == xproto.VisibilityFullyObscured }).Connect(ximage.X, window.Id) window.Map() return window, &obscured }
func xwmInit(fd uintptr) { X := fromFd(fd) defer X.Conn().Close() root := xwindow.New(X, X.RootWin()) if _, err := root.Geometry(); err != nil { panic(err) } // if names, _ := ewmh.DesktopNamesGet(X); len(names) > 0 { // println(names) // } composite.Init(X.Conn()) atomNames := []string{ "WL_SURFACE_ID", "WM_DELETE_WINDOW", "WM_PROTOCOLS", "WM_S0", "WM_NORMAL_HINTS", "WM_TAKE_FOCUS", "WM_STATE", "WM_CLIENT_MACHINE", "_NET_WM_CM_S0", "_NET_WM_NAME", "_NET_WM_PID", "_NET_WM_ICON", "_NET_WM_STATE", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_USER_TIME", "_NET_WM_ICON_NAME", "_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_DESKTOP", "_NET_WM_WINDOW_TYPE_DOCK", "_NET_WM_WINDOW_TYPE_TOOLBAR", "_NET_WM_WINDOW_TYPE_MENU", "_NET_WM_WINDOW_TYPE_UTILITY", "_NET_WM_WINDOW_TYPE_SPLASH", "_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", "_NET_WM_WINDOW_TYPE_POPUP_MENU", "_NET_WM_WINDOW_TYPE_TOOLTIP", "_NET_WM_WINDOW_TYPE_NOTIFICATION", "_NET_WM_WINDOW_TYPE_COMBO", "_NET_WM_WINDOW_TYPE_DND", "_NET_WM_WINDOW_TYPE_NORMAL", "_NET_WM_MOVERESIZE", "_NET_SUPPORTING_WM_CHECK", "_NET_SUPPORTED", "_MOTIF_WM_HINTS", "CLIPBOARD", "CLIPBOARD_MANAGER", "TARGETS", "UTF8_STRING", "_WL_SELECTION", "INCR", "TIMESTAMP", "MULTIPLE", "UTF8_STRING", "COMPOUND_TEXT", "TEXT", "STRING", "text/plain;charset=utf-8", "text/plain", "XdndSelection", "XdndAware", "XdndEnter", "XdndLeave", "XdndDrop", "XdndStatus", "XdndFinished", "XdndTypeList", "XdndActionCopy", } cookies := make([]xproto.InternAtomCookie, len(atomNames)) for i := 0; i < len(atomNames); i++ { cookies[i] = xproto.InternAtom(X.Conn(), false, uint16(len(atomNames[i])), atomNames[i]) } /* Try to select for substructure redirect. */ evMasks := xproto.EventMaskPropertyChange | xproto.EventMaskFocusChange | xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskStructureNotify | xproto.EventMaskSubstructureNotify | xproto.EventMaskSubstructureRedirect root.Listen(evMasks) composite.RedirectSubwindows(X.Conn(), root.Id, composite.RedirectManual) // change config // data := []byte{1} // propAtom, _ := xprop.Atm(X, "_NET_SUPPORTED") // var format byte = 32 // xproto.ChangePropertyChecked(X.Conn(), xproto.PropModeReplace, // root.Id, propAtom, xproto.AtomAtom, format, // uint32(len(data)/(int(format)/8)), data) ewmh.SupportedSet(X, []string{ "_NET_SUPPORTED", "_NET_CLIENT_LIST", "_NET_NUMBER_OF_DESKTOPS", "_NET_DESKTOP_GEOMETRY", "_NET_CURRENT_DESKTOP", "_NET_VISIBLE_DESKTOPS", "_NET_DESKTOP_NAMES", "_NET_ACTIVE_WINDOW", "_NET_SUPPORTING_WM_CHECK", "_NET_CLOSE_WINDOW", "_NET_MOVERESIZE_WINDOW", "_NET_RESTACK_WINDOW", "_NET_WM_NAME", "_NET_WM_DESKTOP", "_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_DESKTOP", "_NET_WM_WINDOW_TYPE_DOCK", "_NET_WM_WINDOW_TYPE_TOOLBAR", "_NET_WM_WINDOW_TYPE_MENU", "_NET_WM_WINDOW_TYPE_UTILITY", "_NET_WM_WINDOW_TYPE_SPLASH", "_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", "_NET_WM_WINDOW_TYPE_POPUP_MENU", "_NET_WM_WINDOW_TYPE_TOOLTIP", "_NET_WM_WINDOW_TYPE_NOTIFICATION", "_NET_WM_WINDOW_TYPE_COMBO", "_NET_WM_WINDOW_TYPE_DND", "_NET_WM_WINDOW_TYPE_NORMAL", "_NET_WM_STATE", "_NET_WM_STATE_STICKY", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_SKIP_TASKBAR", "_NET_WM_STATE_SKIP_PAGER", "_NET_WM_STATE_HIDDEN", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_BELOW", "_NET_WM_STATE_DEMANDS_ATTENTION", "_NET_WM_STATE_FOCUSED", "_NET_WM_ALLOWED_ACTIONS", "_NET_WM_ACTION_MOVE", "_NET_WM_ACTION_RESIZE", "_NET_WM_ACTION_MINIMIZE", "_NET_WM_ACTION_STICK", "_NET_WM_ACTION_MAXIMIZE_HORZ", "_NET_WM_ACTION_MAXIMIZE_VERT", "_NET_WM_ACTION_FULLSCREEN", "_NET_WM_ACTION_CHANGE_DESKTOP", "_NET_WM_ACTION_CLOSE", "_NET_WM_ACTION_ABOVE", "_NET_AM_ACTION_BELOW", "_NET_WM_STRUT_PARTIAL", "_NET_WM_ICON", "_NET_FRAME_EXTENTS", "WM_TRANSIENT_FOR", }) // create wm window win, _ := xwindow.Create(X, root.Id) xproto.MapWindow(X.Conn(), win.Id) atomValues := make([]xproto.Atom, len(atomNames)) for num, cookie := range cookies { reply, _ := cookie.Reply() atomValues[num] = reply.Atom } /* take WM_S0 selection last, which * signals to Xwayland that we're done with setup. */ xproto.SetSelectionOwner(X.Conn(), win.Id, atomValues[3], xproto.TimeCurrentTime, ) mapResquest := func(event xgb.Event) { ev, _ := event.(xproto.MapRequestEvent) log.Info("MapRequest: ", ev) xproto.MapWindow(X.Conn(), ev.Window) icccm.WmStateSet(X, ev.Window, &icccm.WmState{ State: icccm.StateNormal, Icon: ev.Window, }) // TODO: set _net_wm_state } for { x := X.Conn() ev, xerr := x.WaitForEvent() if ev == nil && xerr == nil { fmt.Println("Both event and error are nil. Exiting...") return } // if ev != nil { // fmt.Printf("Event: %s\n", ev) // } if xerr != nil { fmt.Printf("Error: %s\n", xerr) } switch ev.(type) { case xproto.CreateNotifyEvent: createNotify(X, ev) fmt.Printf("Event: %s\n", ev) case xproto.DestroyNotifyEvent: destroyNotify(X, ev) fmt.Printf("Event: %s\n", ev) case xproto.MapRequestEvent: mapResquest(ev) case xproto.ConfigureNotifyEvent: configureNotify(X, ev) case xproto.PropertyNotifyEvent: fmt.Printf("Event: %s\n", ev) case xproto.ClientMessageEvent: clientMessage(X, ev) case xproto.ConfigureRequestEvent: configureRequest(X, ev) case xproto.UnmapNotifyEvent: unmapNotify(X, ev) default: log.Info("Event:", ev) } } // xevent.MapRequestFun( // func(X *xgbutil.XUtil, e xevent.MapRequestEvent) { // println(e.Window) // }).Connect(X, root.Id) // xevent.ConfigureNotifyFun( // func(X *xgbutil.XUtil, e xevent.ConfigureNotifyEvent) { // fmt.Printf("(%d, %d) %dx%d\n", e.X, e.Y, e.Width, e.Height) // }).Connect(X, root.Id) // xevent.FocusInFun( // func(X *xgbutil.XUtil, e xevent.FocusInEvent) { // fmt.Printf("(%v, %v)\n", e.Mode, e.Detail) // }).Connect(X, root.Id) // xevent.Main(X) }