ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/ltk.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
Log | Files | Refs | README | LICENSE

widget.h (17298B)


      1 /*
      2  * Copyright (c) 2021-2024 lumidify <nobody@lumidify.org>
      3  *
      4  * Permission to use, copy, modify, and/or distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 /* need to check what happens when registering signal for destroy, but then calling ltk_destroy_widget from
     18 that handler - maybe loop if container widget deletes children but they call parent->delete_child again */
     19 #ifndef LTK_WIDGET_H
     20 #define LTK_WIDGET_H
     21 
     22 /* FIXME: destroy signal for widgets (also window) */
     23 
     24 #include <stddef.h>
     25 #include "array.h"
     26 #include "event.h"
     27 #include "graphics.h"
     28 #include "rect.h"
     29 #include "util.h"
     30 
     31 struct ltk_widget;
     32 struct ltk_window;
     33 typedef struct ltk_widget ltk_widget;
     34 
     35 typedef enum {
     36 	LTK_WIDGET_UNKNOWN = 0,
     37 	LTK_WIDGET_ANY,
     38 	LTK_WIDGET_GRID,
     39 	LTK_WIDGET_BUTTON,
     40 	LTK_WIDGET_LABEL,
     41 	LTK_WIDGET_BOX,
     42 	LTK_WIDGET_MENU,
     43 	LTK_WIDGET_MENUENTRY,
     44 	LTK_WIDGET_ENTRY,
     45 	LTK_WIDGET_IMAGE,
     46 	LTK_WIDGET_WINDOW,
     47 	LTK_WIDGET_SCROLLBAR,
     48 	LTK_WIDGET_CHECKBUTTON,
     49 	LTK_WIDGET_RADIOBUTTON,
     50 	LTK_WIDGET_COMBOBOX,
     51 	LTK_NUM_WIDGETS,
     52 } ltk_widget_type;
     53 
     54 typedef enum {
     55 	LTK_ACTIVATABLE_NORMAL = 1,
     56 	/* only activatable when "all-activatable"
     57 	   is set to true in the config */
     58 	LTK_ACTIVATABLE_SPECIAL = 2,
     59 	LTK_ACTIVATABLE_ALWAYS = 1|2,
     60 	/* FIXME: redundant or needs better name - is implied by entries in vtable
     61 	   - if there are widgets that have keyboard functions in the vtable but
     62 	     shouldn't have this set, then it's a bad name */
     63 	LTK_NEEDS_KEYBOARD = 4,
     64 	LTK_NEEDS_REDRAW = 8,
     65 	LTK_HOVER_IS_ACTIVE = 16,
     66 } ltk_widget_flags;
     67 
     68 /* FIXME: "sticky" is maybe not the correct name anymore */
     69 typedef enum {
     70 	LTK_STICKY_NONE = 0,
     71 	LTK_STICKY_LEFT = 1 << 0,
     72 	LTK_STICKY_RIGHT = 1 << 1,
     73 	LTK_STICKY_TOP = 1 << 2,
     74 	LTK_STICKY_BOTTOM = 1 << 3,
     75 	LTK_STICKY_SHRINK_WIDTH = 1 << 4,
     76 	LTK_STICKY_SHRINK_HEIGHT = 1 << 5,
     77 	LTK_STICKY_PRESERVE_ASPECT_RATIO = 1 << 6,
     78 } ltk_sticky_mask;
     79 
     80 typedef enum {
     81 	LTK_VERTICAL,
     82 	LTK_HORIZONTAL
     83 } ltk_orientation;
     84 
     85 typedef enum {
     86 	LTK_NORMAL = 0,
     87 	LTK_HOVER = 1,
     88 	LTK_PRESSED = 2,
     89 	LTK_ACTIVE = 4,
     90 	LTK_HOVERACTIVE = 1 | 4,
     91 	LTK_FOCUSED = 8,
     92 	LTK_DISABLED = 16,
     93 } ltk_widget_state;
     94 
     95 /* FIXME: need "ltk_register_type" just to get unique integer for type checking */
     96 
     97 typedef struct {
     98 	union {
     99 		int i;
    100 		size_t sz;
    101 		char c;
    102 		ltk_widget *widget;
    103 		char *str;
    104 		const char *cstr;
    105 		ltk_key_event *key_event;
    106 		ltk_button_event *button_event;
    107 		ltk_scroll_event *scroll_event;
    108 		ltk_motion_event *motion_event;
    109 		ltk_surface *surface;
    110 		void *v;
    111 		/* FIXME: maybe rewrite the functions to take
    112 		   pointers instead so this doesn't increase
    113 		   the size of the union (thereby increasing
    114 		   the size of every arg in the arglist) */
    115 		ltk_rect rect;
    116 	} arg;
    117 	enum {
    118 		LTK_TYPE_INT,
    119 		LTK_TYPE_SIZE_T,
    120 		LTK_TYPE_CHAR,
    121 		LTK_TYPE_WIDGET,
    122 		LTK_TYPE_STRING,
    123 		LTK_TYPE_CONST_STRING,
    124 		LTK_TYPE_KEY_EVENT,
    125 		LTK_TYPE_BUTTON_EVENT,
    126 		LTK_TYPE_SCROLL_EVENT,
    127 		LTK_TYPE_MOTION_EVENT,
    128 		LTK_TYPE_SURFACE,
    129 		LTK_TYPE_RECT,
    130 		LTK_TYPE_VOID,
    131 		LTK_TYPE_VOIDP,
    132 	} type;
    133 } ltk_callback_arg;
    134 
    135 /* FIXME: STRING should be CHARP for consistency */
    136 #define LTK_MAKE_ARG_INT(data) ((ltk_callback_arg){.type = LTK_TYPE_INT, .arg = {.i = (data)}})
    137 #define LTK_MAKE_ARG_SIZE_T(data) ((ltk_callback_arg){.type = LTK_TYPE_SIZE_T, .arg = {.sz = (data)}})
    138 #define LTK_MAKE_ARG_CHAR(data) ((ltk_callback_arg){.type = LTK_TYPE_CHAR, .arg = {.c = (data)}})
    139 #define LTK_MAKE_ARG_WIDGET(data) ((ltk_callback_arg){.type = LTK_TYPE_WIDGET, .arg = {.widget = (data)}})
    140 #define LTK_MAKE_ARG_STRING(data) ((ltk_callback_arg){.type = LTK_TYPE_STRING, .arg = {.str = (data)}})
    141 #define LTK_MAKE_ARG_CONST_STRING(data) ((ltk_callback_arg){.type = LTK_TYPE_CONST_STRING, .arg = {.cstr = (data)}})
    142 #define LTK_MAKE_ARG_KEY_EVENT(data) ((ltk_callback_arg){.type = LTK_TYPE_KEY_EVENT, .arg = {.key_event = (data)}})
    143 #define LTK_MAKE_ARG_BUTTON_EVENT(data) ((ltk_callback_arg){.type = LTK_TYPE_BUTTON_EVENT, .arg = {.button_event = (data)}})
    144 #define LTK_MAKE_ARG_SCROLL_EVENT(data) ((ltk_callback_arg){.type = LTK_TYPE_SCROLL_EVENT, .arg = {.scroll_event = (data)}})
    145 #define LTK_MAKE_ARG_MOTION_EVENT(data) ((ltk_callback_arg){.type = LTK_TYPE_MOTION_EVENT, .arg = {.motion_event = (data)}})
    146 #define LTK_MAKE_ARG_SURFACE(data) ((ltk_callback_arg){.type = LTK_TYPE_SURFACE, .arg = {.surface = (data)}})
    147 #define LTK_MAKE_ARG_RECT(data) ((ltk_callback_arg){.type = LTK_TYPE_RECT, .arg = {.rect = (data)}})
    148 #define LTK_MAKE_ARG_VOIDP(data) ((ltk_callback_arg){.type = LTK_TYPE_VOIDP, .arg = {.v = (data)}})
    149 
    150 #define LTK_ARG_VOID ((ltk_callback_arg){.type = LTK_TYPE_VOID})
    151 
    152 #define LTK_CAST_ARG_INT(carg) (ltk_assert(carg.type == LTK_TYPE_INT), carg.arg.i)
    153 #define LTK_CAST_ARG_SIZE_T(carg) (ltk_assert(carg.type == LTK_TYPE_SIZE_T), carg.arg.sz)
    154 #define LTK_CAST_ARG_CHAR(carg) (ltk_assert(carg.type == LTK_TYPE_CHAR), carg.arg.c)
    155 #define LTK_CAST_ARG_WIDGET(carg) (ltk_assert(carg.type == LTK_TYPE_WIDGET), carg.arg.widget)
    156 #define LTK_CAST_ARG_STRING(carg) (ltk_assert(carg.type == LTK_TYPE_STRING), carg.arg.str)
    157 #define LTK_CAST_ARG_CONST_STRING(carg) (ltk_assert(carg.type == LTK_TYPE_CONST_STRING), carg.arg.cstr)
    158 #define LTK_CAST_ARG_KEY_EVENT(carg) (ltk_assert(carg.type == LTK_TYPE_KEY_EVENT), carg.arg.key_event)
    159 #define LTK_CAST_ARG_BUTTON_EVENT(carg) (ltk_assert(carg.type == LTK_TYPE_BUTTON_EVENT), carg.arg.button_event)
    160 #define LTK_CAST_ARG_SCROLL_EVENT(carg) (ltk_assert(carg.type == LTK_TYPE_SCROLL_EVENT), carg.arg.scroll_event)
    161 #define LTK_CAST_ARG_MOTION_EVENT(carg) (ltk_assert(carg.type == LTK_TYPE_MOTION_EVENT), carg.arg.motion_event)
    162 #define LTK_CAST_ARG_SURFACE(carg) (ltk_assert(carg.type == LTK_TYPE_SURFACE), carg.arg.surface)
    163 #define LTK_CAST_ARG_RECT(carg) (ltk_assert(carg.type == LTK_TYPE_RECT), carg.arg.rect)
    164 #define LTK_CAST_ARG_VOIDP(carg) (ltk_assert(carg.type == LTK_TYPE_VOIDP), carg.arg.v)
    165 
    166 #define LTK_GET_ARG_INT(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_INT(cargs.args[i]))
    167 #define LTK_GET_ARG_SIZE_T(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_SIZE_T(cargs.args[i]))
    168 #define LTK_GET_ARG_CHAR(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_CHAR(cargs.args[i]))
    169 #define LTK_GET_ARG_WIDGET(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_WIDGET(cargs.args[i]))
    170 #define LTK_GET_ARG_STRING(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_STRING(cargs.args[i]))
    171 #define LTK_GET_ARG_CONST_STRING(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_CONST_STRING(cargs.args[i]))
    172 #define LTK_GET_ARG_KEY_EVENT(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_KEY_EVENT(cargs.args[i]))
    173 #define LTK_GET_ARG_BUTTON_EVENT(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_BUTTON_EVENT(cargs.args[i]))
    174 #define LTK_GET_ARG_SCROLL_EVENT(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_SCROLL_EVENT(cargs.args[i]))
    175 #define LTK_GET_ARG_MOTION_EVENT(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_MOTION_EVENT(cargs.args[i]))
    176 #define LTK_GET_ARG_SURFACE(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_SURFACE(cargs.args[i]))
    177 #define LTK_GET_ARG_RECT(cargs, i) (ltk_assert(i >= 0 && i < cargs.num), LTK_CAST_ARG_RECT(cargs.args[i]))
    178 
    179 #define LTK_CAST_WIDGET(w) (&(w)->widget)
    180 #define LTK_CAST_WINDOW(w) (ltk_assert(w->vtable->type == LTK_WIDGET_WINDOW), (ltk_window *)(w))
    181 #define LTK_CAST_LABEL(w) (ltk_assert(w->vtable->type == LTK_WIDGET_LABEL), (ltk_label *)(w))
    182 #define LTK_CAST_BUTTON(w) (ltk_assert(w->vtable->type == LTK_WIDGET_BUTTON), (ltk_button *)(w))
    183 #define LTK_CAST_GRID(w) (ltk_assert(w->vtable->type == LTK_WIDGET_GRID), (ltk_grid *)(w))
    184 #define LTK_CAST_IMAGE_WIDGET(w) (ltk_assert(w->vtable->type == LTK_WIDGET_IMAGE), (ltk_image_widget *)(w))
    185 #define LTK_CAST_ENTRY(w) (ltk_assert(w->vtable->type == LTK_WIDGET_ENTRY), (ltk_entry *)(w))
    186 #define LTK_CAST_MENU(w) (ltk_assert(w->vtable->type == LTK_WIDGET_MENU), (ltk_menu *)(w))
    187 #define LTK_CAST_MENUENTRY(w) (ltk_assert(w->vtable->type == LTK_WIDGET_MENUENTRY), (ltk_menuentry *)(w))
    188 #define LTK_CAST_SCROLLBAR(w) (ltk_assert(w->vtable->type == LTK_WIDGET_SCROLLBAR), (ltk_scrollbar *)(w))
    189 #define LTK_CAST_BOX(w) (ltk_assert(w->vtable->type == LTK_WIDGET_BOX), (ltk_box *)(w))
    190 #define LTK_CAST_CHECKBUTTON(w) (ltk_assert(w->vtable->type == LTK_WIDGET_CHECKBUTTON), (ltk_checkbutton *)(w))
    191 #define LTK_CAST_RADIOBUTTON(w) (ltk_assert(w->vtable->type == LTK_WIDGET_RADIOBUTTON), (ltk_radiobutton *)(w))
    192 #define LTK_CAST_COMBOBOX(w) (ltk_assert(w->vtable->type == LTK_WIDGET_COMBOBOX), (ltk_combobox *)(w))
    193 
    194 /* FIXME: a bit weird because window never gets some of these signals */
    195 #define LTK_WIDGET_SIGNAL_KEY_PRESS          1
    196 #define LTK_WIDGET_SIGNAL_KEY_RELEASE        2
    197 #define LTK_WIDGET_SIGNAL_MOUSE_PRESS        3
    198 #define LTK_WIDGET_SIGNAL_MOUSE_RELEASE      4
    199 #define LTK_WIDGET_SIGNAL_MOUSE_SCROLL       5
    200 #define LTK_WIDGET_SIGNAL_MOTION_NOTIFY      6
    201 #define LTK_WIDGET_SIGNAL_MOUSE_ENTER        7
    202 #define LTK_WIDGET_SIGNAL_MOUSE_LEAVE        8
    203 #define LTK_WIDGET_SIGNAL_PRESS              9
    204 #define LTK_WIDGET_SIGNAL_RELEASE            10
    205 /* FIXME: resize is currently triggered in a lot of cases where nothing is really resized */
    206 #define LTK_WIDGET_SIGNAL_RESIZE             11
    207 #define LTK_WIDGET_SIGNAL_HIDE               12
    208 #define LTK_WIDGET_SIGNAL_DRAW               13
    209 #define LTK_WIDGET_SIGNAL_CHANGE_STATE       14
    210 /* The return value for this is ignored, i.e.
    211    the widget destroy function is always called.
    212    Also, it doesn't receive the 'shallow' argument
    213    that the widget method receives. */
    214 #define LTK_WIDGET_SIGNAL_DESTROY            15
    215 #define LTK_WIDGET_SIGNAL_INVALID            16
    216 
    217 typedef struct {
    218 	ltk_callback_arg *args;
    219 	size_t num;
    220 } ltk_callback_arglist;
    221 
    222 #define LTK_EMPTY_ARGLIST ((ltk_callback_arglist){NULL, 0})
    223 
    224 typedef int (*ltk_signal_callback)(ltk_widget *widget, ltk_callback_arglist args, ltk_callback_arg data);
    225 typedef struct {
    226 	ltk_signal_callback callback;
    227 	ltk_callback_arg data;
    228 	int type;
    229 } ltk_signal_callback_info;
    230 
    231 int ltk_widget_register_signal_handler(ltk_widget *widget, int type, ltk_signal_callback callback, ltk_callback_arg data);
    232 int ltk_widget_emit_signal(ltk_widget *widget, int type, ltk_callback_arglist args);
    233 size_t ltk_widget_remove_signal_handler_by_type(ltk_widget *widget, int type);
    234 size_t ltk_widget_remove_signal_handler_by_callback(ltk_widget *widget, ltk_signal_callback callback);
    235 size_t ltk_widget_remove_signal_handler_by_info(
    236 	ltk_widget *widget,
    237 	int (*filter_func)(ltk_signal_callback_info *to_check, ltk_signal_callback_info *info),
    238 	ltk_signal_callback_info *info
    239 );
    240 void ltk_widget_remove_all_signal_handlers(ltk_widget *widget);
    241 int ltk_widget_register_type(void);
    242 
    243 LTK_ARRAY_INIT_STRUCT_DECL(signal, ltk_signal_callback_info)
    244 
    245 struct ltk_widget {
    246 	struct ltk_window *window;
    247 	struct ltk_widget *parent;
    248 
    249 	struct ltk_widget_vtable *vtable;
    250 
    251 	/* FIXME: crect and lrect are a bit weird still */
    252 	/* FIXME: especially the relative positioning is really weird for
    253 	   popups because they're positioned globally but still have a
    254 	   parent-child relationship - weird things can probably happen */
    255 	/* both rects relative to parent (except for popups) */
    256 	/* collision rect is only part that is actually shown and used for
    257 	   collision with mouse (but may still not be drawn if hidden by
    258 	   something else) - e.g. in a box with scrolling, a widget that
    259 	   is half cut off by a side of the box will have the logical rect
    260 	   going past the side of the box, but the collision rect will only
    261 	   be the part inside the box */
    262 	ltk_rect crect; /* collision rect */
    263 	ltk_rect lrect; /* logical rect */
    264 	unsigned int ideal_w;
    265 	unsigned int ideal_h;
    266 	unsigned int last_dpi;
    267 
    268 	/* maybe mask to determine quickly which callbacks are included?
    269 	default signals only allowed to have one callback? */
    270 	/* could maybe have just uint32_t mask so at least the lower signals
    271 	   can be easily checked */
    272 	ltk_array(signal) *signal_cbs;
    273 
    274 	ltk_widget_state state;
    275 	/* FIXME: store this in grid/box - for row_span, column_span the other cells could be marked with "not top left cell of widget" so they can be skipped */
    276 	ltk_sticky_mask sticky;
    277 	unsigned short row;
    278 	unsigned short column;
    279 	unsigned short row_span;
    280 	unsigned short column_span;
    281 	/* ALSO NEED SIGNALS LIKE ADD-TEXT (called *before* text is inserted to check validity) - these would need argument
    282 	FIGURE OUT HOW TO DO KEY MAPPINGS - should reuse parts of builtin mapping handling
    283 	-> maybe something like tk
    284 	-> or maybe just say everyone needs to override event handler? but makes simple stuff more difficult
    285 	-> also need "global" mappings/key event handler for global shortcuts */
    286 	/* needed to properly handle handle local coordinates since
    287 	   popups are positioned globally instead of locally */
    288 	char popup;
    289 	char dirty;
    290 	char hidden;
    291 	char vtable_copied;
    292 };
    293 
    294 typedef struct ltk_widget_vtable {
    295 	int (*key_press)(struct ltk_widget *, ltk_key_event *);
    296 	int (*key_release)(struct ltk_widget *, ltk_key_event *);
    297 	/* press/release also receive double/triple-click/release */
    298 	int (*mouse_press)(struct ltk_widget *, ltk_button_event *);
    299 	int (*mouse_release)(struct ltk_widget *, ltk_button_event *);
    300 	int (*mouse_scroll)(struct ltk_widget *, ltk_scroll_event *);
    301 	int (*motion_notify)(struct ltk_widget *, ltk_motion_event *);
    302 	int (*mouse_leave)(struct ltk_widget *, ltk_motion_event *);
    303 	int (*mouse_enter)(struct ltk_widget *, ltk_motion_event *);
    304 	int (*press)(struct ltk_widget *);
    305 	int (*release)(struct ltk_widget *);
    306 	void (*cmd_return)(struct ltk_widget *self, char *text, size_t len);
    307 
    308 	/* This is called when the DPI changes. It must not call child_size_change on
    309 	   the parent or do any actual resizing (only ideal_w and ideal_h should be set),
    310 	   but it should call ltk_widget_recalc_ideal_size on any child widgets. */
    311 	/* When a widget is added to a container, the container should call
    312 	   ltk_widget_recalc_ideal_size on the widget in case the DPI changed. */
    313 	void (*recalc_ideal_size)(struct ltk_widget *);
    314 	void (*resize)(struct ltk_widget *);
    315 	void (*hide)(struct ltk_widget *);
    316 	/* draw_surface: surface to draw it on
    317 	   x, y: position of logical rectangle on surface
    318 	   clip: clipping rectangle, relative to logical rectangle */
    319 	void (*draw)(struct ltk_widget *self, ltk_surface *draw_surface, int x, int y, ltk_rect clip);
    320 	void (*change_state)(struct ltk_widget *, ltk_widget_state);
    321 	void (*destroy)(struct ltk_widget *, int);
    322 
    323 	/* rect is in self's coordinate system */
    324 	struct ltk_widget *(*nearest_child)(struct ltk_widget *self, ltk_rect rect);
    325 	struct ltk_widget *(*nearest_child_left)(struct ltk_widget *self, ltk_widget *widget);
    326 	struct ltk_widget *(*nearest_child_right)(struct ltk_widget *self, ltk_widget *widget);
    327 	struct ltk_widget *(*nearest_child_above)(struct ltk_widget *self, ltk_widget *widget);
    328 	struct ltk_widget *(*nearest_child_below)(struct ltk_widget *self, ltk_widget *widget);
    329 	struct ltk_widget *(*next_child)(struct ltk_widget *self, ltk_widget *child);
    330 	struct ltk_widget *(*prev_child)(struct ltk_widget *self, ltk_widget *child);
    331 	struct ltk_widget *(*first_child)(struct ltk_widget *self);
    332 	struct ltk_widget *(*last_child)(struct ltk_widget *self);
    333 
    334 	/* This is called when the ideal size of a child is changed (e.g. text is
    335 	   added to a text entry). */
    336 	void (*child_size_change)(struct ltk_widget *, struct ltk_widget *);
    337 	int (*remove_child)(struct ltk_widget *, struct ltk_widget *);
    338 	/* x and y relative to widget's lrect! */
    339 	struct ltk_widget *(*get_child_at_pos)(struct ltk_widget *, int x, int y);
    340 	/* r is in self's coordinate system */
    341 	void (*ensure_rect_shown)(struct ltk_widget *self, ltk_rect r);
    342 
    343 	ltk_widget_type type;
    344 	ltk_widget_flags flags;
    345 	int invalid_signal;
    346 } ltk_widget_vtable;
    347 
    348 void ltk_widget_hide(ltk_widget *widget);
    349 int ltk_widget_destroy(ltk_widget *widget, int shallow);
    350 void ltk_fill_widget_defaults(
    351     ltk_widget *widget, struct ltk_window *window,
    352     struct ltk_widget_vtable *vtable, int w, int h
    353 );
    354 void ltk_widget_change_state(ltk_widget *widget, ltk_widget_state old_state);
    355 void ltk_widget_resize(ltk_widget *widget);
    356 void ltk_widget_draw(ltk_widget *widget, ltk_surface *draw_surf, int x, int y, ltk_rect clip_rect);
    357 /* FIXME: layout widgets need to recalculate ideal size when children change! */
    358 void ltk_widget_get_ideal_size(ltk_widget *widget, unsigned int *ideal_w_ret, unsigned int *ideal_h_ret);
    359 ltk_point ltk_widget_pos_to_global(ltk_widget *widget, int x, int y);
    360 ltk_point ltk_global_to_widget_pos(ltk_widget *widget, int x, int y);
    361 
    362 ltk_widget_vtable *ltk_widget_get_editable_vtable(ltk_widget *widget);
    363 
    364 void ltk_widget_recalc_ideal_size(ltk_widget *widget);
    365 
    366 #endif /* LTK_WIDGET_H */