Skip to content

2 Rigging up the server

Lukas edited this page Mar 23, 2019 · 1 revision

Commit: 45775df

So we've started up the backend and we're rendering something interesting, but we still aren't running a Wayland server -- Wayland clients aren't connecting to our application. Adding this is actually quite easy:

 func main() {
     server := new(Server)
     
     server.outputs = make([]*Output, 0)
     
     server.display = wlroots.NewDisplay()
     server.backend = wlroots.NewBackend(server.display)
     
     server.backend.OnNewOutput(server.newOuput)
     
+    // setup socket for wayland clients to connect to
+    socket, err := server.display.AddSocketAuto()
+    if err != nil {
+        panic(err)
+    }
     
     // start the backend
     err = server.backend.Start()
     if err != nil {
        panic(err)
     }
     
+    fmt.Printf("Running compositor on wayland display '%s'\n", socket)
+    err = os.Setenv("WAYLAND_DISPLAY", socket)
+    if err != nil {
+       panic(err)
+    }
     
     // and run the display
     server.display.Run()
 }

That's it! If you run McWayface again, it'll print something like this:

Running compositor on wayland display 'wayland-1'

Weston, the Wayland reference compositor, includes a number of simple reference clients. We can use weston-info to connect to our server and list the globals:

$ WAYLAND_DISPLAY=wayland-1 weston-info
interface: 'wl_drm', version: 2, name: 1

If you recall from the Introduction to Wayland, the Wayland server exports a list of globals to clients via the Wayland registry. These globals provide interfaces the client can utilize to interact with the server. We get wl_drm for free with wlroots, but we have not actually wired up anything useful yet. Wlroots provides many "types", of which the majority are implementations of Wayland global interfaces like this.

Some of the wlroots implementations require some rigging from you, but several of them just take care of themselves. Rigging one up is easy:

 func main() {
     server := new(Server)
     
     server.outputs = make([]*Output, 0)
     
     server.display = wlroots.NewDisplay()
     server.backend = wlroots.NewBackend(server.display)
     
     server.backend.OnNewOutput(server.newOuput)
     server.backend.Renderer().InitDisplay(server.display)
     
+    // configure seat
+    server.seat = wlroots.NewSeat(server.display, "seat0")

If we use weston-info again, we should se an additional interface:

interface: 'wl_drm', version: 2, name: 3
interface: 'wl_seat', version: 6, name: 4
        name: seat0
        capabilities:

Some of these interfaces require additional information. Again, we can use globals in order to make the information available. A useful one is:

 func (s *Server) newOuput(output wlroots.Output) {
     out := &Output{
        wlrOutput: output,
        lastFrame: time.Now(),
        color:     [4]float32{1, 0, 0, 1},
     }
     
+    output.CreateGlobal()

It's as simple as that. (Unfortunately, creating other custom globals not possible with go-wlroots currently.) weston-info now shows more info about our outputs:

interface: 'wl_drm', version: 2, name: 3
interface: 'wl_seat', version: 6, name: 4
        name: seat0
        capabilities:
interface: 'wl_output', version: 3, name: 5
        x: 0, y: 0, scale: 1,
        physical_width: 0 mm, physical_height: 0 mm,
        make: 'wayland', model: 'wayland',
        subpixel_orientation: unknown, output_transform: normal,
        mode:
                width: 630 px, height: 1056 px, refresh: 0.000 Hz,
                flags: current

Clone this wiki locally