commit 870fe49e4274af2aa8cdc5315feb6956330d2af7 from: Onana Onana Xavier Manuel date: Thu Sep 11 00:11:01 2025 UTC Event handler update with some cleanup - Added feature where event handler assigns target for mouse_press, mouse_release and mouse_motion events. commit - cb5e051aec61c8910f1a8335320b6dd435005c1d commit + 870fe49e4274af2aa8cdc5315feb6956330d2af7 blob - 2224ddef2b331222a6301be020522753cdebd389 blob + e6d58289f466e26b75f1e9530a22a09cf28e9568 --- Makefile +++ Makefile @@ -23,4 +23,4 @@ mui: ${OBJS} clean: rm -rf ${OBJS} libmui.so -.PHONY: all mui clean fonts uninstall +.PHONY: all mui clean uninstall blob - 3ff5ea8b0ea946d3b5df94cfb36ae72da49356b3 blob + fbc205aaa1aeef164dffa8dbda3a069d3a483556 --- demo/image/Makefile +++ demo/image/Makefile @@ -4,7 +4,7 @@ INCS= -I ${LIBDIR} LIBS=-Wl,-rpath=${LIBDIR} -L ${LIBDIR} -lmui all: - make MUI_DEBUG=1 -C ${LIBDIR} + make -C ${LIBDIR} ${CC} ${SRCS} -o bin ${INCS} ${LIBS} clean: blob - /dev/null blob + fbc205aaa1aeef164dffa8dbda3a069d3a483556 (mode 644) --- /dev/null +++ demo/event/Makefile @@ -0,0 +1,11 @@ +SRCS=main.c +LIBDIR=../.. +INCS= -I ${LIBDIR} +LIBS=-Wl,-rpath=${LIBDIR} -L ${LIBDIR} -lmui + +all: + make -C ${LIBDIR} + ${CC} ${SRCS} -o bin ${INCS} ${LIBS} + +clean: + rm -rf bin bin.core blob - /dev/null blob + 043be9b90254b76b7bcdf9f49dc09e9758c7f0b4 (mode 644) --- /dev/null +++ demo/event/main.c @@ -0,0 +1,146 @@ +/********************************************************/ +/* + * Brief example of event management using mui with a + * set of 5 buttons interacting with the mouse. + */ +/********************************************************/ + +#include "mui.h" + +#define PRESS 0 +#define MOTION 1 +#define RELEASE 2 + +#define WIDTH 100 +#define HEIGHT 100 + +static struct { + struct mui_event_handler *handler; + struct mui_group *group; + struct mui_window *mw; +} window; + +/* + * Keeps track of which drawable is held in a + * specific event + */ +static struct { + void *ptr; + uint16_t id; +} event_recorder[3]; + +struct button { + struct mui_shape *shape; + struct mui_layout *layout; + struct mui_color color[3]; +}; + +int +main(void) +{ + struct mui_event event; + struct button buttons[5]; + + /* Creating the window */ + window.mw = mui_create_window("Events", 320, 240); + window.group = mui_get_window_group(window.mw); + window.handler = mui_get_window_event_handler(window.mw); + + /* TOP LEFT */ + buttons[0].shape = mui_create_rectangle(WIDTH, HEIGHT); + buttons[0].layout = mui_get_shape_layout(buttons[0].shape); + buttons[0].color[PRESS] = (struct mui_color){ 0.5, 0.5, 0.5, 1.0 }; + buttons[0].color[MOTION] = (struct mui_color){ 0.75, 0.75, 0.75, 1.0 }; + buttons[0].color[RELEASE] = (struct mui_color){ 1.0, 1.0, 1.0, 1.0 }; + + + /* TOP RIGHT */ + buttons[1].shape = mui_create_rectangle(WIDTH, HEIGHT); + buttons[1].layout = mui_get_shape_layout(buttons[1].shape); + buttons[1].color[PRESS] = (struct mui_color){ 0.5, 0.5, 0.5, 1.0 }; + buttons[1].color[MOTION] = (struct mui_color){ 0.75, 0.75, 0.75, 1.0 }; + buttons[1].color[RELEASE] = (struct mui_color){ 1.0, 1.0, 1.0, 1.0 }; + + mui_set_layout_flags(buttons[1].layout, MUI_ALIGN_RIGHT | MUI_ANCHOR_RIGHT ); + + /* BOTTOM RIGHT */ + buttons[2].shape = mui_create_rectangle(WIDTH, HEIGHT); + buttons[2].layout = mui_get_shape_layout(buttons[2].shape); + buttons[2].color[PRESS] = (struct mui_color){ 0.5, 0.5, 0.5, 1.0 }; + buttons[2].color[MOTION] = (struct mui_color){ 0.75, 0.75, 0.75, 1.0 }; + buttons[2].color[RELEASE] = (struct mui_color){ 1.0, 1.0, 1.0, 1.0 }; + + mui_set_layout_flags(buttons[2].layout, MUI_ALIGN_RIGHT | MUI_ANCHOR_RIGHT | + MUI_ALIGN_BOTTOM | MUI_ANCHOR_BOTTOM); + + /* BOTTOM LEFT */ + buttons[3].shape = mui_create_rectangle(WIDTH, HEIGHT); + buttons[3].layout = mui_get_shape_layout(buttons[3].shape); + buttons[3].color[PRESS] = (struct mui_color){ 0.5, 0.5, 0.5, 1.0 }; + buttons[3].color[MOTION] = (struct mui_color){ 0.75, 0.75, 0.75, 1.0 }; + buttons[3].color[RELEASE] = (struct mui_color){ 1.0, 1.0, 1.0, 1.0 }; + + mui_set_layout_flags(buttons[3].layout, MUI_ALIGN_BOTTOM | MUI_ANCHOR_BOTTOM); + + /* CENTER */ + buttons[4].shape = mui_create_rectangle(WIDTH, HEIGHT); + buttons[4].layout = mui_get_shape_layout(buttons[4].shape); + buttons[4].color[PRESS] = (struct mui_color){ 0.5, 0.5, 0.5, 1.0 }; + buttons[4].color[MOTION] = (struct mui_color){ 0.75, 0.75, 0.75, 1.0 }; + buttons[4].color[RELEASE] = (struct mui_color){ 1.0, 1.0, 1.0, 1.0 }; + + mui_set_layout_flags(buttons[4].layout, MUI_ALIGN_CENTER_X | MUI_ALIGN_CENTER_Y | + MUI_ANCHOR_CENTER_X | MUI_ANCHOR_CENTER_Y | MUI_KEEP_RATIO); + + /* Adding to the group */ + for (int i = 0; i < 5; i++) { + mui_set_shape_color(buttons[i].shape, buttons[i].color[RELEASE].r, + buttons[i].color[RELEASE].g, buttons[i].color[RELEASE].b, buttons[i].color[RELEASE].a); + + mui_group_add(window.group, MUI_SHAPE, buttons[i].shape); + } + + while (event.type != MUI_EVENT_QUIT) { + event = mui_pop_event(window.handler); + + switch (event.type) { + case MUI_EVENT_MOUSE_MOTION: + if (event_recorder[MOTION].ptr && event.target.ptr != event_recorder[MOTION].ptr) { + if (event_recorder[MOTION].ptr != event_recorder[PRESS].ptr) + mui_set_shape_color(event_recorder[MOTION].ptr, 1.0, 1.0, 1.0, 1.0); + event_recorder[MOTION].ptr = NULL; + } + + if (event.target.ptr && event_recorder[MOTION].ptr != event.target.ptr) { + mui_set_shape_color(event.target.ptr, 0.75, 0.75, 0.75, 1.0); + event_recorder[MOTION].ptr = event.target.ptr; + } + break; + + case MUI_EVENT_MOUSE_PRESS: + if (event.target.ptr && event_recorder[PRESS].ptr != event.target.ptr) { + mui_set_shape_color(event.target.ptr, 0.5, 0.5, 0.5, 1.0); + } + event_recorder[PRESS].ptr = event.target.ptr; + break; + + case MUI_EVENT_MOUSE_RELEASE: + if (event_recorder[PRESS].ptr) { + mui_set_shape_color(event_recorder[PRESS].ptr, 1.0, 1.0, 1.0, 1.0); + event_recorder[PRESS].ptr = NULL; + } + + if (event.target.ptr) { + if (event_recorder[MOTION].ptr) + mui_set_shape_color(event_recorder[MOTION].ptr, 1.0, 1.0, 1.0, 1.0); + + mui_set_shape_color(event.target.ptr, 0.75, 0.75, 0.75, 1.0); + event_recorder[MOTION].ptr = event.target.ptr; + } + } + mui_update(); + } + + + return 0; +} blob - 3ff5ea8b0ea946d3b5df94cfb36ae72da49356b3 blob + fbc205aaa1aeef164dffa8dbda3a069d3a483556 --- demo/shape/Makefile +++ demo/shape/Makefile @@ -4,7 +4,7 @@ INCS= -I ${LIBDIR} LIBS=-Wl,-rpath=${LIBDIR} -L ${LIBDIR} -lmui all: - make MUI_DEBUG=1 -C ${LIBDIR} + make -C ${LIBDIR} ${CC} ${SRCS} -o bin ${INCS} ${LIBS} clean: blob - 3ff5ea8b0ea946d3b5df94cfb36ae72da49356b3 blob + fbc205aaa1aeef164dffa8dbda3a069d3a483556 --- demo/text/Makefile +++ demo/text/Makefile @@ -4,7 +4,7 @@ INCS= -I ${LIBDIR} LIBS=-Wl,-rpath=${LIBDIR} -L ${LIBDIR} -lmui all: - make MUI_DEBUG=1 -C ${LIBDIR} + make -C ${LIBDIR} ${CC} ${SRCS} -o bin ${INCS} ${LIBS} clean: blob - 0bb4a83133f20cb4b6e2c7fea8df799d4a47cc52 blob + d555489a457852e1d81213e465561c078d6ecc12 --- event.c +++ event.c @@ -2,18 +2,20 @@ struct mui_event_handler { uint8_t count; + struct mui_window *mw; TAILQ_HEAD(ev_list, mui_event) head; }; struct mui_event_handler* -mui_create_event_handler() +mui_create_event_handler(struct mui_window *mw) { struct mui_event_handler *handler; handler = calloc(1, sizeof(*handler)); TAILQ_INIT(&handler->head); handler->count = 0; + handler->mw = mw; return handler; } @@ -34,6 +36,10 @@ mui_push_event(struct mui_event_handler *handler, stru current = calloc(1, sizeof(*current)); memcpy(current, event, sizeof(struct mui_event)); + + current->target.id = MUI_UNDEF; + current->target.ptr = NULL; + mui_event_set_target(handler, current); TAILQ_INSERT_HEAD(&handler->head, current, entries); handler->count++; @@ -60,8 +66,159 @@ mui_pop_event(struct mui_event_handler *handler) return event; } + +void set_mouse_press_target(struct mui_event_handler*, struct mui_group*, struct mui_event*); +void set_mouse_release_target(struct mui_event_handler*, struct mui_group*, struct mui_event*); +void set_mouse_motion_target(struct mui_event_handler*, struct mui_group*, struct mui_event*); + void -mui_event_set_target(struct mui_window *mw, struct mui_event *event) +set_mouse_release_target(struct mui_event_handler *handler, struct mui_group *group, + struct mui_event *event) { - struct mui_event_handler *handler; + void *data; + float x; + float y; + uint16_t type; + uint16_t width; + uint16_t height; + float *matrix; + struct member *np; + struct mui_layout *layout; + + np = NULL; + data = NULL; + + while ((np = mui_get_group_next_member(group, np))) { + type = mui_get_group_member_type(np); + data = mui_get_group_member_data(np); + + switch (type) { + case MUI_IMAGE: + layout = mui_get_image_layout(data); + break; + case MUI_SHAPE: + layout = mui_get_shape_layout(data); + break; + case MUI_LABEL: + layout = mui_get_label_layout(data); + break; + case MUI_GROUP: + set_mouse_release_target(handler, data, event); + continue; + } + + if (mui_layout_collide_point(layout, event->mouse_release.x, event->mouse_release.y)) { + event->target.id = type; + event->target.ptr = data; + } + } } + +void +set_mouse_motion_target(struct mui_event_handler *handler, struct mui_group *group, + struct mui_event *event) +{ + void *data; + float x; + float y; + uint16_t type; + uint16_t width; + uint16_t height; + float *matrix; + struct member *np; + struct mui_layout *layout; + + np = NULL; + data = NULL; + + while ((np = mui_get_group_next_member(group, np))) { + type = mui_get_group_member_type(np); + data = mui_get_group_member_data(np); + + switch (type) { + case MUI_IMAGE: + layout = mui_get_image_layout(data); + break; + case MUI_SHAPE: + layout = mui_get_shape_layout(data); + break; + case MUI_LABEL: + layout = mui_get_label_layout(data); + break; + case MUI_GROUP: + set_mouse_motion_target(handler, data, event); + continue; + } + + if (mui_layout_collide_point(layout, event->mouse_motion.x, event->mouse_motion.y)) { + event->target.id = type; + event->target.ptr = data; + } + } +} + +void +set_mouse_press_target(struct mui_event_handler *handler, struct mui_group *group, + struct mui_event *event) +{ + void *data; + float x; + float y; + uint16_t type; + uint16_t width; + uint16_t height; + float *matrix; + struct member *np; + struct mui_layout *layout; + + np = NULL; + data = NULL; + + while ((np = mui_get_group_next_member(group, np))) { + type = mui_get_group_member_type(np); + data = mui_get_group_member_data(np); + + switch (type) { + case MUI_IMAGE: + layout = mui_get_image_layout(data); + break; + case MUI_SHAPE: + layout = mui_get_shape_layout(data); + break; + case MUI_LABEL: + layout = mui_get_label_layout(data); + break; + case MUI_GROUP: + set_mouse_press_target(handler, data, event); + continue; + } + + if (mui_layout_collide_point(layout, event->mouse_press.x, event->mouse_press.y)) { + event->target.id = type; + event->target.ptr = data; + } + } +} + + +void +mui_event_set_target(struct mui_event_handler *handler, struct mui_event *event) +{ + struct mui_group *group; + + group = mui_get_window_group(handler->mw); + + switch (event->type) { + case MUI_EVENT_MOUSE_PRESS: + set_mouse_press_target(handler, group, event); + break; + case MUI_EVENT_MOUSE_RELEASE: + set_mouse_release_target(handler, group, event); + break; + case MUI_EVENT_MOUSE_MOTION: + set_mouse_motion_target(handler, group, event); + break; + default: + break; + } +} blob - 0c08902f9ccd746d7c575b6b0492f8a71e309c01 blob + c9736c535e1c840f9cf282847f9187ef8013f530 --- layout.c +++ layout.c @@ -386,3 +386,34 @@ mui_get_layout_scale_y(struct mui_layout *layout) { return layout->scale_y; } + +int +mui_layout_collide_point(struct mui_layout *layout, int x, int y) +{ + float dx, dy; + float lx, ly; + uint16_t width; + uint16_t height; + + dx = dy = 0; + + if (layout->flags & MUI_ANCHOR_RIGHT) + dx = layout->width * layout->scale_x; + + if (layout->flags & MUI_ANCHOR_CENTER_X) + dx = layout->width / 2.0 * layout->scale_x; + + if (layout->flags & MUI_ANCHOR_CENTER_Y) + dy = layout->height / 2.0 * layout->scale_y; + + if (layout->flags & MUI_ANCHOR_BOTTOM) + dy = layout->height * layout->scale_y; + + lx = layout->x + layout->align_x - dx; + ly = layout->y + layout->align_y - dy; + + width = layout->width * layout->scale_x; + height = layout->height * layout->scale_y; + + return x > lx && x < lx + width && y > ly && y < ly + height; +} blob - 13b3cc23fd96597022a53dc61d2f6b811e1915f7 blob + da95889f4e0ff5ba934cfbafb008d2effea463be --- mui.7 +++ mui.7 @@ -28,6 +28,9 @@ of mui uses XCB to create a context. .sp The context can be reimplemented to be based on OpenGL or other graphics backend by editing the source code. +.Sh EVENT HANDLER +The event handler process events and attach the target drawable. Managing +the callback of these events is up to the developer. .sp .Sh BASICS A mui program needs a display to render its drawable but not to create blob - 31472cc2453fa7899fee5ba80af4de7efa9e60ec blob + 30a8ba0bd7cb98e97ed8cec4a94b029b0316d11e --- mui.h +++ mui.h @@ -98,12 +98,14 @@ struct mui_event { struct mui_event_handler; -struct mui_event_handler *mui_create_event_handler(void); +struct mui_event_handler *mui_create_event_handler(struct mui_window *mw); void mui_push_event(struct mui_event_handler *handler, struct mui_event *event); struct mui_event mui_pop_event(struct mui_event_handler *handler); +void mui_event_set_target(struct mui_event_handler *handler, struct mui_event *event); + /* * This function is very important and should be placed * in the main loop of you GUI program @@ -213,6 +215,8 @@ float mui_get_layout_sca float mui_get_layout_scale_y(struct mui_layout *layout); +int mui_layout_collide_point(struct mui_layout *layout, int x, int y); + /* * This function should be removed later and replaced with a * debugging marcro blob - 5e964f11bdc556ab55781c50157a885f462f5f94 blob + ae3e6a466b9b02b4d8ac140933a1af8bb7b8f830 --- window.c +++ window.c @@ -20,7 +20,7 @@ mui_create_window(const char *name, uint16_t width, ui layout = mui_get_group_layout(mw->group); mui_resize_layout(layout, width, height); mui_set_layout_flags(layout, MUI_EXPAND_X | MUI_EXPAND_Y); - mw->handler = mui_create_event_handler(); + mw->handler = mui_create_event_handler(mw); mw->name = malloc(strlen(name)+1); memcpy(mw->name, name, strlen(name));