/* A window or a subwindow */
struct mbtk_window_s {
union { void *ptr[32]; long int i[32]; } backend_data; /* opaque backend data */
mbtk_display_t *display;
mbtk_widget_t *in_widget; /* if not a native window but an embedded window (subwindow) */
hvbox_t *root;
long x, y; /* native window: last known screen coords; embedded window: coords relative to the parent widget's window (calculated) */
long w, h; /* actual width and height in pixels */
long min_w_user, min_h_user; /* the user doesn't want the window smaller */
long min_w_layout, min_h_layout; /* the widget layout doesn't let the window smaller */
long min_w_last, min_h_last; /* last minimum window size actually set (larger of _user and _layout) */
long content_x0, content_y0; /* subwindow: when scrolled, this is the top-left corner pixel coordinate of the content that should be drawn from the subwindow 0;0 corner */
unsigned focus_has_pointer:1; /* whether the mouse pointer is within the focused widget */
unsigned scrolled:1; /* when set, the root widget can be as large as it wants to be and the window is going to show only a portion of it */
unsigned draw_dirty:1;
unsigned layout_dirty:1;
unsigned entered:1; /* if mouse pointer has entered the window */
void *user_data; /* application may use this to attach data to the window */
struct { /* last known mouse cursor pos (see also: entered) */
long last_x, last_y;
} mouse;
gdl_elem_t link; /* in display->gt;windows */
/* widget states arouns events */
mbtk_widget_t *focus;
mbtk_widget_t *origin; /* drag&drop origin widget; set by the handler, cleared by central event code on release */
long origin_x, origin_y; /* drag&drop origin coords in window coordinate system; set and cleared by central event code on release */
/* lists of resources */
htpxid_t binds; /* pixmap bindings key: (mbtk_pixmap_t *); value: mbtk_px_id_t */
gdl_list_t handlers; /* handlers with extra allocation are registered into a window for destroying handlers when window is destroyed */
vtp0_t watch_close; /* (int *) that are increased if mbtk_window_close() is called on this window */
/* Optional: in case of a subwindow if this call is not NULL, these are called
in low level rendering when the rendering context is already set up.
Argument native_ctx is the backend-specific rendering context to be used.
This call is useful for backend-native rendering code on canvas, e.g.
the canvas_native widget. Pre is called before normal miniboxtk rendering,
post is called after. These functions should not set viewport or flush,
those are done by the backend code. */
int (*native_draw_pre)(mbtk_window_t *subwin, void *native_ctx); /* if returns non-zero, skip normal draw */
void (*native_draw_post)(mbtk_window_t *subwin, void *native_ctx);
};
typedef enum mbtk_window_type_e {
/* base type */
MBTK_WNTY_NORMAL = 0x0001, /* top window, dialog; non-modal */
MBTK_WNTY_MODAL = 0x0002, /* top window, dialog; modal (input grab) */
MBTK_WNTY_DROPDOWN_MENU = 0x0003, /* window of a menu open from the main menu system */
MBTK_WNTY_POPUP_MENU = 0x0004, /* window of a popup-menu */
MBTK_WNTY_TEAROFF_MENU = 0x0005, /* window of a torn-off menu (floating dialog) */
MBTK_WNTY_COMBO = 0x0006, /* combo box menu/selections */
MBTK_WNTY_TOOLTIP = 0x0007, /* tooltip popup only */
/* bitfield */
MBTK_WNTY_OPENGL = 0x0100,
MBTK_WNTY_VULKAN = 0x0200
} mbtk_window_type_t;
/* Open a new window */
mbtk_window_t *mbtk_window_new(mbtk_display_t *disp, mbtk_window_type_t type, const char *title, long x, long y, long w, long h);
/* Create a new subwindow within a widget (within an existing window or subwindow) */
mbtk_window_t *mbtk_subwindow_new(mbtk_display_t *disp, mbtk_widget_t *parent, long x, long y, long w, long h);
/* Change the title of an existing window */
void mbtk_window_set_title(mbtk_window_t *win, const char *title);
/* Move window on top of the windowing stack */
void mbtk_window_raise(mbtk_window_t *win);
/* Change whether the window is hidden or shown */
void mbtk_window_hide(mbtk_window_t *win);
void mbtk_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 mbtk_window_transient4(mbtk_window_t *win, mbtk_window_t *tr_for);
/* Fill in x and y with the last known mouse coordinates. Returns 1 or 0
if mouse cursor is within the window or not. */
int mbtk_window_get_last_mouse_coords(mbtk_window_t *win, long *x, long *y);
/* Immediately close a window (does not generate win close event) */
void mbtk_window_close(mbtk_window_t *win);
/* Set minimum or actual size; actual size has to be greater or equal to
minimum size. */
void mbtk_window_set_min_size(mbtk_window_t *win, long w, long h);
void mbtk_window_set_size(mbtk_window_t *win, long w, long h);
/* Set window's root widget's "win_close" callback; it is called when the
window is requested to be closed by the user through the window manager.
If it returns MBTK_EVENT_HANDLED, processing stops and the window is not
closed. */
void mbtk_window_callback_close(mbtk_window_t *win, mbtk_event_handled_t (*cb)(mbtk_widget_t *w, mbtk_kw_t id, void *user_data), void *user_data);
/* Return the root widget that was added by the caller (first child of the
built-in hvbox root) */
MBTK_INLINE mbtk_widget_t *mbtk_window_get_root(mbtk_window_t *win) { return ((win == NULL) || (win->gt;root == NULL)) ? NULL : (mbtk_widget_t *)(win->gt;root->gt;ch_first); }
MBTK_INLINE void mbtk_window_get_pos(mbtk_window_t *win, long *x, long *y) { *x = win->gt;x; *y = win->gt;y; }
MBTK_INLINE void mbtk_window_get_size(mbtk_window_t *win, long *w, long *h) { *w = win->gt;w; *h = win->gt;h; }
#define mbtk_win_dirty_layout(win) \
do { \
(win)->gt;layout_dirty = 1; \
if ((win)->gt;display != NULL) \
(win)->gt;display->gt;need_win_redraw = 1; \
} while(0)
#define mbtk_win_dirty_draw(win) \
do { \
(win)->gt;draw_dirty = 1; \
(win)->gt;display->gt;need_win_redraw = 1; \
} while(0)
/* Recalculate the layout of a window if needed (or if forced). Useful when
widget content changed and new dimensions need to be known immediately, e.g.
for setting scroll offsets. */
void mbtk_win_update_layout(mbtk_window_t *win, mbtk_bool_t force);