//! Generated by zig-wayland

const std = @import("std");
const assert = std.debug.assert;
const posix = std.posix;
const wayland = @This();

pub const client = struct {
    pub const wl = struct {
        pub const Object = common.Object;
        pub const Message = common.Message;
        pub const Interface = common.Interface;
        pub const list = common.list;
        pub const Array = common.Array;
        pub const Fixed = common.Fixed;
        pub const Argument = common.Argument;

        pub const Proxy = opaque {
            pub inline fn create(factory: *Proxy, interface: *const Interface) error{OutOfMemory}!*Proxy {
                return ffi.client.wl_proxy_create(factory, interface) orelse error.OutOfMemory;
            }

            pub inline fn destroy(proxy: *Proxy) void {
                ffi.client.wl_proxy_destroy(proxy);
            }

            pub inline fn marshal(proxy: *Proxy, opcode: u32, args: ?[*]Argument) void {
                ffi.client.wl_proxy_marshal_array(proxy, opcode, args);
            }

            pub inline fn marshalConstructor(
                proxy: *Proxy,
                opcode: u32,
                args: [*]Argument,
                interface: *const Interface,
            ) error{OutOfMemory}!*Proxy {
                return ffi.client.wl_proxy_marshal_array_constructor(proxy, opcode, args, interface) orelse
                    error.OutOfMemory;
            }

            pub inline fn marshalConstructorVersioned(
                proxy: *Proxy,
                opcode: u32,
                args: [*]Argument,
                interface: *const Interface,
                version: u32,
            ) error{OutOfMemory}!*Proxy {
                return ffi.client.wl_proxy_marshal_array_constructor_versioned(proxy, opcode, args, interface, version) orelse
                    error.OutOfMemory;
            }

            pub const DispatcherFn = fn (
                implementation: ?*const anyopaque,
                proxy: *Proxy,
                opcode: u32,
                message: *const Message,
                args: [*]Argument,
            ) callconv(.c) c_int;
            pub inline fn addDispatcher(
                proxy: *Proxy,
                dispatcher: *const DispatcherFn,
                implementation: ?*const anyopaque,
                data: ?*anyopaque,
            ) void {
                const ret = ffi.client.wl_proxy_add_dispatcher(proxy, dispatcher, implementation, data);
                // Since there is no way to remove listeners, adding a listener to
                // the same proxy twice is always a bug, so assert instead of returning
                // an error.
                assert(ret != -1); // If this fails, a listener was already added
            }

            pub inline fn getUserData(proxy: *Proxy) ?*anyopaque {
                return ffi.client.wl_proxy_get_user_data(proxy);
            }

            pub inline fn getVersion(proxy: *Proxy) u32 {
                return ffi.client.wl_proxy_get_version(proxy);
            }

            pub inline fn getId(proxy: *Proxy) u32 {
                return ffi.client.wl_proxy_get_id(proxy);
            }

            pub inline fn setQueue(proxy: *Proxy, queue: *EventQueue) void {
                ffi.client.wl_proxy_set_queue(proxy, queue);
            }
        };

        pub const EventQueue = opaque {
            pub inline fn destroy(queue: *EventQueue) void {
                ffi.client.wl_event_queue_destroy(queue);
            }
        };

        pub const EglWindow = opaque {
            pub inline fn create(surface: *client.wl.Surface, width: c_int, height: c_int) error{OutOfMemory}!*EglWindow {
                // Why do people use int when they require a positive number?
                assert(width > 0 and height > 0);
                return ffi.egl.wl_egl_window_create(surface, width, height) orelse error.OutOfMemory;
            }

            pub inline fn destroy(egl_window: *EglWindow) void {
                ffi.egl.wl_egl_window_destroy(egl_window);
            }

            pub inline fn resize(egl_window: *EglWindow, width: c_int, height: c_int, dx: c_int, dy: c_int) void {
                ffi.egl.wl_egl_window_resize(egl_window, width, height, dx, dy);
            }

            pub inline fn getAttachedSize(egl_window: *EglWindow, width: *c_int, height: *c_int) void {
                ffi.egl.wl_egl_window_get_attached_size(egl_window, width, height);
            }
        };

        pub const CursorTheme = opaque {
            pub inline fn load(name: ?[*:0]const u8, size: i32, shm: *client.wl.Shm) error{LoadThemeFailed}!*CursorTheme {
                return ffi.cursor.wl_cursor_theme_load(name, @intCast(size), shm) orelse error.LoadThemeFailed;
            }

            pub inline fn destroy(wl_cursor_theme: *CursorTheme) void {
                ffi.cursor.wl_cursor_theme_destroy(wl_cursor_theme);
            }

            pub inline fn getCursor(theme: *CursorTheme, name: [*:0]const u8) ?*Cursor {
                return ffi.cursor.wl_cursor_theme_get_cursor(theme, name);
            }
        };

        pub const Cursor = extern struct {
            image_count: c_uint,
            images: [*]*CursorImage,
            name: [*:0]u8,

            pub inline fn frame(cursor: *Cursor, time: u32) c_int {
                return ffi.cursor.wl_cursor_frame(cursor, time);
            }

            pub inline fn frameAndDuration(cursor: *Cursor, time: u32, duration: *u32) c_int {
                return ffi.cursor.wl_cursor_frame_and_duration(cursor, time, duration);
            }
        };

        pub const CursorImage = extern struct {
            width: u32,
            height: u32,
            hotspot_x: u32,
            hotspot_y: u32,
            delay: u32,

            pub inline fn getBuffer(image: *CursorImage) error{OutOfMemory}!*client.wl.Buffer {
                return ffi.cursor.wl_cursor_image_get_buffer(image) orelse error.OutOfMemory;
            }
        };

        /// The core global object.  This is a special singleton object.  It
        /// is used for internal Wayland protocol features.
        pub const Display = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.display.interface;
            pub const Error = common.wl.display.Error;
            pub inline fn getId(_display: *Display) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_display)).getId();
            }
            pub inline fn getVersion(_display: *Display) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_display)).getVersion();
            }
            pub inline fn getUserData(_display: *Display) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_display)).getUserData();
            }
            pub inline fn setQueue(_display: *Display, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_display);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const error_since_version = 1;
                pub const delete_id_since_version = 1;

                /// The error event is sent out when a fatal (non-recoverable)
                /// error has occurred.  The object_id argument is the object
                /// where the error occurred, most often in response to a request
                /// to that object.  The code identifies the error and is defined
                /// by the object interface.  As such, each interface defines its
                /// own set of error codes.  The message is a brief description
                /// of the error, for (debugging) convenience.
                @"error": struct {
                    object_id: ?*common.Object,
                    code: u32,
                    message: [*:0]const u8,
                },

                /// This event is used internally by the object ID management
                /// logic. When a client deletes an object that it had created,
                /// the server will send this event to acknowledge that it has
                /// seen the delete request. When the client receives this event,
                /// it will know that it can safely reuse the object ID.
                delete_id: struct {
                    id: u32,
                },
            };
            pub inline fn setListener(
                _display: *Display,
                comptime T: type,
                _listener: *const fn (display: *Display, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_display);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Display, T).dispatcher, _listener, _mut_data);
            }
            /// The sync request asks the server to emit the 'done' event
            /// on the returned wl_callback object.  Since requests are
            /// handled in-order and events are delivered in-order, this can
            /// be used as a barrier to ensure all previous requests and the
            /// resulting events have been handled.
            ///
            /// The object returned by this request will be destroyed by the
            /// compositor after the callback is fired and as such the client must not
            /// attempt to use it after that point.
            ///
            /// The callback_data passed in the callback is undefined and should be ignored.
            pub fn sync(_display: *Display) !*client.wl.Callback {
                const _proxy: *client.wl.Proxy = @ptrCast(_display);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(0, &_args, client.wl.Callback.interface));
            }
            pub const sync_since_version = 1;

            /// This request creates a registry object that allows the client
            /// to list and bind the global objects available from the
            /// compositor.
            ///
            /// It should be noted that the server side resources consumed in
            /// response to a get_registry request can only be released when the
            /// client disconnects, not when the client side proxy is destroyed.
            /// Therefore, clients should invoke get_registry as infrequently as
            /// possible to avoid wasting memory.
            pub fn getRegistry(_display: *Display) !*client.wl.Registry {
                const _proxy: *client.wl.Proxy = @ptrCast(_display);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(1, &_args, client.wl.Registry.interface));
            }
            pub const get_registry_since_version = 1;
            pub inline fn connect(name: ?[*:0]const u8) error{ConnectFailed}!*Display {
                return ffi.client.wl_display_connect(name) orelse return error.ConnectFailed;
            }

            pub inline fn connectToFd(fd: c_int) error{ConnectFailed}!*Display {
                return ffi.client.wl_display_connect_to_fd(fd) orelse return error.ConnectFailed;
            }

            pub inline fn disconnect(display: *Display) void {
                ffi.client.wl_display_disconnect(display);
            }

            pub inline fn getFd(display: *Display) c_int {
                return ffi.client.wl_display_get_fd(display);
            }

            pub inline fn dispatch(display: *Display) posix.E {
                return posix.errno(ffi.client.wl_display_dispatch(display));
            }

            pub inline fn dispatchQueue(display: *Display, queue: *client.wl.EventQueue) posix.E {
                return posix.errno(ffi.client.wl_display_dispatch_queue(display, queue));
            }

            pub inline fn dispatchPending(display: *Display) posix.E {
                return posix.errno(ffi.client.wl_display_dispatch_pending(display));
            }

            pub inline fn dispatchQueuePending(display: *Display, queue: *client.wl.EventQueue) posix.E {
                return posix.errno(ffi.client.wl_display_dispatch_queue_pending(display, queue));
            }

            pub inline fn roundtrip(display: *Display) posix.E {
                return posix.errno(ffi.client.wl_display_roundtrip(display));
            }

            pub inline fn roundtripQueue(display: *Display, queue: *client.wl.EventQueue) posix.E {
                return posix.errno(ffi.client.wl_display_roundtrip_queue(display, queue));
            }

            pub inline fn flush(display: *Display) posix.E {
                return posix.errno(ffi.client.wl_display_flush(display));
            }

            pub inline fn createQueue(display: *Display) error{OutOfMemory}!*client.wl.EventQueue {
                return ffi.client.wl_display_create_queue(display) orelse error.OutOfMemory;
            }

            pub inline fn getError(display: *Display) c_int {
                return ffi.client.wl_display_get_error(display);
            }

            /// Succeeds if the queue is empty and returns true.
            /// Fails and returns false if the queue was not empty.
            pub inline fn prepareReadQueue(display: *Display, queue: *client.wl.EventQueue) bool {
                switch (ffi.client.wl_display_prepare_read_queue(display, queue)) {
                    0 => return true,
                    -1 => return false,
                    else => unreachable,
                }
            }

            /// Succeeds if the queue is empty and returns true.
            /// Fails and returns false if the queue was not empty.
            pub inline fn prepareRead(display: *Display) bool {
                switch (ffi.client.wl_display_prepare_read(display)) {
                    0 => return true,
                    -1 => return false,
                    else => unreachable,
                }
            }

            pub inline fn cancelRead(display: *Display) void {
                ffi.client.wl_display_cancel_read(display);
            }

            pub inline fn readEvents(display: *Display) posix.E {
                return posix.errno(ffi.client.wl_display_read_events(display));
            }
        };

        /// The singleton global registry object.  The server has a number of
        /// global objects that are available to all clients.  These objects
        /// typically represent an actual object in the server (for example,
        /// an input device) or they are singleton objects that provide
        /// extension functionality.
        ///
        /// When a client creates a registry object, the registry object
        /// will emit a global event for each global currently in the
        /// registry.  Globals come and go as a result of device or
        /// monitor hotplugs, reconfiguration or other events, and the
        /// registry will send out global and global_remove events to
        /// keep the client up to date with the changes.  To mark the end
        /// of the initial burst of events, the client can use the
        /// wl_display.sync request immediately after calling
        /// wl_display.get_registry.
        ///
        /// A client can bind to a global object by using the bind
        /// request.  This creates a client-side handle that lets the object
        /// emit events to the client and lets the client invoke requests on
        /// the object.
        pub const Registry = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.registry.interface;
            pub inline fn getId(_registry: *Registry) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_registry)).getId();
            }
            pub inline fn getVersion(_registry: *Registry) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_registry)).getVersion();
            }
            pub inline fn getUserData(_registry: *Registry) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_registry)).getUserData();
            }
            pub inline fn setQueue(_registry: *Registry, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_registry);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const global_since_version = 1;
                pub const global_remove_since_version = 1;

                /// Notify the client of global objects.
                ///
                /// The event notifies the client that a global object with
                /// the given name is now available, and it implements the
                /// given version of the given interface.
                global: struct {
                    name: u32,
                    interface: [*:0]const u8,
                    version: u32,
                },

                /// Notify the client of removed global objects.
                ///
                /// This event notifies the client that the global identified
                /// by name is no longer available.  If the client bound to
                /// the global using the bind request, the client should now
                /// destroy that object.
                ///
                /// The object remains valid and requests to the object will be
                /// ignored until the client destroys it, to avoid races between
                /// the global going away and a client sending a request to it.
                global_remove: struct {
                    name: u32,
                },
            };
            pub inline fn setListener(
                _registry: *Registry,
                comptime T: type,
                _listener: *const fn (registry: *Registry, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_registry);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Registry, T).dispatcher, _listener, _mut_data);
            }
            /// Binds a new, client-created object to the server using the
            /// specified name as the identifier.
            pub fn bind(_registry: *Registry, _name: u32, comptime T: type, _version: u32) !*T {
                const version_to_construct = @min(T.generated_version, _version);
                const _proxy: *client.wl.Proxy = @ptrCast(_registry);
                var _args = [_]common.Argument{
                    .{ .u = _name },
                    .{ .s = T.interface.name },
                    .{ .u = version_to_construct },
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructorVersioned(0, &_args, T.interface, version_to_construct));
            }
            pub const bind_since_version = 1;
            pub inline fn destroy(_registry: *Registry) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_registry);
                _proxy.destroy();
            }
        };

        /// Clients can handle the 'done' event to get notified when
        /// the related request is done.
        ///
        /// Note, because wl_callback objects are created from multiple independent
        /// factory interfaces, the wl_callback interface is frozen at version 1.
        pub const Callback = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.callback.interface;
            pub inline fn getId(_callback: *Callback) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_callback)).getId();
            }
            pub inline fn getVersion(_callback: *Callback) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_callback)).getVersion();
            }
            pub inline fn getUserData(_callback: *Callback) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_callback)).getUserData();
            }
            pub inline fn setQueue(_callback: *Callback, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_callback);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const done_since_version = 1;

                /// Notify the client when the related request is done.
                done: struct {
                    callback_data: u32,
                },
            };
            pub inline fn setListener(
                _callback: *Callback,
                comptime T: type,
                _listener: *const fn (callback: *Callback, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_callback);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Callback, T).dispatcher, _listener, _mut_data);
            }
            pub inline fn destroy(_callback: *Callback) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_callback);
                _proxy.destroy();
            }
        };

        /// A buffer provides the content for a wl_surface. Buffers are
        /// 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.
        ///
        /// Color channels are assumed to be electrical rather than optical (in other
        /// words, encoded with a transfer function) unless otherwise specified. If
        /// the buffer uses a format that has an alpha channel, the alpha channel is
        /// assumed to be premultiplied into the electrical color channel values
        /// (after transfer function encoding) unless otherwise specified.
        ///
        /// Note, because wl_buffer objects are created from multiple independent
        /// factory interfaces, the wl_buffer interface is frozen at version 1.
        pub const Buffer = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.buffer.interface;
            pub inline fn getId(_buffer: *Buffer) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_buffer)).getId();
            }
            pub inline fn getVersion(_buffer: *Buffer) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_buffer)).getVersion();
            }
            pub inline fn getUserData(_buffer: *Buffer) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_buffer)).getUserData();
            }
            pub inline fn setQueue(_buffer: *Buffer, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_buffer);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const release_since_version = 1;

                /// Sent when this wl_buffer is no longer used by the compositor.
                ///
                /// For more information on when release events may or may not be sent,
                /// and what consequences it has, please see the description of
                /// wl_surface.attach.
                ///
                /// If a client receives a release event before the frame callback
                /// requested in the same wl_surface.commit that attaches this
                /// wl_buffer to a surface, then the client is immediately free to
                /// reuse the buffer and its backing storage, and does not need a
                /// second buffer for the next surface content update. Typically
                /// this is possible, when the compositor maintains a copy of the
                /// wl_surface contents, e.g. as a GL texture. This is an important
                /// optimization for GL(ES) compositors with wl_shm clients.
                release: void,
            };
            pub inline fn setListener(
                _buffer: *Buffer,
                comptime T: type,
                _listener: *const fn (buffer: *Buffer, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_buffer);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Buffer, T).dispatcher, _listener, _mut_data);
            }
            /// Destroy a buffer. If and how you need to release the backing
            /// storage is defined by the buffer factory interface.
            ///
            /// For possible side-effects to a surface, see wl_surface.attach.
            pub fn destroy(_buffer: *Buffer) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_buffer);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;
        };

        /// A compositor.  This object is a singleton global.  The
        /// compositor is in charge of combining the contents of multiple
        /// surfaces into one displayable output.
        pub const Compositor = opaque {
            pub const generated_version = 4;
            pub const interface = &common.wl.compositor.interface;
            pub inline fn getId(_compositor: *Compositor) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_compositor)).getId();
            }
            pub inline fn getVersion(_compositor: *Compositor) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_compositor)).getVersion();
            }
            pub inline fn getUserData(_compositor: *Compositor) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_compositor)).getUserData();
            }
            pub inline fn setQueue(_compositor: *Compositor, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_compositor);
                _proxy.setQueue(_queue);
            }
            /// Ask the compositor to create a new surface.
            pub fn createSurface(_compositor: *Compositor) !*client.wl.Surface {
                const _proxy: *client.wl.Proxy = @ptrCast(_compositor);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(0, &_args, client.wl.Surface.interface));
            }
            pub const create_surface_since_version = 1;

            /// Ask the compositor to create a new region.
            pub fn createRegion(_compositor: *Compositor) !*client.wl.Region {
                const _proxy: *client.wl.Proxy = @ptrCast(_compositor);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(1, &_args, client.wl.Region.interface));
            }
            pub const create_region_since_version = 1;
            pub inline fn destroy(_compositor: *Compositor) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_compositor);
                _proxy.destroy();
            }
        };

        /// 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
        /// discretion. They can present wl_buffers, receive user input, and
        /// define a local coordinate system.
        ///
        /// The size of a surface (and relative positions on it) is described
        /// in surface-local coordinates, which may differ from the buffer
        /// coordinates of the pixel content, in case a buffer_transform
        /// or a buffer_scale is used.
        ///
        /// A surface without a "role" is fairly useless: a compositor does
        /// not know where, when or how to present it. The role is the
        /// purpose of a wl_surface. Examples of roles are a cursor for a
        /// pointer (as set by wl_pointer.set_cursor), a drag icon
        /// (wl_data_device.start_drag), a sub-surface
        /// (wl_subcompositor.get_subsurface), and a window as defined by a
        /// shell protocol (e.g. wl_shell.get_shell_surface).
        ///
        /// A surface can have only one role at a time. Initially a
        /// wl_surface does not have a role. Once a wl_surface is given a
        /// role, it is set permanently for the whole lifetime of the
        /// wl_surface object. Giving the current role again is allowed,
        /// unless explicitly forbidden by the relevant interface
        /// specification.
        ///
        /// Surface roles are given by requests in other interfaces such as
        /// wl_pointer.set_cursor. The request should explicitly mention
        /// that this request gives a role to a wl_surface. Often, this
        /// request also creates a new protocol object that represents the
        /// role and adds additional functionality to wl_surface. When a
        /// client wants to destroy a wl_surface, they must destroy this role
        /// object before the wl_surface, otherwise a defunct_role_object error is
        /// sent.
        ///
        /// Destroying the role object does not remove the role from the
        /// wl_surface, but it may stop the wl_surface from "playing the role".
        /// For instance, if a wl_subsurface object is destroyed, the wl_surface
        /// it was created for will be unmapped and forget its position and
        /// z-order. It is allowed to create a wl_subsurface for the same
        /// wl_surface again, but it is not allowed to use the wl_surface as
        /// a cursor (cursor is a different role than sub-surface, and role
        /// switching is not allowed).
        pub const Surface = opaque {
            pub const generated_version = 4;
            pub const interface = &common.wl.surface.interface;
            pub const Error = common.wl.surface.Error;
            pub inline fn getId(_surface: *Surface) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_surface)).getId();
            }
            pub inline fn getVersion(_surface: *Surface) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_surface)).getVersion();
            }
            pub inline fn getUserData(_surface: *Surface) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_surface)).getUserData();
            }
            pub inline fn setQueue(_surface: *Surface, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const enter_since_version = 1;
                pub const leave_since_version = 1;

                /// This is emitted whenever a surface's creation, movement, or resizing
                /// results in some part of it being within the scanout region of an
                /// output.
                ///
                /// Note that a surface may be overlapping with zero or more outputs.
                enter: struct {
                    output: ?*client.wl.Output,
                },

                /// This is emitted whenever a surface's creation, movement, or resizing
                /// results in it no longer having any part of it within the scanout region
                /// of an output.
                ///
                /// Clients should not use the number of outputs the surface is on for frame
                /// throttling purposes. The surface might be hidden even if no leave event
                /// has been sent, and the compositor might expect new surface content
                /// updates even if no enter event has been sent. The frame event should be
                /// used instead.
                leave: struct {
                    output: ?*client.wl.Output,
                },
            };
            pub inline fn setListener(
                _surface: *Surface,
                comptime T: type,
                _listener: *const fn (surface: *Surface, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Surface, T).dispatcher, _listener, _mut_data);
            }
            /// Deletes the surface and invalidates its object ID.
            pub fn destroy(_surface: *Surface) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// Set a buffer as the content of this surface.
            ///
            /// The new size of the surface is calculated based on the buffer
            /// size transformed by the inverse buffer_transform and the
            /// inverse buffer_scale. This means that at commit time the supplied
            /// buffer size must be an integer multiple of the buffer_scale. If
            /// that's not the case, an invalid_size error is sent.
            ///
            /// 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. 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. The x and y arguments are ignored
            /// and do not change the pending state. To achieve equivalent semantics,
            /// use wl_surface.offset.
            ///
            /// Surface contents are double-buffered state, see wl_surface.commit.
            ///
            /// The initial surface contents are void; there is no content.
            /// wl_surface.attach assigns the given wl_buffer as the pending
            /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
            /// surface contents, and the size of the surface becomes the size
            /// calculated from the wl_buffer, as described above. After commit,
            /// there is no pending buffer until the next attach.
            ///
            /// Committing a pending wl_buffer allows the compositor to read the
            /// pixels in the wl_buffer. The compositor may access the pixels at
            /// any time after the wl_surface.commit request. When the compositor
            /// will not access the pixels anymore, it will send the
            /// wl_buffer.release event. Only after receiving wl_buffer.release,
            /// the client may reuse the wl_buffer. A wl_buffer that has been
            /// attached and then replaced by another attach instead of committed
            /// will not receive a release event, and is not used by the
            /// compositor.
            ///
            /// If a pending wl_buffer has been committed to more than one wl_surface,
            /// the delivery of wl_buffer.release events becomes undefined. A well
            /// behaved client should not rely on wl_buffer.release events in this
            /// case. Instead, clients hitting this case should use
            /// wl_surface.get_release or use a protocol extension providing per-commit
            /// release notifications (if none of these options are available, a
            /// fallback can be implemented by creating multiple wl_buffer objects from
            /// the same backing storage).
            ///
            /// Destroying the wl_buffer after wl_buffer.release does not change
            /// 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.
            ///
            /// If a pending wl_buffer has been destroyed, the result is not specified.
            /// Many compositors are known to remove the surface content on the following
            /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
            /// maximise compatibility should not destroy pending buffers and should
            /// ensure that they explicitly remove content from surfaces, even after
            /// destroying buffers.
            pub fn attach(_surface: *Surface, _buffer: ?*client.wl.Buffer, _x: i32, _y: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .o = @ptrCast(_buffer) },
                    .{ .i = _x },
                    .{ .i = _y },
                };
                _proxy.marshal(1, &_args);
            }
            pub const attach_since_version = 1;

            /// This request is used to describe the regions where the pending
            /// buffer is different from the current surface contents, and where
            /// the surface therefore needs to be repainted. The compositor
            /// ignores the parts of the damage that fall outside of the surface.
            ///
            /// Damage is double-buffered state, see wl_surface.commit.
            ///
            /// The damage rectangle is specified in surface-local coordinates,
            /// where x and y specify the upper left corner of the damage rectangle.
            ///
            /// The initial value for pending damage is empty: no damage.
            /// wl_surface.damage adds pending damage: the new pending damage
            /// is the union of old pending damage and the given rectangle.
            ///
            /// wl_surface.commit assigns pending damage as the current damage,
            /// and clears pending damage. The server will clear the current
            /// damage as it repaints the surface.
            ///
            /// Note! New clients should not use this request. Instead damage can be
            /// posted with wl_surface.damage_buffer which uses buffer coordinates
            /// instead of surface coordinates.
            pub fn damage(_surface: *Surface, _x: i32, _y: i32, _width: i32, _height: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .i = _x },
                    .{ .i = _y },
                    .{ .i = _width },
                    .{ .i = _height },
                };
                _proxy.marshal(2, &_args);
            }
            pub const damage_since_version = 1;

            /// Request a notification when it is a good time to start drawing a new
            /// frame, by creating a frame callback. This is useful for throttling
            /// redrawing operations, and driving animations.
            ///
            /// When a client is animating on a wl_surface, it can use the 'frame'
            /// request to get notified when it is a good time to draw and commit the
            /// next frame of animation. If the client commits an update earlier than
            /// that, it is likely that some updates will not make it to the display,
            /// and the client is wasting resources by drawing too often.
            ///
            /// The frame request will take effect on the next wl_surface.commit.
            /// The notification will only be posted for one frame unless
            /// requested again. For a wl_surface, the notifications are posted in
            /// the order the frame requests were committed.
            ///
            /// The server must send the notifications so that a client
            /// will not send excessive updates, while still allowing
            /// the highest possible update rate for clients that wait for the reply
            /// before drawing again. The server should give some time for the client
            /// to draw and commit after sending the frame callback events to let it
            /// hit the next output refresh.
            ///
            /// A server should avoid signaling the frame callbacks if the
            /// surface is not visible in any way, e.g. the surface is off-screen,
            /// or completely obscured by other opaque surfaces.
            ///
            /// The object returned by this request will be destroyed by the
            /// compositor after the callback is fired and as such the client must not
            /// attempt to use it after that point.
            ///
            /// The callback_data passed in the callback is the current time, in
            /// milliseconds, with an undefined base.
            pub fn frame(_surface: *Surface) !*client.wl.Callback {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(3, &_args, client.wl.Callback.interface));
            }
            pub const frame_since_version = 1;

            /// This request sets the region of the surface that contains
            /// opaque content.
            ///
            /// The opaque region is an optimization hint for the compositor
            /// that lets it optimize the redrawing of content behind opaque
            /// regions.  Setting an opaque region is not required for correct
            /// behaviour, but marking transparent content as opaque will result
            /// in repaint artifacts.
            ///
            /// The opaque region is specified in surface-local coordinates.
            ///
            /// The compositor ignores the parts of the opaque region that fall
            /// outside of the surface.
            ///
            /// Opaque region is double-buffered state, see wl_surface.commit.
            ///
            /// wl_surface.set_opaque_region changes the pending opaque region.
            /// wl_surface.commit copies the pending region to the current region.
            /// Otherwise, the pending and current regions are never changed.
            ///
            /// The initial value for an opaque region is empty. Setting the pending
            /// opaque region has copy semantics, and the wl_region object can be
            /// destroyed immediately. A NULL wl_region causes the pending opaque
            /// region to be set to empty.
            pub fn setOpaqueRegion(_surface: *Surface, _region: ?*client.wl.Region) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .o = @ptrCast(_region) },
                };
                _proxy.marshal(4, &_args);
            }
            pub const set_opaque_region_since_version = 1;

            /// This request sets the region of the surface that can receive
            /// pointer and touch events.
            ///
            /// Input events happening outside of this region will try the next
            /// surface in the server surface stack. The compositor ignores the
            /// parts of the input region that fall outside of the surface.
            ///
            /// The input region is specified in surface-local coordinates.
            ///
            /// Input region is double-buffered state, see wl_surface.commit.
            ///
            /// wl_surface.set_input_region changes the pending input region.
            /// wl_surface.commit copies the pending region to the current region.
            /// Otherwise the pending and current regions are never changed,
            /// except cursor and icon surfaces are special cases, see
            /// wl_pointer.set_cursor and wl_data_device.start_drag.
            ///
            /// The initial value for an input region is infinite. That means the
            /// whole surface will accept input. Setting the pending input region
            /// has copy semantics, and the wl_region object can be destroyed
            /// immediately. A NULL wl_region causes the input region to be set
            /// to infinite.
            pub fn setInputRegion(_surface: *Surface, _region: ?*client.wl.Region) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .o = @ptrCast(_region) },
                };
                _proxy.marshal(5, &_args);
            }
            pub const set_input_region_since_version = 1;

            /// Surface state (input, opaque, and damage regions, attached buffers,
            /// etc.) is double-buffered. Protocol requests modify the pending state,
            /// as opposed to the active state in use by the compositor.
            ///
            /// All requests that need a commit to become effective are documented
            /// to affect double-buffered state.
            ///
            /// Other interfaces may add further double-buffered surface state.
            ///
            /// A commit request atomically creates a Content Update (CU) from the
            /// pending state, even if the pending state has not been touched. The
            /// content update is placed at the end of a per-surface queue until it
            /// becomes active. After commit, the new pending state is as documented for
            /// each related request.
            ///
            /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
            /// (SCU). If the surface is effectively synchronized at the commit request,
            /// it is a SCU, otherwise a DCU.
            ///
            /// When a surface transitions from effectively synchronized to effectively
            /// desynchronized, all SCUs in its queue which are not reachable by any
            /// DCU become DCUs and dependency edges from outside the queue to these CUs
            /// are removed.
            ///
            /// See wl_subsurface for the definition of 'effectively synchronized' and
            /// 'effectively desynchronized'.
            ///
            /// When a CU is placed in the queue, the CU has a dependency on the CU in
            /// front of it and to the SCU at end of the queue of every direct child
            /// surface if that SCU exists and does not have another dependent. This can
            /// form a directed acyclic graph of CUs with dependencies as edges.
            ///
            /// In addition to surface state, the CU can have constraints that must be
            /// satisfied before it can be applied. Other interfaces may add CU
            /// constraints.
            ///
            /// All DCUs which do not have a SCU in front of themselves in their queue,
            /// are candidates. If the graph that's reachable by a candidate does not
            /// have any unsatisfied constraints, the entire graph must be applied
            /// atomically.
            ///
            /// When a CU is applied, the wl_buffer is applied before all other state.
            /// This means that all coordinates in double-buffered state are relative to
            /// the newly attached wl_buffers, except for wl_surface.attach itself. If
            /// there is no newly attached wl_buffer, the coordinates are relative to
            /// the previous content update.
            pub fn commit(_surface: *Surface) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                _proxy.marshal(6, null);
            }
            pub const commit_since_version = 1;

            /// This request sets the transformation that the client has already applied
            /// to the content of the buffer. The accepted values for the transform
            /// parameter are the values for wl_output.transform.
            ///
            /// The compositor applies the inverse of this transformation whenever it
            /// uses the buffer contents.
            ///
            /// Buffer transform is double-buffered state, see wl_surface.commit.
            ///
            /// A newly created surface has its buffer transformation set to normal.
            ///
            /// wl_surface.set_buffer_transform changes the pending buffer
            /// transformation. wl_surface.commit copies the pending buffer
            /// transformation to the current one. Otherwise, the pending and current
            /// values are never changed.
            ///
            /// The purpose of this request is to allow clients to render content
            /// according to the output transform, thus permitting the compositor to
            /// use certain optimizations even if the display is rotated. Using
            /// hardware overlays and scanning out a client buffer for fullscreen
            /// surfaces are examples of such optimizations. Those optimizations are
            /// highly dependent on the compositor implementation, so the use of this
            /// request should be considered on a case-by-case basis.
            ///
            /// Note that if the transform value includes 90 or 270 degree rotation,
            /// the width of the buffer will become the surface height and the height
            /// of the buffer will become the surface width.
            ///
            /// If transform is not one of the values from the
            /// wl_output.transform enum the invalid_transform protocol error
            /// is raised.
            pub fn setBufferTransform(_surface: *Surface, _transform: common.wl.output.Transform) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .i = switch (@typeInfo(common.wl.output.Transform)) {
                        .@"enum" => @as(i32, @intCast(@intFromEnum(_transform))),
                        .@"struct" => @bitCast(_transform),
                        else => unreachable,
                    } },
                };
                _proxy.marshal(7, &_args);
            }
            pub const set_buffer_transform_since_version = 2;

            /// This request sets an optional scaling factor on how the compositor
            /// interprets the contents of the buffer attached to the window.
            ///
            /// Buffer scale is double-buffered state, see wl_surface.commit.
            ///
            /// A newly created surface has its buffer scale set to 1.
            ///
            /// wl_surface.set_buffer_scale changes the pending buffer scale.
            /// wl_surface.commit copies the pending buffer scale to the current one.
            /// Otherwise, the pending and current values are never changed.
            ///
            /// The purpose of this request is to allow clients to supply higher
            /// resolution buffer data for use on high resolution outputs. It is
            /// intended that you pick the same buffer scale as the scale of the
            /// output that the surface is displayed on. This means the compositor
            /// can avoid scaling when rendering the surface on that output.
            ///
            /// Note that if the scale is larger than 1, then you have to attach
            /// a buffer that is larger (by a factor of scale in each dimension)
            /// than the desired surface size.
            ///
            /// If scale is not greater than 0 the invalid_scale protocol error is
            /// raised.
            pub fn setBufferScale(_surface: *Surface, _scale: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .i = _scale },
                };
                _proxy.marshal(8, &_args);
            }
            pub const set_buffer_scale_since_version = 3;

            /// This request is used to describe the regions where the pending
            /// buffer is different from the current surface contents, and where
            /// the surface therefore needs to be repainted. The compositor
            /// ignores the parts of the damage that fall outside of the surface.
            ///
            /// Damage is double-buffered state, see wl_surface.commit.
            ///
            /// The damage rectangle is specified in buffer coordinates,
            /// where x and y specify the upper left corner of the damage rectangle.
            ///
            /// The initial value for pending damage is empty: no damage.
            /// wl_surface.damage_buffer adds pending damage: the new pending
            /// damage is the union of old pending damage and the given rectangle.
            ///
            /// wl_surface.commit assigns pending damage as the current damage,
            /// and clears pending damage. The server will clear the current
            /// damage as it repaints the surface.
            ///
            /// This request differs from wl_surface.damage in only one way - it
            /// takes damage in buffer coordinates instead of surface-local
            /// coordinates. While this generally is more intuitive than surface
            /// coordinates, it is especially desirable when using wp_viewport
            /// or when a drawing library (like EGL) is unaware of buffer scale
            /// and buffer transform.
            ///
            /// Note: Because buffer transformation changes and damage requests may
            /// be interleaved in the protocol stream, it is impossible to determine
            /// the actual mapping between surface and buffer damage until
            /// wl_surface.commit time. Therefore, compositors wishing to take both
            /// kinds of damage into account will have to accumulate damage from the
            /// two requests separately and only transform from one to the other
            /// after receiving the wl_surface.commit.
            pub fn damageBuffer(_surface: *Surface, _x: i32, _y: i32, _width: i32, _height: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .i = _x },
                    .{ .i = _y },
                    .{ .i = _width },
                    .{ .i = _height },
                };
                _proxy.marshal(9, &_args);
            }
            pub const damage_buffer_since_version = 4;
        };

        /// A region object describes an area.
        ///
        /// Region objects are used to describe the opaque and input
        /// regions of a surface.
        pub const Region = opaque {
            pub const generated_version = 4;
            pub const interface = &common.wl.region.interface;
            pub inline fn getId(_region: *Region) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_region)).getId();
            }
            pub inline fn getVersion(_region: *Region) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_region)).getVersion();
            }
            pub inline fn getUserData(_region: *Region) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_region)).getUserData();
            }
            pub inline fn setQueue(_region: *Region, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_region);
                _proxy.setQueue(_queue);
            }
            /// Destroy the region.  This will invalidate the object ID.
            pub fn destroy(_region: *Region) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_region);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// Add the specified rectangle to the region.
            pub fn add(_region: *Region, _x: i32, _y: i32, _width: i32, _height: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_region);
                var _args = [_]common.Argument{
                    .{ .i = _x },
                    .{ .i = _y },
                    .{ .i = _width },
                    .{ .i = _height },
                };
                _proxy.marshal(1, &_args);
            }
            pub const add_since_version = 1;

            /// Subtract the specified rectangle from the region.
            pub fn subtract(_region: *Region, _x: i32, _y: i32, _width: i32, _height: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_region);
                var _args = [_]common.Argument{
                    .{ .i = _x },
                    .{ .i = _y },
                    .{ .i = _width },
                    .{ .i = _height },
                };
                _proxy.marshal(2, &_args);
            }
            pub const subtract_since_version = 1;
        };

        /// An output describes part of the compositor geometry.  The
        /// compositor works in the 'compositor coordinate system' and an
        /// output corresponds to a rectangular area in that space that is
        /// actually visible.  This typically corresponds to a monitor that
        /// displays part of the compositor space.  This object is published
        /// as global during start up, or when a monitor is hotplugged.
        pub const Output = opaque {
            pub const generated_version = 3;
            pub const interface = &common.wl.output.interface;
            pub const Subpixel = common.wl.output.Subpixel;
            pub const Transform = common.wl.output.Transform;
            pub const Mode = common.wl.output.Mode;
            pub inline fn getId(_output: *Output) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_output)).getId();
            }
            pub inline fn getVersion(_output: *Output) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_output)).getVersion();
            }
            pub inline fn getUserData(_output: *Output) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_output)).getUserData();
            }
            pub inline fn setQueue(_output: *Output, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_output);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const geometry_since_version = 1;
                pub const mode_since_version = 1;
                pub const done_since_version = 2;
                pub const scale_since_version = 2;

                /// The geometry event describes geometric properties of the output.
                /// The event is sent when binding to the output object and whenever
                /// any of the properties change.
                ///
                /// 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).
                ///
                /// Clients should use wl_surface.preferred_buffer_transform instead of the
                /// transform advertised by this event to find the preferred buffer
                /// transform to use for a surface.
                ///
                /// 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 name and description.
                geometry: struct {
                    x: i32,
                    y: i32,
                    physical_width: i32,
                    physical_height: i32,
                    subpixel: Subpixel,
                    make: [*:0]const u8,
                    model: [*:0]const u8,
                    transform: Transform,
                },

                /// The mode event describes an available mode for the output.
                ///
                /// The event is sent when binding to the output object and there
                /// will always be one mode, the current mode.  The event is sent
                /// again if an output changes mode, for the mode that is now
                /// current.  In other words, the current mode is always the last
                /// mode that was received with the current flag set.
                ///
                /// Non-current modes are deprecated. A compositor can decide to only
                /// advertise the current mode and never send other modes. Clients
                /// should not rely on non-current modes.
                ///
                /// The size of a mode is given in physical hardware units of
                /// the output device. This is not necessarily the same as
                /// the output size in the global compositor space. For instance,
                /// the output may be scaled, as described in wl_output.scale,
                /// or transformed, as described in wl_output.transform. Clients
                /// willing to retrieve the output size in the global compositor
                /// space should use xdg_output.logical_size instead.
                ///
                /// 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.
                ///
                /// Note: this information is not always meaningful for all outputs. Some
                /// compositors, such as those exposing virtual outputs, might fake the
                /// refresh rate or the size.
                mode: struct {
                    flags: Mode,
                    width: i32,
                    height: i32,
                    refresh: i32,
                },

                /// This event is sent after all other properties have been
                /// sent after binding to the output object and after any
                /// other property changes done after that. This allows
                /// changes to the output properties to be seen as
                /// atomic, even if they happen via multiple events.
                done: void,
                /// This event contains scaling geometry information
                /// that is not in the geometry event. It may be sent after
                /// binding the output object or if the output scale changes
                /// later. The compositor will emit a non-zero, positive
                /// value for scale. If it is not sent, the client should
                /// assume a scale of 1.
                ///
                /// A scale larger than 1 means that the compositor will
                /// automatically scale surface buffers by this amount
                /// when rendering. This is used for very high resolution
                /// displays where applications rendering at the native
                /// resolution would be too small to be legible.
                ///
                /// Clients should use wl_surface.preferred_buffer_scale
                /// instead of this event to find the preferred buffer
                /// scale to use for a surface.
                ///
                /// The scale event will be followed by a done event.
                scale: struct {
                    factor: i32,
                },
            };
            pub inline fn setListener(
                _output: *Output,
                comptime T: type,
                _listener: *const fn (output: *Output, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_output);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Output, T).dispatcher, _listener, _mut_data);
            }
            /// Using this request a client can tell the server that it is not going to
            /// use the output object anymore.
            pub fn release(_output: *Output) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_output);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const release_since_version = 3;
            pub inline fn destroy(_output: *Output) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_output);
                _proxy.destroy();
            }
        };

        /// 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
        /// device is hot plugged.  A seat typically has a pointer and
        /// maintains a keyboard focus and a pointer focus.
        pub const Seat = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.seat.interface;
            pub const Capability = common.wl.seat.Capability;
            pub const Error = common.wl.seat.Error;
            pub inline fn getId(_seat: *Seat) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_seat)).getId();
            }
            pub inline fn getVersion(_seat: *Seat) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_seat)).getVersion();
            }
            pub inline fn getUserData(_seat: *Seat) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_seat)).getUserData();
            }
            pub inline fn setQueue(_seat: *Seat, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_seat);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const capabilities_since_version = 1;
                pub const name_since_version = 2;

                /// This is sent on binding to the seat global or whenever a seat gains
                /// or loses the pointer, keyboard or touch capabilities.
                /// The argument is a capability enum containing the complete set of
                /// capabilities this seat has.
                ///
                /// When the pointer capability is added, a client may create a
                /// wl_pointer object using the wl_seat.get_pointer request. This object
                /// will receive pointer events until the capability is removed in the
                /// future.
                ///
                /// When the pointer capability is removed, a client should destroy the
                /// wl_pointer objects associated with the seat where the capability was
                /// removed, using the wl_pointer.release request. No further pointer
                /// events will be received on these objects.
                ///
                /// In some compositors, if a seat regains the pointer capability and a
                /// client has a previously obtained wl_pointer object of version 4 or
                /// less, that object may start sending pointer events again. This
                /// behavior is considered a misinterpretation of the intended behavior
                /// and must not be relied upon by the client. wl_pointer objects of
                /// version 5 or later must not send events if created before the most
                /// recent event notifying the client of an added pointer capability.
                ///
                /// The above behavior also applies to wl_keyboard and wl_touch with the
                /// keyboard and touch capabilities, respectively.
                capabilities: struct {
                    capabilities: Capability,
                },

                /// 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, and should be sent
                /// before announcing capabilities. This event 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.
                name: struct {
                    name: [*:0]const u8,
                },
            };
            pub inline fn setListener(
                _seat: *Seat,
                comptime T: type,
                _listener: *const fn (seat: *Seat, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_seat);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Seat, T).dispatcher, _listener, _mut_data);
            }
            /// The ID provided will be initialized to the wl_pointer interface
            /// for this seat.
            ///
            /// This request only takes effect if the seat has the pointer
            /// capability, or has had the pointer capability in the past.
            /// It is a protocol violation to issue this request on a seat that has
            /// never had the pointer capability. The missing_capability error will
            /// be sent in this case.
            pub fn getPointer(_seat: *Seat) !*client.wl.Pointer {
                const _proxy: *client.wl.Proxy = @ptrCast(_seat);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(0, &_args, client.wl.Pointer.interface));
            }
            pub const get_pointer_since_version = 1;

            /// The ID provided will be initialized to the wl_keyboard interface
            /// for this seat.
            ///
            /// This request only takes effect if the seat has the keyboard
            /// capability, or has had the keyboard capability in the past.
            /// It is a protocol violation to issue this request on a seat that has
            /// never had the keyboard capability. The missing_capability error will
            /// be sent in this case.
            pub fn getKeyboard(_seat: *Seat) !*client.wl.Keyboard {
                const _proxy: *client.wl.Proxy = @ptrCast(_seat);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(1, &_args, client.wl.Keyboard.interface));
            }
            pub const get_keyboard_since_version = 1;

            /// The ID provided will be initialized to the wl_touch interface
            /// for this seat.
            ///
            /// This request only takes effect if the seat has the touch
            /// capability, or has had the touch capability in the past.
            /// It is a protocol violation to issue this request on a seat that has
            /// never had the touch capability. The missing_capability error will
            /// be sent in this case.
            pub fn getTouch(_seat: *Seat) !*client.wl.Touch {
                const _proxy: *client.wl.Proxy = @ptrCast(_seat);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(2, &_args, client.wl.Touch.interface));
            }
            pub const get_touch_since_version = 1;

            /// Using this request a client can tell the server that it is not going to
            /// use the seat object anymore.
            pub fn release(_seat: *Seat) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_seat);
                _proxy.marshal(3, null);
                _proxy.destroy();
            }
            pub const release_since_version = 5;
            pub inline fn destroy(_seat: *Seat) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_seat);
                _proxy.destroy();
            }
        };

        /// The wl_pointer interface represents one or more input devices,
        /// such as mice, which control the pointer location and pointer_focus
        /// of a seat.
        ///
        /// The wl_pointer interface generates motion, enter and leave
        /// events for the surfaces that the pointer is located over,
        /// and button and axis events for button presses, button releases
        /// and scrolling.
        pub const Pointer = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.pointer.interface;
            pub const Error = common.wl.pointer.Error;
            pub const ButtonState = common.wl.pointer.ButtonState;
            pub const Axis = common.wl.pointer.Axis;
            pub const AxisSource = common.wl.pointer.AxisSource;
            pub const AxisRelativeDirection = common.wl.pointer.AxisRelativeDirection;
            pub inline fn getId(_pointer: *Pointer) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_pointer)).getId();
            }
            pub inline fn getVersion(_pointer: *Pointer) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_pointer)).getVersion();
            }
            pub inline fn getUserData(_pointer: *Pointer) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_pointer)).getUserData();
            }
            pub inline fn setQueue(_pointer: *Pointer, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_pointer);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const enter_since_version = 1;
                pub const leave_since_version = 1;
                pub const motion_since_version = 1;
                pub const button_since_version = 1;
                pub const axis_since_version = 1;
                pub const frame_since_version = 5;
                pub const axis_source_since_version = 5;
                pub const axis_stop_since_version = 5;
                pub const axis_discrete_since_version = 5;

                /// Notification that this seat's pointer is focused on a certain
                /// surface.
                ///
                /// When a seat's focus enters a surface, the pointer image
                /// is undefined and a client should respond to this event by setting
                /// an appropriate pointer image with the set_cursor request.
                enter: struct {
                    serial: u32,
                    surface: ?*client.wl.Surface,
                    surface_x: common.Fixed,
                    surface_y: common.Fixed,
                },

                /// Notification that this seat's pointer is no longer focused on
                /// a certain surface.
                ///
                /// The leave notification is sent before the enter notification
                /// for the new focus.
                leave: struct {
                    serial: u32,
                    surface: ?*client.wl.Surface,
                },

                /// Notification of pointer location change. The arguments
                /// surface_x and surface_y are the location relative to the
                /// focused surface.
                motion: struct {
                    time: u32,
                    surface_x: common.Fixed,
                    surface_y: common.Fixed,
                },

                /// Mouse button click and release notifications.
                ///
                /// The location of the click is given by the last motion or
                /// enter event.
                /// The time argument is a timestamp with millisecond
                /// granularity, with an undefined base.
                ///
                /// The button is a button code as defined in the Linux kernel's
                /// linux/input-event-codes.h header file, e.g. BTN_LEFT.
                ///
                /// Any 16-bit button code value is reserved for future additions to the
                /// kernel's event code list. All other button codes above 0xFFFF are
                /// currently undefined but may be used in future versions of this
                /// protocol.
                button: struct {
                    serial: u32,
                    time: u32,
                    button: u32,
                    state: ButtonState,
                },

                /// Scroll and other axis notifications.
                ///
                /// For scroll events (vertical and horizontal scroll axes), the
                /// value parameter is the length of a vector along the specified
                /// axis in a coordinate space identical to those of motion events,
                /// representing a relative movement along the specified axis.
                ///
                /// For devices that support movements non-parallel to axes multiple
                /// axis events will be emitted.
                ///
                /// When applicable, for example for touch pads, the server can
                /// choose to emit scroll events where the motion vector is
                /// equivalent to a motion event vector.
                ///
                /// When applicable, a client can transform its content relative to the
                /// scroll distance.
                axis: struct {
                    time: u32,
                    axis: Axis,
                    value: common.Fixed,
                },

                /// Indicates the end of a set of events that logically belong together.
                /// A client is expected to accumulate the data in all events within the
                /// frame before proceeding.
                ///
                /// All wl_pointer events before a wl_pointer.frame event belong
                /// logically together. For example, in a diagonal scroll motion the
                /// compositor will send an optional wl_pointer.axis_source event, two
                /// wl_pointer.axis events (horizontal and vertical) and finally a
                /// wl_pointer.frame event. The client may use this information to
                /// calculate a diagonal vector for scrolling.
                ///
                /// When multiple wl_pointer.axis events occur within the same frame,
                /// the motion vector is the combined motion of all events.
                /// When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
                /// the same frame, this indicates that axis movement in one axis has
                /// stopped but continues in the other axis.
                /// When multiple wl_pointer.axis_stop events occur within the same
                /// frame, this indicates that these axes stopped in the same instance.
                ///
                /// A wl_pointer.frame event is sent for every logical event group,
                /// even if the group only contains a single wl_pointer event.
                /// Specifically, a client may get a sequence: motion, frame, button,
                /// frame, axis, frame, axis_stop, frame.
                ///
                /// The wl_pointer.enter and wl_pointer.leave events are logical events
                /// generated by the compositor and not the hardware. These events are
                /// also grouped by a wl_pointer.frame. When a pointer moves from one
                /// surface to another, a compositor should group the
                /// wl_pointer.leave event within the same wl_pointer.frame.
                /// However, a client must not rely on wl_pointer.leave and
                /// wl_pointer.enter being in the same wl_pointer.frame.
                /// Compositor-specific policies may require the wl_pointer.leave and
                /// wl_pointer.enter event being split across multiple wl_pointer.frame
                /// groups.
                frame: void,
                /// Source information for scroll and other axes.
                ///
                /// This event does not occur on its own. It is sent before a
                /// wl_pointer.frame event and carries the source information for
                /// all events within that frame.
                ///
                /// The source specifies how this event was generated. If the source is
                /// wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
                /// sent when the user lifts the finger off the device.
                ///
                /// If the source is wl_pointer.axis_source.wheel,
                /// wl_pointer.axis_source.wheel_tilt or
                /// wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
                /// or may not be sent. Whether a compositor sends an axis_stop event
                /// for these sources is hardware-specific and implementation-dependent;
                /// clients must not rely on receiving an axis_stop event for these
                /// scroll sources and should treat scroll sequences from these scroll
                /// sources as unterminated by default.
                ///
                /// This event is optional. If the source is unknown for a particular
                /// axis event sequence, no event is sent.
                /// Only one wl_pointer.axis_source event is permitted per frame.
                ///
                /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
                /// not guaranteed.
                axis_source: struct {
                    axis_source: AxisSource,
                },

                /// Stop notification for scroll and other axes.
                ///
                /// For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
                /// is sent to notify a client that the axis sequence has terminated.
                /// This enables the client to implement kinetic scrolling.
                /// See the wl_pointer.axis_source documentation for information on when
                /// this event may be generated.
                ///
                /// Any wl_pointer.axis events with the same axis_source after this
                /// event should be considered as the start of a new axis motion.
                ///
                /// The timestamp is to be interpreted identical to the timestamp in the
                /// wl_pointer.axis event. The timestamp value may be the same as a
                /// preceding wl_pointer.axis event.
                axis_stop: struct {
                    time: u32,
                    axis: Axis,
                },

                /// Discrete step information for scroll and other axes.
                ///
                /// 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
                /// event is always followed by exactly one axis event with the same
                /// 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. 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
                /// steps and do not generate this event.
                ///
                /// The discrete value carries the directional information. e.g. a value
                /// of -2 is two steps towards the negative direction of this axis.
                ///
                /// The axis number is identical to the axis number in the associated
                /// axis event.
                ///
                /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
                /// not guaranteed.
                axis_discrete: struct {
                    axis: Axis,
                    discrete: i32,
                },
            };
            pub inline fn setListener(
                _pointer: *Pointer,
                comptime T: type,
                _listener: *const fn (pointer: *Pointer, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_pointer);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Pointer, T).dispatcher, _listener, _mut_data);
            }
            /// Set the pointer surface, i.e., the surface that contains the
            /// pointer image (cursor). This request gives the surface the role
            /// of a cursor. If the surface already has another role, it raises
            /// a protocol error.
            ///
            /// The cursor actually changes only if the pointer
            /// focus for this device is one of the requesting client's surfaces
            /// or the surface parameter is the current pointer surface. If
            /// there was a previous surface set with this request it is
            /// replaced. If surface is NULL, the pointer image is hidden.
            ///
            /// The parameters hotspot_x and hotspot_y define the position of
            /// the pointer surface relative to the pointer location. Its
            /// top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
            /// where (x, y) are the coordinates of the pointer location, in
            /// surface-local coordinates.
            ///
            /// On wl_surface.offset requests to the pointer surface, hotspot_x
            /// and hotspot_y are decremented by the x and y parameters
            /// passed to the request. The offset must be applied by
            /// wl_surface.commit as usual.
            ///
            /// The hotspot can also be updated by passing the currently set
            /// pointer surface to this request with new values for hotspot_x
            /// and hotspot_y.
            ///
            /// The input region is ignored for wl_surfaces with the role of
            /// a cursor. When the use as a cursor ends, 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.
            pub fn setCursor(_pointer: *Pointer, _serial: u32, _surface: ?*client.wl.Surface, _hotspot_x: i32, _hotspot_y: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .o = @ptrCast(_surface) },
                    .{ .i = _hotspot_x },
                    .{ .i = _hotspot_y },
                };
                _proxy.marshal(0, &_args);
            }
            pub const set_cursor_since_version = 1;

            /// Using this request a client can tell the server that it is not going to
            /// use the pointer object anymore.
            ///
            /// This request destroys the pointer proxy object, so clients must not call
            /// wl_pointer_destroy() after using this request.
            pub fn release(_pointer: *Pointer) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_pointer);
                _proxy.marshal(1, null);
                _proxy.destroy();
            }
            pub const release_since_version = 3;
            pub inline fn destroy(_pointer: *Pointer) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_pointer);
                _proxy.destroy();
            }
        };

        /// The wl_keyboard interface represents one or more keyboards
        /// associated with a seat.
        ///
        /// Each wl_keyboard has the following logical state:
        ///
        /// - an active surface (possibly null),
        /// - the keys currently logically down,
        /// - the active modifiers,
        /// - the active group.
        ///
        /// By default, the active surface is null, the keys currently logically down
        /// are empty, the active modifiers and the active group are 0.
        pub const Keyboard = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.keyboard.interface;
            pub const KeymapFormat = common.wl.keyboard.KeymapFormat;
            pub const KeyState = common.wl.keyboard.KeyState;
            pub inline fn getId(_keyboard: *Keyboard) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_keyboard)).getId();
            }
            pub inline fn getVersion(_keyboard: *Keyboard) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_keyboard)).getVersion();
            }
            pub inline fn getUserData(_keyboard: *Keyboard) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_keyboard)).getUserData();
            }
            pub inline fn setQueue(_keyboard: *Keyboard, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_keyboard);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const keymap_since_version = 1;
                pub const enter_since_version = 1;
                pub const leave_since_version = 1;
                pub const key_since_version = 1;
                pub const modifiers_since_version = 1;
                pub const repeat_info_since_version = 4;

                /// This event provides a file descriptor to the client which can be
                /// 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.
                keymap: struct {
                    format: KeymapFormat,
                    fd: i32,
                    size: u32,
                },

                /// Notification that this seat's keyboard focus is on a certain
                /// surface.
                ///
                /// The compositor must send the wl_keyboard.modifiers event after this
                /// event.
                ///
                /// In the wl_keyboard logical state, this event sets the active surface to
                /// the surface argument and the keys currently logically down to the keys
                /// in the keys argument. The compositor must not send this event if the
                /// wl_keyboard already had an active surface immediately before this event.
                ///
                /// Clients should not use the list of pressed keys to emulate key-press
                /// events. The order of keys in the list is unspecified.
                enter: struct {
                    serial: u32,
                    surface: ?*client.wl.Surface,
                    keys: *common.Array,
                },

                /// Notification that this seat's keyboard focus is no longer on
                /// a certain surface.
                ///
                /// The leave notification is sent before the enter notification
                /// for the new focus.
                ///
                /// In the wl_keyboard logical state, this event resets all values to their
                /// defaults. The compositor must not send this event if the active surface
                /// of the wl_keyboard was not equal to the surface argument immediately
                /// before this event.
                leave: struct {
                    serial: u32,
                    surface: ?*client.wl.Surface,
                },

                /// A key was pressed or released.
                /// The time argument is a timestamp with millisecond
                /// granularity, with an undefined base.
                ///
                /// The key is a platform-specific key code that can be interpreted
                /// by feeding it to the keyboard mapping (see the keymap event).
                ///
                /// If this event produces a change in modifiers, then the resulting
                /// wl_keyboard.modifiers event must be sent after this event.
                ///
                /// In the wl_keyboard logical state, this event adds the key to the keys
                /// currently logically down (if the state argument is pressed) or removes
                /// the key from the keys currently logically down (if the state argument is
                /// released). The compositor must not send this event if the wl_keyboard
                /// did not have an active surface immediately before this event. The
                /// compositor must not send this event if state is pressed (resp. released)
                /// and the key was already logically down (resp. was not logically down)
                /// immediately before this event.
                ///
                /// Since version 10, compositors may send key events with the "repeated"
                /// key state when a wl_keyboard.repeat_info event with a rate argument of
                /// 0 has been received. This allows the compositor to take over the
                /// responsibility of key repetition.
                key: struct {
                    serial: u32,
                    time: u32,
                    key: u32,
                    state: KeyState,
                },

                /// Notifies clients that the modifier and/or group state has
                /// changed, and it should update its local state.
                ///
                /// The compositor may send this event without a surface of the client
                /// having keyboard focus, for example to tie modifier information to
                /// pointer focus instead. If a modifier event with pressed modifiers is sent
                /// without a prior enter event, the client can assume the modifier state is
                /// valid until it receives the next wl_keyboard.modifiers event. In order to
                /// reset the modifier state again, the compositor can send a
                /// wl_keyboard.modifiers event with no pressed modifiers.
                ///
                /// In the wl_keyboard logical state, this event updates the modifiers and
                /// group.
                modifiers: struct {
                    serial: u32,
                    mods_depressed: u32,
                    mods_latched: u32,
                    mods_locked: u32,
                    group: u32,
                },

                /// Informs the client about the keyboard's repeat rate and delay.
                ///
                /// This event is sent as soon as the wl_keyboard object has been created,
                /// and is guaranteed to be received by the client before any key press
                /// event.
                ///
                /// Negative values for either rate or delay are illegal. A rate of zero
                /// will disable any repeating (regardless of the value of delay).
                ///
                /// This event can be sent later on as well with a new value if necessary,
                /// so clients should continue listening for the event past the creation
                /// of wl_keyboard.
                repeat_info: struct {
                    rate: i32,
                    delay: i32,
                },
            };
            pub inline fn setListener(
                _keyboard: *Keyboard,
                comptime T: type,
                _listener: *const fn (keyboard: *Keyboard, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_keyboard);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Keyboard, T).dispatcher, _listener, _mut_data);
            }
            pub fn release(_keyboard: *Keyboard) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_keyboard);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const release_since_version = 3;
            pub inline fn destroy(_keyboard: *Keyboard) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_keyboard);
                _proxy.destroy();
            }
        };

        /// The wl_touch interface represents a touchscreen
        /// associated with a seat.
        ///
        /// Touch interactions can consist of one or more contacts.
        /// For each contact, a series of events is generated, starting
        /// with a down event, followed by zero or more motion events,
        /// and ending with an up event. Events relating to the same
        /// contact point can be identified by the ID of the sequence.
        pub const Touch = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.touch.interface;
            pub inline fn getId(_touch: *Touch) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_touch)).getId();
            }
            pub inline fn getVersion(_touch: *Touch) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_touch)).getVersion();
            }
            pub inline fn getUserData(_touch: *Touch) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_touch)).getUserData();
            }
            pub inline fn setQueue(_touch: *Touch, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_touch);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const down_since_version = 1;
                pub const up_since_version = 1;
                pub const motion_since_version = 1;
                pub const frame_since_version = 1;
                pub const cancel_since_version = 1;

                /// A new touch point has appeared on the surface. This touch point is
                /// assigned a unique ID. Future events from this touch point reference
                /// this ID. The ID ceases to be valid after a touch up event and may be
                /// reused in the future.
                down: struct {
                    serial: u32,
                    time: u32,
                    surface: ?*client.wl.Surface,
                    id: i32,
                    x: common.Fixed,
                    y: common.Fixed,
                },

                /// The touch point has disappeared. No further events will be sent for
                /// this touch point and the touch point's ID is released and may be
                /// reused in a future touch down event.
                up: struct {
                    serial: u32,
                    time: u32,
                    id: i32,
                },

                /// A touch point has changed coordinates.
                motion: struct {
                    time: u32,
                    id: i32,
                    x: common.Fixed,
                    y: common.Fixed,
                },

                /// Indicates the end of a set of events that logically belong together.
                /// A client is expected to accumulate the data in all events within the
                /// frame before proceeding.
                ///
                /// A wl_touch.frame terminates at least one event but otherwise no
                /// guarantee is provided about the set of events within a frame. A client
                /// must assume that any state not updated in a frame is unchanged from the
                /// previously known state.
                frame: void,
                /// Sent if the compositor decides the touch stream is a global
                /// gesture. No further events are sent to the clients from that
                /// particular gesture. Touch cancellation applies to all touch points
                /// currently active on this client's surface. The client is
                /// responsible for finalizing the touch points, future touch points on
                /// this surface may reuse the touch point ID.
                ///
                /// No frame event is required after the cancel event.
                cancel: void,
            };
            pub inline fn setListener(
                _touch: *Touch,
                comptime T: type,
                _listener: *const fn (touch: *Touch, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_touch);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(Touch, T).dispatcher, _listener, _mut_data);
            }
            pub fn release(_touch: *Touch) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_touch);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const release_since_version = 3;
            pub inline fn destroy(_touch: *Touch) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_touch);
                _proxy.destroy();
            }
        };
    };
    pub const ext = struct {
        /// This interface is used to request that the session be locked.
        pub const SessionLockManagerV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.ext.session_lock_manager_v1.interface;
            pub inline fn getId(_session_lock_manager_v1: *SessionLockManagerV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_manager_v1)).getId();
            }
            pub inline fn getVersion(_session_lock_manager_v1: *SessionLockManagerV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_manager_v1)).getVersion();
            }
            pub inline fn getUserData(_session_lock_manager_v1: *SessionLockManagerV1) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_manager_v1)).getUserData();
            }
            pub inline fn setQueue(_session_lock_manager_v1: *SessionLockManagerV1, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_manager_v1);
                _proxy.setQueue(_queue);
            }
            /// This informs the compositor that the session lock manager object will
            /// no longer be used. Existing objects created through this interface
            /// remain valid.
            pub fn destroy(_session_lock_manager_v1: *SessionLockManagerV1) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_manager_v1);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// This request creates a session lock and asks the compositor to lock the
            /// session. The compositor will send either the ext_session_lock_v1.locked
            /// or ext_session_lock_v1.finished event on the created object in
            /// response to this request.
            pub fn lock(_session_lock_manager_v1: *SessionLockManagerV1) !*client.ext.SessionLockV1 {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_manager_v1);
                var _args = [_]common.Argument{
                    .{ .o = null },
                };
                return @ptrCast(try _proxy.marshalConstructor(1, &_args, client.ext.SessionLockV1.interface));
            }
            pub const lock_since_version = 1;
        };

        /// In response to the creation of this object the compositor must send
        /// either the locked or finished event.
        ///
        /// The locked event indicates that the session is locked. This means
        /// that the compositor must stop rendering and providing input to normal
        /// clients. Instead the compositor must blank all outputs with an opaque
        /// color such that their normal content is fully hidden.
        ///
        /// The only surfaces that should be rendered while the session is locked
        /// are the lock surfaces created through this interface and optionally,
        /// at the compositor's discretion, special privileged surfaces such as
        /// input methods or portions of desktop shell UIs.
        ///
        /// The locked event must not be sent until a new "locked" frame (either
        /// from a session lock surface or the compositor blanking the output) has
        /// been presented on all outputs and no security sensitive normal/unlocked
        /// content is possibly visible.
        ///
        /// The finished event should be sent immediately on creation of this
        /// object if the compositor decides that the locked event will not be sent.
        ///
        /// The compositor may wait for the client to create and render session lock
        /// surfaces before sending the locked event to avoid displaying intermediate
        /// blank frames. However, it must impose a reasonable time limit if
        /// waiting and send the locked event as soon as the hard requirements
        /// described above can be met if the time limit expires. Clients should
        /// immediately create lock surfaces for all outputs on creation of this
        /// object to make this possible.
        ///
        /// This behavior of the locked event is required in order to prevent
        /// possible race conditions with clients that wish to suspend the system
        /// or similar after locking the session. Without these semantics, clients
        /// triggering a suspend after receiving the locked event would race with
        /// the first "locked" frame being presented and normal/unlocked frames
        /// might be briefly visible as the system is resumed if the suspend
        /// operation wins the race.
        ///
        /// If the client dies while the session is locked, the compositor must not
        /// unlock the session in response. It is acceptable for the session to be
        /// permanently locked if this happens. The compositor may choose to continue
        /// to display the lock surfaces the client had mapped before it died or
        /// alternatively fall back to a solid color, this is compositor policy.
        ///
        /// Compositors may also allow a secure way to recover the session, the
        /// details of this are compositor policy. Compositors may allow a new
        /// client to create a ext_session_lock_v1 object and take responsibility
        /// for unlocking the session, they may even start a new lock client
        /// instance automatically.
        pub const SessionLockV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.ext.session_lock_v1.interface;
            pub const Error = common.ext.session_lock_v1.Error;
            pub inline fn getId(_session_lock_v1: *SessionLockV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_v1)).getId();
            }
            pub inline fn getVersion(_session_lock_v1: *SessionLockV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_v1)).getVersion();
            }
            pub inline fn getUserData(_session_lock_v1: *SessionLockV1) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_v1)).getUserData();
            }
            pub inline fn setQueue(_session_lock_v1: *SessionLockV1, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_v1);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const locked_since_version = 1;
                pub const finished_since_version = 1;

                /// This client is now responsible for displaying graphics while the
                /// session is locked and deciding when to unlock the session.
                ///
                /// The locked event must not be sent until a new "locked" frame has been
                /// presented on all outputs and no security sensitive normal/unlocked
                /// content is possibly visible.
                ///
                /// If this event is sent, making the destroy request is a protocol error,
                /// the lock object must be destroyed using the unlock_and_destroy request.
                locked: void,
                /// The compositor has decided that the session lock should be destroyed
                /// as it will no longer be used by the compositor. Exactly when this
                /// event is sent is compositor policy, but it must never be sent more
                /// than once for a given session lock object.
                ///
                /// This might be sent because there is already another ext_session_lock_v1
                /// object held by a client, or the compositor has decided to deny the
                /// request to lock the session for some other reason. This might also
                /// be sent because the compositor implements some alternative, secure
                /// way to authenticate and unlock the session.
                ///
                /// The finished event should be sent immediately on creation of this
                /// object if the compositor decides that the locked event will not
                /// be sent.
                ///
                /// If the locked event is sent on creation of this object the finished
                /// event may still be sent at some later time in this object's
                /// lifetime. This is compositor policy.
                ///
                /// Upon receiving this event, the client should make either the destroy
                /// request or the unlock_and_destroy request, depending on whether or
                /// not the locked event was received on this object.
                finished: void,
            };
            pub inline fn setListener(
                _session_lock_v1: *SessionLockV1,
                comptime T: type,
                _listener: *const fn (session_lock_v1: *SessionLockV1, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_v1);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(SessionLockV1, T).dispatcher, _listener, _mut_data);
            }
            /// This informs the compositor that the lock object will no longer be
            /// used. Existing objects created through this interface remain valid.
            ///
            /// After this request is made, lock surfaces created through this object
            /// should be destroyed by the client as they will no longer be used by
            /// the compositor.
            ///
            /// It is a protocol error to make this request if the locked event was
            /// sent, the unlock_and_destroy request must be used instead.
            pub fn destroy(_session_lock_v1: *SessionLockV1) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_v1);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// The client is expected to create lock surfaces for all outputs
            /// currently present and any new outputs as they are advertised. These
            /// won't be displayed by the compositor unless the lock is successful
            /// and the locked event is sent.
            ///
            /// Providing a wl_surface which already has a role or already has a buffer
            /// attached or committed is a protocol error, as is attaching/committing
            /// a buffer before the first ext_session_lock_surface_v1.configure event.
            ///
            /// Attempting to create more than one lock surface for a given output
            /// is a duplicate_output protocol error.
            pub fn getLockSurface(_session_lock_v1: *SessionLockV1, _surface: *client.wl.Surface, _output: *client.wl.Output) !*client.ext.SessionLockSurfaceV1 {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_v1);
                var _args = [_]common.Argument{
                    .{ .o = null },
                    .{ .o = @ptrCast(_surface) },
                    .{ .o = @ptrCast(_output) },
                };
                return @ptrCast(try _proxy.marshalConstructor(1, &_args, client.ext.SessionLockSurfaceV1.interface));
            }
            pub const get_lock_surface_since_version = 1;

            /// This request indicates that the session should be unlocked, for
            /// example because the user has entered their password and it has been
            /// verified by the client.
            ///
            /// This request also informs the compositor that the lock object will
            /// no longer be used and should be destroyed. Existing objects created
            /// through this interface remain valid.
            ///
            /// After this request is made, lock surfaces created through this object
            /// should be destroyed by the client as they will no longer be used by
            /// the compositor.
            ///
            /// It is a protocol error to make this request if the locked event has
            /// not been sent. In that case, the lock object must be destroyed using
            /// the destroy request.
            ///
            /// Note that a correct client that wishes to exit directly after unlocking
            /// the session must use the wl_display.sync request to ensure the server
            /// receives and processes the unlock_and_destroy request. Otherwise
            /// there is no guarantee that the server has unlocked the session due
            /// to the asynchronous nature of the Wayland protocol. For example,
            /// the server might terminate the client with a protocol error before
            /// it processes the unlock_and_destroy request.
            pub fn unlockAndDestroy(_session_lock_v1: *SessionLockV1) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_v1);
                _proxy.marshal(2, null);
                _proxy.destroy();
            }
            pub const unlock_and_destroy_since_version = 1;
        };

        /// The client may use lock surfaces to display a screensaver, render a
        /// dialog to enter a password and unlock the session, or however else it
        /// sees fit.
        ///
        /// On binding this interface the compositor will immediately send the
        /// first configure event. After making the ack_configure request in
        /// response to this event the client should attach and commit the first
        /// buffer. Committing the surface before acking the first configure is a
        /// protocol error. Committing the surface with a null buffer at any time
        /// is a protocol error.
        ///
        /// The compositor is free to handle keyboard/pointer focus for lock
        /// surfaces however it chooses. A reasonable way to do this would be to
        /// give the first lock surface created keyboard focus and change keyboard
        /// focus if the user clicks on other surfaces.
        pub const SessionLockSurfaceV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.ext.session_lock_surface_v1.interface;
            pub const Error = common.ext.session_lock_surface_v1.Error;
            pub inline fn getId(_session_lock_surface_v1: *SessionLockSurfaceV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_surface_v1)).getId();
            }
            pub inline fn getVersion(_session_lock_surface_v1: *SessionLockSurfaceV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_surface_v1)).getVersion();
            }
            pub inline fn getUserData(_session_lock_surface_v1: *SessionLockSurfaceV1) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_session_lock_surface_v1)).getUserData();
            }
            pub inline fn setQueue(_session_lock_surface_v1: *SessionLockSurfaceV1, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_surface_v1);
                _proxy.setQueue(_queue);
            }
            pub const Event = union(enum) {
                pub const configure_since_version = 1;

                /// This event is sent once on binding the interface and may be sent again
                /// at the compositor's discretion, for example if output geometry changes.
                ///
                /// The width and height are in surface-local coordinates and are exact
                /// requirements. Failing to match these surface dimensions in the next
                /// commit after acking a configure is a protocol error.
                configure: struct {
                    serial: u32,
                    width: u32,
                    height: u32,
                },
            };
            pub inline fn setListener(
                _session_lock_surface_v1: *SessionLockSurfaceV1,
                comptime T: type,
                _listener: *const fn (session_lock_surface_v1: *SessionLockSurfaceV1, event: Event, data: T) void,
                _data: T,
            ) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_surface_v1);
                const _mut_data: ?*anyopaque = @ptrFromInt(@intFromPtr(_data));
                _proxy.addDispatcher(common.Dispatcher(SessionLockSurfaceV1, T).dispatcher, _listener, _mut_data);
            }
            /// This informs the compositor that the lock surface object will no
            /// longer be used.
            ///
            /// It is recommended for a lock client to destroy lock surfaces if
            /// their corresponding wl_output global is removed.
            ///
            /// If a lock surface on an active output is destroyed before the
            /// ext_session_lock_v1.unlock_and_destroy event is sent, the compositor
            /// must fall back to rendering a solid color.
            pub fn destroy(_session_lock_surface_v1: *SessionLockSurfaceV1) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_surface_v1);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// When a configure event is received, if a client commits the surface
            /// in response to the configure event, then the client must make an
            /// ack_configure request sometime before the commit request, passing
            /// along the serial of the configure event.
            ///
            /// If the client receives multiple configure events before it can
            /// respond to one, it only has to ack the last configure event.
            ///
            /// A client is not required to commit immediately after sending an
            /// ack_configure request - it may even ack_configure several times
            /// before its next surface commit.
            ///
            /// A client may send multiple ack_configure requests before committing,
            /// but only the last request sent before a commit indicates which
            /// configure event the client really is responding to.
            ///
            /// Sending an ack_configure request consumes the configure event
            /// referenced by the given serial, as well as all older configure events
            /// sent on this object.
            ///
            /// It is a protocol error to issue multiple ack_configure requests
            /// referencing the same configure event or to issue an ack_configure
            /// request referencing a configure event older than the last configure
            /// event acked for a given lock surface.
            pub fn ackConfigure(_session_lock_surface_v1: *SessionLockSurfaceV1, _serial: u32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_session_lock_surface_v1);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                };
                _proxy.marshal(1, &_args);
            }
            pub const ack_configure_since_version = 1;
        };
    };
    pub const wp = struct {
        /// The wp_single_pixel_buffer_manager_v1 interface is a factory for
        /// single-pixel buffers.
        pub const SinglePixelBufferManagerV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wp.single_pixel_buffer_manager_v1.interface;
            pub inline fn getId(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_single_pixel_buffer_manager_v1)).getId();
            }
            pub inline fn getVersion(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_single_pixel_buffer_manager_v1)).getVersion();
            }
            pub inline fn getUserData(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_single_pixel_buffer_manager_v1)).getUserData();
            }
            pub inline fn setQueue(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_single_pixel_buffer_manager_v1);
                _proxy.setQueue(_queue);
            }
            /// Destroy the wp_single_pixel_buffer_manager_v1 object.
            ///
            /// The child objects created via this interface are unaffected.
            pub fn destroy(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_single_pixel_buffer_manager_v1);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// Create a single-pixel buffer from four 32-bit RGBA values.
            ///
            /// Unless specified in another protocol extension, the RGBA values use
            /// pre-multiplied alpha.
            ///
            /// The width and height of the buffer are 1.
            ///
            /// The r, g, b and a arguments valid range is from UINT32_MIN (0)
            /// to UINT32_MAX (0xffffffff).
            ///
            /// These arguments should be interpreted as a percentage, i.e.
            /// - UINT32_MIN = 0% of the given color component
            /// - UINT32_MAX = 100% of the given color component
            pub fn createU32RgbaBuffer(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1, _r: u32, _g: u32, _b: u32, _a: u32) !*client.wl.Buffer {
                const _proxy: *client.wl.Proxy = @ptrCast(_single_pixel_buffer_manager_v1);
                var _args = [_]common.Argument{
                    .{ .o = null },
                    .{ .u = _r },
                    .{ .u = _g },
                    .{ .u = _b },
                    .{ .u = _a },
                };
                return @ptrCast(try _proxy.marshalConstructor(1, &_args, client.wl.Buffer.interface));
            }
            pub const create_u32_rgba_buffer_since_version = 1;
        };

        /// The global interface exposing surface cropping and scaling
        /// capabilities is used to instantiate an interface extension for a
        /// wl_surface object. This extended interface will then allow
        /// cropping and scaling the surface contents, effectively
        /// disconnecting the direct relationship between the buffer and the
        /// surface size.
        pub const Viewporter = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wp.viewporter.interface;
            pub const Error = common.wp.viewporter.Error;
            pub inline fn getId(_viewporter: *Viewporter) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_viewporter)).getId();
            }
            pub inline fn getVersion(_viewporter: *Viewporter) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_viewporter)).getVersion();
            }
            pub inline fn getUserData(_viewporter: *Viewporter) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_viewporter)).getUserData();
            }
            pub inline fn setQueue(_viewporter: *Viewporter, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_viewporter);
                _proxy.setQueue(_queue);
            }
            /// Informs the server that the client will not be using this
            /// protocol object anymore. This does not affect any other objects,
            /// wp_viewport objects included.
            pub fn destroy(_viewporter: *Viewporter) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_viewporter);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// Instantiate an interface extension for the given wl_surface to
            /// crop and scale its content. If the given wl_surface already has
            /// a wp_viewport object associated, the viewport_exists
            /// protocol error is raised.
            pub fn getViewport(_viewporter: *Viewporter, _surface: *client.wl.Surface) !*client.wp.Viewport {
                const _proxy: *client.wl.Proxy = @ptrCast(_viewporter);
                var _args = [_]common.Argument{
                    .{ .o = null },
                    .{ .o = @ptrCast(_surface) },
                };
                return @ptrCast(try _proxy.marshalConstructor(1, &_args, client.wp.Viewport.interface));
            }
            pub const get_viewport_since_version = 1;
        };

        /// An additional interface to a wl_surface object, which allows the
        /// client to specify the cropping and scaling of the surface
        /// contents.
        ///
        /// This interface works with two concepts: the source rectangle (src_x,
        /// src_y, src_width, src_height), and the destination size (dst_width,
        /// dst_height). The contents of the source rectangle are scaled to the
        /// destination size, and content outside the source rectangle is ignored.
        /// This state is double-buffered, see wl_surface.commit.
        ///
        /// The two parts of crop and scale state are independent: the source
        /// rectangle, and the destination size. Initially both are unset, that
        /// is, no scaling is applied. The whole of the current wl_buffer is
        /// used as the source, and the surface size is as defined in
        /// wl_surface.attach.
        ///
        /// If the destination size is set, it causes the surface size to become
        /// dst_width, dst_height. The source (rectangle) is scaled to exactly
        /// this size. This overrides whatever the attached wl_buffer size is,
        /// unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
        /// has no content and therefore no size. Otherwise, the size is always
        /// at least 1x1 in surface local coordinates.
        ///
        /// If the source rectangle is set, it defines what area of the wl_buffer is
        /// taken as the source. If the source rectangle is set and the destination
        /// size is not set, then src_width and src_height must be integers, and the
        /// surface size becomes the source rectangle size. This results in cropping
        /// without scaling. If src_width or src_height are not integers and
        /// destination size is not set, the bad_size protocol error is raised when
        /// the surface state is applied.
        ///
        /// The coordinate transformations from buffer pixel coordinates up to
        /// the surface-local coordinates happen in the following order:
        /// 1. buffer_transform (wl_surface.set_buffer_transform)
        /// 2. buffer_scale (wl_surface.set_buffer_scale)
        /// 3. crop and scale (wp_viewport.set*)
        /// This means, that the source rectangle coordinates of crop and scale
        /// are given in the coordinates after the buffer transform and scale,
        /// i.e. in the coordinates that would be the surface-local coordinates
        /// if the crop and scale was not applied.
        ///
        /// If src_x or src_y are negative, the bad_value protocol error is raised.
        /// Otherwise, if the source rectangle is partially or completely outside of
        /// the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
        /// when the surface state is applied. A NULL wl_buffer does not raise the
        /// out_of_buffer error.
        ///
        /// If the wl_surface associated with the wp_viewport is destroyed,
        /// all wp_viewport requests except 'destroy' raise the protocol error
        /// no_surface.
        ///
        /// If the wp_viewport object is destroyed, the crop and scale
        /// state is removed from the wl_surface. The change will be applied
        /// on the next wl_surface.commit.
        pub const Viewport = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wp.viewport.interface;
            pub const Error = common.wp.viewport.Error;
            pub inline fn getId(_viewport: *Viewport) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_viewport)).getId();
            }
            pub inline fn getVersion(_viewport: *Viewport) u32 {
                return @as(*client.wl.Proxy, @ptrCast(_viewport)).getVersion();
            }
            pub inline fn getUserData(_viewport: *Viewport) ?*anyopaque {
                return @as(*client.wl.Proxy, @ptrCast(_viewport)).getUserData();
            }
            pub inline fn setQueue(_viewport: *Viewport, _queue: *client.wl.EventQueue) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_viewport);
                _proxy.setQueue(_queue);
            }
            /// The associated wl_surface's crop and scale state is removed.
            /// The change is applied on the next wl_surface.commit.
            pub fn destroy(_viewport: *Viewport) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_viewport);
                _proxy.marshal(0, null);
                _proxy.destroy();
            }
            pub const destroy_since_version = 1;

            /// Set the source rectangle of the associated wl_surface. See
            /// wp_viewport for the description, and relation to the wl_buffer
            /// size.
            ///
            /// If all of x, y, width and height are -1.0, the source rectangle is
            /// unset instead. Any other set of values where width or height are zero
            /// or negative, or x or y are negative, raise the bad_value protocol
            /// error.
            ///
            /// The crop and scale state is double-buffered, see wl_surface.commit.
            pub fn setSource(_viewport: *Viewport, _x: common.Fixed, _y: common.Fixed, _width: common.Fixed, _height: common.Fixed) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_viewport);
                var _args = [_]common.Argument{
                    .{ .f = _x },
                    .{ .f = _y },
                    .{ .f = _width },
                    .{ .f = _height },
                };
                _proxy.marshal(1, &_args);
            }
            pub const set_source_since_version = 1;

            /// Set the destination size of the associated wl_surface. See
            /// wp_viewport for the description, and relation to the wl_buffer
            /// size.
            ///
            /// If width is -1 and height is -1, the destination size is unset
            /// instead. Any other pair of values for width and height that
            /// contains zero or negative values raises the bad_value protocol
            /// error.
            ///
            /// The crop and scale state is double-buffered, see wl_surface.commit.
            pub fn setDestination(_viewport: *Viewport, _width: i32, _height: i32) void {
                const _proxy: *client.wl.Proxy = @ptrCast(_viewport);
                var _args = [_]common.Argument{
                    .{ .i = _width },
                    .{ .i = _height },
                };
                _proxy.marshal(2, &_args);
            }
            pub const set_destination_since_version = 1;
        };
    };
};

