widget.h (8719B)
1 /* 2 * Copyright (c) 2021-2023 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 #ifndef LTK_WIDGET_H 18 #define LTK_WIDGET_H 19 20 #include "err.h" 21 #include "rect.h" 22 #include "event.h" 23 #include "config.h" 24 25 /* FIXME: SORT OUT INCLUDES PROPERLY! */ 26 27 typedef struct ltk_widget ltk_widget; 28 typedef uint32_t ltk_widget_type; 29 30 typedef enum { 31 LTK_ACTIVATABLE_NORMAL = 1, 32 LTK_ACTIVATABLE_SPECIAL = 2, 33 LTK_ACTIVATABLE_ALWAYS = 1|2, 34 /* FIXME: redundant or needs better name - is implied by entries in vtable 35 - if there are widgets that have keyboard functions in the vtable but 36 shouldn't have this set, then it's a bad name */ 37 LTK_NEEDS_KEYBOARD = 4, 38 LTK_NEEDS_REDRAW = 8, 39 LTK_HOVER_IS_ACTIVE = 16, 40 } ltk_widget_flags; 41 42 typedef enum { 43 LTK_STICKY_NONE = 0, 44 LTK_STICKY_LEFT = 1 << 0, 45 LTK_STICKY_RIGHT = 1 << 1, 46 LTK_STICKY_TOP = 1 << 2, 47 LTK_STICKY_BOTTOM = 1 << 3, 48 LTK_STICKY_SHRINK_WIDTH = 1 << 4, 49 LTK_STICKY_SHRINK_HEIGHT = 1 << 5, 50 LTK_STICKY_PRESERVE_ASPECT_RATIO = 1 << 6, 51 } ltk_sticky_mask; 52 53 typedef enum { 54 LTK_VERTICAL, 55 LTK_HORIZONTAL 56 } ltk_orientation; 57 58 typedef enum { 59 LTK_NORMAL = 0, 60 LTK_HOVER = 1, 61 LTK_PRESSED = 2, 62 LTK_ACTIVE = 4, 63 LTK_HOVERACTIVE = 1 | 4, 64 LTK_FOCUSED = 8, 65 LTK_DISABLED = 16, 66 } ltk_widget_state; 67 68 #include "surface_cache.h" 69 70 struct ltk_window; 71 72 struct ltk_widget_vtable; 73 74 typedef struct { 75 int client; /* index of client */ 76 uint32_t mask; /* generic event mask */ 77 uint32_t lmask; /* generic lock mask */ 78 uint32_t wmask; /* event mask for specific widget type */ 79 uint32_t lwmask; /* lock event mask for specific widget type */ 80 } client_event_mask; 81 82 struct ltk_widget { 83 struct ltk_window *window; 84 struct ltk_widget *parent; 85 char *id; 86 87 struct ltk_widget_vtable *vtable; 88 89 /* FIXME: crect and lrect are a bit weird still */ 90 /* FIXME: especially the relative positioning is really weird for 91 popups because they're positioned globally but still have a 92 parent-child relationship - weird things can probably happen */ 93 /* both rects relative to parent (except for popups) */ 94 /* collision rect is only part that is actually shown and used for 95 collision with mouse (but may still not be drawn if hidden by 96 something else) - e.g. in a box with scrolling, a widget that 97 is half cut off by a side of the box will have the logical rect 98 going past the side of the box, but the collision rect will only 99 be the part inside the box */ 100 ltk_rect crect; /* collision rect */ 101 ltk_rect lrect; /* logical rect */ 102 unsigned int ideal_w; 103 unsigned int ideal_h; 104 105 client_event_mask *event_masks; 106 /* FIXME: kind of a waste of space to use size_t here */ 107 size_t masks_num; 108 size_t masks_alloc; 109 110 ltk_widget_state state; 111 unsigned int sticky; 112 unsigned short row; 113 unsigned short column; 114 unsigned short row_span; 115 unsigned short column_span; 116 /* needed to properly handle handle local coordinates since 117 popups are positioned globally instead of locally */ 118 char popup; 119 char dirty; 120 char hidden; 121 }; 122 123 struct ltk_widget_vtable { 124 int (*key_press)(struct ltk_widget *, ltk_key_event *); 125 int (*key_release)(struct ltk_widget *, ltk_key_event *); 126 /* press/release also receive double/triple-click/release */ 127 int (*mouse_press)(struct ltk_widget *, ltk_button_event *); 128 int (*mouse_release)(struct ltk_widget *, ltk_button_event *); 129 int (*mouse_scroll)(struct ltk_widget *, ltk_scroll_event *); 130 int (*motion_notify)(struct ltk_widget *, ltk_motion_event *); 131 int (*mouse_leave)(struct ltk_widget *, ltk_motion_event *); 132 int (*mouse_enter)(struct ltk_widget *, ltk_motion_event *); 133 int (*press)(struct ltk_widget *); 134 int (*release)(struct ltk_widget *); 135 void (*cmd_return)(struct ltk_widget *self, char *text, size_t len); 136 137 void (*resize)(struct ltk_widget *); 138 void (*hide)(struct ltk_widget *); 139 /* draw_surface: surface to draw it on 140 x, y: position of logical rectangle on surface 141 clip: clipping rectangle, relative to logical rectangle */ 142 void (*draw)(struct ltk_widget *self, ltk_surface *draw_surface, int x, int y, ltk_rect clip); 143 void (*change_state)(struct ltk_widget *, ltk_widget_state); 144 void (*destroy)(struct ltk_widget *, int); 145 146 /* rect is in self's coordinate system */ 147 struct ltk_widget *(*nearest_child)(struct ltk_widget *self, ltk_rect rect); 148 struct ltk_widget *(*nearest_child_left)(struct ltk_widget *self, ltk_widget *widget); 149 struct ltk_widget *(*nearest_child_right)(struct ltk_widget *self, ltk_widget *widget); 150 struct ltk_widget *(*nearest_child_above)(struct ltk_widget *self, ltk_widget *widget); 151 struct ltk_widget *(*nearest_child_below)(struct ltk_widget *self, ltk_widget *widget); 152 struct ltk_widget *(*next_child)(struct ltk_widget *self, ltk_widget *child); 153 struct ltk_widget *(*prev_child)(struct ltk_widget *self, ltk_widget *child); 154 struct ltk_widget *(*first_child)(struct ltk_widget *self); 155 struct ltk_widget *(*last_child)(struct ltk_widget *self); 156 157 void (*child_size_change)(struct ltk_widget *, struct ltk_widget *); 158 int (*remove_child)(struct ltk_widget *, struct ltk_widget *, ltk_error *); 159 /* x and y relative to widget's lrect! */ 160 struct ltk_widget *(*get_child_at_pos)(struct ltk_widget *, int x, int y); 161 /* r is in self's coordinate system */ 162 void (*ensure_rect_shown)(struct ltk_widget *self, ltk_rect r); 163 164 ltk_widget_type type; 165 ltk_widget_flags flags; 166 }; 167 168 void ltk_widget_hide(ltk_widget *widget); 169 int ltk_widget_destroy(ltk_widget *widget, int shallow, ltk_error *err); 170 int ltk_widget_destroy_cmd(struct ltk_window *window, ltk_cmd_token *tokens, size_t num_tokens, ltk_error *err); 171 void ltk_fill_widget_defaults(ltk_widget *widget, const char *id, struct ltk_window *window, 172 struct ltk_widget_vtable *vtable, int w, int h); 173 void ltk_widget_change_state(ltk_widget *widget, ltk_widget_state old_state); 174 /* FIXME: move to separate window.h */ 175 void ltk_window_key_press_event(ltk_window *window, ltk_key_event *event); 176 void ltk_window_key_release_event(ltk_window *window, ltk_key_event *event); 177 void ltk_window_mouse_press_event(ltk_window *window, ltk_button_event *event); 178 void ltk_window_mouse_scroll_event(ltk_window *window, ltk_scroll_event *event); 179 void ltk_window_mouse_release_event(ltk_window *window, ltk_button_event *event); 180 void ltk_window_motion_notify_event(ltk_window *window, ltk_motion_event *event); 181 void ltk_window_fake_motion_event(ltk_window *window, int x, int y); 182 int ltk_widget_id_free(const char *id); 183 ltk_widget *ltk_get_widget(const char *id, ltk_widget_type type, ltk_error *err); 184 void ltk_set_widget(ltk_widget *widget, const char *id); 185 void ltk_remove_widget(const char *id); 186 void ltk_widgets_init(); 187 void ltk_widget_resize(ltk_widget *widget); 188 void ltk_widget_remove_client(int client); 189 void ltk_widget_set_event_mask(ltk_widget *widget, int client, uint32_t mask); 190 void ltk_widget_set_event_lmask(ltk_widget *widget, int client, uint32_t mask); 191 void ltk_widget_set_event_wmask(ltk_widget *widget, int client, uint32_t mask); 192 void ltk_widget_set_event_lwmask(ltk_widget *widget, int client, uint32_t mask); 193 void ltk_widget_add_to_event_mask(ltk_widget *widget, int client, uint32_t mask); 194 void ltk_widget_add_to_event_lmask(ltk_widget *widget, int client, uint32_t mask); 195 void ltk_widget_add_to_event_wmask(ltk_widget *widget, int client, uint32_t mask); 196 void ltk_widget_add_to_event_lwmask(ltk_widget *widget, int client, uint32_t mask); 197 void ltk_widget_remove_from_event_mask(ltk_widget *widget, int client, uint32_t mask); 198 void ltk_widget_remove_from_event_lmask(ltk_widget *widget, int client, uint32_t mask); 199 void ltk_widget_remove_from_event_wmask(ltk_widget *widget, int client, uint32_t mask); 200 void ltk_widget_remove_from_event_lwmask(ltk_widget *widget, int client, uint32_t mask); 201 202 203 /* FIXME: document that pointers inside binding are taken over! */ 204 int ltk_widget_register_keypress(const char *func_name, size_t func_len, ltk_keypress_binding b); 205 int ltk_widget_register_keyrelease(const char *func_name, size_t func_len, ltk_keyrelease_binding b); 206 void ltk_widget_cleanup(void); 207 208 #endif /* LTK_WIDGET_H */