Commit 057086e389a78c600c0862ea331aa9b834ffbb43

Frank Praznik 2022-07-15T13:44:49

wayland: Add high resolution scroll wheel support Update the Wayland core protocol spec file and add support for the new axis_value120 event to handle high resolution scroll wheels. The axis_value120 replaces the axis_discrete event, which is no longer sent as of version 8 of the protocol. Note that unlike the axis_discrete event, no mention in the spec is made regarding how many axis_value120 events may occur per-axis per-frame, so the values are accumulated and committed when the pointer frame event occurs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 14a2843..94374ea 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -632,37 +632,75 @@ pointer_handle_axis_common_v1(struct SDL_WaylandInput *input,
 }
 
 static void
-pointer_handle_axis_common(struct SDL_WaylandInput *input, SDL_bool discrete,
+pointer_handle_axis_common(struct SDL_WaylandInput *input, enum SDL_WaylandAxisEvent type,
                            uint32_t axis, wl_fixed_t value)
 {
     enum wl_pointer_axis a = axis;
 
     if (input->pointer_focus) {
         switch (a) {
-            case WL_POINTER_AXIS_VERTICAL_SCROLL:
-                if (discrete) {
-                    /* this is a discrete axis event so we process it and flag
-                     * to ignore future continuous axis events in this frame */
-                    input->pointer_curr_axis_info.is_y_discrete = SDL_TRUE;
-                } else if(input->pointer_curr_axis_info.is_y_discrete) {
-                    /* this is a continuous axis event and we have already
-                     * processed a discrete axis event before so we ignore it */
-                    break;
+        case WL_POINTER_AXIS_VERTICAL_SCROLL:
+            switch (type) {
+            case AXIS_EVENT_VALUE120:
+                /*
+                 * High resolution scroll event. The spec doesn't state that axis_value120
+                 * events are limited to one per frame, so the values are accumulated.
+                 */
+                if (input->pointer_curr_axis_info.y_axis_type != AXIS_EVENT_VALUE120) {
+                    input->pointer_curr_axis_info.y_axis_type = AXIS_EVENT_VALUE120;
+                    input->pointer_curr_axis_info.y = 0.0f;
                 }
-                input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(value);
+                input->pointer_curr_axis_info.y += 0 - (float)wl_fixed_to_double(value);
                 break;
-            case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
-                if (discrete) {
-                    /* this is a discrete axis event so we process it and flag
-                     * to ignore future continuous axis events in this frame */
-                    input->pointer_curr_axis_info.is_x_discrete = SDL_TRUE;
-                } else if(input->pointer_curr_axis_info.is_x_discrete) {
-                    /* this is a continuous axis event and we have already
-                     * processed a discrete axis event before so we ignore it */
-                    break;
+            case AXIS_EVENT_DISCRETE:
+                /*
+                 * This is a discrete axis event, so we process it and set the
+                 * flag to ignore future continuous axis events in this frame.
+                 */
+                if (input->pointer_curr_axis_info.y_axis_type != AXIS_EVENT_DISCRETE) {
+                    input->pointer_curr_axis_info.y_axis_type = AXIS_EVENT_DISCRETE;
+                    input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(value);
+                }
+                break;
+            case AXIS_EVENT_CONTINUOUS:
+                /* Only process continuous events if no discrete events have been received. */
+                if (input->pointer_curr_axis_info.y_axis_type == AXIS_EVENT_CONTINUOUS) {
+                    input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(value);
+                }
+                break;
+            }
+            break;
+        case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+            switch (type) {
+            case AXIS_EVENT_VALUE120:
+                /*
+                 * High resolution scroll event. The spec doesn't state that axis_value120
+                 * events are limited to one per frame, so the values are accumulated.
+                 */
+                if (input->pointer_curr_axis_info.x_axis_type != AXIS_EVENT_VALUE120) {
+                    input->pointer_curr_axis_info.x_axis_type = AXIS_EVENT_VALUE120;
+                    input->pointer_curr_axis_info.x = 0.0f;
+                }
+                input->pointer_curr_axis_info.x += (float)wl_fixed_to_double(value);
+                break;
+            case AXIS_EVENT_DISCRETE:
+                /*
+                 * This is a discrete axis event, so we process it and set the
+                 * flag to ignore future continuous axis events in this frame.
+                 */
+                if (input->pointer_curr_axis_info.x_axis_type != AXIS_EVENT_DISCRETE) {
+                    input->pointer_curr_axis_info.x_axis_type = AXIS_EVENT_DISCRETE;
+                    input->pointer_curr_axis_info.x = (float)wl_fixed_to_double(value);
                 }
-                input->pointer_curr_axis_info.x = (float)wl_fixed_to_double(value);
                 break;
+            case AXIS_EVENT_CONTINUOUS:
+                /* Only process continuous events if no discrete events have been received. */
+                if (input->pointer_curr_axis_info.x_axis_type == AXIS_EVENT_CONTINUOUS) {
+                    input->pointer_curr_axis_info.x = (float)wl_fixed_to_double(value);
+                }
+                break;
+            }
+            break;
         }
     }
 }
@@ -674,7 +712,7 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
     struct SDL_WaylandInput *input = data;
 
     if(wl_seat_get_version(input->seat) >= 5)
-        pointer_handle_axis_common(input, SDL_FALSE, axis, value);
+        pointer_handle_axis_common(input, AXIS_EVENT_CONTINUOUS, axis, value);
     else
         pointer_handle_axis_common_v1(input, time, axis, value);
 }
@@ -686,15 +724,29 @@ pointer_handle_frame(void *data, struct wl_pointer *pointer)
     SDL_WindowData *window = input->pointer_focus;
     float x, y;
 
-    if (input->pointer_curr_axis_info.is_x_discrete)
-        x = input->pointer_curr_axis_info.x;
-    else
+    switch(input->pointer_curr_axis_info.x_axis_type) {
+    case AXIS_EVENT_CONTINUOUS:
         x = input->pointer_curr_axis_info.x / WAYLAND_WHEEL_AXIS_UNIT;
+        break;
+    case AXIS_EVENT_DISCRETE:
+        x = input->pointer_curr_axis_info.x;
+        break;
+    case AXIS_EVENT_VALUE120:
+        x = input->pointer_curr_axis_info.x / 120.0f;
+        break;
+    }
 
-    if (input->pointer_curr_axis_info.is_y_discrete)
-        y = input->pointer_curr_axis_info.y;
-    else
+    switch(input->pointer_curr_axis_info.y_axis_type) {
+    case AXIS_EVENT_CONTINUOUS:
         y = input->pointer_curr_axis_info.y / WAYLAND_WHEEL_AXIS_UNIT;
+        break;
+    case AXIS_EVENT_DISCRETE:
+        y = input->pointer_curr_axis_info.y;
+        break;
+    case AXIS_EVENT_VALUE120:
+        y = input->pointer_curr_axis_info.y / 120.0f;
+        break;
+    }
 
     /* clear pointer_curr_axis_info for next frame */
     SDL_memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info);
@@ -725,9 +777,17 @@ pointer_handle_axis_discrete(void *data, struct wl_pointer *pointer,
 {
     struct SDL_WaylandInput *input = data;
 
-    pointer_handle_axis_common(input, SDL_TRUE, axis, wl_fixed_from_int(discrete));
+    pointer_handle_axis_common(input, AXIS_EVENT_DISCRETE, axis, wl_fixed_from_int(discrete));
 }
 
+static void
+pointer_handle_axis_value120(void *data, struct wl_pointer *pointer,
+                             uint32_t axis, int32_t value120)
+{
+    struct SDL_WaylandInput *input = data;
+
+    pointer_handle_axis_common(input, AXIS_EVENT_VALUE120, axis, wl_fixed_from_int(value120));
+}
 
 static const struct wl_pointer_listener pointer_listener = {
     pointer_handle_enter,
@@ -739,6 +799,7 @@ static const struct wl_pointer_listener pointer_listener = {
     pointer_handle_axis_source,     // Version 5
     pointer_handle_axis_stop,       // Version 5
     pointer_handle_axis_discrete,   // Version 5
+    pointer_handle_axis_value120    // Version 8
 };
 
 static void
diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h
index 9bcb2c9..491c385 100644
--- a/src/video/wayland/SDL_waylandevents_c.h
+++ b/src/video/wayland/SDL_waylandevents_c.h
@@ -29,6 +29,13 @@
 #include "SDL_waylanddatamanager.h"
 #include "SDL_waylandkeyboard.h"
 
+enum SDL_WaylandAxisEvent
+{
+    AXIS_EVENT_CONTINUOUS = 0,
+    AXIS_EVENT_DISCRETE,
+    AXIS_EVENT_VALUE120
+};
+
 struct SDL_WaylandTabletSeat;
 
 struct SDL_WaylandTabletObjectListNode {
@@ -113,10 +120,10 @@ struct SDL_WaylandInput {
 
     /* information about axis events on current frame */
     struct {
-        SDL_bool is_x_discrete;
+        enum SDL_WaylandAxisEvent x_axis_type;
         float x;
 
-        SDL_bool is_y_discrete;
+        enum SDL_WaylandAxisEvent y_axis_type;
         float y;
     } pointer_curr_axis_info;
 
diff --git a/wayland-protocols/wayland.xml b/wayland-protocols/wayland.xml
index 471daf6..10781cf 100644
--- a/wayland-protocols/wayland.xml
+++ b/wayland-protocols/wayland.xml
@@ -179,7 +179,7 @@
       the related request is done.
     </description>
 
-    <event name="done">
+    <event name="done" type="destructor">
       <description summary="done event">
 	Notify the client when the related request is done.
       </description>
@@ -187,7 +187,7 @@
     </event>
   </interface>
 
-  <interface name="wl_compositor" version="4">
+  <interface name="wl_compositor" version="5">
     <description summary="the compositor singleton">
       A compositor.  This object is a singleton global.  The
       compositor is in charge of combining the contents of multiple
@@ -258,6 +258,12 @@
 	for the pool from the file descriptor passed when the pool was
 	created, but using the new size.  This request can only be
 	used to make the pool bigger.
+
+        This request only changes the amount of bytes that are mmapped
+        by the server and does not touch the file corresponding to the
+        file descriptor passed at creation time. It is the client's
+        responsibility to ensure that the file is at least as big as
+        the new pool size.
       </description>
       <arg name="size" type="int" summary="new size of the pool, in bytes"/>
     </request>
@@ -271,8 +277,8 @@
       Clients can create wl_shm_pool objects using the create_pool
       request.
 
-      At connection setup time, the wl_shm object emits one or more
-      format events to inform clients about the valid pixel formats
+      On binding the wl_shm object one or more format events
+      are emitted to inform clients about the valid pixel formats
       that can be used for buffers.
     </description>
 
@@ -296,6 +302,9 @@
 	The drm format codes match the macros defined in drm_fourcc.h, except
 	argb8888 and xrgb8888. The formats actually supported by the compositor
 	will be reported by the format event.
+
+	For all wl_shm formats and unless specified in another protocol
+	extension, pre-multiplied alpha is used for pixel values.
       </description>
       <!-- Note to protocol writers: don't update this list manually, instead
 	   run the automated script that keeps it in sync with drm_fourcc.h. -->
@@ -403,6 +412,10 @@
       <entry name="nv15" value="0x3531564e" summary="2x2 subsampled Cr:Cb plane"/>
       <entry name="q410" value="0x30313451"/>
       <entry name="q401" value="0x31303451"/>
+      <entry name="xrgb16161616" value="0x38345258" summary="[63:0] x:R:G:B 16:16:16:16 little endian"/>
+      <entry name="xbgr16161616" value="0x38344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
+      <entry name="argb16161616" value="0x38345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
+      <entry name="abgr16161616" value="0x38344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
     </enum>
 
     <request name="create_pool">
@@ -431,10 +444,15 @@
   <interface name="wl_buffer" version="1">
     <description summary="content for a wl_surface">
       A buffer provides the content for a wl_surface. Buffers are
-      created through factory interfaces such as wl_drm, wl_shm or
-      similar. It has a width and a height and can be attached to a
-      wl_surface, but the mechanism by which a client provides and
-      updates the contents is defined by the buffer factory interface.
+      created through factory interfaces such as wl_shm, wp_linux_buffer_params
+      (from the linux-dmabuf protocol extension) or similar. It has a width and
+      a height and can be attached to a wl_surface, but the mechanism by which a
+      client provides and updates the contents is defined by the buffer factory
+      interface.
+
+      If the buffer uses a format that has an alpha channel, the alpha channel
+      is assumed to be premultiplied in the color channels unless otherwise
+      specified.
     </description>
 
     <request name="destroy" type="destructor">
@@ -878,7 +896,7 @@
 	which will subsequently be used in either the
 	data_device.enter event (for drag-and-drop) or the
 	data_device.selection event (for selections).  Immediately
-	following the data_device_data_offer event, the new data_offer
+	following the data_device.data_offer event, the new data_offer
 	object will send out data_offer.offer events to describe the
 	mime types it offers.
       </description>
@@ -948,9 +966,10 @@
 	immediately before receiving keyboard focus and when a new
 	selection is set while the client has keyboard focus.  The
 	data_offer is valid until a new data_offer or NULL is received
-	or until the client loses keyboard focus.  The client must
-	destroy the previous selection data_offer, if any, upon receiving
-	this event.
+	or until the client loses keyboard focus.  Switching surface with
+	keyboard focus within the same client doesn't mean a new selection
+	will be sent.  The client must destroy the previous selection
+	data_offer, if any, upon receiving this event.
       </description>
       <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
 	   summary="selection data_offer object"/>
@@ -1038,7 +1057,8 @@
       a basic surface.
 
       Note! This protocol is deprecated and not intended for production use.
-      For desktop-style user interfaces, use xdg_shell.
+      For desktop-style user interfaces, use xdg_shell. Compositors and clients
+      should not implement this interface.
     </description>
 
     <enum name="error">
@@ -1332,7 +1352,7 @@
     </event>
   </interface>
 
-  <interface name="wl_surface" version="4">
+  <interface name="wl_surface" version="5">
     <description summary="an onscreen surface">
       A surface is a rectangular area that may be displayed on zero
       or more outputs, and shown any number of times at the compositor's
@@ -1384,6 +1404,7 @@
       <entry name="invalid_scale" value="0" summary="buffer scale value is invalid"/>
       <entry name="invalid_transform" value="1" summary="buffer transform value is invalid"/>
       <entry name="invalid_size" value="2" summary="buffer size is invalid"/>
+      <entry name="invalid_offset" value="3" summary="buffer offset is invalid"/>
     </enum>
 
     <request name="destroy" type="destructor">
@@ -1406,7 +1427,14 @@
 	buffer's upper left corner, relative to the current buffer's upper
 	left corner, in surface-local coordinates. In other words, the
 	x and y, combined with the new surface size define in which
-	directions the surface's size changes.
+	directions the surface's size changes. Setting anything other than 0
+	as x and y arguments is discouraged, and should instead be replaced
+	with using the separate wl_surface.offset request.
+
+	When the bound wl_surface version is 5 or higher, passing any
+	non-zero x or y is a protocol violation, and will result in an
+	'invalid_offset' error being raised. To achieve equivalent semantics,
+	use wl_surface.offset.
 
 	Surface contents are double-buffered state, see wl_surface.commit.
 
@@ -1434,9 +1462,12 @@
 	from the same backing storage or use wp_linux_buffer_release.
 
 	Destroying the wl_buffer after wl_buffer.release does not change
-	the surface contents. However, if the client destroys the
-	wl_buffer before receiving the wl_buffer.release event, the surface
-	contents become undefined immediately.
+	the surface contents. Destroying the wl_buffer before wl_buffer.release
+	is allowed as long as the underlying buffer storage isn't re-used (this
+	can happen e.g. on client process termination). However, if the client
+	destroys the wl_buffer before receiving the wl_buffer.release event and
+	mutates the underlying buffer storage, the surface contents become
+	undefined immediately.
 
 	If wl_surface.attach is sent with a NULL wl_buffer, the
 	following wl_surface.commit will remove the surface content.
@@ -1734,9 +1765,30 @@
       <arg name="width" type="int" summary="width of damage rectangle"/>
       <arg name="height" type="int" summary="height of damage rectangle"/>
     </request>
+
+    <!-- Version 5 additions -->
+
+    <request name="offset" since="5">
+      <description summary="set the surface contents offset">
+	The x and y arguments specify the location of the new pending
+	buffer's upper left corner, relative to the current buffer's upper
+	left corner, in surface-local coordinates. In other words, the
+	x and y, combined with the new surface size define in which
+	directions the surface's size changes.
+
+	Surface location offset is double-buffered state, see
+	wl_surface.commit.
+
+	This request is semantically equivalent to and the replaces the x and y
+	arguments in the wl_surface.attach request in wl_surface versions prior
+	to 5. See wl_surface.attach for details.
+      </description>
+      <arg name="x" type="int" summary="surface-local x coordinate"/>
+      <arg name="y" type="int" summary="surface-local y coordinate"/>
+    </request>
    </interface>
 
-  <interface name="wl_seat" version="7">
+  <interface name="wl_seat" version="8">
     <description summary="group of input devices">
       A seat is a group of keyboards, pointer and touch devices. This
       object is published as a global during start up, or when such a
@@ -1838,9 +1890,22 @@
 
     <event name="name" since="2">
       <description summary="unique identifier for this seat">
-	In a multiseat configuration this can be used by the client to help
-	identify which physical devices the seat represents. Based on
-	the seat configuration used by the compositor.
+	In a multi-seat configuration the seat name can be used by clients to
+	help identify which physical devices the seat represents.
+
+	The seat name is a UTF-8 string with no convention defined for its
+	contents. Each name is unique among all wl_seat globals. The name is
+	only guaranteed to be unique for the current compositor instance.
+
+	The same seat names are used for all clients. Thus, the name can be
+	shared across processes to refer to a specific wl_seat global.
+
+	The name event is sent after binding to the seat global. This event is
+	only sent once per seat object, and the name does not change over the
+	lifetime of the wl_seat global.
+
+	Compositors may re-use the same seat name if the wl_seat global is
+	destroyed and re-created later.
       </description>
       <arg name="name" type="string" summary="seat identifier"/>
     </event>
@@ -1856,7 +1921,7 @@
 
   </interface>
 
-  <interface name="wl_pointer" version="7">
+  <interface name="wl_pointer" version="8">
     <description summary="pointer input device">
       The wl_pointer interface represents one or more input devices,
       such as mice, which control the pointer location and pointer_focus
@@ -1905,6 +1970,10 @@
 	wl_surface is no longer used as the cursor. When the use as a
 	cursor ends, the current and pending input regions become
 	undefined, and the wl_surface is unmapped.
+
+	The serial parameter must match the latest wl_pointer.enter
+	serial number sent to the client. Otherwise the request will be
+	ignored.
       </description>
       <arg name="serial" type="uint" summary="serial number of the enter event"/>
       <arg name="surface" type="object" interface="wl_surface" allow-null="true"
@@ -2152,6 +2221,9 @@
 	This event carries the axis value of the wl_pointer.axis event in
 	discrete steps (e.g. mouse wheel clicks).
 
+	This event is deprecated with wl_pointer version 8 - this event is not
+	sent to clients supporting version 8 or later.
+
 	This event does not occur on its own, it is coupled with a
 	wl_pointer.axis event that represents this axis value on a
 	continuous scale. The protocol guarantees that each axis_discrete
@@ -2159,7 +2231,8 @@
 	axis number within the same wl_pointer.frame. Note that the protocol
 	allows for other events to occur between the axis_discrete and
 	its coupled axis event, including other axis_discrete or axis
-	events.
+	events. A wl_pointer.frame must not contain more than one axis_discrete
+	event per axis type.
 
 	This event is optional; continuous scrolling devices
 	like two-finger scrolling on touchpads do not have discrete
@@ -2177,9 +2250,37 @@
       <arg name="axis" type="uint" enum="axis" summary="axis type"/>
       <arg name="discrete" type="int" summary="number of steps"/>
     </event>
+
+    <event name="axis_value120" since="8">
+      <description summary="axis high-resolution scroll event">
+	Discrete high-resolution scroll information.
+
+	This event carries high-resolution wheel scroll information,
+	with each multiple of 120 representing one logical scroll step
+	(a wheel detent). For example, an axis_value120 of 30 is one quarter of
+	a logical scroll step in the positive direction, a value120 of
+	-240 are two logical scroll steps in the negative direction within the
+	same hardware event.
+	Clients that rely on discrete scrolling should accumulate the
+	value120 to multiples of 120 before processing the event.
+
+	The value120 must not be zero.
+
+	This event replaces the wl_pointer.axis_discrete event in clients
+	supporting wl_pointer version 8 or later.
+
+	Where a wl_pointer.axis_source event occurs in the same
+	wl_pointer.frame, the axis source applies to this event.
+
+	The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
+	not guaranteed.
+      </description>
+      <arg name="axis" type="uint" enum="axis" summary="axis type"/>
+      <arg name="value120" type="int" summary="scroll distance as fraction of 120"/>
+    </event>
   </interface>
 
-  <interface name="wl_keyboard" version="7">
+  <interface name="wl_keyboard" version="8">
     <description summary="keyboard input device">
       The wl_keyboard interface represents one or more keyboards
       associated with a seat.
@@ -2193,13 +2294,14 @@
       <entry name="no_keymap" value="0"
 	     summary="no keymap; client must understand how to interpret the raw keycode"/>
       <entry name="xkb_v1" value="1"
-	     summary="libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
+	     summary="libxkbcommon compatible, null-terminated string; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
     </enum>
 
     <event name="keymap">
       <description summary="keyboard mapping">
 	This event provides a file descriptor to the client which can be
-	memory-mapped to provide a keyboard mapping description.
+	memory-mapped in read-only mode to provide a keyboard mapping
+	description.
 
 	From version 7 onwards, the fd must be mapped with MAP_PRIVATE by
 	the recipient, as MAP_SHARED may fail.
@@ -2305,7 +2407,7 @@
     </event>
   </interface>
 
-  <interface name="wl_touch" version="7">
+  <interface name="wl_touch" version="8">
     <description summary="touchscreen input device">
       The wl_touch interface represents a touchscreen
       associated with a seat.
@@ -2449,7 +2551,7 @@
     </event>
   </interface>
 
-  <interface name="wl_output" version="3">
+  <interface name="wl_output" version="4">
     <description summary="compositor output region">
       An output describes part of the compositor geometry.  The
       compositor works in the 'compositor coordinate system' and an
@@ -2505,12 +2607,15 @@
 	The physical size can be set to zero if it doesn't make sense for this
 	output (e.g. for projectors or virtual outputs).
 
+	The geometry event will be followed by a done event (starting from
+	version 2).
+
 	Note: wl_output only advertises partial information about the output
 	position and identification. Some compositors, for instance those not
 	implementing a desktop-style output layout or those exposing virtual
 	outputs, might fake this information. Instead of using x and y, clients
 	should use xdg_output.logical_position. Instead of using make and model,
-	clients should use xdg_output.name and xdg_output.description.
+	clients should use name and description.
       </description>
       <arg name="x" type="int"
 	   summary="x position within the global compositor space"/>
@@ -2566,6 +2671,9 @@
 	The vertical refresh rate can be set to zero if it doesn't make
 	sense for this output (e.g. for virtual outputs).
 
+	The mode event will be followed by a done event (starting from
+	version 2).
+
 	Clients should not use the refresh rate to schedule frames. Instead,
 	they should use the wl_surface.frame event or the presentation-time
 	protocol.
@@ -2612,6 +2720,8 @@
 	the scale of the output. That way the compositor can
 	avoid scaling the surface, and the client can supply
 	a higher detail image.
+
+	The scale event will be followed by a done event.
       </description>
       <arg name="factor" type="int" summary="scaling factor of output"/>
     </event>
@@ -2624,6 +2734,62 @@
 	use the output object anymore.
       </description>
     </request>
+
+    <!-- Version 4 additions -->
+
+    <event name="name" since="4">
+      <description summary="name of this output">
+	Many compositors will assign user-friendly names to their outputs, show
+	them to the user, allow the user to refer to an output, etc. The client
+	may wish to know this name as well to offer the user similar behaviors.
+
+	The name is a UTF-8 string with no convention defined for its contents.
+	Each name is unique among all wl_output globals. The name is only
+	guaranteed to be unique for the compositor instance.
+
+	The same output name is used for all clients for a given wl_output
+	global. Thus, the name can be shared across processes to refer to a
+	specific wl_output global.
+
+	The name is not guaranteed to be persistent across sessions, thus cannot
+	be used to reliably identify an output in e.g. configuration files.
+
+	Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
+	not assume that the name is a reflection of an underlying DRM connector,
+	X11 connection, etc.
+
+	The name event is sent after binding the output object. This event is
+	only sent once per output object, and the name does not change over the
+	lifetime of the wl_output global.
+
+	Compositors may re-use the same output name if the wl_output global is
+	destroyed and re-created later. Compositors should avoid re-using the
+	same name if possible.
+
+	The name event will be followed by a done event.
+      </description>
+      <arg name="name" type="string" summary="output name"/>
+    </event>
+
+    <event name="description" since="4">
+      <description summary="human-readable description of this output">
+	Many compositors can produce human-readable descriptions of their
+	outputs. The client may wish to know this description as well, e.g. for
+	output selection purposes.
+
+	The description is a UTF-8 string with no convention defined for its
+	contents. The description is not guaranteed to be unique among all
+	wl_output globals. Examples might include 'Foocorp 11" Display' or
+	'Virtual X11 output via :1'.
+
+	The description event is sent after binding the output object and
+	whenever the description changes. The description is optional, and may
+	not be sent at all.
+
+	The description event will be followed by a done event.
+      </description>
+      <arg name="description" type="string" summary="output description"/>
+    </event>
   </interface>
 
   <interface name="wl_region" version="1">