summaryrefslogtreecommitdiffstats
path: root/_posts/2018-02-22-Writing-a-wayland-compositor-part-2.md
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2018-02-22 22:57:17 -0500
committerDrew DeVault <sir@cmpwn.com>2018-02-22 22:57:17 -0500
commit42689d69cbf70839ba3c4f19900b991c6a4461d2 (patch)
treeff339568f10d20be32ccc2aa9a037d171a6b0a43 /_posts/2018-02-22-Writing-a-wayland-compositor-part-2.md
parent2fb59468784f77892b27f42a67db36f98d04e5a1 (diff)
Wayland compositor part 2
Diffstat (limited to '_posts/2018-02-22-Writing-a-wayland-compositor-part-2.md')
-rw-r--r--_posts/2018-02-22-Writing-a-wayland-compositor-part-2.md162
1 files changed, 162 insertions, 0 deletions
diff --git a/_posts/2018-02-22-Writing-a-wayland-compositor-part-2.md b/_posts/2018-02-22-Writing-a-wayland-compositor-part-2.md
new file mode 100644
index 0000000..fc7bb7a
--- /dev/null
+++ b/_posts/2018-02-22-Writing-a-wayland-compositor-part-2.md
@@ -0,0 +1,162 @@
+---
+title: "Writing a Wayland Compositor, Part 2: Rigging up the server"
+layout: post
+---
+
+This is the second in a series of articles on the subject of writing a Wayland
+compositor from scratch using [wlroots](https://github.com/swaywm/wlroots).
+Check out [the first article](/2018/02/17/Writing-a-Wayland-compositor-1.html)
+if you haven't already. Last time, we ended up with an application which fired
+up a wlroots backend, enumerated output devices, and drew some pretty colors on
+the screen. Today, we're going to start accepting Wayland client connections,
+though we aren't going to be doing much with them yet.
+
+The commit that this article dissects is
+[b45c651](https://github.com/SirCmpwn/mcwayland/commit/b45c651).
+
+A quick aside on the nature of these blog posts: it's going to take *a lot* of
+these articles to flesh out our compositor. I'm going to be publishing these
+more frequently than usual, probably 1-2 per week, and continue posting my usual
+articles at the typical rate. Okay? Cool.
+
+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:
+
+```diff
+@@ -113,12 +113,18 @@ int main(int argc, char **argv) {
+ server.new_output.notify = new_output_notify;
+ wl_signal_add(&server.backend->events.new_output, &server.new_output);
+
++ const char *socket = wl_display_add_socket_auto(server.wl_display);
++ assert(socket);
++
+ if (!wlr_backend_start(server.backend)) {
+ fprintf(stderr, "Failed to start backend\n");
+ wl_display_destroy(server.wl_display);
+ return 1;
+ }
+
++ printf("Running compositor on wayland display '%s'\n", socket);
++ setenv("WAYLAND_DISPLAY", socket, true);
++
+ wl_display_run(server.wl_display);
+ wl_display_destroy(server.wl_display);
+ return 0;
+```
+
+That's it! If you run McWayface again, it'll print something like this:
+
+```
+Running compositor on wayland display 'wayland-1'
+```
+
+[Weston](https://cgit.freedesktop.org/wayland/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 my [Introduction to
+Wayland](/2017/06/10/Introduction-to-Wayland.html), 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 these up is easy:
+
+```diff
+ printf("Running compositor on wayland display '%s'\n", socket);
+ setenv("WAYLAND_DISPLAY", socket, true);
++
++ wl_display_init_shm(server.wl_display);
++ wlr_gamma_control_manager_create(server.wl_display);
++ wlr_screenshooter_create(server.wl_display);
++ wlr_primary_selection_device_manager_create(server.wl_display);
++ wlr_idle_create(server.wl_display);
+
+ wl_display_run(server.wl_display);
+ wl_display_destroy(server.wl_display);
+```
+
+Note that some of these interfaces are not necessarily ones that you typically
+would want to expose to all Wayland clients - screenshooter, for example, is
+something that should be secured. We'll get to security in a later article. For
+now, if we run `weston-info` again, we'll see a few more globals have appeared:
+
+```
+$ WAYLAND_DISPLAY=wayland-1 weston-info
+interface: 'wl_shm', version: 1, name: 3
+ formats: XRGB8888 ARGB8888
+interface: 'wl_drm', version: 2, name: 1
+interface: 'gamma_control_manager', version: 1, name: 2
+interface: 'orbital_screenshooter', version: 1, name: 3
+interface: 'gtk_primary_selection_device_manager', version: 1, name: 4
+interface: 'org_kde_kwin_idle', version: 1, name: 5
+```
+
+You'll find that wlroots implements a variety of protocols from a variety of
+sources - here we see protocols from Orbital, GTK, and KDE represented. Wlroots
+includes an example client for the orbital screenshooter - we can use it now to
+take a screenshot of our compositor:
+
+```
+$ WAYLAND_DISPLAY=wayland-1 ./examples/screenshot
+cannot set buffer size
+```
+
+Ah, this is a problem - you may have noticed that we don't have any wl_output
+globals, which the screenshooter client relies on to figure out the resolution
+of the screenshot buffer. We can add these, too:
+
+```diff
+@@ -95,6 +99,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) {
+ wl_signal_add(&wlr_output->events.destroy, &output->destroy);
+ output->frame.notify = output_frame_notify;
+ wl_signal_add(&wlr_output->events.frame, &output->frame);
++
++ wlr_output_create_global(wlr_output);
+ }
+```
+
+Running `weston-info` again will give us some info about our outputs now:
+
+```
+$ WAYLAND_DISPLAY=wayland-1 weston-info
+interface: 'wl_drm', version: 2, name: 1
+interface: 'wl_output', version: 3, name: 2
+ 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: 952 px, height: 521 px, refresh: 0.000 Hz,
+ flags: current
+interface: 'wl_shm', version: 1, name: 3
+ formats: XRGB8888 ARGB8888
+interface: 'gamma_control_manager', version: 1, name: 4
+interface: 'orbital_screenshooter', version: 1, name: 5
+interface: 'gtk_primary_selection_device_manager', version: 1, name: 6
+interface: 'org_kde_kwin_idle', version: 1, name: 7
+```
+
+Now we can take that screenshot! Give it a shot (heh)!
+
+We're getting close to the good stuff now. The next article is going to
+introduce the concept of **surfaces**, and we will use them to render our first
+window. If you had any trouble with this article, please reach out to me at
+[sir@cmpwn.com](mailto:sir@cmpwn.com) or to the wlroots team at
+[#sway-devel](http://webchat.freenode.net/?channels=sway-devel&uio=d4).
+
+<p>
+ Previous &mdash;
+ <a href="/2018/02/17/Writing-a-Wayland-compositor-1.html">
+ Part 1: Hello wlroots
+ </a>
+</p>