pub const server = struct {
    pub const wl = struct {
        pub const Object = common.Object;
        pub const Message = common.Message;
        pub const Interface = common.Interface;
        pub const list = common.list;
        pub const Array = common.Array;
        pub const Fixed = common.Fixed;
        pub const Argument = common.Argument;

        /// This is wayland-server's wl_display. It has been renamed as zig-wayland has
        /// decided to hide wl_resources with opaque pointers in the same way that
        /// wayland-client does with wl_proxys. This of course creates a name conflict.
        pub const Server = opaque {
            pub inline fn create() error{ServerCreateFailed}!*Server {
                return ffi.server.wl_display_create() orelse error.ServerCreateFailed;
            }

            pub inline fn destroy(_server: *Server) void {
                ffi.server.wl_display_destroy(_server);
            }

            pub inline fn getEventLoop(_server: *Server) *EventLoop {
                return ffi.server.wl_display_get_event_loop(_server);
            }

            pub inline fn addSocket(_server: *Server, name: [*:0]const u8) error{AddSocketFailed}!void {
                if (ffi.server.wl_display_add_socket(_server, name) == -1)
                    return error.AddSocketFailed;
            }

            // wayland-client will connect to wayland-0 even if WAYLAND_DISPLAY is
            // unset due to an unfortunate piece of code that was not removed before
            // the library was stabilized. Because of this, it is a good idea to never
            // call the socket wayland-0. So, instead of binding to wayland-server's
            // wl_display_add_socket_auto we implement a version which skips wayland-0.
            pub fn addSocketAuto(_server: *Server, buf: *[11]u8) error{AddSocketFailed}![:0]const u8 {
                // Don't use wayland-0
                var i: u32 = 1;
                while (i <= 32) : (i += 1) {
                    const name = std.fmt.bufPrintZ(buf, "wayland-{}", .{i}) catch unreachable;
                    _server.addSocket(name.ptr) catch continue;
                    return name;
                }
                return error.AddSocketFailed;
            }

            pub inline fn addSocketFd(_server: *Server, sock_fd: c_int) error{AddSocketFailed}!void {
                if (ffi.server.wl_display_add_socket_fd(_server, sock_fd) == -1)
                    return error.AddSocketFailed;
            }

            pub inline fn terminate(_server: *Server) void {
                ffi.server.wl_display_terminate(_server);
            }

            pub inline fn run(_server: *Server) void {
                ffi.server.wl_display_run(_server);
            }

            pub inline fn flushClients(_server: *Server) void {
                ffi.server.wl_display_flush_clients(_server);
            }

            pub inline fn destroyClients(_server: *Server) void {
                ffi.server.wl_display_destroy_clients(_server);
            }

            pub inline fn getSerial(_server: *Server) u32 {
                return ffi.server.wl_display_get_serial(_server);
            }

            pub inline fn nextSerial(_server: *Server) u32 {
                return ffi.server.wl_display_next_serial(_server);
            }

            pub inline fn addDestroyListener(_server: *Server, listener: *Listener(*Server)) void {
                ffi.server.wl_display_add_destroy_listener(_server, listener);
            }

            pub inline fn addClientCreatedListener(_server: *Server, listener: *Listener(*Client)) void {
                ffi.server.wl_display_add_client_created_listener(_server, listener);
            }

            // Doesn't really make sense with our Listener API as we would need to
            // pass a pointer to the wrapper function
            //fn wl_display_get_destroy_listener(_server: *Server, notify: @TypeOf(Listener(*Server).notify)) ?*Listener(*Server);

            pub inline fn setGlobalFilter(
                _server: *Server,
                comptime T: type,
                comptime filter: fn (_client: *const Client, global: *const Global, data: T) bool,
                data: T,
            ) void {
                ffi.server.wl_display_set_global_filter(
                    _server,
                    struct {
                        fn _wrapper(_client: *const Client, global: *const Global, _data: ?*anyopaque) callconv(.c) bool {
                            return filter(_client, global, @ptrCast(@alignCast(_data)));
                        }
                    }._wrapper,
                    data,
                );
            }

            pub inline fn getClientList(_server: *Server) *list.Head(Client, null) {
                return ffi.server.wl_display_get_client_list(_server);
            }

            pub inline fn initShm(_server: *Server) error{OutOfMemory}!void {
                if (ffi.server.wl_display_init_shm(_server) == -1) return error.OutOfMemory;
            }

            pub inline fn addShmFormat(_server: *Server, format: u32) error{OutOfMemory}!*u32 {
                return ffi.server.wl_display_add_shm_format(_server, format) orelse error.OutOfMemory;
            }

            pub inline fn addProtocolLogger(
                _server: *Server,
                comptime T: type,
                comptime func: fn (data: T, direction: ProtocolLogger.Type, message: *const ProtocolLogger.LogMessage) void,
                data: T,
            ) void {
                ffi.server.wl_display_add_protocol_logger(
                    _server,
                    struct {
                        fn _wrapper(_data: ?*anyopaque, _direction: ProtocolLogger.Type, _message: *const ProtocolLogger.LogMessage) callconv(.c) void {
                            func(@ptrCast(@alignCast(_data)), _direction, _message);
                        }
                    }._wrapper,
                    data,
                );
            }
        };

        pub const Client = opaque {
            pub inline fn create(_server: *Server, fd: c_int) ?*Client {
                return ffi.server.wl_client_create(_server, fd);
            }

            pub inline fn destroy(_client: *Client) void {
                ffi.server.wl_client_destroy(_client);
            }

            pub inline fn flush(_client: *Client) void {
                ffi.server.wl_client_flush(_client);
            }

            pub inline fn getLink(_client: *Client) *list.Link {
                return ffi.server.wl_client_get_link(_client);
            }

            pub inline fn fromLink(link: *list.Link) *Client {
                return ffi.server.wl_client_from_link(link);
            }

            pub const Credentials = struct {
                pid: posix.pid_t,
                gid: posix.gid_t,
                uid: posix.uid_t,
            };
            pub inline fn getCredentials(_client: *Client) Credentials {
                var credentials: Credentials = undefined;
                ffi.server.wl_client_get_credentials(_client, &credentials.pid, &credentials.uid, &credentials.gid);
                return credentials;
            }

            pub inline fn addDestroyListener(_client: *Client, listener: *Listener(*Client)) void {
                ffi.server.wl_client_add_destroy_listener(_client, listener);
            }

            // Doesn't really make sense with our Listener API as we would need to
            // pass a pointer to the wrapper function
            //fn wl_client_get_destroy_listener(_client: *Client, notify: @TypeOf(Listener(*Client).notify)) ?*Listener(*Client);

            pub inline fn getObject(_client: *Client, id: u32) ?*Resource {
                return ffi.server.wl_client_get_object(_client, id);
            }

            pub inline fn postNoMemory(_client: *Client) void {
                ffi.server.wl_client_post_no_memory(_client);
            }

            pub inline fn postImplementationError(_client: *Client, msg: [*:0]const u8) void {
                ffi.server.wl_client_post_implementation_error(_client, "%s", msg);
            }

            pub inline fn addResourceCreatedListener(_client: *Client, listener: *Listener(*Resource)) void {
                ffi.server.wl_client_add_resource_created_listener(_client, listener);
            }

            pub const IteratorResult = enum(c_int) { stop, cont };
            pub inline fn forEachResource(
                _client: *Client,
                comptime T: type,
                comptime iterator: fn (resource: *Resource, data: T) IteratorResult,
                data: T,
            ) void {
                ffi.server.wl_client_for_each_resource(
                    _client,
                    struct {
                        fn _wrapper(_resource: *Resource, _data: ?*anyopaque) callconv(.c) IteratorResult {
                            return iterator(_resource, @ptrCast(@alignCast(_data)));
                        }
                    }._wrapper,
                    data,
                );
            }

            pub inline fn getFd(_client: *Client) c_int {
                return ffi.server.wl_client_get_fd(_client);
            }

            pub inline fn getDisplay(_client: *Client) *Server {
                return ffi.server.wl_client_get_display(_client);
            }
        };

        pub const Global = opaque {
            pub inline fn create(
                _server: *Server,
                comptime T: type,
                version: u32,
                comptime DataT: type,
                data: DataT,
                comptime bind: fn (_client: *Client, data: DataT, version: u32, id: u32) void,
            ) error{GlobalCreateFailed}!*Global {
                return ffi.server.wl_global_create(
                    _server,
                    T.interface,
                    @as(c_int, @intCast(version)),
                    data,
                    struct {
                        fn _wrapper(_client: *Client, _data: ?*anyopaque, _version: u32, _id: u32) callconv(.c) void {
                            bind(_client, @ptrCast(@alignCast(_data)), _version, _id);
                        }
                    }._wrapper,
                ) orelse error.GlobalCreateFailed;
            }

            pub inline fn remove(global: *Global) void {
                ffi.server.wl_global_remove(global);
            }

            pub inline fn destroy(global: *Global) void {
                ffi.server.wl_global_destroy(global);
            }

            pub inline fn getInterface(global: *const Global) *const Interface {
                return ffi.server.wl_global_get_interface(global);
            }

            pub inline fn getName(global: *const Global, _client: *const Client) u32 {
                return ffi.server.wl_global_get_name(global, _client);
            }

            pub inline fn getUserData(global: *const Global) ?*anyopaque {
                return ffi.server.wl_global_get_user_data(global);
            }
        };

        pub const Resource = opaque {
            pub inline fn create(_client: *Client, comptime T: type, version: u32, id: u32) error{ResourceCreateFailed}!*Resource {
                // This is only a c_int because of legacy libwayland reasons. Negative versions are invalid.
                // Version is a u32 on the wire and for wl_global, wl_proxy, etc.
                return ffi.server.wl_resource_create(_client, T.interface, @as(c_int, @intCast(version)), id) orelse error.ResourceCreateFailed;
            }

            pub inline fn destroy(resource: *Resource) void {
                ffi.server.wl_resource_destroy(resource);
            }

            pub inline fn postEvent(resource: *Resource, opcode: u32, args: ?[*]Argument) void {
                ffi.server.wl_resource_post_event_array(resource, opcode, args);
            }

            pub inline fn queueEvent(resource: *Resource, opcode: u32, args: ?[*]Argument) void {
                ffi.server.wl_resource_queue_event_array(resource, opcode, args);
            }

            pub inline fn postError(resource: *Resource, code: u32, message: [*:0]const u8) void {
                ffi.server.wl_resource_post_error(resource, code, "%s", message);
            }

            pub inline fn postNoMemory(resource: *Resource) void {
                ffi.server.wl_resource_post_no_memory(resource);
            }

            pub const DispatcherFn = fn (
                implementation: ?*const anyopaque,
                resource: *Resource,
                opcode: u32,
                message: *const Message,
                args: [*]Argument,
            ) callconv(.c) c_int;
            pub const DestroyFn = fn (resource: *Resource) callconv(.c) void;
            pub inline fn setDispatcher(
                resource: *Resource,
                dispatcher: ?*const DispatcherFn,
                implementation: ?*const anyopaque,
                data: ?*anyopaque,
                destroy_fn: ?*const DestroyFn,
            ) void {
                ffi.server.wl_resource_set_dispatcher(resource, dispatcher, implementation, data, destroy_fn);
            }

            pub inline fn getUserData(resource: *Resource) ?*anyopaque {
                return ffi.server.wl_resource_get_user_data(resource);
            }

            pub inline fn getId(resource: *Resource) u32 {
                return ffi.server.wl_resource_get_id(resource);
            }

            pub inline fn getLink(resource: *Resource) *list.Link {
                return ffi.server.wl_resource_get_link(resource);
            }

            pub inline fn fromLink(link: *list.Link) *Resource {
                return ffi.server.wl_resource_from_link(link);
            }

            pub inline fn findForClient(_list: *list.Head(Resource, null), _client: *Client) ?*Resource {
                return ffi.server.wl_resource_find_for_client(_list, _client);
            }

            pub inline fn getClient(resource: *Resource) *Client {
                return ffi.server.wl_resource_get_client(resource);
            }

            pub inline fn getVersion(resource: *Resource) u32 {
                // The fact that wl_resource.version is a int in libwayland is
                // a mistake. Negative versions are impossible and u32 is used
                // everywhere else in libwayland
                return @as(u32, @intCast(ffi.server.wl_resource_get_version(resource)));
            }

            // TOOD: unsure if this should be bound
            //fn wl_resource_set_destructor(resource: *Resource, destroy: DestroyFn) void;

            pub inline fn getClass(resource: *Resource) [*:0]const u8 {
                return ffi.server.wl_resource_get_class(resource);
            }

            pub inline fn addDestroyListener(resource: *Resource, listener: *Listener(*Resource)) void {
                ffi.server.wl_resource_add_destroy_listener(resource, listener);
            }

            // Doesn't really make sense with our Listener API as we would need to
            // pass a pointer to the wrapper function
            //fn wl_resource_get_destroy_listener(resource: *Resource, notify: @TypeOf(Listener(*Resource).notify)) ?*Listener(*Resource);
        };

        pub const ProtocolLogger = opaque {
            pub const Type = enum(c_int) {
                request,
                event,
            };

            pub const LogMessage = extern struct {
                resource: *Resource,
                message_opcode: c_int,
                message: *Message,
                arguments_count: c_int,
                arguments: ?[*]Argument,
            };

            pub inline fn destroy(logger: *ProtocolLogger) void {
                ffi.server.wl_protocol_logger_destroy(logger);
            }
        };

        pub fn Listener(comptime T: type) type {
            return extern struct {
                const Self = @This();

                pub const NotifyFn = if (T == void)
                    fn (listener: *Self) void
                else
                    fn (listener: *Self, data: T) void;

                link: list.Link,
                notify: *const fn (listener: *Self, data: ?*anyopaque) callconv(.c) void,

                pub fn init(comptime notify: NotifyFn) Self {
                    var self: Self = undefined;
                    self.setNotify(notify);
                    return self;
                }

                pub fn setNotify(self: *Self, comptime notify: NotifyFn) void {
                    self.notify = if (T == void)
                        struct {
                            fn wrapper(listener: *Self, _: ?*anyopaque) callconv(.c) void {
                                notify(listener);
                            }
                        }.wrapper
                    else
                        struct {
                            fn wrapper(listener: *Self, data: ?*anyopaque) callconv(.c) void {
                                notify(listener, @ptrFromInt(@intFromPtr(data)));
                            }
                        }.wrapper;
                }
            };
        }

        pub fn Signal(comptime T: type) type {
            return extern struct {
                const Self = @This();

                listener_list: list.Head(Listener(T), .link),

                pub fn init(signal: *Self) void {
                    signal.listener_list.init();
                }

                pub fn add(signal: *Self, listener: *Listener(T)) void {
                    signal.listener_list.append(listener);
                }

                pub fn get(signal: *Self, notify: @TypeOf(Listener(T).notify)) ?*Listener(T) {
                    var it = signal.listener_list.iterator(.forward);
                    return while (it.next()) |listener| {
                        if (listener.notify == notify) break listener;
                    } else null;
                }

                pub const emit = if (T == void)
                    struct {
                        pub inline fn emit(signal: *Self) void {
                            emitInner(signal, null);
                        }
                    }.emit
                else
                    struct {
                        pub inline fn emit(signal: *Self, data: T) void {
                            emitInner(signal, data);
                        }
                    }.emit;

                /// This is similar to wlroots' wlr_signal_emit_safe. It handles
                /// removal of any element in the list during iteration and stops at
                /// whatever the last element was when iteration started.
                fn emitInner(signal: *Self, data: ?*anyopaque) void {
                    var cursor: Listener(T) = undefined;
                    signal.listener_list.prepend(&cursor);

                    var end: Listener(T) = undefined;
                    signal.listener_list.append(&end);

                    while (cursor.link.next != &end.link) {
                        const pos = cursor.link.next.?;
                        const listener: *Listener(T) = @fieldParentPtr("link", pos);

                        cursor.link.remove();
                        pos.insert(&cursor.link);

                        listener.notify(listener, data);
                    }

                    cursor.link.remove();
                    end.link.remove();
                }
            };
        }

        pub const EventMask = packed struct(u32) {
            readable: bool = false,
            writable: bool = false,
            hangup: bool = false,
            @"error": bool = false,

            _: u28 = 0,
        };

        pub const EventLoop = opaque {
            pub inline fn create() error{EventLoopCreateFailed}!*EventLoop {
                return ffi.server.wl_event_loop_create() orelse error.EventLoopCreateFailed;
            }

            pub inline fn destroy(loop: *EventLoop) void {
                ffi.server.wl_event_loop_destroy(loop);
            }

            pub inline fn addFd(
                loop: *EventLoop,
                comptime T: type,
                fd: c_int,
                mask: EventMask,
                comptime func: fn (fd: c_int, mask: EventMask, data: T) c_int,
                data: T,
            ) error{AddFdFailed}!*EventSource {
                return ffi.server.wl_event_loop_add_fd(
                    loop,
                    fd,
                    @bitCast(mask),
                    struct {
                        fn _wrapper(_fd: c_int, _mask: u32, _data: ?*anyopaque) callconv(.c) c_int {
                            return func(_fd, @bitCast(_mask), @ptrCast(@alignCast(_data)));
                        }
                    }._wrapper,
                    data,
                ) orelse error.AddFdFailed;
            }

            pub inline fn addTimer(
                loop: *EventLoop,
                comptime T: type,
                comptime func: fn (data: T) c_int,
                data: T,
            ) error{AddTimerFailed}!*EventSource {
                return ffi.server.wl_event_loop_add_timer(
                    loop,
                    struct {
                        fn _wrapper(_data: ?*anyopaque) callconv(.c) c_int {
                            return func(@ptrCast(@alignCast(_data)));
                        }
                    }._wrapper,
                    data,
                ) orelse error.AddTimerFailed;
            }

            pub inline fn addSignal(
                loop: *EventLoop,
                comptime T: type,
                signal_number: c_int,
                comptime func: fn (signal_number: c_int, data: T) c_int,
                data: T,
            ) error{AddSignalFailed}!*EventSource {
                return ffi.server.wl_event_loop_add_signal(
                    loop,
                    signal_number,
                    struct {
                        fn _wrapper(_signal_number: c_int, _data: ?*anyopaque) callconv(.c) c_int {
                            return func(_signal_number, @ptrCast(@alignCast(_data)));
                        }
                    }._wrapper,
                    data,
                ) orelse error.AddSignalFailed;
            }

            pub inline fn addIdle(
                loop: *EventLoop,
                comptime T: type,
                comptime func: fn (data: T) void,
                data: T,
            ) error{OutOfMemory}!*EventSource {
                return ffi.server.wl_event_loop_add_idle(
                    loop,
                    struct {
                        fn _wrapper(_data: ?*anyopaque) callconv(.c) void {
                            return func(@ptrCast(@alignCast(_data)));
                        }
                    }._wrapper,
                    data,
                ) orelse error.OutOfMemory;
            }

            pub inline fn dispatch(loop: *EventLoop, timeout: c_int) posix.UnexpectedError!void {
                const rc = ffi.server.wl_event_loop_dispatch(loop, timeout);
                switch (posix.errno(rc)) {
                    .SUCCESS => return,
                    // TODO
                    else => |err| return posix.unexpectedErrno(err),
                }
            }

            pub inline fn dispatchIdle(loop: *EventLoop) void {
                ffi.server.wl_event_loop_dispatch_idle(loop);
            }

            pub inline fn getFd(loop: *EventLoop) c_int {
                return ffi.server.wl_event_loop_get_fd(loop);
            }

            pub inline fn addDestroyListener(loop: *EventLoop, listener: *Listener(*EventLoop)) void {
                ffi.server.wl_event_loop_add_destroy_listener(loop, listener);
            }

            //fn wl_event_loop_get_destroy_listener(loop: *EventLoop, notify: @TypeOf(Listener(*EventLoop).notify)) ?*Listener;
            //pub const getDestroyListener = wl_event_loop_get_destroy_listener;
        };

        pub const EventSource = opaque {
            pub inline fn remove(source: *EventSource) void {
                if (ffi.server.wl_event_source_remove(source) != 0) unreachable;
            }

            pub inline fn check(source: *EventSource) void {
                ffi.server.wl_event_source_check(source);
            }

            pub inline fn fdUpdate(source: *EventSource, mask: EventMask) posix.UnexpectedError!void {
                const rc = ffi.server.wl_event_source_fd_update(source, @bitCast(mask));
                switch (posix.errno(rc)) {
                    .SUCCESS => return,
                    // TODO
                    else => |err| return posix.unexpectedErrno(err),
                }
            }

            pub inline fn timerUpdate(source: *EventSource, ms_delay: c_int) posix.UnexpectedError!void {
                const rc = ffi.server.wl_event_source_timer_update(source, ms_delay);
                switch (posix.errno(rc)) {
                    .SUCCESS => return,
                    // TODO
                    else => |err| return posix.unexpectedErrno(err),
                }
            }
        };

        pub const shm = struct {
            pub const Buffer = opaque {
                pub inline fn get(resource: *Resource) ?*shm.Buffer {
                    return ffi.server.wl_shm_buffer_get(resource);
                }

                pub inline fn beginAccess(buffer: *shm.Buffer) void {
                    ffi.server.wl_shm_buffer_begin_access(buffer);
                }

                pub inline fn endAccess(buffer: *shm.Buffer) void {
                    ffi.server.wl_shm_buffer_end_access(buffer);
                }

                pub inline fn getData(buffer: *shm.Buffer) ?*anyopaque {
                    return ffi.server.wl_shm_buffer_get_data(buffer);
                }

                pub inline fn getFormat(buffer: *shm.Buffer) u32 {
                    return ffi.server.wl_shm_buffer_get_format(buffer);
                }

                pub inline fn getHeight(buffer: *shm.Buffer) i32 {
                    return ffi.server.wl_shm_buffer_get_height(buffer);
                }

                pub inline fn getWidth(buffer: *shm.Buffer) i32 {
                    return ffi.server.wl_shm_buffer_get_width(buffer);
                }

                pub inline fn getStride(buffer: *shm.Buffer) i32 {
                    return ffi.server.wl_shm_buffer_get_stride(buffer);
                }

                pub inline fn refPool(buffer: *shm.Buffer) *Pool {
                    return ffi.server.wl_shm_buffer_ref_pool(buffer);
                }
            };

            pub const Pool = opaque {
                pub inline fn unref(pool: *Pool) void {
                    ffi.server.wl_shm_pool_unref(pool);
                }
            };
        };

        /// The core global object.  This is a special singleton object.  It
        /// is used for internal Wayland protocol features.
        pub const Display = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.display.interface;
            pub const Error = common.wl.display.Error;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Display {
                return @ptrCast(try server.wl.Resource.create(_client, Display, _version, _id));
            }
            pub inline fn destroy(_display: *Display) void {
                return @as(*server.wl.Resource, @ptrCast(_display)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Display {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_display: *Display) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_display)).getLink();
            }
            pub inline fn getClient(_display: *Display) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_display)).getClient();
            }
            pub inline fn getId(_display: *Display) u32 {
                return @as(*server.wl.Resource, @ptrCast(_display)).getId();
            }
            pub inline fn getVersion(_display: *Display) u32 {
                return @as(*server.wl.Resource, @ptrCast(_display)).getVersion();
            }
            pub inline fn postNoMemory(_display: *Display) void {
                return @as(*server.wl.Resource, @ptrCast(_display)).postNoMemory();
            }
            pub inline fn getUserData(_display: *Display) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_display)).getUserData();
            }
            pub inline fn postError(_display: *Display, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_display)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const sync_since_version = 1;
                pub const get_registry_since_version = 1;

                /// The sync request asks the server to emit the 'done' event
                /// on the returned wl_callback object.  Since requests are
                /// handled in-order and events are delivered in-order, this can
                /// be used as a barrier to ensure all previous requests and the
                /// resulting events have been handled.
                ///
                /// The object returned by this request will be destroyed by the
                /// compositor after the callback is fired and as such the client must not
                /// attempt to use it after that point.
                ///
                /// The callback_data passed in the callback is undefined and should be ignored.
                sync: struct {
                    callback: u32,
                },

                /// This request creates a registry object that allows the client
                /// to list and bind the global objects available from the
                /// compositor.
                ///
                /// It should be noted that the server side resources consumed in
                /// response to a get_registry request can only be released when the
                /// client disconnects, not when the client side proxy is destroyed.
                /// Therefore, clients should invoke get_registry as infrequently as
                /// possible to avoid wasting memory.
                get_registry: struct {
                    registry: u32,
                },
            };
            pub inline fn setHandler(
                _display: *Display,
                comptime T: type,
                handle_request: *const fn (_display: *Display, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_display: *Display, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_display);
                _resource.setDispatcher(
                    common.Dispatcher(Display, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Display, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// The error event is sent out when a fatal (non-recoverable)
            /// error has occurred.  The object_id argument is the object
            /// where the error occurred, most often in response to a request
            /// to that object.  The code identifies the error and is defined
            /// by the object interface.  As such, each interface defines its
            /// own set of error codes.  The message is a brief description
            /// of the error, for (debugging) convenience.
            pub fn sendError(_display: *Display, _object_id: *common.Object, _code: u32, _message: [*:0]const u8) void {
                const _resource: *server.wl.Resource = @ptrCast(_display);
                var _args = [_]common.Argument{
                    .{ .o = @ptrCast(_object_id) },
                    .{ .u = _code },
                    .{ .s = _message },
                };
                _resource.postEvent(0, &_args);
            }
            pub const error_since_version = 1;

            /// This event is used internally by the object ID management
            /// logic. When a client deletes an object that it had created,
            /// the server will send this event to acknowledge that it has
            /// seen the delete request. When the client receives this event,
            /// it will know that it can safely reuse the object ID.
            pub fn sendDeleteId(_display: *Display, _id: u32) void {
                const _resource: *server.wl.Resource = @ptrCast(_display);
                var _args = [_]common.Argument{
                    .{ .u = _id },
                };
                _resource.postEvent(1, &_args);
            }
            pub const delete_id_since_version = 1;
        };

        /// The singleton global registry object.  The server has a number of
        /// global objects that are available to all clients.  These objects
        /// typically represent an actual object in the server (for example,
        /// an input device) or they are singleton objects that provide
        /// extension functionality.
        ///
        /// When a client creates a registry object, the registry object
        /// will emit a global event for each global currently in the
        /// registry.  Globals come and go as a result of device or
        /// monitor hotplugs, reconfiguration or other events, and the
        /// registry will send out global and global_remove events to
        /// keep the client up to date with the changes.  To mark the end
        /// of the initial burst of events, the client can use the
        /// wl_display.sync request immediately after calling
        /// wl_display.get_registry.
        ///
        /// A client can bind to a global object by using the bind
        /// request.  This creates a client-side handle that lets the object
        /// emit events to the client and lets the client invoke requests on
        /// the object.
        pub const Registry = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.registry.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Registry {
                return @ptrCast(try server.wl.Resource.create(_client, Registry, _version, _id));
            }
            pub inline fn destroy(_registry: *Registry) void {
                return @as(*server.wl.Resource, @ptrCast(_registry)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Registry {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_registry: *Registry) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_registry)).getLink();
            }
            pub inline fn getClient(_registry: *Registry) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_registry)).getClient();
            }
            pub inline fn getId(_registry: *Registry) u32 {
                return @as(*server.wl.Resource, @ptrCast(_registry)).getId();
            }
            pub inline fn getVersion(_registry: *Registry) u32 {
                return @as(*server.wl.Resource, @ptrCast(_registry)).getVersion();
            }
            pub inline fn postNoMemory(_registry: *Registry) void {
                return @as(*server.wl.Resource, @ptrCast(_registry)).postNoMemory();
            }
            pub inline fn getUserData(_registry: *Registry) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_registry)).getUserData();
            }
            pub const Request = union(enum) {
                pub const bind_since_version = 1;

                /// Binds a new, client-created object to the server using the
                /// specified name as the identifier.
                bind: struct {
                    name: u32,
                    interface_name: [*:0]const u8,
                    version: u32,
                    id: u32,
                },
            };
            pub inline fn setHandler(
                _registry: *Registry,
                comptime T: type,
                handle_request: *const fn (_registry: *Registry, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_registry: *Registry, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_registry);
                _resource.setDispatcher(
                    common.Dispatcher(Registry, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Registry, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// Notify the client of global objects.
            ///
            /// The event notifies the client that a global object with
            /// the given name is now available, and it implements the
            /// given version of the given interface.
            pub fn sendGlobal(_registry: *Registry, _name: u32, _interface: [*:0]const u8, _version: u32) void {
                const _resource: *server.wl.Resource = @ptrCast(_registry);
                var _args = [_]common.Argument{
                    .{ .u = _name },
                    .{ .s = _interface },
                    .{ .u = _version },
                };
                _resource.postEvent(0, &_args);
            }
            pub const global_since_version = 1;

            /// Notify the client of removed global objects.
            ///
            /// This event notifies the client that the global identified
            /// by name is no longer available.  If the client bound to
            /// the global using the bind request, the client should now
            /// destroy that object.
            ///
            /// The object remains valid and requests to the object will be
            /// ignored until the client destroys it, to avoid races between
            /// the global going away and a client sending a request to it.
            pub fn sendGlobalRemove(_registry: *Registry, _name: u32) void {
                const _resource: *server.wl.Resource = @ptrCast(_registry);
                var _args = [_]common.Argument{
                    .{ .u = _name },
                };
                _resource.postEvent(1, &_args);
            }
            pub const global_remove_since_version = 1;
        };

        /// Clients can handle the 'done' event to get notified when
        /// the related request is done.
        ///
        /// Note, because wl_callback objects are created from multiple independent
        /// factory interfaces, the wl_callback interface is frozen at version 1.
        pub const Callback = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.callback.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Callback {
                return @ptrCast(try server.wl.Resource.create(_client, Callback, _version, _id));
            }
            pub inline fn destroy(_callback: *Callback) void {
                return @as(*server.wl.Resource, @ptrCast(_callback)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Callback {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_callback: *Callback) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_callback)).getLink();
            }
            pub inline fn getClient(_callback: *Callback) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_callback)).getClient();
            }
            pub inline fn getId(_callback: *Callback) u32 {
                return @as(*server.wl.Resource, @ptrCast(_callback)).getId();
            }
            pub inline fn getVersion(_callback: *Callback) u32 {
                return @as(*server.wl.Resource, @ptrCast(_callback)).getVersion();
            }
            pub inline fn postNoMemory(_callback: *Callback) void {
                return @as(*server.wl.Resource, @ptrCast(_callback)).postNoMemory();
            }
            pub inline fn getUserData(_callback: *Callback) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_callback)).getUserData();
            }
            pub inline fn setHandler(
                _callback: *Callback,
                comptime T: type,
                comptime handle_destroy: ?fn (_callback: *Callback, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_callback);
                _resource.setDispatcher(
                    null,
                    null,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Callback, @ptrCast(__resource)),
                                @as(?*anyopaque, @ptrFromInt(@intFromPtr(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// Notify the client when the related request is done.
            pub fn destroySendDone(_callback: *Callback, _callback_data: u32) void {
                const _resource: *server.wl.Resource = @ptrCast(_callback);
                var _args = [_]common.Argument{
                    .{ .u = _callback_data },
                };
                _resource.postEvent(0, &_args);
                _resource.destroy();
            }
            pub const done_since_version = 1;
        };

        /// A buffer provides the content for a wl_surface. Buffers are
        /// 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.
        ///
        /// Color channels are assumed to be electrical rather than optical (in other
        /// words, encoded with a transfer function) unless otherwise specified. If
        /// the buffer uses a format that has an alpha channel, the alpha channel is
        /// assumed to be premultiplied into the electrical color channel values
        /// (after transfer function encoding) unless otherwise specified.
        ///
        /// Note, because wl_buffer objects are created from multiple independent
        /// factory interfaces, the wl_buffer interface is frozen at version 1.
        pub const Buffer = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wl.buffer.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Buffer {
                return @ptrCast(try server.wl.Resource.create(_client, Buffer, _version, _id));
            }
            pub inline fn destroy(_buffer: *Buffer) void {
                return @as(*server.wl.Resource, @ptrCast(_buffer)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Buffer {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_buffer: *Buffer) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_buffer)).getLink();
            }
            pub inline fn getClient(_buffer: *Buffer) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_buffer)).getClient();
            }
            pub inline fn getId(_buffer: *Buffer) u32 {
                return @as(*server.wl.Resource, @ptrCast(_buffer)).getId();
            }
            pub inline fn getVersion(_buffer: *Buffer) u32 {
                return @as(*server.wl.Resource, @ptrCast(_buffer)).getVersion();
            }
            pub inline fn postNoMemory(_buffer: *Buffer) void {
                return @as(*server.wl.Resource, @ptrCast(_buffer)).postNoMemory();
            }
            pub inline fn getUserData(_buffer: *Buffer) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_buffer)).getUserData();
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;

                /// Destroy a buffer. If and how you need to release the backing
                /// storage is defined by the buffer factory interface.
                ///
                /// For possible side-effects to a surface, see wl_surface.attach.
                destroy: void,
            };
            pub inline fn setHandler(
                _buffer: *Buffer,
                comptime T: type,
                handle_request: *const fn (_buffer: *Buffer, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_buffer: *Buffer, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_buffer);
                _resource.setDispatcher(
                    common.Dispatcher(Buffer, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Buffer, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// Sent when this wl_buffer is no longer used by the compositor.
            ///
            /// For more information on when release events may or may not be sent,
            /// and what consequences it has, please see the description of
            /// wl_surface.attach.
            ///
            /// If a client receives a release event before the frame callback
            /// requested in the same wl_surface.commit that attaches this
            /// wl_buffer to a surface, then the client is immediately free to
            /// reuse the buffer and its backing storage, and does not need a
            /// second buffer for the next surface content update. Typically
            /// this is possible, when the compositor maintains a copy of the
            /// wl_surface contents, e.g. as a GL texture. This is an important
            /// optimization for GL(ES) compositors with wl_shm clients.
            pub fn sendRelease(_buffer: *Buffer) void {
                const _resource: *server.wl.Resource = @ptrCast(_buffer);
                _resource.postEvent(0, null);
            }
            pub const release_since_version = 1;
        };

        /// A compositor.  This object is a singleton global.  The
        /// compositor is in charge of combining the contents of multiple
        /// surfaces into one displayable output.
        pub const Compositor = opaque {
            pub const generated_version = 4;
            pub const interface = &common.wl.compositor.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Compositor {
                return @ptrCast(try server.wl.Resource.create(_client, Compositor, _version, _id));
            }
            pub inline fn destroy(_compositor: *Compositor) void {
                return @as(*server.wl.Resource, @ptrCast(_compositor)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Compositor {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_compositor: *Compositor) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_compositor)).getLink();
            }
            pub inline fn getClient(_compositor: *Compositor) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_compositor)).getClient();
            }
            pub inline fn getId(_compositor: *Compositor) u32 {
                return @as(*server.wl.Resource, @ptrCast(_compositor)).getId();
            }
            pub inline fn getVersion(_compositor: *Compositor) u32 {
                return @as(*server.wl.Resource, @ptrCast(_compositor)).getVersion();
            }
            pub inline fn postNoMemory(_compositor: *Compositor) void {
                return @as(*server.wl.Resource, @ptrCast(_compositor)).postNoMemory();
            }
            pub inline fn getUserData(_compositor: *Compositor) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_compositor)).getUserData();
            }
            pub const Request = union(enum) {
                pub const create_surface_since_version = 1;
                pub const create_region_since_version = 1;

                /// Ask the compositor to create a new surface.
                create_surface: struct {
                    id: u32,
                },

                /// Ask the compositor to create a new region.
                create_region: struct {
                    id: u32,
                },
            };
            pub inline fn setHandler(
                _compositor: *Compositor,
                comptime T: type,
                handle_request: *const fn (_compositor: *Compositor, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_compositor: *Compositor, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_compositor);
                _resource.setDispatcher(
                    common.Dispatcher(Compositor, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Compositor, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
        };

        /// 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
        /// discretion. They can present wl_buffers, receive user input, and
        /// define a local coordinate system.
        ///
        /// The size of a surface (and relative positions on it) is described
        /// in surface-local coordinates, which may differ from the buffer
        /// coordinates of the pixel content, in case a buffer_transform
        /// or a buffer_scale is used.
        ///
        /// A surface without a "role" is fairly useless: a compositor does
        /// not know where, when or how to present it. The role is the
        /// purpose of a wl_surface. Examples of roles are a cursor for a
        /// pointer (as set by wl_pointer.set_cursor), a drag icon
        /// (wl_data_device.start_drag), a sub-surface
        /// (wl_subcompositor.get_subsurface), and a window as defined by a
        /// shell protocol (e.g. wl_shell.get_shell_surface).
        ///
        /// A surface can have only one role at a time. Initially a
        /// wl_surface does not have a role. Once a wl_surface is given a
        /// role, it is set permanently for the whole lifetime of the
        /// wl_surface object. Giving the current role again is allowed,
        /// unless explicitly forbidden by the relevant interface
        /// specification.
        ///
        /// Surface roles are given by requests in other interfaces such as
        /// wl_pointer.set_cursor. The request should explicitly mention
        /// that this request gives a role to a wl_surface. Often, this
        /// request also creates a new protocol object that represents the
        /// role and adds additional functionality to wl_surface. When a
        /// client wants to destroy a wl_surface, they must destroy this role
        /// object before the wl_surface, otherwise a defunct_role_object error is
        /// sent.
        ///
        /// Destroying the role object does not remove the role from the
        /// wl_surface, but it may stop the wl_surface from "playing the role".
        /// For instance, if a wl_subsurface object is destroyed, the wl_surface
        /// it was created for will be unmapped and forget its position and
        /// z-order. It is allowed to create a wl_subsurface for the same
        /// wl_surface again, but it is not allowed to use the wl_surface as
        /// a cursor (cursor is a different role than sub-surface, and role
        /// switching is not allowed).
        pub const Surface = opaque {
            pub const generated_version = 4;
            pub const interface = &common.wl.surface.interface;
            pub const Error = common.wl.surface.Error;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Surface {
                return @ptrCast(try server.wl.Resource.create(_client, Surface, _version, _id));
            }
            pub inline fn destroy(_surface: *Surface) void {
                return @as(*server.wl.Resource, @ptrCast(_surface)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Surface {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_surface: *Surface) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_surface)).getLink();
            }
            pub inline fn getClient(_surface: *Surface) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_surface)).getClient();
            }
            pub inline fn getId(_surface: *Surface) u32 {
                return @as(*server.wl.Resource, @ptrCast(_surface)).getId();
            }
            pub inline fn getVersion(_surface: *Surface) u32 {
                return @as(*server.wl.Resource, @ptrCast(_surface)).getVersion();
            }
            pub inline fn postNoMemory(_surface: *Surface) void {
                return @as(*server.wl.Resource, @ptrCast(_surface)).postNoMemory();
            }
            pub inline fn getUserData(_surface: *Surface) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_surface)).getUserData();
            }
            pub inline fn postError(_surface: *Surface, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_surface)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const attach_since_version = 1;
                pub const damage_since_version = 1;
                pub const frame_since_version = 1;
                pub const set_opaque_region_since_version = 1;
                pub const set_input_region_since_version = 1;
                pub const commit_since_version = 1;
                pub const set_buffer_transform_since_version = 2;
                pub const set_buffer_scale_since_version = 3;
                pub const damage_buffer_since_version = 4;

                /// Deletes the surface and invalidates its object ID.
                destroy: void,
                /// Set a buffer as the content of this surface.
                ///
                /// The new size of the surface is calculated based on the buffer
                /// size transformed by the inverse buffer_transform and the
                /// inverse buffer_scale. This means that at commit time the supplied
                /// buffer size must be an integer multiple of the buffer_scale. If
                /// that's not the case, an invalid_size error is sent.
                ///
                /// 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. 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. The x and y arguments are ignored
                /// and do not change the pending state. To achieve equivalent semantics,
                /// use wl_surface.offset.
                ///
                /// Surface contents are double-buffered state, see wl_surface.commit.
                ///
                /// The initial surface contents are void; there is no content.
                /// wl_surface.attach assigns the given wl_buffer as the pending
                /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
                /// surface contents, and the size of the surface becomes the size
                /// calculated from the wl_buffer, as described above. After commit,
                /// there is no pending buffer until the next attach.
                ///
                /// Committing a pending wl_buffer allows the compositor to read the
                /// pixels in the wl_buffer. The compositor may access the pixels at
                /// any time after the wl_surface.commit request. When the compositor
                /// will not access the pixels anymore, it will send the
                /// wl_buffer.release event. Only after receiving wl_buffer.release,
                /// the client may reuse the wl_buffer. A wl_buffer that has been
                /// attached and then replaced by another attach instead of committed
                /// will not receive a release event, and is not used by the
                /// compositor.
                ///
                /// If a pending wl_buffer has been committed to more than one wl_surface,
                /// the delivery of wl_buffer.release events becomes undefined. A well
                /// behaved client should not rely on wl_buffer.release events in this
                /// case. Instead, clients hitting this case should use
                /// wl_surface.get_release or use a protocol extension providing per-commit
                /// release notifications (if none of these options are available, a
                /// fallback can be implemented by creating multiple wl_buffer objects from
                /// the same backing storage).
                ///
                /// Destroying the wl_buffer after wl_buffer.release does not change
                /// 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.
                ///
                /// If a pending wl_buffer has been destroyed, the result is not specified.
                /// Many compositors are known to remove the surface content on the following
                /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
                /// maximise compatibility should not destroy pending buffers and should
                /// ensure that they explicitly remove content from surfaces, even after
                /// destroying buffers.
                attach: struct {
                    buffer: ?*server.wl.Buffer,
                    x: i32,
                    y: i32,
                },

                /// This request is used to describe the regions where the pending
                /// buffer is different from the current surface contents, and where
                /// the surface therefore needs to be repainted. The compositor
                /// ignores the parts of the damage that fall outside of the surface.
                ///
                /// Damage is double-buffered state, see wl_surface.commit.
                ///
                /// The damage rectangle is specified in surface-local coordinates,
                /// where x and y specify the upper left corner of the damage rectangle.
                ///
                /// The initial value for pending damage is empty: no damage.
                /// wl_surface.damage adds pending damage: the new pending damage
                /// is the union of old pending damage and the given rectangle.
                ///
                /// wl_surface.commit assigns pending damage as the current damage,
                /// and clears pending damage. The server will clear the current
                /// damage as it repaints the surface.
                ///
                /// Note! New clients should not use this request. Instead damage can be
                /// posted with wl_surface.damage_buffer which uses buffer coordinates
                /// instead of surface coordinates.
                damage: struct {
                    x: i32,
                    y: i32,
                    width: i32,
                    height: i32,
                },

                /// Request a notification when it is a good time to start drawing a new
                /// frame, by creating a frame callback. This is useful for throttling
                /// redrawing operations, and driving animations.
                ///
                /// When a client is animating on a wl_surface, it can use the 'frame'
                /// request to get notified when it is a good time to draw and commit the
                /// next frame of animation. If the client commits an update earlier than
                /// that, it is likely that some updates will not make it to the display,
                /// and the client is wasting resources by drawing too often.
                ///
                /// The frame request will take effect on the next wl_surface.commit.
                /// The notification will only be posted for one frame unless
                /// requested again. For a wl_surface, the notifications are posted in
                /// the order the frame requests were committed.
                ///
                /// The server must send the notifications so that a client
                /// will not send excessive updates, while still allowing
                /// the highest possible update rate for clients that wait for the reply
                /// before drawing again. The server should give some time for the client
                /// to draw and commit after sending the frame callback events to let it
                /// hit the next output refresh.
                ///
                /// A server should avoid signaling the frame callbacks if the
                /// surface is not visible in any way, e.g. the surface is off-screen,
                /// or completely obscured by other opaque surfaces.
                ///
                /// The object returned by this request will be destroyed by the
                /// compositor after the callback is fired and as such the client must not
                /// attempt to use it after that point.
                ///
                /// The callback_data passed in the callback is the current time, in
                /// milliseconds, with an undefined base.
                frame: struct {
                    callback: u32,
                },

                /// This request sets the region of the surface that contains
                /// opaque content.
                ///
                /// The opaque region is an optimization hint for the compositor
                /// that lets it optimize the redrawing of content behind opaque
                /// regions.  Setting an opaque region is not required for correct
                /// behaviour, but marking transparent content as opaque will result
                /// in repaint artifacts.
                ///
                /// The opaque region is specified in surface-local coordinates.
                ///
                /// The compositor ignores the parts of the opaque region that fall
                /// outside of the surface.
                ///
                /// Opaque region is double-buffered state, see wl_surface.commit.
                ///
                /// wl_surface.set_opaque_region changes the pending opaque region.
                /// wl_surface.commit copies the pending region to the current region.
                /// Otherwise, the pending and current regions are never changed.
                ///
                /// The initial value for an opaque region is empty. Setting the pending
                /// opaque region has copy semantics, and the wl_region object can be
                /// destroyed immediately. A NULL wl_region causes the pending opaque
                /// region to be set to empty.
                set_opaque_region: struct {
                    region: ?*server.wl.Region,
                },

                /// This request sets the region of the surface that can receive
                /// pointer and touch events.
                ///
                /// Input events happening outside of this region will try the next
                /// surface in the server surface stack. The compositor ignores the
                /// parts of the input region that fall outside of the surface.
                ///
                /// The input region is specified in surface-local coordinates.
                ///
                /// Input region is double-buffered state, see wl_surface.commit.
                ///
                /// wl_surface.set_input_region changes the pending input region.
                /// wl_surface.commit copies the pending region to the current region.
                /// Otherwise the pending and current regions are never changed,
                /// except cursor and icon surfaces are special cases, see
                /// wl_pointer.set_cursor and wl_data_device.start_drag.
                ///
                /// The initial value for an input region is infinite. That means the
                /// whole surface will accept input. Setting the pending input region
                /// has copy semantics, and the wl_region object can be destroyed
                /// immediately. A NULL wl_region causes the input region to be set
                /// to infinite.
                set_input_region: struct {
                    region: ?*server.wl.Region,
                },

                /// Surface state (input, opaque, and damage regions, attached buffers,
                /// etc.) is double-buffered. Protocol requests modify the pending state,
                /// as opposed to the active state in use by the compositor.
                ///
                /// All requests that need a commit to become effective are documented
                /// to affect double-buffered state.
                ///
                /// Other interfaces may add further double-buffered surface state.
                ///
                /// A commit request atomically creates a Content Update (CU) from the
                /// pending state, even if the pending state has not been touched. The
                /// content update is placed at the end of a per-surface queue until it
                /// becomes active. After commit, the new pending state is as documented for
                /// each related request.
                ///
                /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
                /// (SCU). If the surface is effectively synchronized at the commit request,
                /// it is a SCU, otherwise a DCU.
                ///
                /// When a surface transitions from effectively synchronized to effectively
                /// desynchronized, all SCUs in its queue which are not reachable by any
                /// DCU become DCUs and dependency edges from outside the queue to these CUs
                /// are removed.
                ///
                /// See wl_subsurface for the definition of 'effectively synchronized' and
                /// 'effectively desynchronized'.
                ///
                /// When a CU is placed in the queue, the CU has a dependency on the CU in
                /// front of it and to the SCU at end of the queue of every direct child
                /// surface if that SCU exists and does not have another dependent. This can
                /// form a directed acyclic graph of CUs with dependencies as edges.
                ///
                /// In addition to surface state, the CU can have constraints that must be
                /// satisfied before it can be applied. Other interfaces may add CU
                /// constraints.
                ///
                /// All DCUs which do not have a SCU in front of themselves in their queue,
                /// are candidates. If the graph that's reachable by a candidate does not
                /// have any unsatisfied constraints, the entire graph must be applied
                /// atomically.
                ///
                /// When a CU is applied, the wl_buffer is applied before all other state.
                /// This means that all coordinates in double-buffered state are relative to
                /// the newly attached wl_buffers, except for wl_surface.attach itself. If
                /// there is no newly attached wl_buffer, the coordinates are relative to
                /// the previous content update.
                commit: void,
                /// This request sets the transformation that the client has already applied
                /// to the content of the buffer. The accepted values for the transform
                /// parameter are the values for wl_output.transform.
                ///
                /// The compositor applies the inverse of this transformation whenever it
                /// uses the buffer contents.
                ///
                /// Buffer transform is double-buffered state, see wl_surface.commit.
                ///
                /// A newly created surface has its buffer transformation set to normal.
                ///
                /// wl_surface.set_buffer_transform changes the pending buffer
                /// transformation. wl_surface.commit copies the pending buffer
                /// transformation to the current one. Otherwise, the pending and current
                /// values are never changed.
                ///
                /// The purpose of this request is to allow clients to render content
                /// according to the output transform, thus permitting the compositor to
                /// use certain optimizations even if the display is rotated. Using
                /// hardware overlays and scanning out a client buffer for fullscreen
                /// surfaces are examples of such optimizations. Those optimizations are
                /// highly dependent on the compositor implementation, so the use of this
                /// request should be considered on a case-by-case basis.
                ///
                /// Note that if the transform value includes 90 or 270 degree rotation,
                /// the width of the buffer will become the surface height and the height
                /// of the buffer will become the surface width.
                ///
                /// If transform is not one of the values from the
                /// wl_output.transform enum the invalid_transform protocol error
                /// is raised.
                set_buffer_transform: struct {
                    transform: common.wl.output.Transform,
                },

                /// This request sets an optional scaling factor on how the compositor
                /// interprets the contents of the buffer attached to the window.
                ///
                /// Buffer scale is double-buffered state, see wl_surface.commit.
                ///
                /// A newly created surface has its buffer scale set to 1.
                ///
                /// wl_surface.set_buffer_scale changes the pending buffer scale.
                /// wl_surface.commit copies the pending buffer scale to the current one.
                /// Otherwise, the pending and current values are never changed.
                ///
                /// The purpose of this request is to allow clients to supply higher
                /// resolution buffer data for use on high resolution outputs. It is
                /// intended that you pick the same buffer scale as the scale of the
                /// output that the surface is displayed on. This means the compositor
                /// can avoid scaling when rendering the surface on that output.
                ///
                /// Note that if the scale is larger than 1, then you have to attach
                /// a buffer that is larger (by a factor of scale in each dimension)
                /// than the desired surface size.
                ///
                /// If scale is not greater than 0 the invalid_scale protocol error is
                /// raised.
                set_buffer_scale: struct {
                    scale: i32,
                },

                /// This request is used to describe the regions where the pending
                /// buffer is different from the current surface contents, and where
                /// the surface therefore needs to be repainted. The compositor
                /// ignores the parts of the damage that fall outside of the surface.
                ///
                /// Damage is double-buffered state, see wl_surface.commit.
                ///
                /// The damage rectangle is specified in buffer coordinates,
                /// where x and y specify the upper left corner of the damage rectangle.
                ///
                /// The initial value for pending damage is empty: no damage.
                /// wl_surface.damage_buffer adds pending damage: the new pending
                /// damage is the union of old pending damage and the given rectangle.
                ///
                /// wl_surface.commit assigns pending damage as the current damage,
                /// and clears pending damage. The server will clear the current
                /// damage as it repaints the surface.
                ///
                /// This request differs from wl_surface.damage in only one way - it
                /// takes damage in buffer coordinates instead of surface-local
                /// coordinates. While this generally is more intuitive than surface
                /// coordinates, it is especially desirable when using wp_viewport
                /// or when a drawing library (like EGL) is unaware of buffer scale
                /// and buffer transform.
                ///
                /// Note: Because buffer transformation changes and damage requests may
                /// be interleaved in the protocol stream, it is impossible to determine
                /// the actual mapping between surface and buffer damage until
                /// wl_surface.commit time. Therefore, compositors wishing to take both
                /// kinds of damage into account will have to accumulate damage from the
                /// two requests separately and only transform from one to the other
                /// after receiving the wl_surface.commit.
                damage_buffer: struct {
                    x: i32,
                    y: i32,
                    width: i32,
                    height: i32,
                },
            };
            pub inline fn setHandler(
                _surface: *Surface,
                comptime T: type,
                handle_request: *const fn (_surface: *Surface, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_surface: *Surface, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_surface);
                _resource.setDispatcher(
                    common.Dispatcher(Surface, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Surface, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// This is emitted whenever a surface's creation, movement, or resizing
            /// results in some part of it being within the scanout region of an
            /// output.
            ///
            /// Note that a surface may be overlapping with zero or more outputs.
            pub fn sendEnter(_surface: *Surface, _output: *server.wl.Output) void {
                const _resource: *server.wl.Resource = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .o = @ptrCast(_output) },
                };
                _resource.postEvent(0, &_args);
            }
            pub const enter_since_version = 1;

            /// This is emitted whenever a surface's creation, movement, or resizing
            /// results in it no longer having any part of it within the scanout region
            /// of an output.
            ///
            /// Clients should not use the number of outputs the surface is on for frame
            /// throttling purposes. The surface might be hidden even if no leave event
            /// has been sent, and the compositor might expect new surface content
            /// updates even if no enter event has been sent. The frame event should be
            /// used instead.
            pub fn sendLeave(_surface: *Surface, _output: *server.wl.Output) void {
                const _resource: *server.wl.Resource = @ptrCast(_surface);
                var _args = [_]common.Argument{
                    .{ .o = @ptrCast(_output) },
                };
                _resource.postEvent(1, &_args);
            }
            pub const leave_since_version = 1;
        };

        /// A region object describes an area.
        ///
        /// Region objects are used to describe the opaque and input
        /// regions of a surface.
        pub const Region = opaque {
            pub const generated_version = 4;
            pub const interface = &common.wl.region.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Region {
                return @ptrCast(try server.wl.Resource.create(_client, Region, _version, _id));
            }
            pub inline fn destroy(_region: *Region) void {
                return @as(*server.wl.Resource, @ptrCast(_region)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Region {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_region: *Region) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_region)).getLink();
            }
            pub inline fn getClient(_region: *Region) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_region)).getClient();
            }
            pub inline fn getId(_region: *Region) u32 {
                return @as(*server.wl.Resource, @ptrCast(_region)).getId();
            }
            pub inline fn getVersion(_region: *Region) u32 {
                return @as(*server.wl.Resource, @ptrCast(_region)).getVersion();
            }
            pub inline fn postNoMemory(_region: *Region) void {
                return @as(*server.wl.Resource, @ptrCast(_region)).postNoMemory();
            }
            pub inline fn getUserData(_region: *Region) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_region)).getUserData();
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const add_since_version = 1;
                pub const subtract_since_version = 1;

                /// Destroy the region.  This will invalidate the object ID.
                destroy: void,
                /// Add the specified rectangle to the region.
                add: struct {
                    x: i32,
                    y: i32,
                    width: i32,
                    height: i32,
                },

                /// Subtract the specified rectangle from the region.
                subtract: struct {
                    x: i32,
                    y: i32,
                    width: i32,
                    height: i32,
                },
            };
            pub inline fn setHandler(
                _region: *Region,
                comptime T: type,
                handle_request: *const fn (_region: *Region, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_region: *Region, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_region);
                _resource.setDispatcher(
                    common.Dispatcher(Region, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Region, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
        };

        /// An output describes part of the compositor geometry.  The
        /// compositor works in the 'compositor coordinate system' and an
        /// output corresponds to a rectangular area in that space that is
        /// actually visible.  This typically corresponds to a monitor that
        /// displays part of the compositor space.  This object is published
        /// as global during start up, or when a monitor is hotplugged.
        pub const Output = opaque {
            pub const generated_version = 3;
            pub const interface = &common.wl.output.interface;
            pub const Subpixel = common.wl.output.Subpixel;
            pub const Transform = common.wl.output.Transform;
            pub const Mode = common.wl.output.Mode;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Output {
                return @ptrCast(try server.wl.Resource.create(_client, Output, _version, _id));
            }
            pub inline fn destroy(_output: *Output) void {
                return @as(*server.wl.Resource, @ptrCast(_output)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Output {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_output: *Output) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_output)).getLink();
            }
            pub inline fn getClient(_output: *Output) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_output)).getClient();
            }
            pub inline fn getId(_output: *Output) u32 {
                return @as(*server.wl.Resource, @ptrCast(_output)).getId();
            }
            pub inline fn getVersion(_output: *Output) u32 {
                return @as(*server.wl.Resource, @ptrCast(_output)).getVersion();
            }
            pub inline fn postNoMemory(_output: *Output) void {
                return @as(*server.wl.Resource, @ptrCast(_output)).postNoMemory();
            }
            pub inline fn getUserData(_output: *Output) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_output)).getUserData();
            }
            pub const Request = union(enum) {
                pub const release_since_version = 3;

                /// Using this request a client can tell the server that it is not going to
                /// use the output object anymore.
                release: void,
            };
            pub inline fn setHandler(
                _output: *Output,
                comptime T: type,
                handle_request: *const fn (_output: *Output, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_output: *Output, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_output);
                _resource.setDispatcher(
                    common.Dispatcher(Output, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Output, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// The geometry event describes geometric properties of the output.
            /// The event is sent when binding to the output object and whenever
            /// any of the properties change.
            ///
            /// 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).
            ///
            /// Clients should use wl_surface.preferred_buffer_transform instead of the
            /// transform advertised by this event to find the preferred buffer
            /// transform to use for a surface.
            ///
            /// 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 name and description.
            pub fn sendGeometry(_output: *Output, _x: i32, _y: i32, _physical_width: i32, _physical_height: i32, _subpixel: Subpixel, _make: [*:0]const u8, _model: [*:0]const u8, _transform: Transform) void {
                const _resource: *server.wl.Resource = @ptrCast(_output);
                var _args = [_]common.Argument{
                    .{ .i = _x },
                    .{ .i = _y },
                    .{ .i = _physical_width },
                    .{ .i = _physical_height },
                    .{ .i = switch (@typeInfo(Subpixel)) {
                        .@"enum" => @as(i32, @intCast(@intFromEnum(_subpixel))),
                        .@"struct" => @bitCast(_subpixel),
                        else => unreachable,
                    } },
                    .{ .s = _make },
                    .{ .s = _model },
                    .{ .i = switch (@typeInfo(Transform)) {
                        .@"enum" => @as(i32, @intCast(@intFromEnum(_transform))),
                        .@"struct" => @bitCast(_transform),
                        else => unreachable,
                    } },
                };
                _resource.postEvent(0, &_args);
            }
            pub const geometry_since_version = 1;

            /// The mode event describes an available mode for the output.
            ///
            /// The event is sent when binding to the output object and there
            /// will always be one mode, the current mode.  The event is sent
            /// again if an output changes mode, for the mode that is now
            /// current.  In other words, the current mode is always the last
            /// mode that was received with the current flag set.
            ///
            /// Non-current modes are deprecated. A compositor can decide to only
            /// advertise the current mode and never send other modes. Clients
            /// should not rely on non-current modes.
            ///
            /// The size of a mode is given in physical hardware units of
            /// the output device. This is not necessarily the same as
            /// the output size in the global compositor space. For instance,
            /// the output may be scaled, as described in wl_output.scale,
            /// or transformed, as described in wl_output.transform. Clients
            /// willing to retrieve the output size in the global compositor
            /// space should use xdg_output.logical_size instead.
            ///
            /// 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.
            ///
            /// Note: this information is not always meaningful for all outputs. Some
            /// compositors, such as those exposing virtual outputs, might fake the
            /// refresh rate or the size.
            pub fn sendMode(_output: *Output, _flags: Mode, _width: i32, _height: i32, _refresh: i32) void {
                const _resource: *server.wl.Resource = @ptrCast(_output);
                var _args = [_]common.Argument{
                    .{ .u = switch (@typeInfo(Mode)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_flags))),
                        .@"struct" => @bitCast(_flags),
                        else => unreachable,
                    } },
                    .{ .i = _width },
                    .{ .i = _height },
                    .{ .i = _refresh },
                };
                _resource.postEvent(1, &_args);
            }
            pub const mode_since_version = 1;

            /// This event is sent after all other properties have been
            /// sent after binding to the output object and after any
            /// other property changes done after that. This allows
            /// changes to the output properties to be seen as
            /// atomic, even if they happen via multiple events.
            pub fn sendDone(_output: *Output) void {
                const _resource: *server.wl.Resource = @ptrCast(_output);
                _resource.postEvent(2, null);
            }
            pub const done_since_version = 2;

            /// This event contains scaling geometry information
            /// that is not in the geometry event. It may be sent after
            /// binding the output object or if the output scale changes
            /// later. The compositor will emit a non-zero, positive
            /// value for scale. If it is not sent, the client should
            /// assume a scale of 1.
            ///
            /// A scale larger than 1 means that the compositor will
            /// automatically scale surface buffers by this amount
            /// when rendering. This is used for very high resolution
            /// displays where applications rendering at the native
            /// resolution would be too small to be legible.
            ///
            /// Clients should use wl_surface.preferred_buffer_scale
            /// instead of this event to find the preferred buffer
            /// scale to use for a surface.
            ///
            /// The scale event will be followed by a done event.
            pub fn sendScale(_output: *Output, _factor: i32) void {
                const _resource: *server.wl.Resource = @ptrCast(_output);
                var _args = [_]common.Argument{
                    .{ .i = _factor },
                };
                _resource.postEvent(3, &_args);
            }
            pub const scale_since_version = 2;
        };

        /// 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
        /// device is hot plugged.  A seat typically has a pointer and
        /// maintains a keyboard focus and a pointer focus.
        pub const Seat = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.seat.interface;
            pub const Capability = common.wl.seat.Capability;
            pub const Error = common.wl.seat.Error;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Seat {
                return @ptrCast(try server.wl.Resource.create(_client, Seat, _version, _id));
            }
            pub inline fn destroy(_seat: *Seat) void {
                return @as(*server.wl.Resource, @ptrCast(_seat)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Seat {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_seat: *Seat) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_seat)).getLink();
            }
            pub inline fn getClient(_seat: *Seat) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_seat)).getClient();
            }
            pub inline fn getId(_seat: *Seat) u32 {
                return @as(*server.wl.Resource, @ptrCast(_seat)).getId();
            }
            pub inline fn getVersion(_seat: *Seat) u32 {
                return @as(*server.wl.Resource, @ptrCast(_seat)).getVersion();
            }
            pub inline fn postNoMemory(_seat: *Seat) void {
                return @as(*server.wl.Resource, @ptrCast(_seat)).postNoMemory();
            }
            pub inline fn getUserData(_seat: *Seat) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_seat)).getUserData();
            }
            pub inline fn postError(_seat: *Seat, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_seat)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const get_pointer_since_version = 1;
                pub const get_keyboard_since_version = 1;
                pub const get_touch_since_version = 1;
                pub const release_since_version = 5;

                /// The ID provided will be initialized to the wl_pointer interface
                /// for this seat.
                ///
                /// This request only takes effect if the seat has the pointer
                /// capability, or has had the pointer capability in the past.
                /// It is a protocol violation to issue this request on a seat that has
                /// never had the pointer capability. The missing_capability error will
                /// be sent in this case.
                get_pointer: struct {
                    id: u32,
                },

                /// The ID provided will be initialized to the wl_keyboard interface
                /// for this seat.
                ///
                /// This request only takes effect if the seat has the keyboard
                /// capability, or has had the keyboard capability in the past.
                /// It is a protocol violation to issue this request on a seat that has
                /// never had the keyboard capability. The missing_capability error will
                /// be sent in this case.
                get_keyboard: struct {
                    id: u32,
                },

                /// The ID provided will be initialized to the wl_touch interface
                /// for this seat.
                ///
                /// This request only takes effect if the seat has the touch
                /// capability, or has had the touch capability in the past.
                /// It is a protocol violation to issue this request on a seat that has
                /// never had the touch capability. The missing_capability error will
                /// be sent in this case.
                get_touch: struct {
                    id: u32,
                },

                /// Using this request a client can tell the server that it is not going to
                /// use the seat object anymore.
                release: void,
            };
            pub inline fn setHandler(
                _seat: *Seat,
                comptime T: type,
                handle_request: *const fn (_seat: *Seat, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_seat: *Seat, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_seat);
                _resource.setDispatcher(
                    common.Dispatcher(Seat, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Seat, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// This is sent on binding to the seat global or whenever a seat gains
            /// or loses the pointer, keyboard or touch capabilities.
            /// The argument is a capability enum containing the complete set of
            /// capabilities this seat has.
            ///
            /// When the pointer capability is added, a client may create a
            /// wl_pointer object using the wl_seat.get_pointer request. This object
            /// will receive pointer events until the capability is removed in the
            /// future.
            ///
            /// When the pointer capability is removed, a client should destroy the
            /// wl_pointer objects associated with the seat where the capability was
            /// removed, using the wl_pointer.release request. No further pointer
            /// events will be received on these objects.
            ///
            /// In some compositors, if a seat regains the pointer capability and a
            /// client has a previously obtained wl_pointer object of version 4 or
            /// less, that object may start sending pointer events again. This
            /// behavior is considered a misinterpretation of the intended behavior
            /// and must not be relied upon by the client. wl_pointer objects of
            /// version 5 or later must not send events if created before the most
            /// recent event notifying the client of an added pointer capability.
            ///
            /// The above behavior also applies to wl_keyboard and wl_touch with the
            /// keyboard and touch capabilities, respectively.
            pub fn sendCapabilities(_seat: *Seat, _capabilities: Capability) void {
                const _resource: *server.wl.Resource = @ptrCast(_seat);
                var _args = [_]common.Argument{
                    .{ .u = switch (@typeInfo(Capability)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_capabilities))),
                        .@"struct" => @bitCast(_capabilities),
                        else => unreachable,
                    } },
                };
                _resource.postEvent(0, &_args);
            }
            pub const capabilities_since_version = 1;

            /// 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, and should be sent
            /// before announcing capabilities. This event 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.
            pub fn sendName(_seat: *Seat, _name: [*:0]const u8) void {
                const _resource: *server.wl.Resource = @ptrCast(_seat);
                var _args = [_]common.Argument{
                    .{ .s = _name },
                };
                _resource.postEvent(1, &_args);
            }
            pub const name_since_version = 2;
        };

        /// The wl_pointer interface represents one or more input devices,
        /// such as mice, which control the pointer location and pointer_focus
        /// of a seat.
        ///
        /// The wl_pointer interface generates motion, enter and leave
        /// events for the surfaces that the pointer is located over,
        /// and button and axis events for button presses, button releases
        /// and scrolling.
        pub const Pointer = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.pointer.interface;
            pub const Error = common.wl.pointer.Error;
            pub const ButtonState = common.wl.pointer.ButtonState;
            pub const Axis = common.wl.pointer.Axis;
            pub const AxisSource = common.wl.pointer.AxisSource;
            pub const AxisRelativeDirection = common.wl.pointer.AxisRelativeDirection;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Pointer {
                return @ptrCast(try server.wl.Resource.create(_client, Pointer, _version, _id));
            }
            pub inline fn destroy(_pointer: *Pointer) void {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Pointer {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_pointer: *Pointer) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).getLink();
            }
            pub inline fn getClient(_pointer: *Pointer) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).getClient();
            }
            pub inline fn getId(_pointer: *Pointer) u32 {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).getId();
            }
            pub inline fn getVersion(_pointer: *Pointer) u32 {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).getVersion();
            }
            pub inline fn postNoMemory(_pointer: *Pointer) void {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).postNoMemory();
            }
            pub inline fn getUserData(_pointer: *Pointer) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).getUserData();
            }
            pub inline fn postError(_pointer: *Pointer, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_pointer)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const set_cursor_since_version = 1;
                pub const release_since_version = 3;

                /// Set the pointer surface, i.e., the surface that contains the
                /// pointer image (cursor). This request gives the surface the role
                /// of a cursor. If the surface already has another role, it raises
                /// a protocol error.
                ///
                /// The cursor actually changes only if the pointer
                /// focus for this device is one of the requesting client's surfaces
                /// or the surface parameter is the current pointer surface. If
                /// there was a previous surface set with this request it is
                /// replaced. If surface is NULL, the pointer image is hidden.
                ///
                /// The parameters hotspot_x and hotspot_y define the position of
                /// the pointer surface relative to the pointer location. Its
                /// top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
                /// where (x, y) are the coordinates of the pointer location, in
                /// surface-local coordinates.
                ///
                /// On wl_surface.offset requests to the pointer surface, hotspot_x
                /// and hotspot_y are decremented by the x and y parameters
                /// passed to the request. The offset must be applied by
                /// wl_surface.commit as usual.
                ///
                /// The hotspot can also be updated by passing the currently set
                /// pointer surface to this request with new values for hotspot_x
                /// and hotspot_y.
                ///
                /// The input region is ignored for wl_surfaces with the role of
                /// a cursor. When the use as a cursor ends, 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.
                set_cursor: struct {
                    serial: u32,
                    surface: ?*server.wl.Surface,
                    hotspot_x: i32,
                    hotspot_y: i32,
                },

                /// Using this request a client can tell the server that it is not going to
                /// use the pointer object anymore.
                ///
                /// This request destroys the pointer proxy object, so clients must not call
                /// wl_pointer_destroy() after using this request.
                release: void,
            };
            pub inline fn setHandler(
                _pointer: *Pointer,
                comptime T: type,
                handle_request: *const fn (_pointer: *Pointer, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_pointer: *Pointer, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                _resource.setDispatcher(
                    common.Dispatcher(Pointer, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Pointer, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// Notification that this seat's pointer is focused on a certain
            /// surface.
            ///
            /// When a seat's focus enters a surface, the pointer image
            /// is undefined and a client should respond to this event by setting
            /// an appropriate pointer image with the set_cursor request.
            pub fn sendEnter(_pointer: *Pointer, _serial: u32, _surface: *server.wl.Surface, _surface_x: common.Fixed, _surface_y: common.Fixed) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .o = @ptrCast(_surface) },
                    .{ .f = _surface_x },
                    .{ .f = _surface_y },
                };
                _resource.postEvent(0, &_args);
            }
            pub const enter_since_version = 1;

            /// Notification that this seat's pointer is no longer focused on
            /// a certain surface.
            ///
            /// The leave notification is sent before the enter notification
            /// for the new focus.
            pub fn sendLeave(_pointer: *Pointer, _serial: u32, _surface: *server.wl.Surface) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .o = @ptrCast(_surface) },
                };
                _resource.postEvent(1, &_args);
            }
            pub const leave_since_version = 1;

            /// Notification of pointer location change. The arguments
            /// surface_x and surface_y are the location relative to the
            /// focused surface.
            pub fn sendMotion(_pointer: *Pointer, _time: u32, _surface_x: common.Fixed, _surface_y: common.Fixed) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = _time },
                    .{ .f = _surface_x },
                    .{ .f = _surface_y },
                };
                _resource.postEvent(2, &_args);
            }
            pub const motion_since_version = 1;

            /// Mouse button click and release notifications.
            ///
            /// The location of the click is given by the last motion or
            /// enter event.
            /// The time argument is a timestamp with millisecond
            /// granularity, with an undefined base.
            ///
            /// The button is a button code as defined in the Linux kernel's
            /// linux/input-event-codes.h header file, e.g. BTN_LEFT.
            ///
            /// Any 16-bit button code value is reserved for future additions to the
            /// kernel's event code list. All other button codes above 0xFFFF are
            /// currently undefined but may be used in future versions of this
            /// protocol.
            pub fn sendButton(_pointer: *Pointer, _serial: u32, _time: u32, _button: u32, _state: ButtonState) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .u = _time },
                    .{ .u = _button },
                    .{ .u = switch (@typeInfo(ButtonState)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_state))),
                        .@"struct" => @bitCast(_state),
                        else => unreachable,
                    } },
                };
                _resource.postEvent(3, &_args);
            }
            pub const button_since_version = 1;

            /// Scroll and other axis notifications.
            ///
            /// For scroll events (vertical and horizontal scroll axes), the
            /// value parameter is the length of a vector along the specified
            /// axis in a coordinate space identical to those of motion events,
            /// representing a relative movement along the specified axis.
            ///
            /// For devices that support movements non-parallel to axes multiple
            /// axis events will be emitted.
            ///
            /// When applicable, for example for touch pads, the server can
            /// choose to emit scroll events where the motion vector is
            /// equivalent to a motion event vector.
            ///
            /// When applicable, a client can transform its content relative to the
            /// scroll distance.
            pub fn sendAxis(_pointer: *Pointer, _time: u32, _axis: Axis, _value: common.Fixed) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = _time },
                    .{ .u = switch (@typeInfo(Axis)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_axis))),
                        .@"struct" => @bitCast(_axis),
                        else => unreachable,
                    } },
                    .{ .f = _value },
                };
                _resource.postEvent(4, &_args);
            }
            pub const axis_since_version = 1;

            /// Indicates the end of a set of events that logically belong together.
            /// A client is expected to accumulate the data in all events within the
            /// frame before proceeding.
            ///
            /// All wl_pointer events before a wl_pointer.frame event belong
            /// logically together. For example, in a diagonal scroll motion the
            /// compositor will send an optional wl_pointer.axis_source event, two
            /// wl_pointer.axis events (horizontal and vertical) and finally a
            /// wl_pointer.frame event. The client may use this information to
            /// calculate a diagonal vector for scrolling.
            ///
            /// When multiple wl_pointer.axis events occur within the same frame,
            /// the motion vector is the combined motion of all events.
            /// When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
            /// the same frame, this indicates that axis movement in one axis has
            /// stopped but continues in the other axis.
            /// When multiple wl_pointer.axis_stop events occur within the same
            /// frame, this indicates that these axes stopped in the same instance.
            ///
            /// A wl_pointer.frame event is sent for every logical event group,
            /// even if the group only contains a single wl_pointer event.
            /// Specifically, a client may get a sequence: motion, frame, button,
            /// frame, axis, frame, axis_stop, frame.
            ///
            /// The wl_pointer.enter and wl_pointer.leave events are logical events
            /// generated by the compositor and not the hardware. These events are
            /// also grouped by a wl_pointer.frame. When a pointer moves from one
            /// surface to another, a compositor should group the
            /// wl_pointer.leave event within the same wl_pointer.frame.
            /// However, a client must not rely on wl_pointer.leave and
            /// wl_pointer.enter being in the same wl_pointer.frame.
            /// Compositor-specific policies may require the wl_pointer.leave and
            /// wl_pointer.enter event being split across multiple wl_pointer.frame
            /// groups.
            pub fn sendFrame(_pointer: *Pointer) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                _resource.postEvent(5, null);
            }
            pub const frame_since_version = 5;

            /// Source information for scroll and other axes.
            ///
            /// This event does not occur on its own. It is sent before a
            /// wl_pointer.frame event and carries the source information for
            /// all events within that frame.
            ///
            /// The source specifies how this event was generated. If the source is
            /// wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
            /// sent when the user lifts the finger off the device.
            ///
            /// If the source is wl_pointer.axis_source.wheel,
            /// wl_pointer.axis_source.wheel_tilt or
            /// wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
            /// or may not be sent. Whether a compositor sends an axis_stop event
            /// for these sources is hardware-specific and implementation-dependent;
            /// clients must not rely on receiving an axis_stop event for these
            /// scroll sources and should treat scroll sequences from these scroll
            /// sources as unterminated by default.
            ///
            /// This event is optional. If the source is unknown for a particular
            /// axis event sequence, no event is sent.
            /// Only one wl_pointer.axis_source event is permitted per frame.
            ///
            /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
            /// not guaranteed.
            pub fn sendAxisSource(_pointer: *Pointer, _axis_source: AxisSource) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = switch (@typeInfo(AxisSource)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_axis_source))),
                        .@"struct" => @bitCast(_axis_source),
                        else => unreachable,
                    } },
                };
                _resource.postEvent(6, &_args);
            }
            pub const axis_source_since_version = 5;

            /// Stop notification for scroll and other axes.
            ///
            /// For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
            /// is sent to notify a client that the axis sequence has terminated.
            /// This enables the client to implement kinetic scrolling.
            /// See the wl_pointer.axis_source documentation for information on when
            /// this event may be generated.
            ///
            /// Any wl_pointer.axis events with the same axis_source after this
            /// event should be considered as the start of a new axis motion.
            ///
            /// The timestamp is to be interpreted identical to the timestamp in the
            /// wl_pointer.axis event. The timestamp value may be the same as a
            /// preceding wl_pointer.axis event.
            pub fn sendAxisStop(_pointer: *Pointer, _time: u32, _axis: Axis) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = _time },
                    .{ .u = switch (@typeInfo(Axis)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_axis))),
                        .@"struct" => @bitCast(_axis),
                        else => unreachable,
                    } },
                };
                _resource.postEvent(7, &_args);
            }
            pub const axis_stop_since_version = 5;

            /// Discrete step information for scroll and other axes.
            ///
            /// 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
            /// event is always followed by exactly one axis event with the same
            /// 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. 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
            /// steps and do not generate this event.
            ///
            /// The discrete value carries the directional information. e.g. a value
            /// of -2 is two steps towards the negative direction of this axis.
            ///
            /// The axis number is identical to the axis number in the associated
            /// axis event.
            ///
            /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
            /// not guaranteed.
            pub fn sendAxisDiscrete(_pointer: *Pointer, _axis: Axis, _discrete: i32) void {
                const _resource: *server.wl.Resource = @ptrCast(_pointer);
                var _args = [_]common.Argument{
                    .{ .u = switch (@typeInfo(Axis)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_axis))),
                        .@"struct" => @bitCast(_axis),
                        else => unreachable,
                    } },
                    .{ .i = _discrete },
                };
                _resource.postEvent(8, &_args);
            }
            pub const axis_discrete_since_version = 5;
        };

        /// The wl_keyboard interface represents one or more keyboards
        /// associated with a seat.
        ///
        /// Each wl_keyboard has the following logical state:
        ///
        /// - an active surface (possibly null),
        /// - the keys currently logically down,
        /// - the active modifiers,
        /// - the active group.
        ///
        /// By default, the active surface is null, the keys currently logically down
        /// are empty, the active modifiers and the active group are 0.
        pub const Keyboard = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.keyboard.interface;
            pub const KeymapFormat = common.wl.keyboard.KeymapFormat;
            pub const KeyState = common.wl.keyboard.KeyState;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Keyboard {
                return @ptrCast(try server.wl.Resource.create(_client, Keyboard, _version, _id));
            }
            pub inline fn destroy(_keyboard: *Keyboard) void {
                return @as(*server.wl.Resource, @ptrCast(_keyboard)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Keyboard {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_keyboard: *Keyboard) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_keyboard)).getLink();
            }
            pub inline fn getClient(_keyboard: *Keyboard) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_keyboard)).getClient();
            }
            pub inline fn getId(_keyboard: *Keyboard) u32 {
                return @as(*server.wl.Resource, @ptrCast(_keyboard)).getId();
            }
            pub inline fn getVersion(_keyboard: *Keyboard) u32 {
                return @as(*server.wl.Resource, @ptrCast(_keyboard)).getVersion();
            }
            pub inline fn postNoMemory(_keyboard: *Keyboard) void {
                return @as(*server.wl.Resource, @ptrCast(_keyboard)).postNoMemory();
            }
            pub inline fn getUserData(_keyboard: *Keyboard) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_keyboard)).getUserData();
            }
            pub const Request = union(enum) {
                pub const release_since_version = 3;
                release: void,
            };
            pub inline fn setHandler(
                _keyboard: *Keyboard,
                comptime T: type,
                handle_request: *const fn (_keyboard: *Keyboard, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_keyboard: *Keyboard, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_keyboard);
                _resource.setDispatcher(
                    common.Dispatcher(Keyboard, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Keyboard, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// This event provides a file descriptor to the client which can be
            /// 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.
            pub fn sendKeymap(_keyboard: *Keyboard, _format: KeymapFormat, _fd: i32, _size: u32) void {
                const _resource: *server.wl.Resource = @ptrCast(_keyboard);
                var _args = [_]common.Argument{
                    .{ .u = switch (@typeInfo(KeymapFormat)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_format))),
                        .@"struct" => @bitCast(_format),
                        else => unreachable,
                    } },
                    .{ .h = _fd },
                    .{ .u = _size },
                };
                _resource.postEvent(0, &_args);
            }
            pub const keymap_since_version = 1;

            /// Notification that this seat's keyboard focus is on a certain
            /// surface.
            ///
            /// The compositor must send the wl_keyboard.modifiers event after this
            /// event.
            ///
            /// In the wl_keyboard logical state, this event sets the active surface to
            /// the surface argument and the keys currently logically down to the keys
            /// in the keys argument. The compositor must not send this event if the
            /// wl_keyboard already had an active surface immediately before this event.
            ///
            /// Clients should not use the list of pressed keys to emulate key-press
            /// events. The order of keys in the list is unspecified.
            pub fn sendEnter(_keyboard: *Keyboard, _serial: u32, _surface: *server.wl.Surface, _keys: *common.Array) void {
                const _resource: *server.wl.Resource = @ptrCast(_keyboard);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .o = @ptrCast(_surface) },
                    .{ .a = _keys },
                };
                _resource.postEvent(1, &_args);
            }
            pub const enter_since_version = 1;

            /// Notification that this seat's keyboard focus is no longer on
            /// a certain surface.
            ///
            /// The leave notification is sent before the enter notification
            /// for the new focus.
            ///
            /// In the wl_keyboard logical state, this event resets all values to their
            /// defaults. The compositor must not send this event if the active surface
            /// of the wl_keyboard was not equal to the surface argument immediately
            /// before this event.
            pub fn sendLeave(_keyboard: *Keyboard, _serial: u32, _surface: *server.wl.Surface) void {
                const _resource: *server.wl.Resource = @ptrCast(_keyboard);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .o = @ptrCast(_surface) },
                };
                _resource.postEvent(2, &_args);
            }
            pub const leave_since_version = 1;

            /// A key was pressed or released.
            /// The time argument is a timestamp with millisecond
            /// granularity, with an undefined base.
            ///
            /// The key is a platform-specific key code that can be interpreted
            /// by feeding it to the keyboard mapping (see the keymap event).
            ///
            /// If this event produces a change in modifiers, then the resulting
            /// wl_keyboard.modifiers event must be sent after this event.
            ///
            /// In the wl_keyboard logical state, this event adds the key to the keys
            /// currently logically down (if the state argument is pressed) or removes
            /// the key from the keys currently logically down (if the state argument is
            /// released). The compositor must not send this event if the wl_keyboard
            /// did not have an active surface immediately before this event. The
            /// compositor must not send this event if state is pressed (resp. released)
            /// and the key was already logically down (resp. was not logically down)
            /// immediately before this event.
            ///
            /// Since version 10, compositors may send key events with the "repeated"
            /// key state when a wl_keyboard.repeat_info event with a rate argument of
            /// 0 has been received. This allows the compositor to take over the
            /// responsibility of key repetition.
            pub fn sendKey(_keyboard: *Keyboard, _serial: u32, _time: u32, _key: u32, _state: KeyState) void {
                const _resource: *server.wl.Resource = @ptrCast(_keyboard);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .u = _time },
                    .{ .u = _key },
                    .{ .u = switch (@typeInfo(KeyState)) {
                        .@"enum" => @as(u32, @intCast(@intFromEnum(_state))),
                        .@"struct" => @bitCast(_state),
                        else => unreachable,
                    } },
                };
                _resource.postEvent(3, &_args);
            }
            pub const key_since_version = 1;

            /// Notifies clients that the modifier and/or group state has
            /// changed, and it should update its local state.
            ///
            /// The compositor may send this event without a surface of the client
            /// having keyboard focus, for example to tie modifier information to
            /// pointer focus instead. If a modifier event with pressed modifiers is sent
            /// without a prior enter event, the client can assume the modifier state is
            /// valid until it receives the next wl_keyboard.modifiers event. In order to
            /// reset the modifier state again, the compositor can send a
            /// wl_keyboard.modifiers event with no pressed modifiers.
            ///
            /// In the wl_keyboard logical state, this event updates the modifiers and
            /// group.
            pub fn sendModifiers(_keyboard: *Keyboard, _serial: u32, _mods_depressed: u32, _mods_latched: u32, _mods_locked: u32, _group: u32) void {
                const _resource: *server.wl.Resource = @ptrCast(_keyboard);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .u = _mods_depressed },
                    .{ .u = _mods_latched },
                    .{ .u = _mods_locked },
                    .{ .u = _group },
                };
                _resource.postEvent(4, &_args);
            }
            pub const modifiers_since_version = 1;

            /// Informs the client about the keyboard's repeat rate and delay.
            ///
            /// This event is sent as soon as the wl_keyboard object has been created,
            /// and is guaranteed to be received by the client before any key press
            /// event.
            ///
            /// Negative values for either rate or delay are illegal. A rate of zero
            /// will disable any repeating (regardless of the value of delay).
            ///
            /// This event can be sent later on as well with a new value if necessary,
            /// so clients should continue listening for the event past the creation
            /// of wl_keyboard.
            pub fn sendRepeatInfo(_keyboard: *Keyboard, _rate: i32, _delay: i32) void {
                const _resource: *server.wl.Resource = @ptrCast(_keyboard);
                var _args = [_]common.Argument{
                    .{ .i = _rate },
                    .{ .i = _delay },
                };
                _resource.postEvent(5, &_args);
            }
            pub const repeat_info_since_version = 4;
        };

        /// The wl_touch interface represents a touchscreen
        /// associated with a seat.
        ///
        /// Touch interactions can consist of one or more contacts.
        /// For each contact, a series of events is generated, starting
        /// with a down event, followed by zero or more motion events,
        /// and ending with an up event. Events relating to the same
        /// contact point can be identified by the ID of the sequence.
        pub const Touch = opaque {
            pub const generated_version = 5;
            pub const interface = &common.wl.touch.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Touch {
                return @ptrCast(try server.wl.Resource.create(_client, Touch, _version, _id));
            }
            pub inline fn destroy(_touch: *Touch) void {
                return @as(*server.wl.Resource, @ptrCast(_touch)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Touch {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_touch: *Touch) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_touch)).getLink();
            }
            pub inline fn getClient(_touch: *Touch) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_touch)).getClient();
            }
            pub inline fn getId(_touch: *Touch) u32 {
                return @as(*server.wl.Resource, @ptrCast(_touch)).getId();
            }
            pub inline fn getVersion(_touch: *Touch) u32 {
                return @as(*server.wl.Resource, @ptrCast(_touch)).getVersion();
            }
            pub inline fn postNoMemory(_touch: *Touch) void {
                return @as(*server.wl.Resource, @ptrCast(_touch)).postNoMemory();
            }
            pub inline fn getUserData(_touch: *Touch) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_touch)).getUserData();
            }
            pub const Request = union(enum) {
                pub const release_since_version = 3;
                release: void,
            };
            pub inline fn setHandler(
                _touch: *Touch,
                comptime T: type,
                handle_request: *const fn (_touch: *Touch, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_touch: *Touch, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_touch);
                _resource.setDispatcher(
                    common.Dispatcher(Touch, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Touch, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// A new touch point has appeared on the surface. This touch point is
            /// assigned a unique ID. Future events from this touch point reference
            /// this ID. The ID ceases to be valid after a touch up event and may be
            /// reused in the future.
            pub fn sendDown(_touch: *Touch, _serial: u32, _time: u32, _surface: *server.wl.Surface, _id: i32, _x: common.Fixed, _y: common.Fixed) void {
                const _resource: *server.wl.Resource = @ptrCast(_touch);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .u = _time },
                    .{ .o = @ptrCast(_surface) },
                    .{ .i = _id },
                    .{ .f = _x },
                    .{ .f = _y },
                };
                _resource.postEvent(0, &_args);
            }
            pub const down_since_version = 1;

            /// The touch point has disappeared. No further events will be sent for
            /// this touch point and the touch point's ID is released and may be
            /// reused in a future touch down event.
            pub fn sendUp(_touch: *Touch, _serial: u32, _time: u32, _id: i32) void {
                const _resource: *server.wl.Resource = @ptrCast(_touch);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .u = _time },
                    .{ .i = _id },
                };
                _resource.postEvent(1, &_args);
            }
            pub const up_since_version = 1;

            /// A touch point has changed coordinates.
            pub fn sendMotion(_touch: *Touch, _time: u32, _id: i32, _x: common.Fixed, _y: common.Fixed) void {
                const _resource: *server.wl.Resource = @ptrCast(_touch);
                var _args = [_]common.Argument{
                    .{ .u = _time },
                    .{ .i = _id },
                    .{ .f = _x },
                    .{ .f = _y },
                };
                _resource.postEvent(2, &_args);
            }
            pub const motion_since_version = 1;

            /// Indicates the end of a set of events that logically belong together.
            /// A client is expected to accumulate the data in all events within the
            /// frame before proceeding.
            ///
            /// A wl_touch.frame terminates at least one event but otherwise no
            /// guarantee is provided about the set of events within a frame. A client
            /// must assume that any state not updated in a frame is unchanged from the
            /// previously known state.
            pub fn sendFrame(_touch: *Touch) void {
                const _resource: *server.wl.Resource = @ptrCast(_touch);
                _resource.postEvent(3, null);
            }
            pub const frame_since_version = 1;

            /// Sent if the compositor decides the touch stream is a global
            /// gesture. No further events are sent to the clients from that
            /// particular gesture. Touch cancellation applies to all touch points
            /// currently active on this client's surface. The client is
            /// responsible for finalizing the touch points, future touch points on
            /// this surface may reuse the touch point ID.
            ///
            /// No frame event is required after the cancel event.
            pub fn sendCancel(_touch: *Touch) void {
                const _resource: *server.wl.Resource = @ptrCast(_touch);
                _resource.postEvent(4, null);
            }
            pub const cancel_since_version = 1;
        };
    };
    pub const ext = struct {
        /// This interface is used to request that the session be locked.
        pub const SessionLockManagerV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.ext.session_lock_manager_v1.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*SessionLockManagerV1 {
                return @ptrCast(try server.wl.Resource.create(_client, SessionLockManagerV1, _version, _id));
            }
            pub inline fn destroy(_session_lock_manager_v1: *SessionLockManagerV1) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_manager_v1)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *SessionLockManagerV1 {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_session_lock_manager_v1: *SessionLockManagerV1) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_manager_v1)).getLink();
            }
            pub inline fn getClient(_session_lock_manager_v1: *SessionLockManagerV1) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_manager_v1)).getClient();
            }
            pub inline fn getId(_session_lock_manager_v1: *SessionLockManagerV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_manager_v1)).getId();
            }
            pub inline fn getVersion(_session_lock_manager_v1: *SessionLockManagerV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_manager_v1)).getVersion();
            }
            pub inline fn postNoMemory(_session_lock_manager_v1: *SessionLockManagerV1) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_manager_v1)).postNoMemory();
            }
            pub inline fn getUserData(_session_lock_manager_v1: *SessionLockManagerV1) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_manager_v1)).getUserData();
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const lock_since_version = 1;

                /// This informs the compositor that the session lock manager object will
                /// no longer be used. Existing objects created through this interface
                /// remain valid.
                destroy: void,
                /// This request creates a session lock and asks the compositor to lock the
                /// session. The compositor will send either the ext_session_lock_v1.locked
                /// or ext_session_lock_v1.finished event on the created object in
                /// response to this request.
                lock: struct {
                    id: u32,
                },
            };
            pub inline fn setHandler(
                _session_lock_manager_v1: *SessionLockManagerV1,
                comptime T: type,
                handle_request: *const fn (_session_lock_manager_v1: *SessionLockManagerV1, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_session_lock_manager_v1: *SessionLockManagerV1, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_session_lock_manager_v1);
                _resource.setDispatcher(
                    common.Dispatcher(SessionLockManagerV1, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*SessionLockManagerV1, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
        };

        /// In response to the creation of this object the compositor must send
        /// either the locked or finished event.
        ///
        /// The locked event indicates that the session is locked. This means
        /// that the compositor must stop rendering and providing input to normal
        /// clients. Instead the compositor must blank all outputs with an opaque
        /// color such that their normal content is fully hidden.
        ///
        /// The only surfaces that should be rendered while the session is locked
        /// are the lock surfaces created through this interface and optionally,
        /// at the compositor's discretion, special privileged surfaces such as
        /// input methods or portions of desktop shell UIs.
        ///
        /// The locked event must not be sent until a new "locked" frame (either
        /// from a session lock surface or the compositor blanking the output) has
        /// been presented on all outputs and no security sensitive normal/unlocked
        /// content is possibly visible.
        ///
        /// The finished event should be sent immediately on creation of this
        /// object if the compositor decides that the locked event will not be sent.
        ///
        /// The compositor may wait for the client to create and render session lock
        /// surfaces before sending the locked event to avoid displaying intermediate
        /// blank frames. However, it must impose a reasonable time limit if
        /// waiting and send the locked event as soon as the hard requirements
        /// described above can be met if the time limit expires. Clients should
        /// immediately create lock surfaces for all outputs on creation of this
        /// object to make this possible.
        ///
        /// This behavior of the locked event is required in order to prevent
        /// possible race conditions with clients that wish to suspend the system
        /// or similar after locking the session. Without these semantics, clients
        /// triggering a suspend after receiving the locked event would race with
        /// the first "locked" frame being presented and normal/unlocked frames
        /// might be briefly visible as the system is resumed if the suspend
        /// operation wins the race.
        ///
        /// If the client dies while the session is locked, the compositor must not
        /// unlock the session in response. It is acceptable for the session to be
        /// permanently locked if this happens. The compositor may choose to continue
        /// to display the lock surfaces the client had mapped before it died or
        /// alternatively fall back to a solid color, this is compositor policy.
        ///
        /// Compositors may also allow a secure way to recover the session, the
        /// details of this are compositor policy. Compositors may allow a new
        /// client to create a ext_session_lock_v1 object and take responsibility
        /// for unlocking the session, they may even start a new lock client
        /// instance automatically.
        pub const SessionLockV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.ext.session_lock_v1.interface;
            pub const Error = common.ext.session_lock_v1.Error;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*SessionLockV1 {
                return @ptrCast(try server.wl.Resource.create(_client, SessionLockV1, _version, _id));
            }
            pub inline fn destroy(_session_lock_v1: *SessionLockV1) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *SessionLockV1 {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_session_lock_v1: *SessionLockV1) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).getLink();
            }
            pub inline fn getClient(_session_lock_v1: *SessionLockV1) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).getClient();
            }
            pub inline fn getId(_session_lock_v1: *SessionLockV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).getId();
            }
            pub inline fn getVersion(_session_lock_v1: *SessionLockV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).getVersion();
            }
            pub inline fn postNoMemory(_session_lock_v1: *SessionLockV1) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).postNoMemory();
            }
            pub inline fn getUserData(_session_lock_v1: *SessionLockV1) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).getUserData();
            }
            pub inline fn postError(_session_lock_v1: *SessionLockV1, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_v1)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const get_lock_surface_since_version = 1;
                pub const unlock_and_destroy_since_version = 1;

                /// This informs the compositor that the lock object will no longer be
                /// used. Existing objects created through this interface remain valid.
                ///
                /// After this request is made, lock surfaces created through this object
                /// should be destroyed by the client as they will no longer be used by
                /// the compositor.
                ///
                /// It is a protocol error to make this request if the locked event was
                /// sent, the unlock_and_destroy request must be used instead.
                destroy: void,
                /// The client is expected to create lock surfaces for all outputs
                /// currently present and any new outputs as they are advertised. These
                /// won't be displayed by the compositor unless the lock is successful
                /// and the locked event is sent.
                ///
                /// Providing a wl_surface which already has a role or already has a buffer
                /// attached or committed is a protocol error, as is attaching/committing
                /// a buffer before the first ext_session_lock_surface_v1.configure event.
                ///
                /// Attempting to create more than one lock surface for a given output
                /// is a duplicate_output protocol error.
                get_lock_surface: struct {
                    id: u32,
                    surface: *server.wl.Surface,
                    output: *server.wl.Output,
                },

                /// This request indicates that the session should be unlocked, for
                /// example because the user has entered their password and it has been
                /// verified by the client.
                ///
                /// This request also informs the compositor that the lock object will
                /// no longer be used and should be destroyed. Existing objects created
                /// through this interface remain valid.
                ///
                /// After this request is made, lock surfaces created through this object
                /// should be destroyed by the client as they will no longer be used by
                /// the compositor.
                ///
                /// It is a protocol error to make this request if the locked event has
                /// not been sent. In that case, the lock object must be destroyed using
                /// the destroy request.
                ///
                /// Note that a correct client that wishes to exit directly after unlocking
                /// the session must use the wl_display.sync request to ensure the server
                /// receives and processes the unlock_and_destroy request. Otherwise
                /// there is no guarantee that the server has unlocked the session due
                /// to the asynchronous nature of the Wayland protocol. For example,
                /// the server might terminate the client with a protocol error before
                /// it processes the unlock_and_destroy request.
                unlock_and_destroy: void,
            };
            pub inline fn setHandler(
                _session_lock_v1: *SessionLockV1,
                comptime T: type,
                handle_request: *const fn (_session_lock_v1: *SessionLockV1, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_session_lock_v1: *SessionLockV1, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_session_lock_v1);
                _resource.setDispatcher(
                    common.Dispatcher(SessionLockV1, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*SessionLockV1, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// This client is now responsible for displaying graphics while the
            /// session is locked and deciding when to unlock the session.
            ///
            /// The locked event must not be sent until a new "locked" frame has been
            /// presented on all outputs and no security sensitive normal/unlocked
            /// content is possibly visible.
            ///
            /// If this event is sent, making the destroy request is a protocol error,
            /// the lock object must be destroyed using the unlock_and_destroy request.
            pub fn sendLocked(_session_lock_v1: *SessionLockV1) void {
                const _resource: *server.wl.Resource = @ptrCast(_session_lock_v1);
                _resource.postEvent(0, null);
            }
            pub const locked_since_version = 1;

            /// The compositor has decided that the session lock should be destroyed
            /// as it will no longer be used by the compositor. Exactly when this
            /// event is sent is compositor policy, but it must never be sent more
            /// than once for a given session lock object.
            ///
            /// This might be sent because there is already another ext_session_lock_v1
            /// object held by a client, or the compositor has decided to deny the
            /// request to lock the session for some other reason. This might also
            /// be sent because the compositor implements some alternative, secure
            /// way to authenticate and unlock the session.
            ///
            /// The finished event should be sent immediately on creation of this
            /// object if the compositor decides that the locked event will not
            /// be sent.
            ///
            /// If the locked event is sent on creation of this object the finished
            /// event may still be sent at some later time in this object's
            /// lifetime. This is compositor policy.
            ///
            /// Upon receiving this event, the client should make either the destroy
            /// request or the unlock_and_destroy request, depending on whether or
            /// not the locked event was received on this object.
            pub fn sendFinished(_session_lock_v1: *SessionLockV1) void {
                const _resource: *server.wl.Resource = @ptrCast(_session_lock_v1);
                _resource.postEvent(1, null);
            }
            pub const finished_since_version = 1;
        };

        /// The client may use lock surfaces to display a screensaver, render a
        /// dialog to enter a password and unlock the session, or however else it
        /// sees fit.
        ///
        /// On binding this interface the compositor will immediately send the
        /// first configure event. After making the ack_configure request in
        /// response to this event the client should attach and commit the first
        /// buffer. Committing the surface before acking the first configure is a
        /// protocol error. Committing the surface with a null buffer at any time
        /// is a protocol error.
        ///
        /// The compositor is free to handle keyboard/pointer focus for lock
        /// surfaces however it chooses. A reasonable way to do this would be to
        /// give the first lock surface created keyboard focus and change keyboard
        /// focus if the user clicks on other surfaces.
        pub const SessionLockSurfaceV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.ext.session_lock_surface_v1.interface;
            pub const Error = common.ext.session_lock_surface_v1.Error;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*SessionLockSurfaceV1 {
                return @ptrCast(try server.wl.Resource.create(_client, SessionLockSurfaceV1, _version, _id));
            }
            pub inline fn destroy(_session_lock_surface_v1: *SessionLockSurfaceV1) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *SessionLockSurfaceV1 {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_session_lock_surface_v1: *SessionLockSurfaceV1) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).getLink();
            }
            pub inline fn getClient(_session_lock_surface_v1: *SessionLockSurfaceV1) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).getClient();
            }
            pub inline fn getId(_session_lock_surface_v1: *SessionLockSurfaceV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).getId();
            }
            pub inline fn getVersion(_session_lock_surface_v1: *SessionLockSurfaceV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).getVersion();
            }
            pub inline fn postNoMemory(_session_lock_surface_v1: *SessionLockSurfaceV1) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).postNoMemory();
            }
            pub inline fn getUserData(_session_lock_surface_v1: *SessionLockSurfaceV1) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).getUserData();
            }
            pub inline fn postError(_session_lock_surface_v1: *SessionLockSurfaceV1, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_session_lock_surface_v1)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const ack_configure_since_version = 1;

                /// This informs the compositor that the lock surface object will no
                /// longer be used.
                ///
                /// It is recommended for a lock client to destroy lock surfaces if
                /// their corresponding wl_output global is removed.
                ///
                /// If a lock surface on an active output is destroyed before the
                /// ext_session_lock_v1.unlock_and_destroy event is sent, the compositor
                /// must fall back to rendering a solid color.
                destroy: void,
                /// When a configure event is received, if a client commits the surface
                /// in response to the configure event, then the client must make an
                /// ack_configure request sometime before the commit request, passing
                /// along the serial of the configure event.
                ///
                /// If the client receives multiple configure events before it can
                /// respond to one, it only has to ack the last configure event.
                ///
                /// A client is not required to commit immediately after sending an
                /// ack_configure request - it may even ack_configure several times
                /// before its next surface commit.
                ///
                /// A client may send multiple ack_configure requests before committing,
                /// but only the last request sent before a commit indicates which
                /// configure event the client really is responding to.
                ///
                /// Sending an ack_configure request consumes the configure event
                /// referenced by the given serial, as well as all older configure events
                /// sent on this object.
                ///
                /// It is a protocol error to issue multiple ack_configure requests
                /// referencing the same configure event or to issue an ack_configure
                /// request referencing a configure event older than the last configure
                /// event acked for a given lock surface.
                ack_configure: struct {
                    serial: u32,
                },
            };
            pub inline fn setHandler(
                _session_lock_surface_v1: *SessionLockSurfaceV1,
                comptime T: type,
                handle_request: *const fn (_session_lock_surface_v1: *SessionLockSurfaceV1, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_session_lock_surface_v1: *SessionLockSurfaceV1, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_session_lock_surface_v1);
                _resource.setDispatcher(
                    common.Dispatcher(SessionLockSurfaceV1, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*SessionLockSurfaceV1, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
            /// This event is sent once on binding the interface and may be sent again
            /// at the compositor's discretion, for example if output geometry changes.
            ///
            /// The width and height are in surface-local coordinates and are exact
            /// requirements. Failing to match these surface dimensions in the next
            /// commit after acking a configure is a protocol error.
            pub fn sendConfigure(_session_lock_surface_v1: *SessionLockSurfaceV1, _serial: u32, _width: u32, _height: u32) void {
                const _resource: *server.wl.Resource = @ptrCast(_session_lock_surface_v1);
                var _args = [_]common.Argument{
                    .{ .u = _serial },
                    .{ .u = _width },
                    .{ .u = _height },
                };
                _resource.postEvent(0, &_args);
            }
            pub const configure_since_version = 1;
        };
    };
    pub const wp = struct {
        /// The wp_single_pixel_buffer_manager_v1 interface is a factory for
        /// single-pixel buffers.
        pub const SinglePixelBufferManagerV1 = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wp.single_pixel_buffer_manager_v1.interface;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*SinglePixelBufferManagerV1 {
                return @ptrCast(try server.wl.Resource.create(_client, SinglePixelBufferManagerV1, _version, _id));
            }
            pub inline fn destroy(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) void {
                return @as(*server.wl.Resource, @ptrCast(_single_pixel_buffer_manager_v1)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *SinglePixelBufferManagerV1 {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_single_pixel_buffer_manager_v1)).getLink();
            }
            pub inline fn getClient(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_single_pixel_buffer_manager_v1)).getClient();
            }
            pub inline fn getId(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_single_pixel_buffer_manager_v1)).getId();
            }
            pub inline fn getVersion(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) u32 {
                return @as(*server.wl.Resource, @ptrCast(_single_pixel_buffer_manager_v1)).getVersion();
            }
            pub inline fn postNoMemory(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) void {
                return @as(*server.wl.Resource, @ptrCast(_single_pixel_buffer_manager_v1)).postNoMemory();
            }
            pub inline fn getUserData(_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_single_pixel_buffer_manager_v1)).getUserData();
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const create_u32_rgba_buffer_since_version = 1;

                /// Destroy the wp_single_pixel_buffer_manager_v1 object.
                ///
                /// The child objects created via this interface are unaffected.
                destroy: void,
                /// Create a single-pixel buffer from four 32-bit RGBA values.
                ///
                /// Unless specified in another protocol extension, the RGBA values use
                /// pre-multiplied alpha.
                ///
                /// The width and height of the buffer are 1.
                ///
                /// The r, g, b and a arguments valid range is from UINT32_MIN (0)
                /// to UINT32_MAX (0xffffffff).
                ///
                /// These arguments should be interpreted as a percentage, i.e.
                /// - UINT32_MIN = 0% of the given color component
                /// - UINT32_MAX = 100% of the given color component
                create_u32_rgba_buffer: struct {
                    id: u32,
                    r: u32,
                    g: u32,
                    b: u32,
                    a: u32,
                },
            };
            pub inline fn setHandler(
                _single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1,
                comptime T: type,
                handle_request: *const fn (_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_single_pixel_buffer_manager_v1: *SinglePixelBufferManagerV1, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_single_pixel_buffer_manager_v1);
                _resource.setDispatcher(
                    common.Dispatcher(SinglePixelBufferManagerV1, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*SinglePixelBufferManagerV1, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
        };

        /// The global interface exposing surface cropping and scaling
        /// capabilities is used to instantiate an interface extension for a
        /// wl_surface object. This extended interface will then allow
        /// cropping and scaling the surface contents, effectively
        /// disconnecting the direct relationship between the buffer and the
        /// surface size.
        pub const Viewporter = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wp.viewporter.interface;
            pub const Error = common.wp.viewporter.Error;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Viewporter {
                return @ptrCast(try server.wl.Resource.create(_client, Viewporter, _version, _id));
            }
            pub inline fn destroy(_viewporter: *Viewporter) void {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Viewporter {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_viewporter: *Viewporter) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).getLink();
            }
            pub inline fn getClient(_viewporter: *Viewporter) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).getClient();
            }
            pub inline fn getId(_viewporter: *Viewporter) u32 {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).getId();
            }
            pub inline fn getVersion(_viewporter: *Viewporter) u32 {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).getVersion();
            }
            pub inline fn postNoMemory(_viewporter: *Viewporter) void {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).postNoMemory();
            }
            pub inline fn getUserData(_viewporter: *Viewporter) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).getUserData();
            }
            pub inline fn postError(_viewporter: *Viewporter, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_viewporter)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const get_viewport_since_version = 1;

                /// Informs the server that the client will not be using this
                /// protocol object anymore. This does not affect any other objects,
                /// wp_viewport objects included.
                destroy: void,
                /// Instantiate an interface extension for the given wl_surface to
                /// crop and scale its content. If the given wl_surface already has
                /// a wp_viewport object associated, the viewport_exists
                /// protocol error is raised.
                get_viewport: struct {
                    id: u32,
                    surface: *server.wl.Surface,
                },
            };
            pub inline fn setHandler(
                _viewporter: *Viewporter,
                comptime T: type,
                handle_request: *const fn (_viewporter: *Viewporter, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_viewporter: *Viewporter, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_viewporter);
                _resource.setDispatcher(
                    common.Dispatcher(Viewporter, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Viewporter, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
        };

        /// An additional interface to a wl_surface object, which allows the
        /// client to specify the cropping and scaling of the surface
        /// contents.
        ///
        /// This interface works with two concepts: the source rectangle (src_x,
        /// src_y, src_width, src_height), and the destination size (dst_width,
        /// dst_height). The contents of the source rectangle are scaled to the
        /// destination size, and content outside the source rectangle is ignored.
        /// This state is double-buffered, see wl_surface.commit.
        ///
        /// The two parts of crop and scale state are independent: the source
        /// rectangle, and the destination size. Initially both are unset, that
        /// is, no scaling is applied. The whole of the current wl_buffer is
        /// used as the source, and the surface size is as defined in
        /// wl_surface.attach.
        ///
        /// If the destination size is set, it causes the surface size to become
        /// dst_width, dst_height. The source (rectangle) is scaled to exactly
        /// this size. This overrides whatever the attached wl_buffer size is,
        /// unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
        /// has no content and therefore no size. Otherwise, the size is always
        /// at least 1x1 in surface local coordinates.
        ///
        /// If the source rectangle is set, it defines what area of the wl_buffer is
        /// taken as the source. If the source rectangle is set and the destination
        /// size is not set, then src_width and src_height must be integers, and the
        /// surface size becomes the source rectangle size. This results in cropping
        /// without scaling. If src_width or src_height are not integers and
        /// destination size is not set, the bad_size protocol error is raised when
        /// the surface state is applied.
        ///
        /// The coordinate transformations from buffer pixel coordinates up to
        /// the surface-local coordinates happen in the following order:
        /// 1. buffer_transform (wl_surface.set_buffer_transform)
        /// 2. buffer_scale (wl_surface.set_buffer_scale)
        /// 3. crop and scale (wp_viewport.set*)
        /// This means, that the source rectangle coordinates of crop and scale
        /// are given in the coordinates after the buffer transform and scale,
        /// i.e. in the coordinates that would be the surface-local coordinates
        /// if the crop and scale was not applied.
        ///
        /// If src_x or src_y are negative, the bad_value protocol error is raised.
        /// Otherwise, if the source rectangle is partially or completely outside of
        /// the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
        /// when the surface state is applied. A NULL wl_buffer does not raise the
        /// out_of_buffer error.
        ///
        /// If the wl_surface associated with the wp_viewport is destroyed,
        /// all wp_viewport requests except 'destroy' raise the protocol error
        /// no_surface.
        ///
        /// If the wp_viewport object is destroyed, the crop and scale
        /// state is removed from the wl_surface. The change will be applied
        /// on the next wl_surface.commit.
        pub const Viewport = opaque {
            pub const generated_version = 1;
            pub const interface = &common.wp.viewport.interface;
            pub const Error = common.wp.viewport.Error;
            pub inline fn create(_client: *server.wl.Client, _version: u32, _id: u32) error{ResourceCreateFailed}!*Viewport {
                return @ptrCast(try server.wl.Resource.create(_client, Viewport, _version, _id));
            }
            pub inline fn destroy(_viewport: *Viewport) void {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).destroy();
            }
            pub inline fn fromLink(_link: *server.wl.list.Link) *Viewport {
                return @ptrCast(server.wl.Resource.fromLink(_link));
            }
            pub inline fn getLink(_viewport: *Viewport) *server.wl.list.Link {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).getLink();
            }
            pub inline fn getClient(_viewport: *Viewport) *server.wl.Client {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).getClient();
            }
            pub inline fn getId(_viewport: *Viewport) u32 {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).getId();
            }
            pub inline fn getVersion(_viewport: *Viewport) u32 {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).getVersion();
            }
            pub inline fn postNoMemory(_viewport: *Viewport) void {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).postNoMemory();
            }
            pub inline fn getUserData(_viewport: *Viewport) ?*anyopaque {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).getUserData();
            }
            pub inline fn postError(_viewport: *Viewport, _err: Error, _message: [*:0]const u8) void {
                return @as(*server.wl.Resource, @ptrCast(_viewport)).postError(@intCast(@intFromEnum(_err)), _message);
            }
            pub const Request = union(enum) {
                pub const destroy_since_version = 1;
                pub const set_source_since_version = 1;
                pub const set_destination_since_version = 1;

                /// The associated wl_surface's crop and scale state is removed.
                /// The change is applied on the next wl_surface.commit.
                destroy: void,
                /// Set the source rectangle of the associated wl_surface. See
                /// wp_viewport for the description, and relation to the wl_buffer
                /// size.
                ///
                /// If all of x, y, width and height are -1.0, the source rectangle is
                /// unset instead. Any other set of values where width or height are zero
                /// or negative, or x or y are negative, raise the bad_value protocol
                /// error.
                ///
                /// The crop and scale state is double-buffered, see wl_surface.commit.
                set_source: struct {
                    x: common.Fixed,
                    y: common.Fixed,
                    width: common.Fixed,
                    height: common.Fixed,
                },

                /// Set the destination size of the associated wl_surface. See
                /// wp_viewport for the description, and relation to the wl_buffer
                /// size.
                ///
                /// If width is -1 and height is -1, the destination size is unset
                /// instead. Any other pair of values for width and height that
                /// contains zero or negative values raises the bad_value protocol
                /// error.
                ///
                /// The crop and scale state is double-buffered, see wl_surface.commit.
                set_destination: struct {
                    width: i32,
                    height: i32,
                },
            };
            pub inline fn setHandler(
                _viewport: *Viewport,
                comptime T: type,
                handle_request: *const fn (_viewport: *Viewport, request: Request, data: T) void,
                comptime handle_destroy: ?fn (_viewport: *Viewport, data: T) void,
                _data: T,
            ) void {
                const _resource: *server.wl.Resource = @ptrCast(_viewport);
                _resource.setDispatcher(
                    common.Dispatcher(Viewport, T).dispatcher,
                    handle_request,
                    @ptrFromInt(@intFromPtr(_data)),
                    if (handle_destroy) |_handler| struct {
                        fn _wrapper(__resource: *server.wl.Resource) callconv(.c) void {
                            _handler(
                                @as(*Viewport, @ptrCast(__resource)),
                                @as(T, @ptrCast(@alignCast(__resource.getUserData()))),
                            );
                        }
                    }._wrapper else null,
                );
            }
        };
    };
};

