func newWindow(X *xgbutil.XUtil) { win, err := xwindow.Generate(X) if err != nil { log.Fatal(err) } win.Create(X.RootWin(), 0, 0, 200, 200, xproto.CwBackPixel|xproto.CwEventMask, 0, xproto.EventMaskButtonRelease) win.WMGracefulClose( func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(X) Done <- true }) win.Map() err = mousebind.ButtonReleaseFun( func(X *xgbutil.XUtil, ev xevent.ButtonReleaseEvent) { newWindow(X) }).Connect(X, win.Id, "1", false, false) if err != nil { log.Fatal(err) } }
func newWindow(controlCh *controlCh, X *xgbutil.XUtil, width, height int) *xwindow.Window { var ( err error win *xwindow.Window ) win, err = xwindow.Generate(X) if err != nil { panic(err) } win.Create(X.RootWin(), 0, 0, width, height, xproto.CwBackPixel|xproto.CwEventMask, 0, xproto.EventMaskButtonRelease) // Xorg application exits when the window is closed. win.WMGracefulClose( func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(X) controlCh.exit <- true }) // In order to get ConfigureNotify events, we must listen to the window // using the 'StructureNotify' mask. win.Listen(xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskKeyPress | xproto.EventMaskKeyRelease | xproto.EventMaskStructureNotify) win.Map() return win }
// 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 newWindow(X *xgbutil.XUtil, width, height int) *xwindow.Window { var ( err error win *xwindow.Window ) win, err = xwindow.Generate(X) if err != nil { log.Fatal(err) } win.Create(X.RootWin(), 0, 0, width, height, xproto.CwBackPixel|xproto.CwEventMask, 0, xproto.EventMaskButtonRelease) win.WMGracefulClose( func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(X) }) win.Map() if err != nil { log.Fatal(err) } return win }
// newWindow creates a new window with a random background color. It sets the // WM_PROTOCOLS property to contain the WM_DELETE_WINDOW atom. It also sets // up a ClientMessage event handler so that we know when to destroy the window. // We also set up a mouse binding so that clicking inside a window will // create another one. func newWindow(X *xgbutil.XUtil) { counter++ win, err := xwindow.Generate(X) if err != nil { log.Fatal(err) } // Get a random background color, create the window (ask to receive button // release events while we're at it) and map the window. bgColor := rand.Intn(0xffffff + 1) win.Create(X.RootWin(), 0, 0, 200, 200, xproto.CwBackPixel|xproto.CwEventMask, uint32(bgColor), xproto.EventMaskButtonRelease) // WMGracefulClose does all of the work for us. It sets the appropriate // values for WM_PROTOCOLS, and listens for ClientMessages that implement // the WM_DELETE_WINDOW protocol. When one is found, the provided callback // is executed. win.WMGracefulClose( func(w *xwindow.Window) { // Detach all event handlers. // This should always be done when a window can no longer // receive events. xevent.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() // Exit if there are no more windows left. counter-- if counter == 0 { os.Exit(0) } }) // It's important that the map comes after setting WMGracefulClose, since // the WM isn't obliged to watch updates to the WM_PROTOCOLS property. win.Map() // A mouse binding so that a left click will spawn a new window. // Note that we don't issue a grab here. Typically, window managers will // grab a button press on the client window (which usually activates the // window), so that we'd end up competing with the window manager if we // tried to grab it. // Instead, we set a ButtonRelease mask when creating the window and attach // a mouse binding *without* a grab. err = mousebind.ButtonReleaseFun( func(X *xgbutil.XUtil, ev xevent.ButtonReleaseEvent) { newWindow(X) }).Connect(X, win.Id, "1", false, false) if err != nil { log.Fatal(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 newWindow(X *xgbutil.XUtil, width, height int) *xwindow.Window { var ( err error win *xwindow.Window ) win, err = xwindow.Generate(X) if err != nil { log.Fatal(err) } win.Create(X.RootWin(), 0, 0, width, height, xproto.CwBackPixel|xproto.CwEventMask, 0, xproto.EventMaskButtonRelease) win.WMGracefulClose( func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) // w.Destroy() xevent.Quit(X) application.Exit() }) // In order to get ConfigureNotify events, we must listen to the window // using the 'StructureNotify' mask. win.Listen(xproto.EventMaskStructureNotify) win.Map() xevent.ConfigureNotifyFun( func(X *xgbutil.XUtil, ev xevent.ConfigureNotifyEvent) { reshape(int(ev.Width), int(ev.Height)) }).Connect(X, win.Id) // err = mousebind.ButtonReleaseFun( // func(X *xgbutil.XUtil, ev xevent.ButtonReleaseEvent) { // newWindow(X) // }).Connect(X, win.Id, "1", false, false) if err != nil { log.Fatal(err) } return win }
// 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 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 }
// Detach will detach this window's event handlers from all xevent, keybind // and mousebind callbacks. func (w *Window) Detach() { keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) xevent.Detach(w.X, w.Id) }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Anytime the mousebind (keybind) package is used, mousebind.Initialize // *should* be called once. In the case of the mousebind package, this // isn't strictly necessary, but the 'Drag' features of the mousebind // package won't work without it. mousebind.Initialize(X) // Before attaching callbacks, wrap them in a callback function type. // The mouse package exposes two such callback types: // mousebind.ButtonPressFun and mousebind.ButtonReleaseFun. cb1 := mousebind.ButtonPressFun( func(X *xgbutil.XUtil, e xevent.ButtonPressEvent) { log.Println("Button press!") }) // We can now attach the callback to a particular window and button // combination. This particular example grabs a button on the root window, // which makes it a global mouse binding. // Also, "Mod4-1" typically corresponds to pressing down the "Super" or // "Windows" key on your keyboard, and then pressing the left mouse button. // The last two parameters are whether to make a synchronous grab and // whether to actually issue a grab, respectively. // (The parameters used here are the common case.) // See the documentation for the Connect method for more details. err = cb1.Connect(X, X.RootWin(), "Mod4-1", false, true) // A mouse binding can fail if the mouse string could not be parsed, or if // you're trying to bind a button that has already been grabbed by another // client. if err != nil { log.Fatal(err) } // We can even attach multiple callbacks to the same button. err = mousebind.ButtonPressFun( func(X *xgbutil.XUtil, e xevent.ButtonPressEvent) { log.Println("A second handler always happens after the first.") }).Connect(X, X.RootWin(), "Mod4-1", false, true) if err != nil { log.Fatal(err) } // Finally, if we want this client to stop responding to mouse events, we // can attach another handler that, when run, detaches all previous // handlers. // This time, we'll show an example of a ButtonRelease binding. err = mousebind.ButtonReleaseFun( func(X *xgbutil.XUtil, e xevent.ButtonReleaseEvent) { // Use mousebind.Detach to detach the root window // from all ButtonPress *and* ButtonRelease handlers. mousebind.Detach(X, X.RootWin()) mousebind.Detach(X, X.RootWin()) log.Printf("Detached all Button{Press,Release}Events from the "+ "root window (%d).", X.RootWin()) }).Connect(X, X.RootWin(), "Mod4-Shift-1", false, true) if err != nil { log.Fatal(err) } // Finally, start the main event loop. This will route any appropriate // ButtonPressEvents to your callback function. log.Println("Program initialized. Start pressing mouse buttons!") xevent.Main(X) }
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 }
// Creates and displays a new plot window. // Defaults to an all white background with the upper left corner at (0,0). // If title is "" then the title will be an auto incrementing "Figure - #" func NewPlotWindow(width, height int, title string) (*PlotWindow, error) { if width <= 0 { err := errors.New("Width is negative or 0, this is invalid.") return nil, err } if height <= 0 { err := errors.New("Height is negative or 0, this is invalid.") return nil, err } system, err := Initialize() if system == nil { return nil, err } resultantPlotWindow := new(PlotWindow) win, err := xwindow.Generate(system.X) if err != nil { return nil, err } resultantPlotWindow.window = win xpos := 0 ypos := 0 var backgroundColor uint32 backgroundColor = 0xffffffff // Create window, checked because we want to fail if this doesn't work. err = win.CreateChecked( system.X.RootWin(), xpos, ypos, width, height, xproto.CwBackPixel|xproto.CwEventMask, backgroundColor, xproto.EventMaskButtonRelease) if err != nil { return nil, err } // Gracefully removes event handling system on window close. // In addition it removes the plotWindow from the DVSystem which // sends off all the required plotWindow closing messages. win.WMGracefulClose( func(w *xwindow.Window) { // Detach all event handlers. // This should always be done when a window can no longer // receive events. xevent.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() // We need to remove the plot from the DVSystem list since it's now // no longer visible. system.removePlotWindow(resultantPlotWindow) }) if title == "" { title = system.getNextPlotWindowDefaultName() } resultantPlotWindow.SetTitle(title) system.addPlotWindow(resultantPlotWindow) // Show the underlying window win.Map() // Hand back the PlotWindow return resultantPlotWindow, nil }