diff --git a/build.zig b/build.zig index 6af443f..a0767ec 100644 --- a/build.zig +++ b/build.zig @@ -7,7 +7,7 @@ pub fn build(b: *std.Build) void { const libxev = b.dependency("libxev", .{}).module("xev"); const wayland = b.addModule("wayland", .{ - .root_source_file = b.path("./src/lib.zig"), + .root_source_file = b.path("./wayland/lib.zig"), .imports = &.{ .{ .name = "xev", .module = libxev }, }, diff --git a/build.zig.zon b/build.zig.zon index 7e7e01d..d593e4e 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ // vi: ft=zig .{ - .name = "zoinx", + .name = "way-z", .version = "0.0.0", .paths = .{""}, .dependencies = .{ diff --git a/examples/hello.zig b/examples/hello.zig index f39568d..9e62599 100644 --- a/examples/hello.zig +++ b/examples/hello.zig @@ -14,8 +14,8 @@ const SurfaceCtx = struct { wl_surface: wl.Surface, xdg_surface: xdg.Surface, xdg_toplevel: xdg.Toplevel, - width: u32, - height: u32, + width: u31, + height: u31, offset: f32, last_frame: u32, }; diff --git a/examples/kb_grab.zig b/examples/kb_grab.zig index 9c62b37..c0118b8 100644 --- a/examples/kb_grab.zig +++ b/examples/kb_grab.zig @@ -19,8 +19,8 @@ const SurfaceCtx = struct { wl_surface: wl.Surface, layer_surface: wayland.zwlr.LayerSurfaceV1, shortcut_inhibitor: zwp.KeyboardShortcutsInhibitorV1, - width: u32, - height: u32, + width: u31, + height: u31, offset: f32, last_frame: u32, }; diff --git a/readme.md b/readme.md index da6fae6..5e9a876 100644 --- a/readme.md +++ b/readme.md @@ -5,9 +5,10 @@ Native Zig Wayland client library and widget toolkit ## Description This project has a few different parts: - - Wayland client library (in `src/`): This can be used to crate a statically linked binary capable of displaying CPU rendered graphics. - - Widget toolkit (in `toolkit/`): This builds over the wayland client and povides a Data Oriented library for creating GUI apps - - Apps (in `apps/`): Demo apps built using the widget toolkit + +- Wayland client library (in `wayland/`): This can be used to crate a statically linked binary capable of displaying CPU rendered graphics. +- Widget toolkit (in `toolkit/`): This builds over the wayland client and povides a Data Oriented library for creating GUI apps +- Apps (in `apps/`): Demo apps built using the widget toolkit ## Getting Started diff --git a/src/argument.zig b/wayland/argument.zig similarity index 100% rename from src/argument.zig rename to wayland/argument.zig diff --git a/src/client.zig b/wayland/client.zig similarity index 100% rename from src/client.zig rename to wayland/client.zig diff --git a/src/cmsghdr.zig b/wayland/cmsghdr.zig similarity index 100% rename from src/cmsghdr.zig rename to wayland/cmsghdr.zig diff --git a/src/generated/wl.zig b/wayland/generated/wl.zig similarity index 95% rename from src/generated/wl.zig rename to wayland/generated/wl.zig index daa6f4c..3e6e064 100644 --- a/src/generated/wl.zig +++ b/wayland/generated/wl.zig @@ -103,7 +103,7 @@ pub const Display = enum(u32) { /// 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 event serial. + /// The callback_data passed in the callback is undefined and should be ignored. sync: struct { callback: Callback = @enumFromInt(0), // callback object for the sync request }, @@ -323,7 +323,7 @@ pub const ShmPool = enum(u32) { _, pub const interface = Interface{ .name = "wl_shm_pool", - .version = 1, + .version = 2, .request_names = &.{ "create_buffer", "destroy", @@ -395,7 +395,7 @@ pub const Shm = enum(u32) { _, pub const interface = Interface{ .name = "wl_shm", - .version = 1, + .version = 2, .event_signatures = &.{ &.{.uint}, }, @@ -404,6 +404,7 @@ pub const Shm = enum(u32) { }, .request_names = &.{ "create_pool", + "release", }, }; pub const Error = enum(c_int) { @@ -520,6 +521,21 @@ pub const Shm = enum(u32) { xbgr16161616 = 942948952, argb16161616 = 942953025, abgr16161616 = 942948929, + c1 = 538980675, + c2 = 538980931, + c4 = 538981443, + d1 = 538980676, + d2 = 538980932, + d4 = 538981444, + d8 = 538982468, + r1 = 538980690, + r2 = 538980946, + r4 = 538981458, + r10 = 540029266, + r12 = 540160338, + avuy8888 = 1498764865, + xvuy8888 = 1498764888, + p030 = 808661072, }; pub const Event = union(enum) { /// Informs the client about a valid pixel format that @@ -554,12 +570,18 @@ pub const Shm = enum(u32) { fd: std.posix.fd_t, // file descriptor for the pool size: i32, // pool size, in bytes }, + /// Using this request a client can tell the server that it is not going to + /// use the shm object anymore. + /// + /// Objects created via this interface remain unaffected. + release: void, pub fn ReturnType( request: std.meta.Tag(Request), ) type { return switch (request) { .create_pool => ShmPool, + .release => void, }; } }; @@ -572,9 +594,11 @@ pub const Shm = enum(u32) { /// client provides and updates the contents is defined by the buffer factory /// interface. /// -/// If the buffer uses a format that has an alpha channel, the alpha channel -/// is assumed to be premultiplied in the color channels unless otherwise -/// specified. +/// 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. @@ -1068,6 +1092,7 @@ pub const DataDevice = enum(u32) { }; pub const Error = enum(c_int) { role = 0, + used_source = 1, }; pub const Event = union(enum) { /// The data_offer event introduces a new wl_data_offer object, @@ -1187,7 +1212,7 @@ pub const DataDevice = enum(u32) { /// The icon surface is an optional (can be NULL) surface that /// provides an icon to be moved around with the cursor. Initially, /// the top-left corner of the icon surface is placed at the cursor - /// hotspot, but subsequent wl_surface.attach request can move the + /// hotspot, but subsequent wl_surface.offset requests can move the /// relative position. Attach requests must be confirmed with /// wl_surface.commit as usual. The icon surface is given the role of /// a drag-and-drop icon. If the icon surface already has another role, @@ -1195,6 +1220,10 @@ pub const DataDevice = enum(u32) { /// /// The input region is ignored for wl_surfaces with the role of a /// drag-and-drop icon. + /// + /// The given source may not be used in any further set_selection or + /// start_drag requests. Attempting to reuse a previously-used source + /// may send a used_source error. start_drag: struct { source: ?DataSource, // data source for the eventual transfer origin: ?Surface, // surface where the drag originates @@ -1205,6 +1234,10 @@ pub const DataDevice = enum(u32) { /// to the data from the source on behalf of the client. /// /// To unset the selection, set the source to NULL. + /// + /// The given source may not be used in any further set_selection or + /// start_drag requests. Attempting to reuse a previously-used source + /// may send a used_source error. set_selection: struct { source: ?DataSource, // data source for the selection serial: u32, // serial number of the event that triggered this request @@ -1696,19 +1729,27 @@ pub const Surface = enum(u32) { /// This event indicates the preferred buffer scale for this surface. It is /// sent whenever the compositor's preference changes. /// + /// Before receiving this event the preferred buffer scale for this surface + /// is 1. + /// /// It is intended that scaling aware clients use this event to scale their /// content and use wl_surface.set_buffer_scale to indicate the scale they /// have rendered with. This allows clients to supply a higher detail /// buffer. + /// + /// The compositor shall emit a scale value greater than 0. preferred_buffer_scale: struct { factor: i32, // preferred scaling factor }, /// This event indicates the preferred buffer transform for this surface. /// It is sent whenever the compositor's preference changes. /// - /// It is intended that transform aware clients use this event to apply the - /// transform to their content and use wl_surface.set_buffer_transform to - /// indicate the transform they have rendered with. + /// Before receiving this event the preferred buffer transform for this + /// surface is normal. + /// + /// Applying this transformation to the surface buffer contents and using + /// wl_surface.set_buffer_transform might allow the compositor to use the + /// surface buffer more efficiently. preferred_buffer_transform: struct { transform: Output.Transform, // preferred transform }, @@ -1802,6 +1843,13 @@ pub const Surface = enum(u32) { /// /// 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: ?Buffer, // buffer of surface contents x: i32, // surface-local x coordinate @@ -1923,26 +1971,30 @@ pub const Surface = enum(u32) { }, /// Surface state (input, opaque, and damage regions, attached buffers, /// etc.) is double-buffered. Protocol requests modify the pending state, - /// as opposed to the current state in use by the compositor. A commit - /// request atomically applies all pending state, replacing the current - /// state. After commit, the new pending state is as documented for each - /// related request. + /// as opposed to the active state in use by the compositor. /// - /// On commit, a pending wl_buffer is applied first, and all other state - /// second. This means that all coordinates in double-buffered state are - /// relative to the new wl_buffer coming into use, except for - /// wl_surface.attach itself. If there is no pending wl_buffer, the - /// coordinates are relative to the current surface contents. + /// A commit request atomically creates a content update from the pending + /// state, even if the pending state has not been touched. The content + /// update is placed in a queue until it becomes active. After commit, the + /// new pending state is as documented for each related request. + /// + /// When the content update 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. /// /// 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. commit: void, - /// This request sets an optional transformation on how the compositor - /// interprets the contents of the buffer attached to the surface. The - /// accepted values for the transform parameter are the values for - /// wl_output.transform. + /// 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. /// @@ -1992,10 +2044,10 @@ pub const Surface = enum(u32) { /// a buffer that is larger (by a factor of scale in each dimension) /// than the desired surface size. /// - /// If scale is not positive the invalid_scale protocol error is + /// If scale is not greater than 0 the invalid_scale protocol error is /// raised. set_buffer_scale: struct { - scale: i32, // positive scale for interpreting buffer contents + scale: i32, // scale for interpreting buffer contents }, /// This request is used to describe the regions where the pending /// buffer is different from the current surface contents, and where @@ -2632,9 +2684,9 @@ pub const Pointer = enum(u32) { /// where (x, y) are the coordinates of the pointer location, in /// surface-local coordinates. /// - /// On surface.attach requests to the pointer surface, hotspot_x + /// 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. Attach must be confirmed by + /// 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 @@ -2674,6 +2726,16 @@ pub const Pointer = enum(u32) { /// 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 = enum(u32) { _, pub const interface = Interface{ @@ -2724,10 +2786,15 @@ pub const Keyboard = enum(u32) { /// /// 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. enter: struct { serial: u32, // serial number of the enter event surface: ?Surface, // surface gaining keyboard focus - keys: []u8, // the currently pressed keys + keys: []u8, // the keys currently logically down }, /// Notification that this seat's keyboard focus is no longer on /// a certain surface. @@ -2735,8 +2802,10 @@ pub const Keyboard = enum(u32) { /// The leave notification is sent before the enter notification /// for the new focus. /// - /// After this event client must assume that all keys, including modifiers, - /// are lifted and also it must stop key repeating if there's some going on. + /// 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, // serial number of the leave event surface: ?Surface, // surface that lost keyboard focus @@ -2750,6 +2819,15 @@ pub const Keyboard = enum(u32) { /// /// 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. key: struct { serial: u32, // serial number of the key event time: u32, // timestamp with millisecond granularity @@ -2758,6 +2836,17 @@ pub const Keyboard = enum(u32) { }, /// 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, // serial number of the modifiers event mods_depressed: u32, // depressed modifiers @@ -2925,6 +3014,8 @@ pub const Touch = enum(u32) { /// 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, /// Sent when a touchpoint has changed its shape. /// @@ -3111,6 +3202,10 @@ pub const Output = enum(u32) { /// 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 @@ -3125,7 +3220,7 @@ pub const Output = enum(u32) { subpixel: Subpixel, // subpixel orientation of the output make: [:0]const u8, // textual description of the manufacturer model: [:0]const u8, // textual description of the model - transform: Transform, // transform that maps framebuffer to output + transform: Transform, // additional transformation applied to buffer contents during presentation }, /// The mode event describes an available mode for the output. /// @@ -3175,8 +3270,9 @@ pub const Output = enum(u32) { /// 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. If it is not sent, the client should assume a - /// scale of 1. + /// 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 @@ -3184,12 +3280,9 @@ pub const Output = enum(u32) { /// displays where applications rendering at the native /// resolution would be too small to be legible. /// - /// It is intended that scaling aware clients track the - /// current output of a surface, and if it is on a scaled - /// output it should use wl_surface.set_buffer_scale with - /// the scale of the output. That way the compositor can - /// avoid scaling the surface, and the client can supply - /// a higher detail image. + /// 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 { @@ -3470,6 +3563,11 @@ pub const Subcompositor = enum(u32) { /// /// If the parent wl_surface object is destroyed, the sub-surface is /// unmapped. +/// +/// A sub-surface never has the keyboard focus of any seat. +/// +/// The wl_surface.offset request is ignored: clients must use set_position +/// instead to move the sub-surface. pub const Subsurface = enum(u32) { _, pub const interface = Interface{ @@ -3500,9 +3598,7 @@ pub const Subsurface = enum(u32) { /// surface area. Negative values are allowed. /// /// The scheduled coordinates will take effect whenever the state of the - /// parent surface is applied. When this happens depends on whether the - /// parent surface is in synchronized mode or not. See - /// wl_subsurface.set_sync and wl_subsurface.set_desync for details. + /// parent surface is applied. /// /// If more than one set_position request is invoked by the client before /// the commit of the parent surface, the position of a new request always @@ -3522,9 +3618,7 @@ pub const Subsurface = enum(u32) { /// The z-order is double-buffered. Requests are handled in order and /// applied immediately to a pending state. The final pending state is /// copied to the active state the next time the state of the parent - /// surface is applied. When this happens depends on whether the parent - /// surface is in synchronized mode or not. See wl_subsurface.set_sync and - /// wl_subsurface.set_desync for details. + /// surface is applied. /// /// A new sub-surface is initially added as the top-most in the stack /// of its siblings and parent. diff --git a/src/generated/wp.zig b/wayland/generated/wp.zig similarity index 97% rename from src/generated/wp.zig rename to wayland/generated/wp.zig index b8ffe4f..cdb343e 100644 --- a/src/generated/wp.zig +++ b/wayland/generated/wp.zig @@ -63,8 +63,7 @@ pub const CursorShapeManagerV1 = enum(u32) { }; }; -/// This interface advertises the list of supported cursor shapes for a -/// device, and allows clients to set the cursor shape. +/// This interface allows clients to set the cursor shape. pub const CursorShapeDeviceV1 = enum(u32) { _, pub const interface = Interface{ diff --git a/src/generated/xdg.zig b/wayland/generated/xdg.zig similarity index 99% rename from src/generated/xdg.zig rename to wayland/generated/xdg.zig index 4ad66fc..bd6a5af 100644 --- a/src/generated/xdg.zig +++ b/wayland/generated/xdg.zig @@ -270,7 +270,7 @@ pub const Positioner = enum(u32) { /// /// The default adjustment is none. set_constraint_adjustment: struct { - constraint_adjustment: u32, // bit mask of constraint adjustments + constraint_adjustment: ConstraintAdjustment, // bit mask of constraint adjustments }, /// Specify the surface position offset relative to the position of the /// anchor on the anchor rectangle and the anchor on the surface. For diff --git a/src/generated/zwlr.zig b/wayland/generated/zwlr.zig similarity index 100% rename from src/generated/zwlr.zig rename to wayland/generated/zwlr.zig diff --git a/src/generated/zwp.zig b/wayland/generated/zwp.zig similarity index 100% rename from src/generated/zwp.zig rename to wayland/generated/zwp.zig diff --git a/src/lib.zig b/wayland/lib.zig similarity index 100% rename from src/lib.zig rename to wayland/lib.zig diff --git a/protocols/wlr-layer-shell-unstable-v1.xml b/wayland/protocols/wlr-layer-shell-unstable-v1.xml similarity index 100% rename from protocols/wlr-layer-shell-unstable-v1.xml rename to wayland/protocols/wlr-layer-shell-unstable-v1.xml diff --git a/src/proxy.zig b/wayland/proxy.zig similarity index 100% rename from src/proxy.zig rename to wayland/proxy.zig diff --git a/src/ring_buffer.zig b/wayland/ring_buffer.zig similarity index 100% rename from src/ring_buffer.zig rename to wayland/ring_buffer.zig diff --git a/scanner.py b/wayland/scanner.py old mode 100644 new mode 100755 similarity index 99% rename from scanner.py rename to wayland/scanner.py index e59976f..76c44c0 --- a/scanner.py +++ b/wayland/scanner.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # pyright: strict # TODO: Use ZigEtc everywhere @@ -781,13 +782,14 @@ def emit(self, fd: TextIO): const {g} = @import("{g}.zig");""" ) +script_dir = Path(__file__).parent def main(): global protocols xml_protocols = [ "/usr/share/wayland/wayland.xml", "/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml", - "./protocols/wlr-layer-shell-unstable-v1.xml", + script_dir / "./protocols/wlr-layer-shell-unstable-v1.xml", "/usr/share/wayland-protocols/unstable/tablet/tablet-unstable-v2.xml", "/usr/share/wayland-protocols/staging/cursor-shape/cursor-shape-v1.xml", "/usr/share/wayland-protocols/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml", @@ -799,7 +801,7 @@ def main(): Namespace.get(p.prefix).protocols.append(p) for ns in Namespace.instances.values(): - out = Path(__file__).parent / f"src/generated/{ns.name}.zig" + out = script_dir / f"generated/{ns.name}.zig" out.parent.mkdir(exist_ok=True) with out.open("w") as f: ns.emit(f) diff --git a/src/shm.zig b/wayland/shm.zig similarity index 100% rename from src/shm.zig rename to wayland/shm.zig