func main() {
	X, err := xgb.NewConn()
	if err != nil {
		fmt.Println(err)
		return
	}

	// xproto.Setup retrieves the Setup information from the setup bytes
	// gathered during connection.
	setup := xproto.Setup(X)

	// This is the default screen with all its associated info.
	screen := setup.DefaultScreen(X)

	// Any time a new resource (i.e., a window, pixmap, graphics context, etc.)
	// is created, we need to generate a resource identifier.
	// If the resource is a window, then use xproto.NewWindowId. If it's for
	// a pixmap, then use xproto.NewPixmapId. And so on...
	wid, _ := xproto.NewWindowId(X)

	// CreateWindow takes a boatload of parameters.
	xproto.CreateWindow(X, screen.RootDepth, wid, screen.Root,
		0, 0, 500, 500, 0,
		xproto.WindowClassInputOutput, screen.RootVisual, 0, []uint32{})

	// This call to ChangeWindowAttributes could be factored out and
	// included with the above CreateWindow call, but it is left here for
	// instructive purposes. It tells X to send us events when the 'structure'
	// of the window is changed (i.e., when it is resized, mapped, unmapped,
	// etc.) and when a key press or a key release has been made when the
	// window has focus.
	// We also set the 'BackPixel' to white so that the window isn't butt ugly.
	xproto.ChangeWindowAttributes(X, wid,
		xproto.CwBackPixel|xproto.CwEventMask,
		[]uint32{ // values must be in the order defined by the protocol
			0xffffffff,
			xproto.EventMaskStructureNotify |
				xproto.EventMaskKeyPress |
				xproto.EventMaskKeyRelease})

	// MapWindow makes the window we've created appear on the screen.
	// We demonstrated the use of a 'checked' request here.
	// A checked request is a fancy way of saying, "do error handling
	// synchronously." Namely, if there is a problem with the MapWindow request,
	// we'll get the error *here*. If we were to do a normal unchecked
	// request (like the above CreateWindow and ChangeWindowAttributes
	// requests), then we would only see the error arrive in the main event
	// loop.
	//
	// Typically, checked requests are useful when you need to make sure they
	// succeed. Since they are synchronous, they incur a round trip cost before
	// the program can continue, but this is only going to be noticeable if
	// you're issuing tons of requests in succession.
	//
	// Note that requests without replies are by default unchecked while
	// requests *with* replies are checked by default.
	err = xproto.MapWindowChecked(X, wid).Check()
	if err != nil {
		fmt.Printf("Checked Error for mapping window %d: %s\n", wid, err)
	} else {
		fmt.Printf("Map window %d successful!\n", wid)
	}

	// This is an example of an invalid MapWindow request and what an error
	// looks like.
	err = xproto.MapWindowChecked(X, 0).Check()
	if err != nil {
		fmt.Printf("Checked Error for mapping window 0x1: %s\n", err)
	} else { // neva
		fmt.Printf("Map window 0x1 successful!\n")
	}

	// Start the main event loop.
	for {
		// WaitForEvent either returns an event or an error and never both.
		// If both are nil, then something went wrong and the loop should be
		// halted.
		//
		// An error can only be seen here as a response to an unchecked
		// request.
		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)
		}
	}
}
Exemple #2
0
func initDesktop(xScreen *xp.ScreenInfo) {
	xFont, err := xp.NewFontId(xConn)
	if err != nil {
		log.Fatal(err)
	}
	xCursor, err := xp.NewCursorId(xConn)
	if err != nil {
		log.Fatal(err)
	}
	err = xp.OpenFontChecked(xConn, xFont, uint16(len("cursor")), "cursor").Check()
	if err != nil {
		log.Fatal(err)
	}
	const xcLeftPtr = 68 // XC_left_ptr from cursorfont.h.
	err = xp.CreateGlyphCursorChecked(
		xConn, xCursor, xFont, xFont, xcLeftPtr, xcLeftPtr+1,
		0xffff, 0xffff, 0xffff, 0, 0, 0).Check()
	if err != nil {
		log.Fatal(err)
	}
	err = xp.CloseFontChecked(xConn, xFont).Check()
	if err != nil {
		log.Fatal(err)
	}

	desktopXWin, err = xp.NewWindowId(xConn)
	if err != nil {
		log.Fatal(err)
	}
	desktopXGC, err = xp.NewGcontextId(xConn)
	if err != nil {
		log.Fatal(err)
	}
	desktopWidth = xScreen.WidthInPixels
	desktopHeight = xScreen.HeightInPixels

	if err := xp.CreateWindowChecked(
		xConn, xScreen.RootDepth, desktopXWin, xScreen.Root,
		0, 0, desktopWidth, desktopHeight, 0,
		xp.WindowClassInputOutput,
		xScreen.RootVisual,
		xp.CwOverrideRedirect|xp.CwEventMask,
		[]uint32{
			1,
			xp.EventMaskExposure,
		},
	).Check(); err != nil {
		log.Fatal(err)
	}

	if len(xSettings) != 0 {
		initXSettings()
	}

	if err := xp.ConfigureWindowChecked(
		xConn,
		desktopXWin,
		xp.ConfigWindowStackMode,
		[]uint32{
			xp.StackModeBelow,
		},
	).Check(); err != nil {
		log.Fatal(err)
	}

	if err := xp.ChangeWindowAttributesChecked(
		xConn,
		desktopXWin,
		xp.CwBackPixel|xp.CwCursor,
		[]uint32{
			xScreen.BlackPixel,
			uint32(xCursor),
		},
	).Check(); err != nil {
		log.Fatal(err)
	}

	if err := xp.CreateGCChecked(
		xConn,
		desktopXGC,
		xp.Drawable(xScreen.Root),
		0,
		nil,
	).Check(); err != nil {
		log.Fatal(err)
	}

	if err := xp.MapWindowChecked(xConn, desktopXWin).Check(); err != nil {
		log.Fatal(err)
	}
}
Exemple #3
0
func manage(xWin xp.Window, mapRequest bool) {
	callFocus := false
	w := findWindow(func(w *window) bool { return w.xWin == xWin })
	if w == nil {
		wmDeleteWindow, wmTakeFocus := false, false
		if prop, err := xp.GetProperty(xConn, false, xWin, atomWMProtocols,
			xp.GetPropertyTypeAny, 0, 64).Reply(); err != nil {
			log.Println(err)
		} else if prop != nil {
			for v := prop.Value; len(v) >= 4; v = v[4:] {
				switch xp.Atom(u32(v)) {
				case atomWMDeleteWindow:
					wmDeleteWindow = true
				case atomWMTakeFocus:
					wmTakeFocus = true
				}
			}
		}

		transientFor := (*window)(nil)
		if prop, err := xp.GetProperty(xConn, false, xWin, atomWMTransientFor,
			xp.GetPropertyTypeAny, 0, 64).Reply(); err != nil {
			log.Println(err)
		} else if prop != nil {
			if v := prop.Value; len(v) == 4 {
				transientForXWin := xp.Window(u32(v))
				transientFor = findWindow(func(w *window) bool {
					return w.xWin == transientForXWin
				})
			}
		}

		k := screens[0].workspace
		if p, err := xp.QueryPointer(xConn, rootXWin).Reply(); err != nil {
			log.Println(err)
		} else if p != nil {
			k = screenContaining(p.RootX, p.RootY).workspace
		}
		w = &window{
			transientFor: transientFor,
			xWin:         xWin,
			rect: xp.Rectangle{
				X:      offscreenXY,
				Y:      offscreenXY,
				Width:  1,
				Height: 1,
			},
			wmDeleteWindow: wmDeleteWindow,
			wmTakeFocus:    wmTakeFocus,
		}
		f := k.focusedFrame
		previous := k.dummyWindow.link[prev]
		if transientFor != nil {
			previous = transientFor
		} else if f.window != nil {
			previous = f.window
		}
		w.link[next] = previous.link[next]
		w.link[prev] = previous
		w.link[next].link[prev] = w
		w.link[prev].link[next] = w

		if transientFor != nil && transientFor.frame != nil {
			f = transientFor.frame
			f.window, transientFor.frame = nil, nil
		} else if f.window != nil {
			f = k.mainFrame.firstEmptyFrame()
		}
		if f != nil {
			f.window, w.frame = w, f
			callFocus = f == k.focusedFrame
		} else {
			pulseChan <- time.Now()
		}

		check(xp.ChangeWindowAttributesChecked(xConn, xWin, xp.CwEventMask,
			[]uint32{xp.EventMaskEnterWindow | xp.EventMaskStructureNotify},
		))
		w.configure()
		if transientFor != nil {
			transientFor.hasTransientFor = true
			transientFor.configure()
		}
	}
	if mapRequest {
		check(xp.MapWindowChecked(xConn, xWin))
	}
	if callFocus {
		focus(w)
	}
	makeLists()
	pulseChan <- time.Now()
}