summaryrefslogtreecommitdiff
path: root/src/wayland/internal.h
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-11 21:53:42 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-11 21:53:42 +0300
commit927ae621c9a3d46dbc401b8e9ea7bbed1bf2e97b (patch)
treeaeb00c16770dcf5a36d28c1167cc39c6759059fb /src/wayland/internal.h
initial: Yet Another Surface Library (YASL) 0.1.0
A minimal, modern desktop window surface library in C. Supports Wayland on Linux and Cocoa/Metal on macOS with presentation timing, fractional scaling, IME, and CSD.
Diffstat (limited to 'src/wayland/internal.h')
-rw-r--r--src/wayland/internal.h418
1 files changed, 418 insertions, 0 deletions
diff --git a/src/wayland/internal.h b/src/wayland/internal.h
new file mode 100644
index 0000000..dc85943
--- /dev/null
+++ b/src/wayland/internal.h
@@ -0,0 +1,418 @@
+#ifndef YASL_WAYLAND_INTERNAL_H
+#define YASL_WAYLAND_INTERNAL_H
+
+#define _GNU_SOURCE
+
+#include "yasl/yasl.h"
+#include "yasl/timing.h"
+#include "clipboard.h"
+
+#include <wayland-client.h>
+#include <wayland-cursor.h>
+#include "protocols/xdg-shell-client-protocol.h"
+#include "protocols/xdg-decoration-client-protocol.h"
+#include "protocols/cursor-shape-v1-client-protocol.h"
+#include "protocols/fractional-scale-v1-client-protocol.h"
+#include "protocols/viewporter-client-protocol.h"
+#include "protocols/tablet-v2-client-protocol.h"
+#include "protocols/text-input-unstable-v3-client-protocol.h"
+#include "protocols/tearing-control-v1-client-protocol.h"
+#include "protocols/presentation-time-client-protocol.h"
+#include "protocols/fifo-v1-client-protocol.h"
+#include "protocols/commit-timing-v1-client-protocol.h"
+#include "protocols/xdg-toplevel-drag-v1-client-protocol.h"
+#include "protocols/primary-selection-unstable-v1-client-protocol.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <time.h>
+#include <linux/input-event-codes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/timerfd.h>
+#include <unistd.h>
+#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
+
+#define NBUF 3
+
+struct yasl_surface;
+struct tablet_tool;
+struct tablet_device;
+struct tablet_pad;
+
+struct buffer {
+ struct yasl_surface *owner;
+ struct wl_shm_pool *pool;
+ struct wl_buffer *proxy;
+ uint32_t *pixels;
+ size_t capacity;
+ int width, height;
+ bool busy;
+ bool presented;
+};
+
+struct wl_conn_output {
+ struct yasl_display *conn;
+ struct wl_output *proxy;
+ struct wl_conn_output *next;
+ uint64_t mask;
+ uint32_t name;
+ int32_t scale, pending_scale;
+ uint32_t refresh_ns, pending_refresh_ns;
+};
+
+struct pending_press {
+ struct yasl_surface *surface;
+ struct yasl_vector2i pos;
+ int button;
+ bool release;
+};
+
+struct press_queue {
+ struct pending_press ev[8];
+ int n;
+};
+
+struct drag_icon {
+ struct wl_surface *surface;
+ struct wl_buffer *buffer;
+ struct wl_shm_pool *pool;
+ struct wp_viewport *viewport;
+ void *mapping;
+ size_t size;
+ int fd;
+};
+
+struct conn_drag {
+ struct wl_data_source *source;
+ struct xdg_toplevel_drag_v1 *toplevel;
+ struct drag_icon icon;
+ const struct yasl_drag_listener *listener;
+ void *ud;
+ uint32_t scale_120;
+ struct seat *seat;
+ bool dropped;
+ bool carrying;
+};
+
+#define SEAT_TOUCH_POINTS 10
+
+struct touch_point {
+ struct yasl_surface *surface;
+ int32_t id;
+ double x, y;
+ bool active;
+ bool down, moved, up;
+};
+
+struct seat {
+ struct yasl_display *conn;
+ struct seat *next;
+ struct wl_seat *proxy;
+ uint32_t name;
+ struct wl_keyboard *keyboard;
+ struct wl_pointer *pointer;
+ struct wl_touch *touch;
+ struct wp_cursor_shape_device_v1 *cursor_shape_dev;
+ struct wl_surface *cursor_surface;
+ struct wp_viewport *cursor_viewport;
+ struct zwp_tablet_seat_v2 *tablet_seat;
+ struct tablet_tool *tablet_tools;
+ struct tablet_device *tablet_devices;
+ struct tablet_pad *tablet_pads;
+ struct zwp_text_input_v3 *text_input;
+ struct clipboard *clipboard;
+
+ struct xkb_keymap *xkb_keymap;
+ struct xkb_state *xkb_state;
+ xkb_mod_mask_t input_mod_masks[8];
+ xkb_mod_index_t mod_shift, mod_alt, mod_ctrl, mod_super;
+ bool input_mods_ready;
+ uint64_t repeat_started_ns;
+ int repeat_fd, repeat_watch;
+ int32_t repeat_rate, repeat_delay;
+ uint32_t repeat_key;
+ bool repeat_held;
+
+ struct yasl_surface *pointer_focus;
+ struct yasl_surface *keyboard_focus;
+ struct yasl_surface *tablet_focus;
+ struct yasl_surface *ime_focus;
+ struct yasl_surface *focus_leaving;
+ uint32_t input_serial;
+ uint32_t press_serial;
+ struct yasl_surface *press_surface;
+
+ uint32_t pointer_serial;
+ int cursor_shape;
+ struct yasl_vector2i pointer_pos;
+ uint64_t pointer_buttons;
+ double axis_v, axis_h, frame_v;
+ int frame_v120;
+ int axis_discrete_v, axis_discrete_h;
+ int axis_value120_v, axis_value120_h;
+ bool axis_has_v120_v, axis_has_v120_h;
+ bool axis_smooth;
+ bool motion_pending;
+ struct press_queue ptr_presses;
+ struct yasl_surface *ptr_left;
+ struct yasl_vector2i ptr_left_pos;
+ bool ptr_left_motion;
+
+ struct tablet_tool *tool;
+ struct press_queue tool_presses;
+ struct yasl_vector2i tool_pos;
+ uint64_t tool_buttons;
+ struct yasl_pointer_pen pen;
+ int tool_wheel;
+ bool tool_motion;
+
+ struct touch_point touch_points[SEAT_TOUCH_POINTS];
+ struct touch_point *touch_primary;
+ bool touch_pressed;
+ bool touch_scrolling;
+ double touch_scroll_y, touch_scroll_rest;
+};
+
+#define YASL_QUEUE_CAP 256
+struct input_queue {
+ struct yasl_input_event events[YASL_QUEUE_CAP];
+ int head;
+ int tail;
+ int count;
+};
+
+static inline void input_queue_push(struct input_queue *q, const struct yasl_input_event *ev)
+{
+ if (q->count >= YASL_QUEUE_CAP) return;
+ q->events[q->tail] = *ev;
+ q->tail = (q->tail + 1) % YASL_QUEUE_CAP;
+ q->count++;
+}
+
+static inline bool input_queue_pop(struct input_queue *q, struct yasl_input_event *ev)
+{
+ if (q->count <= 0) return false;
+ *ev = q->events[q->head];
+ q->head = (q->head + 1) % YASL_QUEUE_CAP;
+ q->count--;
+ return true;
+}
+
+static inline void input_queue_clear(struct input_queue *q)
+{
+ q->head = q->tail = q->count = 0;
+}
+
+struct yasl_display {
+ struct wl_display *wl;
+ struct wl_registry *registry;
+ struct wl_compositor *compositor;
+ struct wl_shm *shm;
+ struct wl_conn_output *outputs;
+ uint64_t output_masks;
+ struct xdg_wm_base *wm_base;
+ struct zxdg_decoration_manager_v1 *decor_mgr;
+ struct wp_fractional_scale_manager_v1 *scale_mgr;
+ struct wp_viewporter *viewporter;
+ struct seat *seats;
+ struct seat *active_seat;
+ struct wl_data_device_manager *data_manager;
+ struct zwp_primary_selection_device_manager_v1 *primary_selection_mgr;
+ struct wp_cursor_shape_manager_v1 *cursor_shape_mgr;
+ struct wl_cursor_theme *cursor_theme;
+ const char *cursor_theme_name;
+ int cursor_size, cursor_theme_scale;
+ struct zwp_tablet_manager_v2 *tablet_mgr;
+ struct zwp_text_input_manager_v3 *text_input_mgr;
+ struct wp_tearing_control_manager_v1 *tearing_mgr;
+ struct wp_presentation *presentation;
+ struct wp_fifo_manager_v1 *fifo_mgr;
+ struct wp_commit_timing_manager_v1 *commit_timing_mgr;
+ struct xkb_context *xkb_ctx;
+ struct yasl_loop *loop;
+ const struct yasl_display_cbs *cbs;
+ void *ud;
+ char *app_id;
+ clockid_t pres_clock;
+ bool pres_clock_known;
+ struct xdg_toplevel_drag_manager_v1 *toplevel_drag_mgr;
+ struct conn_drag drag;
+ struct yasl_surface *surfaces;
+ struct yasl_surface *paste_target;
+ int watch;
+ int depth;
+ struct yasl_surface *dead;
+ bool reading;
+ bool lost;
+};
+
+struct yasl_surface {
+ struct yasl_display *conn;
+ struct yasl_surface *conn_next;
+ struct yasl_surface *dead_next;
+ struct yasl_surface *parent;
+ struct wl_surface *surface;
+ struct xdg_surface *xdg_surface;
+ struct xdg_toplevel *toplevel;
+ struct xdg_popup *popup;
+ struct zxdg_toplevel_decoration_v1 *toplevel_decor;
+ bool server_decorated;
+ struct wp_fractional_scale_v1 *frac_scale;
+ struct wp_viewport *viewport;
+
+ char *ime_preedit;
+ char *ime_commit;
+ char *ime_shown;
+ int ime_cursor_begin, ime_cursor_end;
+ int ime_shown_begin, ime_shown_end;
+ struct yasl_rect2i ime_caret;
+ struct seat *ime_seat;
+ struct wp_tearing_control_v1 *tearing_control;
+ struct latency_feedback *latency_feedbacks;
+ struct wp_fifo_v1 *fifo;
+ struct wp_commit_timer_v1 *commit_timer;
+ struct wl_callback *frame_cb;
+ const struct yasl_surface_cbs *cbs;
+ void *ud;
+ uint64_t frames_skipped;
+
+ struct yasl_frame_clock clock;
+ struct input_queue input;
+
+ struct buffer buffers[NBUF];
+ struct yasl_frame frame;
+ struct yasl_damage_list damage;
+ bool frame_active;
+ bool frame_presented;
+
+ int floating_width, floating_height;
+ struct yasl_rect2i content;
+ int cur;
+ int width, height;
+ int logical_width, logical_height;
+ int req_width, req_height;
+ int bound_width, bound_height;
+ uint32_t scale_120;
+ uint32_t pending_scale_120;
+ uint32_t pending_serial;
+ double scale_factor;
+ uint64_t outputs;
+
+ bool tiled;
+ bool size_pending;
+ bool sample_refresh;
+ bool has_pending_serial;
+ bool configured;
+ bool closed;
+ bool destroyed;
+ bool opaque;
+ bool fullscreen;
+ bool maximized;
+ bool activated;
+ bool suspended;
+ bool want_draw;
+};
+
+char *yasl_utf8_sanitize_dup(const char *str);
+bool yasl_utf8_validate(const char *str, size_t len);
+
+int device_px(int logical, uint32_t scale_120);
+bool buffer_size(int width, int height, size_t *bytes);
+int buffer_reserve(struct yasl_surface *w, struct buffer *b, size_t needed);
+void buffer_destroy(struct buffer *b);
+int buffer_pick_free_index(const struct buffer *bufs, int cur);
+int buffer_prepare(struct yasl_surface *w, struct buffer *b, int width, int height,
+ const struct wl_buffer_listener *listener);
+int apply_pending_geometry(struct yasl_surface *w);
+int logical_px_ceil(int device, uint32_t scale_120);
+
+static inline void wl_damage_list(struct wl_surface *s, const struct yasl_damage_list *d)
+{
+ if (d->n < 0) {
+ wl_surface_damage_buffer(s, d->bounds.x, d->bounds.y,
+ d->bounds.width, d->bounds.height);
+ return;
+ }
+ for (int i = 0; i < d->n; i++)
+ wl_surface_damage_buffer(s, d->rects[i].x, d->rects[i].y,
+ d->rects[i].width, d->rects[i].height);
+}
+
+void surface_update_opaque_region(struct yasl_surface *w);
+int surface_init_scaling(struct yasl_surface *w);
+
+static inline bool surface_gets_preferred_scale(struct wl_surface *s)
+{
+ return wl_proxy_get_version((struct wl_proxy *)s) >=
+ WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION;
+}
+
+uint64_t conn_output_mask(const struct yasl_display *c, const struct wl_output *proxy);
+uint32_t conn_output_scale_120(const struct yasl_display *c, uint64_t outputs);
+void conn_destroy_outputs(struct yasl_display *c);
+void surface_follow_outputs(struct yasl_surface *w);
+uint64_t conn_pres_to_mono(const struct yasl_display *c, uint64_t ns);
+uint64_t conn_mono_to_pres(const struct yasl_display *c, uint64_t ns);
+void surface_draw_frame(struct yasl_surface *w);
+void surface_fail(struct yasl_surface *w);
+void display_enter(struct yasl_display *c);
+void display_leave(struct yasl_display *c);
+
+struct yasl_surface *conn_surface_for(struct yasl_display *c, struct wl_surface *s);
+
+static inline struct yasl_surface *surface_root(struct yasl_surface *w)
+{
+ while (w && w->parent)
+ w = w->parent;
+ return w;
+}
+
+void conn_drag_end(struct yasl_display *c);
+void conn_drop_target(struct yasl_display *c, enum yasl_drop_event ev,
+ struct wl_surface *on, double x, double y);
+void conn_drag_target(struct yasl_display *c, enum yasl_drag_event ev,
+ struct wl_surface *on, double x, double y);
+
+void seat_bind(struct yasl_display *c, struct wl_registry *registry,
+ uint32_t name, uint32_t version);
+bool seat_remove(struct yasl_display *c, uint32_t name);
+void seat_destroy(struct seat *s);
+struct seat *conn_active_seat(const struct yasl_display *c);
+void seat_note_input(struct seat *s, uint32_t serial);
+void seat_forget_surface(struct seat *s, struct yasl_surface *w);
+void seat_clipboard_ensure(struct seat *s);
+int display_input_init(struct yasl_display *c);
+extern const struct wl_seat_listener seat_listener;
+
+void keyboard_repeat_stop(struct seat *s);
+void keyboard_repeat_sync(struct seat *s);
+int keyboard_repeat_init(struct seat *s);
+void keyboard_settle_focus(struct yasl_display *c);
+bool conn_keyboard_on(const struct yasl_display *c, const struct yasl_surface *w,
+ const struct seat *except);
+extern const struct wl_keyboard_listener keyboard_listener;
+int seat_modifiers(const struct seat *s);
+
+void surface_init_cursor(struct yasl_display *c);
+void seat_destroy_tablet(struct seat *s);
+void seat_pointer_reset(struct seat *s);
+
+extern const struct zwp_text_input_v3_listener text_input_listener;
+void ime_reset(struct yasl_surface *w);
+void ime_send_caret(struct yasl_surface *w);
+
+int surface_init_shell(struct yasl_surface *w, const char *title);
+extern const struct xdg_surface_listener shell_surface_listener;
+extern const struct wl_registry_listener registry_listener;
+
+void surface_feedback_destroy(struct yasl_surface *w);
+void surface_request_presentation_feedback(struct yasl_surface *w);
+
+#endif