Commit Diff


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));