struct rtb_element * rtb_elem_nearest_clearable(struct rtb_element *self) { struct rtb_surface *surface = self->surface; for (; self != RTB_ELEMENT(surface); self = self->parent) if (rtb_elem_is_clearable(self)) return self; return RTB_ELEMENT(surface); }
static int dispatch_click_event(struct rtb_button *self, const struct rtb_mouse_event *e) { struct rtb_button_event event = *((struct rtb_button_event *) e); event.type = RTB_BUTTON_CLICK; event.cursor.x -= self->x; event.cursor.y -= self->y; return rtb_handle(RTB_ELEMENT(self), RTB_EVENT(&event)); }
static void attached(struct rtb_element *elem, struct rtb_element *parent, struct rtb_window *window) { SELF_FROM(elem); super.attached(elem, parent, window); self->type = rtb_type_ref(window, self->type, "net.illest.rutabaga.window"); rtb_style_resolve_list(self, self->style_list); self->restyle(RTB_ELEMENT(self)); }
int rtb_button_init(struct rtb_button *self) { if (RTB_SUBCLASS(RTB_ELEMENT(self), rtb_elem_init, &super)) return -1; rtb_label_init(&self->label); rtb_elem_add_child(RTB_ELEMENT(self), RTB_ELEMENT(&self->label), RTB_ADD_HEAD); self->label.align = RTB_ALIGN_MIDDLE; self->outer_pad.x = self->outer_pad.y = 0.f; self->on_event = on_event; self->attached = attached; self->layout_cb = rtb_layout_hpack_center; self->size_cb = rtb_size_hfit_children; self->reflow = reflow; return 0; }
void rtb_window_reinit(struct rtb_window *self) { struct rtb_element *elem = RTB_ELEMENT(self); self->x = self->y = 0.f; glScissor(0, 0, self->w, self->h); if (!self->window) self->attached(elem, NULL, self); rtb_elem_trigger_reflow(elem, elem, RTB_DIRECTION_LEAFWARD); }
int rtb_elem_is_clearable(struct rtb_element *self) { struct rtb_surface *surface = self->surface; /* XXX: shouldn't depend on stylequad like this */ for (self = self->parent; self != RTB_ELEMENT(surface); self = self->parent) if (self->stylequad.properties.bg_color) return 0; return 1; }
static void mark_dirty(struct rtb_element *self) { struct rtb_surface *surface = self->surface; self = rtb_elem_nearest_clearable(self); if (!surface || surface->surface_state == RTB_SURFACE_INVALID || self->render_entry.tqe_next || self->render_entry.tqe_prev) return; TAILQ_INSERT_TAIL(&surface->render_queue, self, render_entry); rtb_elem_mark_dirty(RTB_ELEMENT(surface)); }
static int handle_key_press(struct rtb_button *self, const struct rtb_key_event *e) { struct rtb_button_event event = { .type = RTB_BUTTON_CLICK, .source = RTB_EVENT_SYNTHETIC }; if ((e->keysym == RTB_KEY_NORMAL && e->character == ' ') || (e->keysym == RTB_KEY_ENTER)) { rtb_handle(RTB_ELEMENT(self), RTB_EVENT(&event)); return 1; } return 0; }
int main(int argc, char **argv) { struct rutabaga *delicious; struct rtb_window *win; struct rtb_button click_me; delicious = rtb_new(); assert(delicious); win = rtb_window_open(delicious, 600, 700, "rtb basic demo"); assert(win); rtb_elem_set_size_cb(RTB_ELEMENT(win), rtb_size_hfit_children); rtb_elem_set_layout(RTB_ELEMENT(win), rtb_layout_hpack_center); rtb_label_init(&click_counter); rtb_button_init(&click_me); click_counter.align = RTB_ALIGN_MIDDLE; click_me.align = RTB_ALIGN_MIDDLE; click_me.flags |= RTB_ELEM_CLICK_FOCUS; rtb_button_set_label(&click_me, "click me"); update_label(); rtb_register_handler(RTB_ELEMENT(&click_me), RTB_BUTTON_CLICK, button_clicked, NULL); rtb_elem_add_child(RTB_ELEMENT(win), RTB_ELEMENT(&click_counter), RTB_ADD_TAIL); rtb_elem_add_child(RTB_ELEMENT(win), RTB_ELEMENT(&click_me), RTB_ADD_TAIL); rtb_event_loop(delicious); rtb_window_lock(win); rtb_label_fini(&click_counter); rtb_window_close(delicious->win); rtb_free(delicious); }
int rtb_window_draw(struct rtb_window *self, int force_redraw) { const struct rtb_style_property_definition *prop; struct rtb_window_event ev; if (self->state == RTB_STATE_UNATTACHED || self->visibility == RTB_FULLY_OBSCURED) return 0; ev.type = RTB_FRAME_START; ev.source = RTB_EVENT_GENUINE; ev.window = self; rtb_dispatch_raw(RTB_ELEMENT(self), RTB_EVENT(&ev)); if (!self->dirty || force_redraw) return 0; glViewport(0, 0, self->w, self->h); prop = rtb_style_query_prop(RTB_ELEMENT(self), "background-color", RTB_STYLE_PROP_COLOR, 1); glEnable(GL_DITHER); glEnable(GL_BLEND); glEnable(GL_SCISSOR_TEST); glClearColor( prop->color.r, prop->color.g, prop->color.b, prop->color.a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); rtb_render_push(RTB_ELEMENT(self)); self->draw(RTB_ELEMENT(self)); rtb_render_pop(RTB_ELEMENT(self)); self->dirty = 0; ev.type = RTB_FRAME_END; rtb_dispatch_raw(RTB_ELEMENT(self), RTB_EVENT(&ev)); return 1; }
static int win_event(struct rtb_element *elem, const struct rtb_event *e) { SELF_FROM(elem); switch (e->type) { case RTB_WINDOW_CLOSE: if (!rtb_handle(elem, e)) rtb_event_loop_stop(self->rtb); return 1; case RTB_KEY_PRESS: case RTB_KEY_RELEASE: if (self->focus && self->focus != RTB_ELEMENT(self)) if (rtb_elem_deliver_event(self->focus, e)) return 1; if (rtb_handle(elem, e)) return 1; } return super.on_event(elem, e); }
struct rtb_window * rtb_window_open_under(struct rutabaga *r, intptr_t parent, int w, int h, const char *title) { struct rtb_style_data stdata; struct rtb_window *self; assert(r); assert(h > 0); assert(w > 0); assert(!r->win); self = window_impl_open(r, w, h, title, parent); if (!self) goto err_window_impl; init_gl(); if (RTB_SUBCLASS(RTB_SURFACE(self), rtb_surface_init, &super)) goto err_surface_init; self->w = w; self->h = h; self->surface = RTB_SURFACE(self); stdata = rtb_style_get_defaults(); self->style_list = stdata.style; self->style_fonts = calloc(stdata.nfonts, sizeof(*self->style_fonts)); if (shaders_init(self)) goto err_shaders; if (ibos_init(self)) goto err_ibos; if (rtb_font_manager_init(&self->font_manager, self->dpi.x, self->dpi.y)) goto err_font; rtb_elem_set_layout(RTB_ELEMENT(self), rtb_layout_vpack_top); self->on_event = win_event; self->mark_dirty = mark_dirty; self->attached = attached; self->flags = RTB_ELEM_CLICK_FOCUS; /* for core profiles */ glGenVertexArrays(1, &self->vao); glBindVertexArray(self->vao); self->rtb = r; r->win = self; self->mouse.current_cursor = RTB_MOUSE_CURSOR_DEFAULT; return self; err_font: ibos_fini(self); err_ibos: shaders_fini(self); err_shaders: err_surface_init: window_impl_close(self); err_window_impl: return NULL; }
void rtb_button_fini(struct rtb_button *self) { rtb_label_fini(&self->label); rtb_elem_fini(RTB_ELEMENT(self)); }