summaryrefslogtreecommitdiff
path: root/src/common/backend.h
blob: 876a4ca93e9871164e5d58e0075d0fdcd7c2d131 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#ifndef YASL_BACKEND_H
#define YASL_BACKEND_H

#include "yasl/yasl.h"
#include "yasl/loop.h"
#include "yasl/native.h"
#include "common/input.h"
#include "common/timing.h"

#include <string.h>

struct yasl_backend_ops;
struct yasl_event_state;

struct yasl_display {
    const struct yasl_backend_ops *ops;
    void *native_handle;
    struct yasl_display_cbs callbacks;
    struct yasl_loop *loop;
    void *app_runner;
    /* Backend's copy of yasl_display_spec.app_id, or NULL; for desktop services. */
    const char *app_id;
    void *callback_ud;
    struct yasl_event_state *events;
    struct yasl_surface *surfaces;
};

struct yasl_surface {
    struct yasl_display *display;
    void *native_handle;
    struct yasl_vector2i size;
    uint32_t scale_120;
    uint32_t state; /* Authoritative YASL_STATE_* bitmask, maintained by the backend. */
    uint32_t bg_color;
    struct yasl_window_cbs callbacks;
    void *ud;
    uint64_t frame_generation;
    struct input_queue input;
    enum yasl_pointer_mode pointer_mode;
    struct yasl_frame_clock clock;
    uint64_t frames_skipped;
    yasl_timer_id *timers;
    int timer_count;
    int timer_capacity;
    void *app_surface;
    struct yasl_surface *event_next;
    uint64_t id;
    void *userdata;
    bool popup;
    bool drawing;
    bool frame_presented;
    uint32_t reported_scale;
    uint64_t draw_index;
    struct yasl_frame *active_frame;
    yasl_pacing_mode pacing;
    yasl_timer_id pacing_timer;
};

bool yasl_events_open(struct yasl_display *d);
void yasl_events_close(struct yasl_display *d);
int yasl_events_error(struct yasl_display *d);
bool yasl_events_pending(struct yasl_display *d);
struct yasl_surface *yasl_events_find(struct yasl_display *d, uint64_t id);
bool yasl_events_register(struct yasl_surface *s);
void yasl_events_unregister(struct yasl_surface *s);
bool yasl_events_push(struct yasl_display *d, struct yasl_surface *queue_owner,
                      const struct yasl_event *event);
bool yasl_events_poll_surface(struct yasl_surface *s, struct yasl_event *event);
void yasl_surface_notify_configure(struct yasl_surface *s, struct yasl_geometry geometry);
void yasl_surface_notify_close(struct yasl_surface *s);
void yasl_surface_notify_state(struct yasl_surface *s, uint32_t state);
void yasl_surface_notify_drag(struct yasl_surface *s, enum yasl_drag_event ev, struct yasl_vector2i pos);
void yasl_surface_notify_drop(struct yasl_surface *s, enum yasl_drop_event ev, struct yasl_vector2i pos);
void yasl_surface_notify_composition(struct yasl_surface *s, const char *text, int begin, int end);
void yasl_surface_draw(struct yasl_surface *s, struct yasl_frame *frame);
void yasl_display_notify_event(struct yasl_display *d, enum yasl_event_type type);
void yasl_surface_complete_paste(struct yasl_surface *s, uint64_t request_id,
        enum yasl_transfer_status status, const char *text, size_t len);
uint64_t yasl_events_request_id(struct yasl_display *d);

void yasl_surface_clear_timers(struct yasl_surface *s);
struct yasl_surface *yasl_create_toplevel(struct yasl_display *d,
        const struct yasl_window_spec *spec, void *graphics_device);

/* Report a presented CPU frame's extent, and copy it when out can hold it. */
static inline bool yasl_copy_frame(const uint32_t *pixels, struct yasl_vector2i extent,
        uint32_t *out, size_t cap, struct yasl_vector2i *size)
{
    *size = extent;
    size_t count = (size_t)extent.x * (size_t)extent.y;
    if (!count || count > cap) return false;
    memcpy(out, pixels, count * sizeof(*pixels));
    return true;
}

static inline uint64_t yasl_frame_begin(struct yasl_surface *s)
{
    if (++s->frame_generation == 0) ++s->frame_generation;
    return s->frame_generation;
}

