// When a cross is declared in its object literal form, it may not have the appropriate window. // this function creates a new X11 window for the cross with the correct geometry depending // on its Icon* parameters. func (c *Cross) CreateWindow(X *xgbutil.XUtil, icons_per_direction int, bg_color uint32) (*xwindow.Window, error) { // calculate the dimensions of the spars of our cross + // width/height reflect the vertical-orientation rectangle width := c.IconMargin*2 + c.IconSize // padding between the icons, margin on the edges height := c.IconSize*icons_per_direction + c.IconPadding*(icons_per_direction-1) + c.IconMargin*2 // intitialize a basic window for the cross win, err := xwindow.Generate(X) if err != nil { return nil, err } win.Create(X.RootWin(), 0, 0, height, height, xproto.CwBackPixel|xproto.CwOverrideRedirect, bg_color, 1) // the rects we will be adding together to form the shape of the cross vert := xrect.New(0, 0, width, height) horiz := xrect.New(0, 0, height, width) struts := []xrect.Rect{vert, horiz} geom, err := win.Geometry() if err != nil { return nil, err } // center struts over window x, y := util.CenterChild(vert, geom) vert.XSet(x) vert.YSet(y) x, y = util.CenterChild(horiz, geom) horiz.XSet(x) horiz.YSet(y) // build the cross shape from our friendly rectangles err = ComposeShape(X, win.Id, struts) if err != nil { return nil, err } // add the window to our cross struct c.Window = win // create icons from our images clr := RGB(bg_color) if c.imagesToBecomeIcons != nil { icons := make(map[string]*Icon, len(c.imagesToBecomeIcons)) for name, img := range c.imagesToBecomeIcons { icon := NewIcon(X, img, win.Id) icon.Background = clr icons[name] = icon } c.Icons = icons } else { return nil, errors.New("Cross: you must create crosses using the NewCross function (this cross has now iconsToBecomeImage)") } return win, nil }
func newParent(X *xgbutil.XUtil, cid xproto.Window) (*Parent, error) { parent, err := xwindow.Generate(X) if err != nil { logger.Error.Printf("Could not create a parent window for client "+ "with id '%d' because: %s", cid, err) logger.Error.Fatalf("In a state where no new windows can be created. " + "Unfortunately, we must exit.") } err = parent.CreateChecked(X.RootWin(), 0, 0, 1, 1, xproto.CwEventMask, xproto.EventMaskSubstructureRedirect| xproto.EventMaskButtonPress|xproto.EventMaskButtonRelease) if err != nil { return nil, err } err = xproto.ReparentWindowChecked(X.Conn(), cid, parent.Id, 0, 0).Check() if err != nil { return nil, err } return &Parent{parent}, nil }
// compose a number of rectabgles into a window shape func ComposeShape(X *xgbutil.XUtil, dst xproto.Window, rects []xrect.Rect) (err error) { combine_bounds := make([]shape.CombineCookie, len(rects)) combine_clip := make([]shape.CombineCookie, len(rects)) var operation shape.Op for i, rect := range rects { // make rectangular window of correct goemetry win, err := xwindow.Generate(X) if err != nil { log.Fatalf("ComposeShape: Error creating rectange %v window.", rect) return err } win.Create(X.RootWin(), rect.X(), rect.Y(), rect.Width(), rect.Height(), xproto.CwBackPixel, 0xffffff) // choose operation. on the first one, we want to set the shape. if i == 0 { operation = shape.SoSet } else { operation = shape.SoUnion } // combine window request x, y := int16(rect.X()), int16(rect.Y()) combine_kind := shape.Kind(shape.SkBounding) combine_bounds[i] = shape.CombineChecked(X.Conn(), operation, combine_kind, combine_kind, dst, x, y, win.Id) combine_kind = shape.Kind(shape.SkClip) combine_clip[i] = shape.CombineChecked(X.Conn(), operation, combine_kind, combine_kind, dst, x, y, win.Id) } return nil }
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(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 }
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 }
// New allocates and initializes a new DockApp. NewDockApp does not initialize // the window contents and does not map the window to the display screen. The // window is mapped to the screen when the Main method is called on the // returned DockApp. func New(x *xgbutil.XUtil, rect image.Rectangle) (*DockApp, error) { win, err := xwindow.Generate(x) if err != nil { log.Fatalf("generate window: %v", err) } win.Create(x.RootWin(), 0, 0, rect.Size().X, rect.Size().Y, 0) // Set WM hints so that Openbox puts the window into the dock. hints := &icccm.Hints{ Flags: icccm.HintState | icccm.HintIconWindow, InitialState: icccm.StateWithdrawn, IconWindow: win.Id, WindowGroup: win.Id, } err = icccm.WmHintsSet(x, win.Id, hints) if err != nil { win.Destroy() return nil, fmt.Errorf("wm hints: %v", err) } img := xgraphics.New(x, rect) err = img.XSurfaceSet(win.Id) if err != nil { img.Destroy() win.Destroy() return nil, fmt.Errorf("xsurface set: %v", err) } app := &DockApp{ x: x, img: img, win: win, } return app, nil }
func (f *Borders) newPieceWindow(ident string, cursor xproto.Cursor) *xwindow.Window { win, err := xwindow.Generate(f.X) if err != nil { logger.Error.Printf("Could not create a frame window for client "+ "with id '%d' because: %s", f.client.Id(), err) logger.Error.Fatalf("In a state where no new windows can be created. " + "Unfortunately, we must exit.") } err = win.CreateChecked(f.parent.Id, 0, 0, 1, 1, xproto.CwBackPixmap|xproto.CwEventMask|xproto.CwCursor, xproto.BackPixmapParentRelative, xproto.EventMaskButtonPress|xproto.EventMaskButtonRelease| xproto.EventMaskButtonMotion|xproto.EventMaskPointerMotion, uint32(cursor)) if err != nil { logger.Warning.Println(err) } f.client.FramePieceMouseSetup("borders_"+ident, win.Id) return win }
func (m *TrayManager) Manage() bool { m.destroyOwnerWindow() win, _ := xwindow.Generate(TrayXU) m.owner = win.Id xproto.CreateWindowChecked(TrayXU.Conn(), 0, m.owner, TrayXU.RootWin(), 0, 0, 1, 1, 0, xproto.WindowClassInputOnly, m.visual, 0, nil) TrayXU.Sync() win.Listen(xproto.EventMaskStructureNotify) return m.tryOwner() }
// 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 }
// newWndow creates a new window and dies on failure. // This includes mapping the window but not setting up the event handlers. // (The event handlers require the channels, and we don't create the channels // until all images have been decoded. But we want to show the window to the // user before that task is complete.) func newWindow(X *xgbutil.XUtil) *window { xwin, err := xwindow.Generate(X) if err != nil { errLg.Fatalf("Could not create window: %s", err) } w := &window{ Window: xwin, } w.create() return w }
func NewWindow(width, height int) (w *Window, err error) { w = new(Window) w.width, w.height = width, height w.xu, err = xgbutil.NewConn() if err != nil { return } w.conn = w.xu.Conn() screen := w.xu.Screen() w.win, err = xwindow.Generate(w.xu) if err != nil { return } err = w.win.CreateChecked(screen.Root, 600, 500, width, height, 0) if err != nil { return } w.win.Listen(AllEventsMask) err = icccm.WmProtocolsSet(w.xu, w.win.Id, []string{"WM_DELETE_WINDOW"}) if err != nil { fmt.Println(err) err = nil } w.bufferLck = &sync.Mutex{} w.buffer = xgraphics.New(w.xu, image.Rect(0, 0, width, height)) w.buffer.XSurfaceSet(w.win.Id) keyMap, modMap := keybind.MapsGet(w.xu) keybind.KeyMapSet(w.xu, keyMap) keybind.ModMapSet(w.xu, modMap) w.events = make(chan interface{}) w.SetIcon(Gordon) w.SetIconName("Go") go w.handleEvents() return }
// newWindow creates a new window that listens to MotionNotify events with // the given backgroundcolor. func newWindow(X *xgbutil.XUtil, color uint32) *xwindow.Window { win, err := xwindow.Generate(X) if err != nil { log.Fatal(err) } err = win.CreateChecked(X.RootWin(), 0, 0, 400, 400, xproto.CwBackPixel|xproto.CwEventMask, color, xproto.EventMaskPointerMotion) if err != nil { log.Fatal(err) } win.Map() return win }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Anytime the keybind (mousebind) package is used, keybind.Initialize // *should* be called once. It isn't strictly necessary, but allows your // keybindings to persist even if the keyboard mapping is changed during // run-time. (Assuming you're using the xevent package's event loop.) // It also handles the case when your modifier map is changed. keybind.Initialize(X) // Create a new window. We will listen for key presses and translate them // only when this window is in focus. (Similar to how `xev` works.) win, err := xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } win.Create(X.RootWin(), 0, 0, 500, 500, xproto.CwBackPixel, 0xffffffff) // Listen for Key{Press,Release} events. win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskKeyRelease) // Map the window. win.Map() // Notice that we use xevent.KeyPressFun instead of keybind.KeyPressFun, // because we aren't trying to make a grab *and* because we want to listen // to *all* key press events, rather than just a particular key sequence // that has been pressed. xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { // keybind.LookupString does the magic of implementing parts of // the X Keyboard Encoding to determine an english representation // of the modifiers/keycode tuple. // N.B. It's working for me, but probably isn't 100% correct in // all environments yet. log.Println("Key:", keybind.LookupString(X, e.State, e.Detail)) }).Connect(X, win.Id) // Finally, start the main event loop. This will route any appropriate // KeyPressEvents to your callback function. log.Println("Program initialized. Start pressing keys!") xevent.Main(X) }
func newParent(X *xgbutil.XUtil, cid xproto.Window) (*Parent, error) { parent, err := xwindow.Generate(X) if err != nil { logger.Error.Printf("Could not create a parent window for client "+ "with id '%d' because: %s", cid, err) logger.Error.Fatalf("In a state where no new windows can be created. " + "Unfortunately, we must exit.") } // clientAttrs, err := xproto.GetWindowAttributes(X.Conn(), cid).Reply() // if err != nil { // return nil, fmt.Errorf("Could not get window attributes: %s", err) // } // visual := clientAttrs.Visual // vdepth := getVisualDepth(X, visual) visual := X.Screen().RootVisual vdepth := X.Screen().RootDepth // logger.Debug.Printf("Visualid: %x, Depth: %d", visual, vdepth) err = xproto.CreateWindowChecked(X.Conn(), vdepth, parent.Id, X.RootWin(), 0, 0, 1, 1, 0, xproto.WindowClassInputOutput, visual, xproto.CwEventMask, []uint32{ xproto.EventMaskSubstructureRedirect | xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskFocusChange, }).Check() if err != nil { return nil, fmt.Errorf("Could not create window: %s", err) } err = xproto.ReparentWindowChecked(X.Conn(), cid, parent.Id, 0, 0).Check() if err != nil { return nil, fmt.Errorf("Could not reparent window: %s", err) } return &Parent{ Window: parent, MoveState: &MoveState{}, ResizeState: &ResizeState{}, isMapped: false, }, nil }
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 }
func main() { var err error X, err = xgbutil.NewConn() if err != nil { log.Fatal(err) } clientids, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } for _, clientid := range clientids { name, err := ewmh.WmNameGet(X, clientid) if err != nil { continue } if name == "Super Hexagon" { HexWindow = xwindow.New(X, clientid) break } } if HexWindow == nil { log.Fatal("Couldn't find Super Hexagon window.") } //Create a window DisplayWindow, err = xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } dgeom, _ := HexWindow.DecorGeometry() DisplayWindow.Create(X.RootWin(), 0, 0, dgeom.Width(), dgeom.Height(), xproto.CwBackPixel, 0) DisplayWindow.Map() //Start the routine that updates the window go updater() xevent.Main(X) }
// 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 main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Create the cursor. You can find a list of available cursors in // xcursor/cursordef.go. // We'll make an umbrella here, with an orange foreground and a blue // background. (The background it typically the outline of the cursor.) // Note that each component of the RGB color is a 16 bit color. I think // using the most significant byte to specify each component is good // enough. cursor, err := xcursor.CreateCursorExtra(X, xcursor.Umbrella, 0xff00, 0x5500, 0x0000, 0x3300, 0x6600, 0xff00) if err != nil { log.Fatal(err) } // Create a new window. In the create window request, we'll set the // background color and set the cursor we created above. // This results in changing the cursor only when it moves into this window. win, err := xwindow.Generate(X) if err != nil { log.Fatal(err) } win.Create(X.RootWin(), 0, 0, 500, 500, xproto.CwBackPixel|xproto.CwCursor, 0xffffffff, uint32(cursor)) win.Map() // We can free the cursor now that we've set it. // If you plan on using this cursor again, then it shouldn't be freed. // (i.e., if you try to free this before setting it as the cursor in a // window, you'll get a BadCursor error when trying to use it.) xproto.FreeCursor(X.Conn(), cursor) // Block. No need to process any events. select {} }
// newGradientWindow creates a new X window, paints the initial gradient // image, and listens for ConfigureNotify events. (A new gradient image must // be painted in response to each ConfigureNotify event, since a // ConfigureNotify event corresponds to a change in the window's geometry.) func newGradientWindow(X *xgbutil.XUtil, width, height int, start, end color.RGBA) { // Generate a new window id. win, err := xwindow.Generate(X) if err != nil { log.Fatal(err) } // Create the window and die if it fails. err = win.CreateChecked(X.RootWin(), 0, 0, width, height, 0) if err != nil { log.Fatal(err) } // In order to get ConfigureNotify events, we must listen to the window // using the 'StructureNotify' mask. win.Listen(xproto.EventMaskStructureNotify) // Paint the initial gradient to the window and then map the window. paintGradient(X, win.Id, width, height, start, end) win.Map() xevent.ConfigureNotifyFun( func(X *xgbutil.XUtil, ev xevent.ConfigureNotifyEvent) { // If the width and height have not changed, skip this one. if int(ev.Width) == width && int(ev.Height) == height { return } // Compress ConfigureNotify events so that we don't lag when // drawing gradients in response. ev = compressConfigureNotify(X, ev) // Update the width and height and paint the gradient image. width, height = int(ev.Width), int(ev.Height) paintGradient(X, win.Id, width, height, start, end) }).Connect(X, win.Id) }
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 }
// 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 }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Println(err) return } //Initialize the keybind package keybind.Initialize(X) //Create a window win, err := xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } win.Create(X.RootWin(), 0, 0, 1024, 768, xproto.CwBackPixel, 0x606060ff) // Listen for Key{Press,Release} events. win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskKeyRelease) // Map the window. This is what makes it on the screen win.Map() //Make a ...callback... for the events and connect xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { modStr := keybind.ModifierString(e.State) keyStr := keybind.LookupString(X, e.State, e.Detail) if len(modStr) > 0 { log.Printf("Key: %s-%s\n", modStr, keyStr) } else { log.Println("Key:", keyStr) } if keybind.KeyMatch(X, "Escape", e.State, e.Detail) { if e.State&xproto.ModMaskControl > 0 { log.Println("Control-Escape detected. Quitting...") xevent.Quit(X) } } }).Connect(X, win.Id) //So here i'm going to try to make a image..' img := xgraphics.New(X, image.Rect(0, 0, 1024, 768)) err = img.XSurfaceSet(win.Id) if err != nil { log.Printf("Error while setting window surface to image %d: %s\n", win, err) } else { log.Printf("Window %d surface set to image OK\n", win) } // I /think/ XDraw actually sends data to server? img.XDraw() // I /think/ XPaint tells the server to paint image to window img.XPaint(win.Id) //Start the routine that updates the window go updater(img, win) //This seems to start a main loop for listening to xevents 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 }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Anytime the keybind (mousebind) package is used, keybind.Initialize // *should* be called once. It isn't strictly necessary, but allows your // keybindings to persist even if the keyboard mapping is changed during // run-time. (Assuming you're using the xevent package's event loop.) // It also handles the case when your modifier map is changed. keybind.Initialize(X) // Create a new window. We will listen for key presses and translate them // only when this window is in focus. (Similar to how `xev` works.) win, err := xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } win.Create(X.RootWin(), 0, 0, 500, 500, xproto.CwBackPixel, 0xffffffff) // Listen for Key{Press,Release} events. win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskKeyRelease) // Map the window. win.Map() // Notice that we use xevent.KeyPressFun instead of keybind.KeyPressFun, // because we aren't trying to make a grab *and* because we want to listen // to *all* key press events, rather than just a particular key sequence // that has been pressed. wid := win.Id if flagRoot { wid = X.RootWin() } xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { // keybind.LookupString does the magic of implementing parts of // the X Keyboard Encoding to determine an english representation // of the modifiers/keycode tuple. // N.B. It's working for me, but probably isn't 100% correct in // all environments yet. modStr := keybind.ModifierString(e.State) keyStr := keybind.LookupString(X, e.State, e.Detail) if len(modStr) > 0 { log.Printf("Key: %s-%s\n", modStr, keyStr) } else { log.Println("Key:", keyStr) } if keybind.KeyMatch(X, "Escape", e.State, e.Detail) { if e.State&xproto.ModMaskControl > 0 { log.Println("Control-Escape detected. Quitting...") xevent.Quit(X) } } }).Connect(X, wid) // If we want root, then we take over the entire keyboard. if flagRoot { if err := keybind.GrabKeyboard(X, X.RootWin()); err != nil { log.Fatalf("Could not grab keyboard: %s", err) } log.Println("WARNING: We are taking *complete* control of the root " + "window. The only way out is to press 'Control + Escape' or to " + "close the window with the mouse.") } // Finally, start the main event loop. This will route any appropriate // KeyPressEvents to your callback function. log.Println("Program initialized. Start pressing keys!") xevent.Main(X) }