diff options
| author | Federico Angelilli <code@fedang.net> | 2023-11-19 01:32:37 +0100 |
|---|---|---|
| committer | Federico Angelilli <code@fedang.net> | 2023-11-19 01:32:37 +0100 |
| commit | 07646612acbc833ec50479eee3564af37636f272 (patch) | |
| tree | b3cfa4d2e90218714c144277b0819065a80090f1 /src | |
| parent | 6dd4c979c40804756ef4d3ca5ac34671c3bcc7e2 (diff) | |
Check button clicks and trigger actions
Diffstat (limited to 'src')
| -rw-r--r-- | src/comet.c | 7 | ||||
| -rw-r--r-- | src/connect.c | 74 | ||||
| -rw-r--r-- | src/draw.c | 9 | ||||
| -rw-r--r-- | src/draw.h | 10 |
4 files changed, 88 insertions, 12 deletions
diff --git a/src/comet.c b/src/comet.c index 21bad7a..2b0cf40 100644 --- a/src/comet.c +++ b/src/comet.c @@ -39,6 +39,11 @@ static void log_handler(const char *log_domain, g_print("%s\n", message); } +static void action(Button *btn) +{ + log_info("Called action: %s", btn->text); +} + int main(int argc, char **argv) { g_log_set_default_handler(log_handler, (gpointer)G_LOG_LEVEL_DEBUG); @@ -65,10 +70,12 @@ int main(int argc, char **argv) for (int i = 0; i < 9; ++i) { char text[] = { '1' + i, '\0' }; Button *btn = button_create(text, true); + button_set_action(btn, action); state_add_button(state, btn); } Button *btn = button_create("long button", false); + button_set_action(btn, action); state_add_button(state, btn); draw_compute_layout(draw, state->btns, window_get_context(win)); diff --git a/src/connect.c b/src/connect.c index 9272a5c..bc45812 100644 --- a/src/connect.c +++ b/src/connect.c @@ -48,6 +48,62 @@ static void update_scale(Connection *con) } } +static inline bool in_rect(int px, int py, int x, int y, int w, int h) +{ + return px >= x && px <= x + w && py >= y && py <= y + h; +} + +static inline bool in_circle(int px, int py, int x, int y, int r) +{ + int dx = x - px; + int dy = y - py; + return (dx * dx + dy * dy) <= r * r; +} + +static inline bool in_capsule(int px, int py, int x, int y, int w, int h) +{ + g_assert(w >= h); + int radius = h / 2; + + // Circle case + if (w == h) return in_circle(px, py, x + radius, y + radius, radius); + + // Capsule case + return in_circle(px, py, x + radius, y + radius, radius) + || in_circle(px, py, x + w - radius, y + radius, radius) + || in_rect(px, py, x + radius, y, w - 2 * radius, h); +} + +static void button_action(State *state, xcb_button_release_event_t *button) +{ + log_debug("Button release event [x=%d, y=%d]", button->event_x, button->event_y); + + for (GList *it = state->draw->layouts; it != NULL; it = it->next) { + Layout *layout = it->data; + + // Skip + if (layout->x + layout->width < button->event_x) continue; + if (layout->x > button->event_x) break; + + bool check = in_capsule(button->event_x, button->event_y, + layout->x, layout->y, + layout->width, layout->height); + + log_debug("Button layout [x=%d, y=%d, w=%d, h=%d]", + layout->x, layout->y, layout->width, layout->height); + + if (check) { + log_debug("Triggering action for button"); + if (layout->btn->action != NULL) { + layout->btn->action(layout->btn); + } + return; + } + } + + log_debug("Ignoring button release"); +} + typedef struct { GSource source; Connection *con; @@ -115,9 +171,21 @@ static gboolean source_dispatch(GSource *source, GSourceFunc callback, gpointer } case XCB_BUTTON_RELEASE: { - log_debug("Mouse event"); - - // TODO: Handle click generically by translating the button code + xcb_button_release_event_t *button = (xcb_button_release_event_t *)xsource->event; + log_debug("Processing event 'ButtonRelease' [type=%d]", XCB_BUTTON_RELEASE); + + // TODO: Handle different actions properly + switch (button->detail) { + case XCB_BUTTON_INDEX_2: // left click + case XCB_BUTTON_INDEX_1: // right click + case XCB_BUTTON_INDEX_3: // middle click + button_action(xsource->con->state, button); + break; + + default: + log_debug("Ignoring button release [button=%d]", button->detail); + break; + } break; } @@ -12,14 +12,6 @@ // (this will also work for animations in the future) // or use some flags to trigger drawing -typedef struct { - Button *btn; - int x, y; - int width, height; - int text_w, text_h; - PangoLayout *pl; -} Layout; - static void layout_destroy(Layout *layout) { g_object_unref(layout->pl); @@ -114,7 +106,6 @@ void draw_paint(Drawable *draw, Window *win) pango_cairo_update_layout(cr, layout->pl); pango_cairo_show_layout(cr, layout->pl); - } cairo_destroy(cr); @@ -3,8 +3,10 @@ #include <glib.h> #include <pango/pango-font.h> +#include <pango/pangocairo.h> #include "window.h" +#include "button.h" typedef struct Drawable Drawable; @@ -18,6 +20,14 @@ struct Drawable { PangoFontDescription *desc; }; +typedef struct { + Button *btn; + int x, y; + int width, height; + int text_w, text_h; + PangoLayout *pl; +} Layout; + Drawable *draw_create(const char *font, int height, int left_pad, int right_pad, int top_pad, double alpha); void draw_compute_layout(Drawable *draw, GList *btns, cairo_t *cr); |
