internal API to drive a graphical backend; see: doc/ref/backend.html

struct mbtk_pixmap_s { int w, h; unsigned has_alpha:1; struct { unsigned long ul; void *p, *raw; } bedata; }; struct mbtk_backend_s { const char *name; int (*be_init)(mbtk_backend_t *be); void (*be_uninit)(mbtk_backend_t *be); int (*display_init)(mbtk_backend_t *be, mbtk_display_t *disp, int *argc, char **argv[]); int (*display_uninit)(mbtk_backend_t *be, mbtk_display_t *disp); /* Wait for an event. Returns 1 if there was an event and load it in dst, return 0 if no event available waiting for at most timeout. If block is true, return only when an event is available. Timeout: - for non-blocking waits: wait at most until timeout for events and return 0 if nothing has arrived; for - for blocking waits: timeout sets how often the process wakes up to restart the blocking poll. */ int (*iterate)(mbtk_display_t *display, mbtk_event_t *dst, double timeout, int block); /* Clipboard is per display and string only. clipboard_get() returns NULL or a string that needs to be free'd using clipboard_free(). */ void (*clipboard_set)(mbtk_display_t *display, const char *new_content); char *(*clipboard_get)(mbtk_display_t *display); void (*clipboard_free)(mbtk_display_t *display, char *str_got); /* Return time elapsed from display init, in seconds. Resolution is backend dependent but is at least millisec. */ double (*get_time_el)(mbtk_display_t *display); /* Create a new window of type. If disp is NULL use the default display. If x or y is negative, window top-left corner is not hinted. If w or h is negagive, window width and height are not hinted. */ mbtk_window_t *(*window_new)(mbtk_display_t *disp, mbtk_window_type_t type, const char *title, long x, long y, long w, long h); mbtk_window_t *(*subwindow_new)(mbtk_display_t *disp, mbtk_widget_t *parent, long x, long y, long w, long h); /* Called to (un)assign a subwindow from/to its parent */ void (*subwindow_assign)(mbtk_window_t *subwin, mbtk_window_t *direct_parent); void (*subwindow_unassign)(mbtk_window_t *subwin); /* Inform the backend upon change in subwindow geometry (when host widget changes geometry; coords are host widget's coords, relative to direct parent window */ void (*subwindow_geometry)(mbtk_window_t *subwin, long x, long y, long w, long h); /* Immediately close a window */ void (*window_close)(mbtk_window_t *win); /* Return the render win for a window; in some backends (e.g. glfw, sdl2) only the topmost (WM-visible) window is a render win, subwindows need to use that for rendering; in other backends (e.g. xlib) each subwindow can render of its own. This call is made with the given (sub)window and the backend can decide to return it as-is or return any of its "parent" windows using the render_win of ->gt;in_widget. */ mbtk_window_t *(*win2render_win)(mbtk_window_t *win); /* Change the title of an existing window */ void (*window_set_title)(mbtk_window_t *win, const char *title); /* Set minimum or actual size; actual size has to be greater or equal to minimum size. */ void (*window_set_min_size)(mbtk_window_t *win, long w, long h); void (*window_set_size)(mbtk_window_t *win, long w, long h); /* Returns 0 on success and fills in window size in w and h */ int (*window_get_size)(mbtk_window_t *win, long *w, long *h); /* Move window on top, change whether the window is hidden or shown */ void (*window_raise)(mbtk_window_t *win); void (*window_hide)(mbtk_window_t *win); void (*window_show)(mbtk_window_t *win); /* win is transient for tr_for; this matters in modality and stacking, depending on the WM; may be a no-op. */ void (*window_transient4)(mbtk_window_t *win, mbtk_window_t *tr_for); /* Going to change the topwin of display to win. Topwin is managed by the central code, this function needs to be implemented only if the backend has side effects for changing topwin. */ void (*set_topwin)(mbtk_display_t *disp, mbtk_window_t *win); /* Resolve a font into a font id from backend-specific arguments. New fonts may be loaded, allocations may be made. Fonts are free'd only when display is discarded. On failyre it returns a font id with .l == -1 */ mbtk_font_id_t (*resolve_font)(mbtk_display_t *display, int argc, char *argv[]); /* Low level draw functions */ void (*draw_start)(mbtk_window_t *win); /* call before redraw of a window */ int (*draw_color)(mbtk_window_t *win, int r, int g, int b, int a); /* returns 0 on success */ void (*draw_fillrect)(mbtk_window_t *win, int x1, int y1, int x2, int y2); void (*draw_line)(mbtk_window_t *win, int x1, int y1, int x2, int y2); void (*draw_hline)(mbtk_window_t *win, int x1, int y1, int x2); void (*draw_vline)(mbtk_window_t *win, int x1, int y1, int y2); void (*draw_flush)(mbtk_window_t *win); /* call at the end of the redraw */ int (*draw_set_font)(mbtk_window_t *win, mbtk_font_id_t fontid); /* returns 0 on success */ void (*draw_query_text)(mbtk_window_t *win, int *w, int *ascent, int *descent, char *s, int slen); long (*draw_query_text_pos)(mbtk_window_t *win, long *char_start_px, long *char_end_px, long pxpos, long delta_chr, char *s, int slen); /* returns character index or -1; fills in char_*_px; pxpos is relative to the text; delta_chr (+n or -1) modifies the lookup jumping to the next/previous character */ void (*draw_text)(mbtk_window_t *win, int x, int y, char *s, int slen, void **cache); void (*draw_free_text)(mbtk_window_t *win, void **cache); int (*draw_import_pixmap)(mbtk_display_t *display, mbtk_pixmap_t *dst, unsigned char *pixels, int width, int height, int has_alpha); void (*draw_free_pixmap)(mbtk_display_t *display, mbtk_pixmap_t *px); mbtk_px_id_t (*draw_bind_pixmap)(mbtk_window_t *win, mbtk_pixmap_t *px); void (*draw_unbind_pixmap)(mbtk_window_t *win, mbtk_px_id_t pxid); void (*draw_pixmap)(mbtk_window_t *win, int x, int y, mbtk_px_id_t pxid); /* mouse cursor */ mbtk_mocu_t *(*mocu_create_named)(mbtk_display_t *disp, mbtk_mocu_named_t name); mbtk_mocu_t *(*mocu_create_pixmap)(mbtk_display_t *disp, int width, int height, unsigned const char *px, unsigned const char *mask, int hot_x, int hot_y); void (*mocu_free_cursor)(mbtk_display_t *disp, mbtk_mocu_t *curs); void (*mocu_set_cursor)(mbtk_display_t *disp, mbtk_mocu_t *curs); /* query keyboard modifiers */ mbtk_keymod_t (*query_kbd_mods)(mbtk_display_t *disp); /* non-gui event related functions */ void (*watch_stdin_read)(mbtk_display_t *disp, int enable); void (*watch_fd)(mbtk_display_t *disp, int fd, int for_read, int for_write); /* read-only config */ unsigned has_alpha:1; /* if 0, backend will ignore alpha channel */

/*** administrative ***/

gdl_elem_t link; /* store active backends in a linked list so mbtk_uninit() can free them */ gdl_list_t displays; /* all displays open using this backend - uninit on the backend would remove these displays as well */

/*** private ***/

void *be_data; /* allocated at init, free'd at uninit */ }; /* Backands shall use this macro to ensure display and window backend_data are large enough to host their private structs */ #define mbtk_be_check_priv_sizes(disp_ty, win_ty) \ do { \ mbtk_display_t *d; \ mbtk_window_t *w; \ if (sizeof(disp_ty) >gt; sizeof(d->gt;backend_data)) { \ mbtk_error("Failed to initialize display: " #disp_ty " does not fit in mbtk_display_t backend_data: %ld >gt; %ld\n", (long)sizeof(disp_ty), (long)sizeof(d->gt;backend_data)); \ return -1; \ } \ if (sizeof(win_ty) >gt; sizeof(w->gt;backend_data)) { \ mbtk_error("Failed to initialize display: " #win_ty " does not fit in mbtk_window_t backend_data: %ld >gt; %ld\n", (long)sizeof(win_ty), (long)sizeof(w->gt;backend_data)); \ return -1; \ } \ } while(0)