struct yasl_backend_ops {
    enum yasl_backend type;
    struct yasl_display *(*display_open)(struct yasl_loop *loop, const struct yasl_display_spec *spec);
    void (*display_close)(struct yasl_display *d);
    uint32_t (*display_caps)(const struct yasl_display *d);
    int (*display_dispatch_timeout)(struct yasl_display *d, int timeout_ms);
    void (*display_flush)(struct yasl_display *d);
    int (*display_modifiers)(const struct yasl_display *d);
    /* Optional; returns zero or less when the system reports no interval. */
    int (*display_double_click_ms)(const struct yasl_display *d);
    void (*display_copy)(struct yasl_display *d, enum yasl_selection sel, const char *text);
    void (*display_paste)(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *target);
    bool (*display_copy_text)(struct yasl_display *d, enum yasl_selection sel, const char *text);
    bool (*display_request_paste)(struct yasl_display *d, enum yasl_selection sel,
                                  struct yasl_surface *target, uint64_t request_id);
    bool (*display_drag_start)(struct yasl_display *d, struct yasl_surface *origin, const struct yasl_drag_image *image, const struct yasl_drag_listener *l, void *ud);
    void (*display_drag_cancel)(struct yasl_display *d);
    /* Create with callbacks disabled; common code installs them after return. */
    struct yasl_surface *(*surface_create_toplevel)(struct yasl_display *d,
            const struct yasl_window_spec *spec, void *graphics_device);
    struct yasl_surface *(*surface_create_popup)(struct yasl_surface *parent, const struct yasl_popup_spec *spec);
    bool (*surface_popup_reposition)(struct yasl_surface *popup, const struct yasl_popup_spec *spec);
    void (*surface_destroy)(struct yasl_surface *s);
    struct input_queue *(*surface_input_queue)(struct yasl_surface *s);
    bool (*surface_set_size)(struct yasl_surface *s, struct yasl_vector2i size_logical);
    bool (*surface_set_fullscreen)(struct yasl_surface *s, bool enabled);
    bool (*surface_set_maximized)(struct yasl_surface *s, bool enabled);
    bool (*surface_minimize)(struct yasl_surface *s);
    struct yasl_display *(*surface_display)(const struct yasl_surface *s);
    /* Copy only; must not invoke application callbacks. */
    void (*surface_set_callbacks)(struct yasl_surface *s, const struct yasl_window_cbs *cbs, void *ud);
    void (*surface_set_title)(struct yasl_surface *s, const char *title);
    void (*surface_schedule_redraw)(struct yasl_surface *s);
    bool (*surface_present)(struct yasl_surface *s, const struct yasl_framebuffer *fb, const struct yasl_damage_list *damage);
    /* Optional; NULL means the common input queue is drained. */
    bool (*surface_poll_event)(struct yasl_surface *s, struct yasl_event *ev);
    /* Optional; NULL means only YASL_POINTER_NORMAL is supported. Backends that
     * implement RELATIVE push POINTER_MOTION with delta set and pos frozen. */
    bool (*surface_set_pointer_mode)(struct yasl_surface *s, enum yasl_pointer_mode mode);
    struct yasl_geometry (*surface_geometry)(const struct yasl_surface *s);
    struct yasl_timing (*surface_timing)(const struct yasl_surface *s);
    uint64_t (*surface_frame_time_ns)(struct yasl_surface *s, uint64_t now);
    void (*surface_set_cursor)(struct yasl_surface *s, enum yasl_cursor cursor);
    void (*surface_set_background_color)(struct yasl_surface *s, uint32_t bg);
    const char *(*surface_ime_preedit)(const struct yasl_surface *s);
    bool (*surface_ime_preedit_cursor)(const struct yasl_surface *s, int *begin, int *end);
    void (*surface_set_ime_caret)(struct yasl_surface *s, struct yasl_rect2i caret);
    bool (*surface_start_interactive_move)(struct yasl_surface *s);
    bool (*surface_start_interactive_resize)(struct yasl_surface *s, enum yasl_resize_edge edge);
    bool (*surface_show_window_menu)(struct yasl_surface *s, struct yasl_vector2i pos);
    bool (*surface_drag_carry)(struct yasl_surface *s, struct yasl_vector2i offset);
    bool (*surface_place_under_pointer)(struct yasl_surface *s, struct yasl_vector2i at);
    /* Optional; NULL means the bell is unsupported. */
    bool (*surface_bell)(struct yasl_surface *s);
    /* Optional; NULL means no readback. Fills size only for an available frame. */
    bool (*surface_read_pixels)(struct yasl_surface *s, uint32_t *out, size_t cap,
            struct yasl_vector2i *size);
    void *(*display_get_native_handle)(struct yasl_display *d);
    void *(*surface_get_native_handle)(struct yasl_surface *s);
    bool (*surface_get_native_frame)(struct yasl_surface *s,
            const struct yasl_framebuffer *target, struct yasl_native_frame *out);
};

#if YASL_HAS_WAYLAND
extern const struct yasl_backend_ops yasl_wayland_backend;
#endif
#if YASL_HAS_X11
extern const struct yasl_backend_ops yasl_x11_backend;
#endif
#if YASL_HAS_COCOA
extern const struct yasl_backend_ops yasl_cocoa_backend;
#endif

#endif