const common = struct {
    const Object = opaque {};

    const Message = extern struct {
        name: [*:0]const u8,
        signature: [*:0]const u8,
        types: ?[*]const ?*const Interface,
    };

    const Interface = extern struct {
        name: [*:0]const u8,
        version: c_int,
        method_count: c_int,
        methods: ?[*]const Message,
        event_count: c_int,
        events: ?[*]const Message,
    };

    const list = struct {
        pub const Link = extern struct {
            prev: ?*Link,
            next: ?*Link,

            pub fn init(link: *Link) void {
                link.* = .{ .prev = link, .next = link };
            }

            pub fn insert(link: *Link, other: *Link) void {
                other.prev = link;
                other.next = link.next;
                link.next = other;
                other.next.?.prev = other;
            }

            pub fn remove(link: *Link) void {
                link.prev.?.next = link.next;
                link.next.?.prev = link.prev;
                link.* = .{ .prev = null, .next = null };
            }

            pub fn replaceWith(link: *Link, other: *Link) void {
                other.next = link.next;
                other.next.?.prev = other;
                other.prev = link.prev;
                other.prev.?.next = other;

                link.* = .{ .prev = null, .next = null };
            }

            pub fn swapWith(link: *Link, other: *Link) void {
                const old_other_prev = other.prev.?;
                other.remove();

                link.replaceWith(other);

                if (old_other_prev == link) {
                    other.insert(link);
                } else {
                    old_other_prev.insert(link);
                }
            }

            /// private helper that doesn't handle empty lists and assumes that
            /// other is the link of a Head.
            fn insertList(link: *Link, other: *Link) void {
                other.next.?.prev = link;
                other.prev.?.next = link.next;
                link.next.?.prev = other.prev;
                link.next = other.next;

                other.init();
            }
        };

        pub const Direction = enum {
            forward,
            reverse,
        };

        /// This has the same ABI as wl.list.Link/wl_list. If link_field is null, then
        /// T.getLink()/T.fromLink() will be used. This allows for compatiability
        /// with wl.Client and wl.Resource
        pub fn Head(comptime T: type, comptime link_field: ?@EnumLiteral()) type {
            return extern struct {
                const Self = @This();

                link: Link,

                pub fn init(head: *Self) void {
                    head.link.init();
                }

                pub fn prepend(head: *Self, elem: *T) void {
                    head.link.insert(linkFromElem(elem));
                }

                pub fn append(head: *Self, elem: *T) void {
                    head.link.prev.?.insert(linkFromElem(elem));
                }

                pub fn prependList(head: *Self, other: *Self) void {
                    if (other.empty()) return;
                    head.link.insertList(&other.link);
                }

                pub fn appendList(head: *Self, other: *Self) void {
                    if (other.empty()) return;
                    head.link.prev.?.insertList(&other.link);
                }

                pub fn first(head: *Self) ?*T {
                    if (head.empty()) {
                        return null;
                    } else {
                        return elemFromLink(head.link.next.?);
                    }
                }

                pub fn last(head: *Self) ?*T {
                    if (head.empty()) {
                        return null;
                    } else {
                        return elemFromLink(head.link.prev.?);
                    }
                }

                pub fn length(head: *const Self) usize {
                    var count: usize = 0;
                    var current = head.link.next.?;
                    while (current != &head.link) : (current = current.next.?) {
                        count += 1;
                    }
                    return count;
                }

                pub fn empty(head: *const Self) bool {
                    return head.link.next == &head.link;
                }

                /// Removal of the current element during iteration is permitted.
                /// Removal of other elements is illegal.
                pub fn Iterator(comptime direction: Direction) type {
                    return struct {
                        head: *Link,
                        current: *Link,
                        future: *Link,

                        pub fn next(it: *@This()) ?*T {
                            it.current = it.future;
                            it.future = switch (direction) {
                                .forward => it.future.next.?,
                                .reverse => it.future.prev.?,
                            };
                            if (it.current == it.head) return null;
                            return elemFromLink(it.current);
                        }
                    };
                }

                /// Removal of the current element during iteration is permitted.
                /// Removal of other elements is illegal.
                pub fn iterator(head: *Self, comptime direction: Direction) Iterator(direction) {
                    return .{
                        .head = &head.link,
                        .current = &head.link,
                        .future = switch (direction) {
                            .forward => head.link.next.?,
                            .reverse => head.link.prev.?,
                        },
                    };
                }

                pub const safeIterator = iterator;
                pub const SafeIterator = Iterator;

                fn linkFromElem(elem: *T) *Link {
                    if (link_field) |f| {
                        return &@field(elem, @tagName(f));
                    } else {
                        return elem.getLink();
                    }
                }

                fn elemFromLink(link: *Link) *T {
                    if (link_field) |f| {
                        return @alignCast(@fieldParentPtr(@tagName(f), link));
                    } else {
                        return T.fromLink(link);
                    }
                }
            };
        }
    };

    const Array = extern struct {
        size: usize,
        alloc: usize,
        data: ?*anyopaque,

        /// Does not clone memory
        pub fn fromArrayList(comptime T: type, array_list: std.ArrayList(T)) Array {
            return Array{
                .size = array_list.items.len * @sizeOf(T),
                .alloc = array_list.capacity * @sizeOf(T),
                .data = array_list.items.ptr,
            };
        }

        pub fn slice(array: Array, comptime T: type) []align(4) T {
            const data = array.data orelse return &[0]T{};
            // The wire protocol/libwayland only guarantee 32-bit word alignment.
            const ptr: [*]align(4) T = @ptrCast(@alignCast(data));
            return ptr[0..@divExact(array.size, @sizeOf(T))];
        }
    };

    /// A 24.8 signed fixed-point number.
    const Fixed = enum(i32) {
        _,

        pub fn toInt(f: Fixed) i24 {
            return @truncate(@intFromEnum(f) >> 8);
        }

        pub fn fromInt(i: i24) Fixed {
            return @enumFromInt(@as(i32, i) << 8);
        }

        pub fn toDouble(f: Fixed) f64 {
            return @as(f64, @floatFromInt(@intFromEnum(f))) / 256;
        }

        pub fn fromDouble(d: f64) Fixed {
            return @enumFromInt(@as(i32, @intFromFloat(d * 256)));
        }
    };

    const Argument = extern union {
        i: i32,
        u: u32,
        f: Fixed,
        s: ?[*:0]const u8,
        o: ?*Object,
        n: u32,
        a: ?*Array,
        h: i32,
    };

    fn Dispatcher(comptime Obj: type, comptime Data: type) type {
        const client_side = @hasDecl(Obj, "Event");
        const Payload = if (client_side) Obj.Event else Obj.Request;
        return struct {
            fn dispatcher(
                implementation: ?*const anyopaque,
                object: if (client_side) *client.wl.Proxy else *server.wl.Resource,
                opcode: u32,
                _: *const Message,
                args: [*]Argument,
            ) callconv(.c) c_int {
                inline for (@typeInfo(Payload).@"union".fields, 0..) |payload_field, payload_num| {
                    if (payload_num == opcode) {
                        var payload_data: payload_field.type = undefined;
                        if (payload_field.type != void) {
                            inline for (@typeInfo(payload_field.type).@"struct".fields, 0..) |f, i| {
                                switch (@typeInfo(f.type)) {
                                    // signed/unsigned ints, fds, new_ids, bitfield enums
                                    .int, .@"struct" => @field(payload_data, f.name) = @as(f.type, @bitCast(args[i].u)),
                                    // objects, strings, arrays
                                    .pointer, .optional => @field(payload_data, f.name) = @as(f.type, @ptrFromInt(@intFromPtr(args[i].o))),
                                    // non-bitfield enums
                                    .@"enum" => @field(payload_data, f.name) = @as(f.type, @enumFromInt(args[i].i)),
                                    else => unreachable,
                                }
                            }
                        }

                        const HandlerFn = fn (*Obj, Payload, Data) void;
                        @as(*const HandlerFn, @ptrCast(@alignCast(implementation)))(
                            @as(*Obj, @ptrCast(object)),
                            @unionInit(Payload, payload_field.name, payload_data),
                            @as(Data, @ptrFromInt(@intFromPtr(object.getUserData()))),
                        );

                        return 0;
                    }
                }
                unreachable;
            }
        };
    }
    const wl = struct {
        const display = struct {
            const interface: common.Interface = .{
                .name = "wl_display",
                .version = 1,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "sync",
                        .signature = "n",
                        .types = &.{
                            &common.wl.callback.interface,
                        },
                    },
                    .{
                        .name = "get_registry",
                        .signature = "n",
                        .types = &.{
                            &common.wl.registry.interface,
                        },
                    },
                },
                .event_count = 2,
                .events = &.{
                    .{
                        .name = "error",
                        .signature = "ous",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "delete_id",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
            /// These errors are global and can be emitted in response to any
            /// server request.
            const Error = enum(c_int) {
                pub const invalid_object_since_version = 1;
                pub const invalid_method_since_version = 1;
                pub const no_memory_since_version = 1;
                pub const implementation_since_version = 1;

                invalid_object = 0,
                invalid_method = 1,
                no_memory = 2,
                implementation = 3,
                _,
            };
        };
        const registry = struct {
            const interface: common.Interface = .{
                .name = "wl_registry",
                .version = 1,
                .method_count = 1,
                .methods = &.{
                    .{
                        .name = "bind",
                        .signature = "usun",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                },
                .event_count = 2,
                .events = &.{
                    .{
                        .name = "global",
                        .signature = "usu",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "global_remove",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
        };
        const callback = struct {
            const interface: common.Interface = .{
                .name = "wl_callback",
                .version = 1,
                .method_count = 0,
                .methods = null,
                .event_count = 1,
                .events = &.{
                    .{
                        .name = "done",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
        };
        const buffer = struct {
            const interface: common.Interface = .{
                .name = "wl_buffer",
                .version = 1,
                .method_count = 1,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                },
                .event_count = 1,
                .events = &.{
                    .{
                        .name = "release",
                        .signature = "",
                        .types = null,
                    },
                },
            };
        };
        const compositor = struct {
            const interface: common.Interface = .{
                .name = "wl_compositor",
                .version = 7,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "create_surface",
                        .signature = "n",
                        .types = &.{
                            &common.wl.surface.interface,
                        },
                    },
                    .{
                        .name = "create_region",
                        .signature = "n",
                        .types = &.{
                            &common.wl.region.interface,
                        },
                    },
                    .{
                        .name = "release",
                        .signature = "7",
                        .types = null,
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const surface = struct {
            const interface: common.Interface = .{
                .name = "wl_surface",
                .version = 7,
                .method_count = 12,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "attach",
                        .signature = "?oii",
                        .types = &.{
                            &common.wl.buffer.interface,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "damage",
                        .signature = "iiii",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "frame",
                        .signature = "n",
                        .types = &.{
                            &common.wl.callback.interface,
                        },
                    },
                    .{
                        .name = "set_opaque_region",
                        .signature = "?o",
                        .types = &.{
                            &common.wl.region.interface,
                        },
                    },
                    .{
                        .name = "set_input_region",
                        .signature = "?o",
                        .types = &.{
                            &common.wl.region.interface,
                        },
                    },
                    .{
                        .name = "commit",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "set_buffer_transform",
                        .signature = "2i",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "set_buffer_scale",
                        .signature = "3i",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "damage_buffer",
                        .signature = "4iiii",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "offset",
                        .signature = "5ii",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "get_release",
                        .signature = "7n",
                        .types = &.{
                            &common.wl.callback.interface,
                        },
                    },
                },
                .event_count = 4,
                .events = &.{
                    .{
                        .name = "enter",
                        .signature = "o",
                        .types = &.{
                            &common.wl.output.interface,
                        },
                    },
                    .{
                        .name = "leave",
                        .signature = "o",
                        .types = &.{
                            &common.wl.output.interface,
                        },
                    },
                    .{
                        .name = "preferred_buffer_scale",
                        .signature = "6i",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "preferred_buffer_transform",
                        .signature = "6u",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
            /// These errors can be emitted in response to wl_surface requests.
            const Error = enum(c_int) {
                pub const invalid_scale_since_version = 1;
                pub const invalid_transform_since_version = 1;
                pub const invalid_size_since_version = 1;
                pub const invalid_offset_since_version = 1;
                pub const defunct_role_object_since_version = 1;
                pub const no_buffer_since_version = 1;

                invalid_scale = 0,
                invalid_transform = 1,
                invalid_size = 2,
                invalid_offset = 3,
                defunct_role_object = 4,
                no_buffer = 5,
                _,
            };
        };
        const region = struct {
            const interface: common.Interface = .{
                .name = "wl_region",
                .version = 7,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "add",
                        .signature = "iiii",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "subtract",
                        .signature = "iiii",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const shm = struct {
            const interface: common.Interface = .{
                .name = "wl_shm",
                .version = 2,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "create_pool",
                        .signature = "nhi",
                        .types = &.{
                            &common.wl.shm_pool.interface,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "release",
                        .signature = "2",
                        .types = null,
                    },
                },
                .event_count = 1,
                .events = &.{
                    .{
                        .name = "format",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
        };
        const shm_pool = struct {
            const interface: common.Interface = .{
                .name = "wl_shm_pool",
                .version = 2,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "create_buffer",
                        .signature = "niiiiu",
                        .types = &.{
                            &common.wl.buffer.interface,
                            null,
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "resize",
                        .signature = "i",
                        .types = &.{
                            null,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const data_device_manager = struct {
            const interface: common.Interface = .{
                .name = "wl_data_device_manager",
                .version = 4,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "create_data_source",
                        .signature = "n",
                        .types = &.{
                            &common.wl.data_source.interface,
                        },
                    },
                    .{
                        .name = "get_data_device",
                        .signature = "no",
                        .types = &.{
                            &common.wl.data_device.interface,
                            &common.wl.seat.interface,
                        },
                    },
                    .{
                        .name = "release",
                        .signature = "4",
                        .types = null,
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const data_source = struct {
            const interface: common.Interface = .{
                .name = "wl_data_source",
                .version = 4,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "offer",
                        .signature = "s",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "set_actions",
                        .signature = "3u",
                        .types = &.{
                            null,
                        },
                    },
                },
                .event_count = 6,
                .events = &.{
                    .{
                        .name = "target",
                        .signature = "?s",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "send",
                        .signature = "sh",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "cancelled",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "dnd_drop_performed",
                        .signature = "3",
                        .types = null,
                    },
                    .{
                        .name = "dnd_finished",
                        .signature = "3",
                        .types = null,
                    },
                    .{
                        .name = "action",
                        .signature = "3u",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
        };
        const data_device = struct {
            const interface: common.Interface = .{
                .name = "wl_data_device",
                .version = 4,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "start_drag",
                        .signature = "?oo?ou",
                        .types = &.{
                            &common.wl.data_source.interface,
                            &common.wl.surface.interface,
                            &common.wl.surface.interface,
                            null,
                        },
                    },
                    .{
                        .name = "set_selection",
                        .signature = "?ou",
                        .types = &.{
                            &common.wl.data_source.interface,
                            null,
                        },
                    },
                    .{
                        .name = "release",
                        .signature = "2",
                        .types = null,
                    },
                },
                .event_count = 6,
                .events = &.{
                    .{
                        .name = "data_offer",
                        .signature = "n",
                        .types = &.{
                            &common.wl.data_offer.interface,
                        },
                    },
                    .{
                        .name = "enter",
                        .signature = "uoff?o",
                        .types = &.{
                            null,
                            &common.wl.surface.interface,
                            null,
                            null,
                            &common.wl.data_offer.interface,
                        },
                    },
                    .{
                        .name = "leave",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "motion",
                        .signature = "uff",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "drop",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "selection",
                        .signature = "?o",
                        .types = &.{
                            &common.wl.data_offer.interface,
                        },
                    },
                },
            };
        };
        const data_offer = struct {
            const interface: common.Interface = .{
                .name = "wl_data_offer",
                .version = 4,
                .method_count = 5,
                .methods = &.{
                    .{
                        .name = "accept",
                        .signature = "u?s",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "receive",
                        .signature = "sh",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "finish",
                        .signature = "3",
                        .types = null,
                    },
                    .{
                        .name = "set_actions",
                        .signature = "3uu",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                },
                .event_count = 3,
                .events = &.{
                    .{
                        .name = "offer",
                        .signature = "s",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "source_actions",
                        .signature = "3u",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "action",
                        .signature = "3u",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
        };
        const shell = struct {
            const interface: common.Interface = .{
                .name = "wl_shell",
                .version = 1,
                .method_count = 1,
                .methods = &.{
                    .{
                        .name = "get_shell_surface",
                        .signature = "no",
                        .types = &.{
                            &common.wl.shell_surface.interface,
                            &common.wl.surface.interface,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const shell_surface = struct {
            const interface: common.Interface = .{
                .name = "wl_shell_surface",
                .version = 1,
                .method_count = 10,
                .methods = &.{
                    .{
                        .name = "pong",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "move",
                        .signature = "ou",
                        .types = &.{
                            &common.wl.seat.interface,
                            null,
                        },
                    },
                    .{
                        .name = "resize",
                        .signature = "ouu",
                        .types = &.{
                            &common.wl.seat.interface,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "set_toplevel",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "set_transient",
                        .signature = "oiiu",
                        .types = &.{
                            &common.wl.surface.interface,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "set_fullscreen",
                        .signature = "uu?o",
                        .types = &.{
                            null,
                            null,
                            &common.wl.output.interface,
                        },
                    },
                    .{
                        .name = "set_popup",
                        .signature = "ouoiiu",
                        .types = &.{
                            &common.wl.seat.interface,
                            null,
                            &common.wl.surface.interface,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "set_maximized",
                        .signature = "?o",
                        .types = &.{
                            &common.wl.output.interface,
                        },
                    },
                    .{
                        .name = "set_title",
                        .signature = "s",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "set_class",
                        .signature = "s",
                        .types = &.{
                            null,
                        },
                    },
                },
                .event_count = 3,
                .events = &.{
                    .{
                        .name = "ping",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "configure",
                        .signature = "uii",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "popup_done",
                        .signature = "",
                        .types = null,
                    },
                },
            };
        };
        const seat = struct {
            const interface: common.Interface = .{
                .name = "wl_seat",
                .version = 10,
                .method_count = 4,
                .methods = &.{
                    .{
                        .name = "get_pointer",
                        .signature = "n",
                        .types = &.{
                            &common.wl.pointer.interface,
                        },
                    },
                    .{
                        .name = "get_keyboard",
                        .signature = "n",
                        .types = &.{
                            &common.wl.keyboard.interface,
                        },
                    },
                    .{
                        .name = "get_touch",
                        .signature = "n",
                        .types = &.{
                            &common.wl.touch.interface,
                        },
                    },
                    .{
                        .name = "release",
                        .signature = "5",
                        .types = null,
                    },
                },
                .event_count = 2,
                .events = &.{
                    .{
                        .name = "capabilities",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "name",
                        .signature = "2s",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
            /// This is a bitmask of capabilities this seat has; if a member is
            /// set, then it is present on the seat.
            const Capability = packed struct(u32) {
                pub const pointer_since_version = 1;
                pub const keyboard_since_version = 1;
                pub const touch_since_version = 1;

                pointer: bool = false,
                keyboard: bool = false,
                touch: bool = false,
                _padding3: bool = false,
                _padding4: bool = false,
                _padding5: bool = false,
                _padding6: bool = false,
                _padding7: bool = false,
                _padding8: bool = false,
                _padding9: bool = false,
                _padding10: bool = false,
                _padding11: bool = false,
                _padding12: bool = false,
                _padding13: bool = false,
                _padding14: bool = false,
                _padding15: bool = false,
                _padding16: bool = false,
                _padding17: bool = false,
                _padding18: bool = false,
                _padding19: bool = false,
                _padding20: bool = false,
                _padding21: bool = false,
                _padding22: bool = false,
                _padding23: bool = false,
                _padding24: bool = false,
                _padding25: bool = false,
                _padding26: bool = false,
                _padding27: bool = false,
                _padding28: bool = false,
                _padding29: bool = false,
                _padding30: bool = false,
                _padding31: bool = false,
                pub const Enum = enum(c_int) {
                    pub const pointer_since_version = 1;
                    pub const keyboard_since_version = 1;
                    pub const touch_since_version = 1;

                    pointer = 1,
                    keyboard = 2,
                    touch = 4,
                    _,
                };
            };

            /// These errors can be emitted in response to wl_seat requests.
            const Error = enum(c_int) {
                pub const missing_capability_since_version = 1;

                missing_capability = 0,
                _,
            };
        };
        const pointer = struct {
            const interface: common.Interface = .{
                .name = "wl_pointer",
                .version = 10,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "set_cursor",
                        .signature = "u?oii",
                        .types = &.{
                            null,
                            &common.wl.surface.interface,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "release",
                        .signature = "3",
                        .types = null,
                    },
                },
                .event_count = 11,
                .events = &.{
                    .{
                        .name = "enter",
                        .signature = "uoff",
                        .types = &.{
                            null,
                            &common.wl.surface.interface,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "leave",
                        .signature = "uo",
                        .types = &.{
                            null,
                            &common.wl.surface.interface,
                        },
                    },
                    .{
                        .name = "motion",
                        .signature = "uff",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "button",
                        .signature = "uuuu",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "axis",
                        .signature = "uuf",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "frame",
                        .signature = "5",
                        .types = null,
                    },
                    .{
                        .name = "axis_source",
                        .signature = "5u",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "axis_stop",
                        .signature = "5uu",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "axis_discrete",
                        .signature = "5ui",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "axis_value120",
                        .signature = "8ui",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "axis_relative_direction",
                        .signature = "9uu",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                },
            };
            const Error = enum(c_int) {
                pub const role_since_version = 1;

                role = 0,
                _,
            };

            /// Describes the physical state of a button that produced the button
            /// event.
            const ButtonState = enum(c_int) {
                pub const released_since_version = 1;
                pub const pressed_since_version = 1;

                released = 0,
                pressed = 1,
                _,
            };

            /// Describes the axis types of scroll events.
            const Axis = enum(c_int) {
                pub const vertical_scroll_since_version = 1;
                pub const horizontal_scroll_since_version = 1;

                vertical_scroll = 0,
                horizontal_scroll = 1,
                _,
            };

            /// Describes the source types for axis events. This indicates to the
            /// client how an axis event was physically generated; a client may
            /// adjust the user interface accordingly. For example, scroll events
            /// from a "finger" source may be in a smooth coordinate space with
            /// kinetic scrolling whereas a "wheel" source may be in discrete steps
            /// of a number of lines.
            ///
            /// The "continuous" axis source is a device generating events in a
            /// continuous coordinate space, but using something other than a
            /// finger. One example for this source is button-based scrolling where
            /// the vertical motion of a device is converted to scroll events while
            /// a button is held down.
            ///
            /// The "wheel tilt" axis source indicates that the actual device is a
            /// wheel but the scroll event is not caused by a rotation but a
            /// (usually sideways) tilt of the wheel.
            const AxisSource = enum(c_int) {
                pub const wheel_since_version = 1;
                pub const finger_since_version = 1;
                pub const continuous_since_version = 1;

                wheel = 0,
                finger = 1,
                continuous = 2,
                _,
            };

            /// This specifies the direction of the physical motion that caused a
            /// wl_pointer.axis event, relative to the wl_pointer.axis direction.
            const AxisRelativeDirection = enum(c_int) {
                pub const identical_since_version = 1;
                pub const inverted_since_version = 1;

                identical = 0,
                inverted = 1,
                _,
            };
        };
        const keyboard = struct {
            const interface: common.Interface = .{
                .name = "wl_keyboard",
                .version = 10,
                .method_count = 1,
                .methods = &.{
                    .{
                        .name = "release",
                        .signature = "3",
                        .types = null,
                    },
                },
                .event_count = 6,
                .events = &.{
                    .{
                        .name = "keymap",
                        .signature = "uhu",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "enter",
                        .signature = "uoa",
                        .types = &.{
                            null,
                            &common.wl.surface.interface,
                            null,
                        },
                    },
                    .{
                        .name = "leave",
                        .signature = "uo",
                        .types = &.{
                            null,
                            &common.wl.surface.interface,
                        },
                    },
                    .{
                        .name = "key",
                        .signature = "uuuu",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "modifiers",
                        .signature = "uuuuu",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "repeat_info",
                        .signature = "4ii",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                },
            };
            /// This specifies the format of the keymap provided to the
            /// client with the wl_keyboard.keymap event.
            const KeymapFormat = enum(c_int) {
                pub const no_keymap_since_version = 1;
                pub const xkb_v1_since_version = 1;

                no_keymap = 0,
                xkb_v1 = 1,
                _,
            };

            /// Describes the physical state of a key that produced the key event.
            ///
            /// Since version 10, the key can be in a "repeated" pseudo-state which
            /// means the same as "pressed", but is used to signal repetition in the
            /// key event.
            ///
            /// The key may only enter the repeated state after entering the pressed
            /// state and before entering the released state. This event may be
            /// generated multiple times while the key is down.
            const KeyState = enum(c_int) {
                pub const released_since_version = 1;
                pub const pressed_since_version = 1;

                released = 0,
                pressed = 1,
                _,
            };
        };
        const touch = struct {
            const interface: common.Interface = .{
                .name = "wl_touch",
                .version = 10,
                .method_count = 1,
                .methods = &.{
                    .{
                        .name = "release",
                        .signature = "3",
                        .types = null,
                    },
                },
                .event_count = 7,
                .events = &.{
                    .{
                        .name = "down",
                        .signature = "uuoiff",
                        .types = &.{
                            null,
                            null,
                            &common.wl.surface.interface,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "up",
                        .signature = "uui",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "motion",
                        .signature = "uiff",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "frame",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "cancel",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "shape",
                        .signature = "6iff",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "orientation",
                        .signature = "6if",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                },
            };
        };
        const output = struct {
            const interface: common.Interface = .{
                .name = "wl_output",
                .version = 4,
                .method_count = 1,
                .methods = &.{
                    .{
                        .name = "release",
                        .signature = "3",
                        .types = null,
                    },
                },
                .event_count = 6,
                .events = &.{
                    .{
                        .name = "geometry",
                        .signature = "iiiiissi",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "mode",
                        .signature = "uiii",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "done",
                        .signature = "2",
                        .types = null,
                    },
                    .{
                        .name = "scale",
                        .signature = "2i",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "name",
                        .signature = "4s",
                        .types = &.{
                            null,
                        },
                    },
                    .{
                        .name = "description",
                        .signature = "4s",
                        .types = &.{
                            null,
                        },
                    },
                },
            };
            /// This enumeration describes how the physical
            /// pixels on an output are laid out.
            const Subpixel = enum(c_int) {
                pub const unknown_since_version = 1;
                pub const none_since_version = 1;
                pub const horizontal_rgb_since_version = 1;
                pub const horizontal_bgr_since_version = 1;
                pub const vertical_rgb_since_version = 1;
                pub const vertical_bgr_since_version = 1;

                unknown = 0,
                none = 1,
                horizontal_rgb = 2,
                horizontal_bgr = 3,
                vertical_rgb = 4,
                vertical_bgr = 5,
                _,
            };

            /// This describes transformations that clients and compositors apply to
            /// buffer contents.
            ///
            /// The flipped values correspond to an initial flip around a
            /// vertical axis followed by rotation.
            ///
            /// The purpose is mainly to allow clients to render accordingly and
            /// tell the compositor, so that for fullscreen surfaces, the
            /// compositor will still be able to scan out directly from client
            /// surfaces.
            const Transform = enum(c_int) {
                pub const normal_since_version = 1;
                pub const @"90_since_version" = 1;
                pub const @"180_since_version" = 1;
                pub const @"270_since_version" = 1;
                pub const flipped_since_version = 1;
                pub const flipped_90_since_version = 1;
                pub const flipped_180_since_version = 1;
                pub const flipped_270_since_version = 1;

                normal = 0,
                @"90" = 1,
                @"180" = 2,
                @"270" = 3,
                flipped = 4,
                flipped_90 = 5,
                flipped_180 = 6,
                flipped_270 = 7,
                _,
            };

            /// These flags describe properties of an output mode.
            /// They are used in the flags bitfield of the mode event.
            const Mode = packed struct(u32) {
                pub const current_since_version = 1;
                pub const preferred_since_version = 1;

                current: bool = false,
                preferred: bool = false,
                _padding2: bool = false,
                _padding3: bool = false,
                _padding4: bool = false,
                _padding5: bool = false,
                _padding6: bool = false,
                _padding7: bool = false,
                _padding8: bool = false,
                _padding9: bool = false,
                _padding10: bool = false,
                _padding11: bool = false,
                _padding12: bool = false,
                _padding13: bool = false,
                _padding14: bool = false,
                _padding15: bool = false,
                _padding16: bool = false,
                _padding17: bool = false,
                _padding18: bool = false,
                _padding19: bool = false,
                _padding20: bool = false,
                _padding21: bool = false,
                _padding22: bool = false,
                _padding23: bool = false,
                _padding24: bool = false,
                _padding25: bool = false,
                _padding26: bool = false,
                _padding27: bool = false,
                _padding28: bool = false,
                _padding29: bool = false,
                _padding30: bool = false,
                _padding31: bool = false,
                pub const Enum = enum(c_int) {
                    pub const current_since_version = 1;
                    pub const preferred_since_version = 1;

                    current = 0x1,
                    preferred = 0x2,
                    _,
                };
            };
        };
        const subcompositor = struct {
            const interface: common.Interface = .{
                .name = "wl_subcompositor",
                .version = 1,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "get_subsurface",
                        .signature = "noo",
                        .types = &.{
                            &common.wl.subsurface.interface,
                            &common.wl.surface.interface,
                            &common.wl.surface.interface,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const subsurface = struct {
            const interface: common.Interface = .{
                .name = "wl_subsurface",
                .version = 1,
                .method_count = 6,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "set_position",
                        .signature = "ii",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "place_above",
                        .signature = "o",
                        .types = &.{
                            &common.wl.surface.interface,
                        },
                    },
                    .{
                        .name = "place_below",
                        .signature = "o",
                        .types = &.{
                            &common.wl.surface.interface,
                        },
                    },
                    .{
                        .name = "set_sync",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "set_desync",
                        .signature = "",
                        .types = null,
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const fixes = struct {
            const interface: common.Interface = .{
                .name = "wl_fixes",
                .version = 1,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "destroy_registry",
                        .signature = "o",
                        .types = &.{
                            &common.wl.registry.interface,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
    };
    const ext = struct {
        const session_lock_manager_v1 = struct {
            const interface: common.Interface = .{
                .name = "ext_session_lock_manager_v1",
                .version = 1,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "lock",
                        .signature = "n",
                        .types = &.{
                            &common.ext.session_lock_v1.interface,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const session_lock_v1 = struct {
            const interface: common.Interface = .{
                .name = "ext_session_lock_v1",
                .version = 1,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "get_lock_surface",
                        .signature = "noo",
                        .types = &.{
                            &common.ext.session_lock_surface_v1.interface,
                            &common.wl.surface.interface,
                            &common.wl.output.interface,
                        },
                    },
                    .{
                        .name = "unlock_and_destroy",
                        .signature = "",
                        .types = null,
                    },
                },
                .event_count = 2,
                .events = &.{
                    .{
                        .name = "locked",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "finished",
                        .signature = "",
                        .types = null,
                    },
                },
            };
            const Error = enum(c_int) {
                pub const invalid_destroy_since_version = 1;
                pub const invalid_unlock_since_version = 1;
                pub const role_since_version = 1;
                pub const duplicate_output_since_version = 1;
                pub const already_constructed_since_version = 1;

                invalid_destroy = 0,
                invalid_unlock = 1,
                role = 2,
                duplicate_output = 3,
                already_constructed = 4,
                _,
            };
        };
        const session_lock_surface_v1 = struct {
            const interface: common.Interface = .{
                .name = "ext_session_lock_surface_v1",
                .version = 1,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "ack_configure",
                        .signature = "u",
                        .types = &.{
                            null,
                        },
                    },
                },
                .event_count = 1,
                .events = &.{
                    .{
                        .name = "configure",
                        .signature = "uuu",
                        .types = &.{
                            null,
                            null,
                            null,
                        },
                    },
                },
            };
            const Error = enum(c_int) {
                pub const commit_before_first_ack_since_version = 1;
                pub const null_buffer_since_version = 1;
                pub const dimensions_mismatch_since_version = 1;
                pub const invalid_serial_since_version = 1;

                commit_before_first_ack = 0,
                null_buffer = 1,
                dimensions_mismatch = 2,
                invalid_serial = 3,
                _,
            };
        };
    };
    const wp = struct {
        const single_pixel_buffer_manager_v1 = struct {
            const interface: common.Interface = .{
                .name = "wp_single_pixel_buffer_manager_v1",
                .version = 1,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "create_u32_rgba_buffer",
                        .signature = "nuuuu",
                        .types = &.{
                            &common.wl.buffer.interface,
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
        };
        const viewporter = struct {
            const interface: common.Interface = .{
                .name = "wp_viewporter",
                .version = 1,
                .method_count = 2,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "get_viewport",
                        .signature = "no",
                        .types = &.{
                            &common.wp.viewport.interface,
                            &common.wl.surface.interface,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
            const Error = enum(c_int) {
                pub const viewport_exists_since_version = 1;

                viewport_exists = 0,
                _,
            };
        };
        const viewport = struct {
            const interface: common.Interface = .{
                .name = "wp_viewport",
                .version = 1,
                .method_count = 3,
                .methods = &.{
                    .{
                        .name = "destroy",
                        .signature = "",
                        .types = null,
                    },
                    .{
                        .name = "set_source",
                        .signature = "ffff",
                        .types = &.{
                            null,
                            null,
                            null,
                            null,
                        },
                    },
                    .{
                        .name = "set_destination",
                        .signature = "ii",
                        .types = &.{
                            null,
                            null,
                        },
                    },
                },
                .event_count = 0,
                .events = null,
            };
            const Error = enum(c_int) {
                pub const bad_value_since_version = 1;
                pub const bad_size_since_version = 1;
                pub const out_of_buffer_since_version = 1;
                pub const no_surface_since_version = 1;

                bad_value = 0,
                bad_size = 1,
                out_of_buffer = 2,
                no_surface = 3,
                _,
            };
        };
    };
};
const ffi = struct {
    const Argument = common.Argument;
    const Interface = common.Interface;
    const list = common.list;

    pub const client = struct {
        const wl = wayland.client.wl;

        extern fn wl_display_cancel_read(display: *wl.Display) void;
        extern fn wl_display_connect_to_fd(fd: c_int) ?*wl.Display;
        extern fn wl_display_connect(name: ?[*:0]const u8) ?*wl.Display;
        extern fn wl_display_create_queue(display: *wl.Display) ?*wl.EventQueue;
        extern fn wl_display_disconnect(display: *wl.Display) void;
        extern fn wl_display_dispatch_pending(display: *wl.Display) c_int;
        extern fn wl_display_dispatch_queue_pending(display: *wl.Display, queue: *wl.EventQueue) c_int;
        extern fn wl_display_dispatch_queue(display: *wl.Display, queue: *wl.EventQueue) c_int;
        extern fn wl_display_dispatch(display: *wl.Display) c_int;
        extern fn wl_display_flush(display: *wl.Display) c_int;
        extern fn wl_display_get_error(display: *wl.Display) c_int;
        extern fn wl_display_get_fd(display: *wl.Display) c_int;
        extern fn wl_display_prepare_read_queue(display: *wl.Display, queue: *wl.EventQueue) c_int;
        extern fn wl_display_prepare_read(display: *wl.Display) c_int;
        extern fn wl_display_read_events(display: *wl.Display) c_int;
        extern fn wl_display_roundtrip_queue(display: *wl.Display, queue: *wl.EventQueue) c_int;
        extern fn wl_display_roundtrip(display: *wl.Display) c_int;
        extern fn wl_event_queue_destroy(queue: *wl.EventQueue) void;
        extern fn wl_proxy_add_dispatcher(
            proxy: *wl.Proxy,
            dispatcher: *const wl.Proxy.DispatcherFn,
            implementation: ?*const anyopaque,
            data: ?*anyopaque,
        ) c_int;
        extern fn wl_proxy_create(factory: *wl.Proxy, interface: *const Interface) ?*wl.Proxy;
        extern fn wl_proxy_destroy(proxy: *wl.Proxy) void;
        extern fn wl_proxy_get_id(proxy: *wl.Proxy) u32;
        extern fn wl_proxy_get_user_data(proxy: *wl.Proxy) ?*anyopaque;
        extern fn wl_proxy_get_version(proxy: *wl.Proxy) u32;
        extern fn wl_proxy_marshal_array_constructor_versioned(
            proxy: *wl.Proxy,
            opcode: u32,
            args: [*]Argument,
            interface: *const Interface,
            version: u32,
        ) ?*wl.Proxy;
        extern fn wl_proxy_marshal_array_constructor(
            proxy: *wl.Proxy,
            opcode: u32,
            args: [*]Argument,
            interface: *const Interface,
        ) ?*wl.Proxy;
        extern fn wl_proxy_marshal_array(proxy: *wl.Proxy, opcode: u32, args: ?[*]Argument) void;
        extern fn wl_proxy_set_queue(proxy: *wl.Proxy, queue: *wl.EventQueue) void;
    };

    pub const cursor = struct {
        const wl = wayland.client.wl;

        extern fn wl_cursor_frame(cursor: *wl.Cursor, time: u32) c_int;
        extern fn wl_cursor_frame_and_duration(cursor: *wl.Cursor, time: u32, duration: *u32) c_int;
        extern fn wl_cursor_image_get_buffer(image: *wl.CursorImage) ?*wl.Buffer;
        extern fn wl_cursor_theme_load(name: ?[*:0]const u8, size: c_int, shm: *wl.Shm) ?*wl.CursorTheme;
        extern fn wl_cursor_theme_destroy(wl_cursor_theme: *wl.CursorTheme) void;
        extern fn wl_cursor_theme_get_cursor(theme: *wl.CursorTheme, name: [*:0]const u8) ?*wl.Cursor;
    };

    pub const egl = struct {
        const wl = wayland.client.wl;

        extern fn wl_egl_window_create(surface: *wl.Surface, width: c_int, height: c_int) ?*wl.EglWindow;
        extern fn wl_egl_window_destroy(egl_window: *wl.EglWindow) void;
        extern fn wl_egl_window_resize(egl_window: *wl.EglWindow, width: c_int, height: c_int, dx: c_int, dy: c_int) void;
        extern fn wl_egl_window_get_attached_size(egl_window: *wl.EglWindow, width: *c_int, height: *c_int) void;
    };

    pub const server = struct {
        const wl = wayland.server.wl;

        extern fn wl_display_create() ?*wl.Server;
        extern fn wl_display_destroy(_server: *wl.Server) void;
        extern fn wl_display_get_event_loop(_server: *wl.Server) *wl.EventLoop;
        extern fn wl_display_add_socket(_server: *wl.Server, name: [*:0]const u8) c_int;
        extern fn wl_display_add_socket_fd(_server: *wl.Server, sock_fd: c_int) c_int;
        extern fn wl_display_terminate(_server: *wl.Server) void;
        extern fn wl_display_run(_server: *wl.Server) void;
        extern fn wl_display_flush_clients(_server: *wl.Server) void;
        extern fn wl_display_destroy_clients(_server: *wl.Server) void;
        extern fn wl_display_get_serial(_server: *wl.Server) u32;
        extern fn wl_display_next_serial(_server: *wl.Server) u32;
        extern fn wl_display_add_destroy_listener(_server: *wl.Server, listener: *wl.Listener(*wl.Server)) void;
        extern fn wl_display_add_client_created_listener(_server: *wl.Server, listener: *wl.Listener(*wl.Client)) void;
        extern fn wl_display_set_global_filter(
            server: *wl.Server,
            filter: *const fn (_client: *const wl.Client, global: *const wl.Global, data: ?*anyopaque) callconv(.c) bool,
            data: ?*anyopaque,
        ) void;
        extern fn wl_display_get_client_list(_server: *wl.Server) *list.Head(wl.Client, null);
        extern fn wl_display_init_shm(_server: *wl.Server) c_int;
        extern fn wl_display_add_shm_format(_server: *wl.Server, format: u32) ?*u32;
        extern fn wl_display_add_protocol_logger(
            _server: *wl.Server,
            func: *const fn (data: ?*anyopaque, direction: wl.ProtocolLogger.Type, message: *const wl.ProtocolLogger.LogMessage) callconv(.c) void,
            data: ?*anyopaque,
        ) void;
        extern fn wl_client_create(_server: *wl.Server, fd: c_int) ?*wl.Client;
        extern fn wl_client_destroy(_client: *wl.Client) void;
        extern fn wl_client_flush(_client: *wl.Client) void;
        extern fn wl_client_get_link(_client: *wl.Client) *list.Link;
        extern fn wl_client_from_link(link: *list.Link) *wl.Client;
        extern fn wl_client_get_credentials(_client: *wl.Client, pid: *posix.pid_t, uid: *posix.uid_t, gid: *posix.gid_t) void;
        extern fn wl_client_add_destroy_listener(_client: *wl.Client, listener: *wl.Listener(*wl.Client)) void;
        extern fn wl_client_get_object(_client: *wl.Client, id: u32) ?*wl.Resource;
        extern fn wl_client_post_no_memory(_client: *wl.Client) void;
        extern fn wl_client_post_implementation_error(_client: *wl.Client, msg: [*:0]const u8, ...) void;
        extern fn wl_client_add_resource_created_listener(_client: *wl.Client, listener: *wl.Listener(*wl.Resource)) void;
        extern fn wl_client_for_each_resource(
            _client: *wl.Client,
            iterator: *const fn (resource: *wl.Resource, data: ?*anyopaque) callconv(.c) wl.IteratorResult,
            data: ?*anyopaque,
        ) void;
        extern fn wl_client_get_fd(_client: *wl.Client) c_int;
        extern fn wl_client_get_display(_client: *wl.Client) *wl.Server;
        extern fn wl_global_create(
            _server: *wl.Server,
            interface: *const Interface,
            version: c_int,
            data: ?*anyopaque,
            bind: *const fn (_client: *wl.Client, data: ?*anyopaque, version: u32, id: u32) callconv(.c) void,
        ) ?*wl.Global;
        extern fn wl_global_remove(global: *wl.Global) void;
        extern fn wl_global_destroy(global: *wl.Global) void;
        extern fn wl_global_get_interface(global: *const wl.Global) *const Interface;
        extern fn wl_global_get_name(global: *const wl.Global, _client: *const wl.Client) u32;
        extern fn wl_global_get_user_data(global: *const wl.Global) ?*anyopaque;
        extern fn wl_resource_create(_client: *wl.Client, interface: *const Interface, version: c_int, id: u32) ?*wl.Resource;
        extern fn wl_resource_destroy(resource: *wl.Resource) void;
        extern fn wl_resource_post_event_array(resource: *wl.Resource, opcode: u32, args: ?[*]Argument) void;
        extern fn wl_resource_queue_event_array(resource: *wl.Resource, opcode: u32, args: ?[*]Argument) void;
        extern fn wl_resource_post_error(resource: *wl.Resource, code: u32, message: [*:0]const u8, ...) void;
        extern fn wl_resource_post_no_memory(resource: *wl.Resource) void;
        extern fn wl_resource_set_dispatcher(
            resource: *wl.Resource,
            dispatcher: ?*const wl.Resource.DispatcherFn,
            implementation: ?*const anyopaque,
            data: ?*anyopaque,
            destroy_fn: ?*const wl.Resource.DestroyFn,
        ) void;
        extern fn wl_resource_get_user_data(resource: *wl.Resource) ?*anyopaque;
        extern fn wl_resource_get_id(resource: *wl.Resource) u32;
        extern fn wl_resource_get_link(resource: *wl.Resource) *list.Link;
        extern fn wl_resource_from_link(link: *list.Link) *wl.Resource;
        extern fn wl_resource_find_for_client(_list: *list.Head(wl.Resource, null), _client: *wl.Client) ?*wl.Resource;
        extern fn wl_resource_get_client(resource: *wl.Resource) *wl.Client;
        extern fn wl_resource_get_version(resource: *wl.Resource) c_int;
        extern fn wl_resource_get_class(resource: *wl.Resource) [*:0]const u8;
        extern fn wl_resource_add_destroy_listener(resource: *wl.Resource, listener: *wl.Listener(*wl.Resource)) void;
        extern fn wl_protocol_logger_destroy(logger: *wl.ProtocolLogger) void;
        extern fn wl_event_loop_create() ?*wl.EventLoop;
        extern fn wl_event_loop_destroy(loop: *wl.EventLoop) void;
        extern fn wl_event_loop_add_fd(
            loop: *wl.EventLoop,
            fd: c_int,
            mask: u32,
            func: *const fn (fd: c_int, mask: u32, data: ?*anyopaque) callconv(.c) c_int,
            data: ?*anyopaque,
        ) ?*wl.EventSource;
        extern fn wl_event_loop_add_timer(
            loop: *wl.EventLoop,
            func: *const fn (data: ?*anyopaque) callconv(.c) c_int,
            data: ?*anyopaque,
        ) ?*wl.EventSource;
        extern fn wl_event_loop_add_signal(
            loop: *wl.EventLoop,
            signal_number: c_int,
            func: *const fn (c_int, ?*anyopaque) callconv(.c) c_int,
            data: ?*anyopaque,
        ) ?*wl.EventSource;
        extern fn wl_event_loop_add_idle(
            loop: *wl.EventLoop,
            func: *const fn (data: ?*anyopaque) callconv(.c) void,
            data: ?*anyopaque,
        ) ?*wl.EventSource;
        extern fn wl_event_loop_dispatch(loop: *wl.EventLoop, timeout: c_int) c_int;
        extern fn wl_event_loop_dispatch_idle(loop: *wl.EventLoop) void;
        extern fn wl_event_loop_get_fd(loop: *wl.EventLoop) c_int;
        extern fn wl_event_loop_add_destroy_listener(loop: *wl.EventLoop, listener: *wl.Listener(*wl.EventLoop)) void;
        extern fn wl_event_source_remove(source: *wl.EventSource) c_int;
        extern fn wl_event_source_check(source: *wl.EventSource) void;
        extern fn wl_event_source_fd_update(source: *wl.EventSource, mask: u32) c_int;
        extern fn wl_event_source_timer_update(source: *wl.EventSource, ms_delay: c_int) c_int;
        extern fn wl_shm_buffer_get(resource: *wl.Resource) ?*wl.shm.Buffer;
        extern fn wl_shm_buffer_begin_access(buffer: *wl.shm.Buffer) void;
        extern fn wl_shm_buffer_end_access(buffer: *wl.shm.Buffer) void;
        extern fn wl_shm_buffer_get_data(buffer: *wl.shm.Buffer) ?*anyopaque;
        extern fn wl_shm_buffer_get_format(buffer: *wl.shm.Buffer) u32;
        extern fn wl_shm_buffer_get_height(buffer: *wl.shm.Buffer) i32;
        extern fn wl_shm_buffer_get_width(buffer: *wl.shm.Buffer) i32;
        extern fn wl_shm_buffer_get_stride(buffer: *wl.shm.Buffer) i32;
        extern fn wl_shm_buffer_ref_pool(buffer: *wl.shm.Buffer) *wl.Pool;
        extern fn wl_shm_pool_unref(pool: *wl.Pool) void;
    };
};
