### Start the X Event Loop Source: https://context7.com/burntsushi/xgbutil/llms.txt Enters the main event loop to process X events. This should typically be the last call in a xgbutil application. ```go xevent.Main(X) ``` -------------------------------- ### Run Main Event Loop Source: https://context7.com/burntsushi/xgbutil/llms.txt Starts the primary event loop to dispatch X events, with an alternative for integrating multiple event sources. ```go package main import ( "log" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/keybind" "github.com/BurntSushi/xgbutil/xevent" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } keybind.Initialize(X) // Simple event loop log.Println("Starting event loop...") xevent.Main(X) // Alternative: MainPing for multiple event sources // pingBefore, pingAfter, pingQuit := xevent.MainPing(X) // for { // select { // case <-pingBefore: // <-pingAfter // Wait for event processing // case val := <-someOtherChannel: // // Handle other events // case <-pingQuit: // return // } // } } ``` -------------------------------- ### Implement Dragging for Window Moving Source: https://context7.com/burntsushi/xgbutil/llms.txt Sets up a drag handler for window moving using a modifier key and mouse button. It includes callbacks for the start, step, and end of the drag operation. ```go mousebind.Drag(X, win.Id, win.Id, "Mod4-1", true, // Begin: called when drag starts func(X *xgbutil.XUtil, rootX, rootY, eventX, eventY int) (bool, xproto.Cursor) { startX, startY = rootX, rootY return true, 0 // true = proceed with drag, 0 = default cursor }, // Step: called on each mouse movement func(X *xgbutil.XUtil, rootX, rootY, eventX, eventY int) { dx, dy := rootX-startX, rootY-startY log.Printf("Dragging: delta (%d, %d)", dx, dy) }, // End: called when drag ends func(X *xgbutil.XUtil, rootX, rootY, eventX, eventY int) { log.Println("Drag ended") }, ) ``` -------------------------------- ### Manipulate X Window Properties with xprop Source: https://context7.com/burntsushi/xgbutil/llms.txt Use `xprop` functions to set and get string and numeric properties on X windows. Ensure you have a connection to the X server and a valid window ID. ```go package main import ( "log" "github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/xprop" "github.com/BurntSushi/xgbutil/xwindow" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } win, _ := xwindow.Generate(X) win.Create(X.RootWin(), 0, 0, 200, 200, xproto.CwBackPixel, 0xffffff) // Set string property (8-bit format) xprop.ChangeProp(X, win.Id, 8, "MY_CUSTOM_PROP", "STRING", []byte("Hello World")) // Set 32-bit property (cardinal numbers) xprop.ChangeProp32(X, win.Id, "MY_NUMBER_PROP", "CARDINAL", 42, 100, 200) // Get string property reply, err := xprop.GetProperty(X, win.Id, "MY_CUSTOM_PROP") if err == nil { str, _ := xprop.PropValStr(reply, nil) log.Printf("String property: %s", str) } // Get numeric property reply, err = xprop.GetProperty(X, win.Id, "MY_NUMBER_PROP") if err == nil { nums, _ := xprop.PropValNums(reply, nil) log.Printf("Number properties: %v", nums) } // Get/create atoms atom, err := xprop.Atom(X, "MY_ATOM", false) // false = create if not exists if err == nil { log.Printf("Atom ID: %d", atom) } // Get atom name from ID atomName, _ := xprop.AtomName(X, atom) log.Printf("Atom name: %s", atomName) // Shorthand for getting atom (with caching) myAtom, _ := xprop.Atm(X, "ANOTHER_ATOM") log.Printf("Another atom: %d", myAtom) win.Map() } ``` -------------------------------- ### Get Window Geometry Source: https://context7.com/burntsushi/xgbutil/llms.txt Retrieves the current position and dimensions of a window. ```go geom, _ := win.Geometry() ``` -------------------------------- ### Initialize and Use Keyboard Bindings in Go Source: https://context7.com/burntsushi/xgbutil/llms.txt Demonstrates parsing key strings, converting between keycodes and keysyms, and performing keyboard grabs using the xgbutil library. ```go package main import ( "log" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/keybind" "github.com/BurntSushi/xgbutil/xevent" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } keybind.Initialize(X) // Parse key string to modifiers and keycodes mods, keycodes, err := keybind.ParseString(X, "Control-Shift-a") if err != nil { log.Fatal(err) } log.Printf("Modifiers: %d, Keycodes: %v", mods, keycodes) // Convert key name to keycodes codes := keybind.StrToKeycodes(X, "Return") log.Printf("Return keycodes: %v", codes) // Get keysym from keycode keymap := keybind.KeyMapGet(X) if len(codes) > 0 { keysym := keybind.KeysymGet(X, codes[0], 0) // column 0 = unshifted log.Printf("Keysym for Return: 0x%x", keysym) // Convert keysym back to string symStr := keybind.KeysymToStr(keysym) log.Printf("Keysym string: %s", symStr) } log.Printf("Keysyms per keycode: %d", keymap.KeysymsPerKeycode) // Grab entire keyboard (all keys go to this window) err = keybind.GrabKeyboard(X, X.RootWin()) if err != nil { log.Printf("Could not grab keyboard: %v", err) } else { log.Println("Keyboard grabbed!") // Release keyboard grab keybind.UngrabKeyboard(X) } // Smart grab (with key event redirection) // keybind.SmartGrab(X, X.RootWin()) // keybind.SmartUngrab(X) // Grab single key // keybind.Grab(X, X.RootWin(), mods, codes[0]) // keybind.Ungrab(X, X.RootWin(), mods, codes[0]) xevent.Main(X) } ``` -------------------------------- ### Initialize XGButil Connection Source: https://context7.com/burntsushi/xgbutil/llms.txt Establishes a connection to the X server. Handles potential connection errors. ```go X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } ``` -------------------------------- ### Create a Window with Basic Properties Source: https://context7.com/burntsushi/xgbutil/llms.txt Creates a window with specified position, dimensions, background color, and event mask. Note: This version does not return an error. ```go win, _ := xwindow.Generate(X) win.Create(X.RootWin(), 100, 100, 300, 200, xproto.CwBackPixel|xproto.CwEventMask, 0x00ff00, xproto.EventMaskButtonRelease) win.Map() ``` -------------------------------- ### Initialize Mouse Binding System Source: https://context7.com/burntsushi/xgbutil/llms.txt Initializes the mouse binding system for the given X connection. ```go mousebind.Initialize(X) ``` -------------------------------- ### Interact with EWMH window manager hints in Go Source: https://context7.com/burntsushi/xgbutil/llms.txt Demonstrates retrieving window lists, active window status, and setting EWMH properties like window names and types. ```go package main import ( "log" "github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/ewmh" "github.com/BurntSushi/xgbutil/xwindow" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Get list of all client windows clients, err := ewmh.ClientListGet(X) if err != nil { log.Printf("Could not get client list: %v", err) } else { for _, client := range clients { name, _ := ewmh.WmNameGet(X, client) log.Printf("Window 0x%x: %s", client, name) } } // Get current active window active, err := ewmh.ActiveWindowGet(X) if err == nil { name, _ := ewmh.WmNameGet(X, active) log.Printf("Active window: %s", name) } // Get number of desktops numDesks, _ := ewmh.NumberOfDesktopsGet(X) log.Printf("Number of desktops: %d", numDesks) // Get current desktop currentDesk, _ := ewmh.CurrentDesktopGet(X) log.Printf("Current desktop: %d", currentDesk) // Create a window and set EWMH properties win, _ := xwindow.Generate(X) win.Create(X.RootWin(), 0, 0, 400, 300, xproto.CwBackPixel, 0x00ff00) // Set window name ewmh.WmNameSet(X, win.Id, "My EWMH Window") // Set window type (normal, dialog, dock, etc.) ewmh.WmWindowTypeSet(X, win.Id, []string{"_NET_WM_WINDOW_TYPE_NORMAL"}) // Request to make window fullscreen // ewmh.WmStateReq(X, win.Id, ewmh.StateAdd, "_NET_WM_STATE_FULLSCREEN") // Request focus (polite way via window manager) win.Map() ewmh.ActiveWindowReq(X, win.Id) // Move/resize via window manager ewmh.MoveresizeWindow(X, win.Id, 100, 100, 500, 400) // Close window gracefully via window manager // ewmh.CloseWindow(X, win.Id) } ``` -------------------------------- ### Establish X Server Connection Source: https://context7.com/burntsushi/xgbutil/llms.txt Connects to the X server using the DISPLAY environment variable or a custom display string. ```go package main import ( "log" "github.com/BurntSushi/xgbutil" ) func main() { // Connect to X server using DISPLAY environment variable X, err := xgbutil.NewConn() if err != nil { log.Fatalf("Could not connect to X server: %v", err) } // Access connection info log.Printf("Root window: 0x%x", X.RootWin()) log.Printf("Screen dimensions: %dx%d", X.Screen().WidthInPixels, X.Screen().HeightInPixels) // For custom display strings: // X, err := xgbutil.NewConnDisplay(":1") // X, err := xgbutil.NewConnDisplay("hostname:2.1") } ``` -------------------------------- ### Render Image to X Window in Go Source: https://context7.com/burntsushi/xgbutil/llms.txt Utilize the `xgraphics` package to create and manipulate images, then render them to X windows. Supports direct pixel manipulation and scaling. Requires xgbutil, xgraphics, and xwindow packages. ```go package main import ( "image" "image/color" "log" "github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/xevent" "github.com/BurntSushi/xgbutil/xgraphics" "github.com/BurntSushi/xgbutil/xwindow" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Create a new xgraphics image width, height := 400, 300 ximg := xgraphics.New(X, image.Rect(0, 0, width, height)) // Draw gradient using ForExp (fast pixel manipulation) ximg.ForExp(func(x, y int) (r, g, b, a uint8) { return uint8(x * 255 / width), // Red gradient uint8(y * 255 / height), // Green gradient 128, // Blue constant 255 // Alpha opaque }) // Alternative: Set individual pixels for x := 50; x < 100; x++ { for y := 50; y < 100; y++ { ximg.Set(x, y, color.RGBA{255, 0, 0, 255}) } } // Create window using convenience method (handles pixmap setup) win := ximg.Window(X.RootWin()) win.Map() // Manual approach for more control: // win2, _ := xwindow.Generate(X) // win2.Create(X.RootWin(), 0, 0, width, height, 0) // ximg.XSurfaceSet(win2.Id) // Set pixmap as window background // ximg.XDraw() // Draw image data to pixmap // ximg.XPaint(win2.Id) // Paint pixmap to window // ximg.Destroy() // Free pixmap when done // win2.Map() // Scale image // scaledImg := ximg.Scale(800, 600) // Save to file // ximg.SavePng("output.png") // Handle window close win.Listen(xproto.EventMaskStructureNotify) xevent.DestroyNotifyFun(func(X *xgbutil.XUtil, e xevent.DestroyNotifyEvent) { xevent.Quit(X) }).Connect(X, win.Id) xevent.Main(X) } ``` -------------------------------- ### Listen for Window Events Source: https://context7.com/burntsushi/xgbutil/llms.txt Configures a window to listen for specific X events, such as KeyPress and Exposure. ```go win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskExposure) ``` -------------------------------- ### Map (Show) a Window Source: https://context7.com/burntsushi/xgbutil/llms.txt Makes a created window visible on the screen. ```go win.Map() ``` -------------------------------- ### Create a New X Window Source: https://context7.com/burntsushi/xgbutil/llms.txt Generates a new window ID and creates a window with specified geometry, attributes, and event masks. Use CreateChecked for error handling. ```go win, err := xwindow.Generate(X) if err != nil { log.Fatal(err) } // Create window with geometry and attributes // CreateChecked returns error if window creation fails err = win.CreateChecked(X.RootWin(), 50, 50, 400, 300, xproto.CwBackPixel|xproto.CwEventMask, 0x0000ff, // Blue background xproto.EventMaskStructureNotify|xproto.EventMaskKeyPress) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Set Window Focus Source: https://context7.com/burntsushi/xgbutil/llms.txt Gives keyboard focus to the specified window. ```go win.Focus() ``` -------------------------------- ### Configure Keyboard Bindings Source: https://context7.com/burntsushi/xgbutil/llms.txt Registers keyboard shortcuts to callback handlers using the [Modifier]-Key format. ```go package main import ( "log" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/keybind" "github.com/BurntSushi/xgbutil/xevent" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Initialize keybind (required for persistent bindings on keymap changes) keybind.Initialize(X) // Bind Mod4+j (Super+j) to root window (global hotkey) err = keybind.KeyPressFun(func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { log.Printf("Key pressed! Keycode: %d, State: %d", e.Detail, e.State) }).Connect(X, X.RootWin(), "Mod4-j", true) // true = grab key if err != nil { log.Fatal(err) } // Bind Escape to quit err = keybind.KeyPressFun(func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { log.Println("Quitting...") xevent.Quit(X) }).Connect(X, X.RootWin(), "Escape", true) if err != nil { log.Fatal(err) } // Detach all key bindings from a window // keybind.Detach(X, X.RootWin()) log.Println("Press Mod4+j to trigger, Escape to quit") xevent.Main(X) } ``` -------------------------------- ### Set ICCCM Window Properties in Go Source: https://context7.com/burntsushi/xgbutil/llms.txt Use this to set standard window properties like title, icon name, size hints, and class for compatibility with older window managers. Requires xgbutil and icccm packages. ```go package main import ( "log" "github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/icccm" "github.com/BurntSushi/xgbutil/xwindow" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } win, _ := xwindow.Generate(X) win.Create(X.RootWin(), 0, 0, 400, 300, xproto.CwBackPixel, 0xff0000) // Set WM_NAME (window title for older WMs) icccm.WmNameSet(X, win.Id, "My ICCCM Window") // Set WM_ICON_NAME (iconified title) icccm.WmIconNameSet(X, win.Id, "MyIcon") // Set size hints (min/max size, resize increments, etc.) hints := &icccm.NormalHints{ Flags: icccm.SizeHintPMinSize | icccm.SizeHintPMaxSize, MinWidth: 200, MinHeight: 150, MaxWidth: 800, MaxHeight: 600, } icccm.WmNormalHintsSet(X, win.Id, hints) // Set WM_HINTS (input focus, initial state, etc.) wmHints := &icccm.Hints{ Flags: icccm.HintInput | icccm.HintState, Input: 1, // Accept input focus InitialState: icccm.StateNormal, } icccm.WmHintsSet(X, win.Id, wmHints) // Set WM_CLASS (app name and class for WM classification) icccm.WmClassSet(X, win.Id, &icccm.WmClass{ Instance: "myapp", Class: "MyApp", }) // Get size hints from another window client := X.RootWin() if normalHints, err := icccm.WmNormalHintsGet(X, client); err == nil { log.Printf("Min size: %dx%d", normalHints.MinWidth, normalHints.MinHeight) } win.Map() } ``` -------------------------------- ### Manage X Event Queue with xevent Source: https://context7.com/burntsushi/xgbutil/llms.txt Utilize `xevent` for advanced event queue management, including event compression and custom error handling. Ensure the window is listening for relevant events. ```go package main import ( "log" "github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/xevent" "github.com/BurntSushi/xgbutil/xwindow" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } win, _ := xwindow.Generate(X) win.Create(X.RootWin(), 0, 0, 400, 300, xproto.CwBackPixel, 0x0000ff) win.Listen(xproto.EventMaskStructureNotify) win.Map() // ConfigureNotify with event compression xevent.ConfigureNotifyFun(func(X *xgbutil.XUtil, e xevent.ConfigureNotifyEvent) { // Sync and read any pending events X.Sync() xevent.Read(X, false) // false = non-blocking // Peek at the queue to find newer ConfigureNotify events lastEvent := e for i, queued := range xevent.Peek(X) { if queued.Err != nil { continue } if cn, ok := queued.Event.(xproto.ConfigureNotifyEvent); ok { if cn.Window == e.Window { lastEvent = xevent.ConfigureNotifyEvent{&cn} // Dequeue this event (use defer for LIFO order) defer xevent.DequeueAt(X, i) } } } // Process only the most recent event log.Printf("Window resized to: %dx%d", lastEvent.Width, lastEvent.Height) }).Connect(X, win.Id) // Check if queue is empty if xevent.Empty(X) { log.Println("Event queue is empty") } // Set custom error handler xevent.ErrorHandlerSet(X, func(err xgb.Error) { log.Printf("X Error: %v", err) }) // Quit the event loop gracefully // xevent.Quit(X) xevent.Main(X) } ``` -------------------------------- ### Handle Graceful Window Close Source: https://context7.com/burntsushi/xgbutil/llms.txt Implements the ICCCM WM_DELETE_WINDOW protocol to allow graceful window closing, detaching event handlers and destroying the window. ```go win.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(X) }) ``` -------------------------------- ### Connect X event callbacks in Go Source: https://context7.com/burntsushi/xgbutil/llms.txt Uses xevent to register typed callbacks for specific window events like ConfigureNotify, Expose, and pointer movements. ```go package main import ( "log" "github.com/BurntSushi/xgb/xproto" "github.com/BurntSushi/xgbutil" "github.com/BurntSushi/xgbutil/xevent" "github.com/BurntSushi/xgbutil/xwindow" ) func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } win, _ := xwindow.Generate(X) win.Create(X.RootWin(), 0, 0, 400, 300, xproto.CwBackPixel, 0xffffff) win.Listen(xproto.EventMaskStructureNotify, xproto.EventMaskExposure, xproto.EventMaskEnterWindow, xproto.EventMaskLeaveWindow) win.Map() // ConfigureNotify: window geometry changes xevent.ConfigureNotifyFun(func(X *xgbutil.XUtil, e xevent.ConfigureNotifyEvent) { log.Printf("Window configured: (%d, %d) %dx%d", e.X, e.Y, e.Width, e.Height) }).Connect(X, win.Id) // Expose: window needs redrawing xevent.ExposeFun(func(X *xgbutil.XUtil, e xevent.ExposeEvent) { log.Printf("Expose event: region (%d, %d) %dx%d", e.X, e.Y, e.Width, e.Height) }).Connect(X, win.Id) // EnterNotify: pointer enters window xevent.EnterNotifyFun(func(X *xgbutil.XUtil, e xevent.EnterNotifyEvent) { log.Println("Pointer entered window") }).Connect(X, win.Id) // LeaveNotify: pointer leaves window xevent.LeaveNotifyFun(func(X *xgbutil.XUtil, e xevent.LeaveNotifyEvent) { log.Println("Pointer left window") }).Connect(X, win.Id) // DestroyNotify: window destroyed xevent.DestroyNotifyFun(func(X *xgbutil.XUtil, e xevent.DestroyNotifyEvent) { log.Println("Window destroyed") xevent.Quit(X) }).Connect(X, win.Id) // Detach all callbacks from a window when done // xevent.Detach(X, win.Id) xevent.Main(X) } ``` -------------------------------- ### Stack Window Above Others Source: https://context7.com/burntsushi/xgbutil/llms.txt Changes the stacking order of a window to be above other sibling windows. ```go win.Stack(xproto.StackModeAbove) ``` -------------------------------- ### Move a Window Source: https://context7.com/burntsushi/xgbutil/llms.txt Changes the position of an existing window on the screen. ```go win.Move(100, 100) ``` -------------------------------- ### Resize a Window Source: https://context7.com/burntsushi/xgbutil/llms.txt Changes the dimensions of an existing window. ```go win.Resize(500, 400) ``` -------------------------------- ### Move and Resize a Window Simultaneously Source: https://context7.com/burntsushi/xgbutil/llms.txt Adjusts both the position and dimensions of a window in a single operation. ```go win.MoveResize(200, 200, 600, 500) ``` -------------------------------- ### Handle Mouse Button Release Events Source: https://context7.com/burntsushi/xgbutil/llms.txt Connects a function to handle ButtonRelease events for a specific window. Useful for simple click detection. ```go err = mousebind.ButtonReleaseFun(func(X *xgbutil.XUtil, e xevent.ButtonReleaseEvent) { log.Printf("Click at (%d, %d)", e.EventX, e.EventY) }).Connect(X, win.Id, "1", false, false) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.