URI: 
       widget.h - ltk - GUI toolkit for X11 (WIP)
  HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/ltk.git (encrypted, but very slow)
  HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR 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 */