#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 #include #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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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