URI: 
       Move keypress/keyrelease handling to separate functions - ltk - GUI toolkit for X11 (WIP)
  HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/ltk.git (encrypted, but very slow)
  HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 9b2b4596605e6594a2538f6b3bce3ffd9e90c652
   DIR parent 5a0a7594e75569bc17cc48a0ec0e5975ec51d54d
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Fri, 10 May 2024 17:59:26 +0200
       
       Move keypress/keyrelease handling to separate functions
       
       Diffstat:
         M src/ltk/combobox.c                  |      19 +++----------------
         M src/ltk/entry.c                     |      55 ++++++++++++-------------------
         M src/ltk/label.c                     |       2 +-
         M src/ltk/label.h                     |       1 -
         M src/ltk/menu.c                      |       1 +
         M src/ltk/menu.h                      |       1 -
         M src/ltk/scrollbar.c                 |       2 ++
         M src/ltk/scrollbar.h                 |       1 -
         M src/ltk/widget.c                    |      41 +++++++++++++++++++++++++++++++
         M src/ltk/widget_internal.h           |       3 +++
         M src/ltk/window.c                    |      31 ++++---------------------------
         M src/ltk/window.h                    |       2 --
       
       12 files changed, 76 insertions(+), 83 deletions(-)
       ---
   DIR diff --git a/src/ltk/combobox.c b/src/ltk/combobox.c
       @@ -373,7 +373,7 @@ choose_external(ltk_widget *self, ltk_key_event *event) {
                (void)event;
                ltk_combobox *combo = LTK_CAST_COMBOBOX(self);
                if (!combo->dropdown || ltk_menu_get_num_entries(combo->dropdown) == 0)
       -                return 0;
       +                return 1;
                ltk_general_config *config = ltk_config_get_general();
                /* FIXME: allow arguments to key mappings - this would allow to have different key mappings
                   for different editors instead of just one command */
       @@ -390,25 +390,12 @@ choose_external(ltk_widget *self, ltk_key_event *event) {
                        ltk_call_cmd(self, config->option_chooser, txtbuf_get_text(tmpbuf), txtbuf_len(tmpbuf));
                        txtbuf_destroy(tmpbuf);
                }
       -        return 0;
       +        return 1;
        }
        
        static int
        ltk_combobox_key_press(ltk_widget *self, ltk_key_event *event) {
       -        ltk_keypress_binding b;
       -        for (size_t i = 0; i < ltk_array_len(keypresses); i++) {
       -                b = ltk_array_get(keypresses, i).b;
       -                if ((b.mods == event->modmask && b.sym != LTK_KEY_NONE && b.sym == event->sym) ||
       -                    (b.mods == (event->modmask & ~LTK_MOD_SHIFT) &&
       -                     ((b.text && event->mapped && !strcmp(b.text, event->mapped)) ||
       -                      (b.rawtext && event->text && !strcmp(b.rawtext, event->text))))) {
       -                        ltk_array_get(keypresses, i).cb.func(self, event);
       -                        self->dirty = 1;
       -                        ltk_window_invalidate_widget_rect(self->window, self);
       -                        return 1;
       -                }
       -        }
       -        return 0;
       +        return ltk_widget_handle_keypress_bindings(self, event, keypresses, 0);
        }
        
        const char *
   DIR diff --git a/src/ltk/entry.c b/src/ltk/entry.c
       @@ -300,7 +300,7 @@ cursor_to_beginning(ltk_widget *self, ltk_key_event *event) {
                wipe_selection(entry);
                entry->pos = 0;
                ensure_cursor_shown(entry);
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -310,7 +310,7 @@ cursor_to_end(ltk_widget *self, ltk_key_event *event) {
                wipe_selection(entry);
                entry->pos = entry->len;
                ensure_cursor_shown(entry);
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -323,7 +323,7 @@ cursor_left(ltk_widget *self, ltk_key_event *event) {
                        entry->pos = ltk_text_line_move_cursor_visually(entry->tl, entry->pos, -1, NULL);
                wipe_selection(entry);
                ensure_cursor_shown(entry);
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -336,7 +336,7 @@ cursor_right(ltk_widget *self, ltk_key_event *event) {
                        entry->pos = ltk_text_line_move_cursor_visually(entry->tl, entry->pos, 1, NULL);
                wipe_selection(entry);
                ensure_cursor_shown(entry);
       -        return 0;
       +        return 1;
        }
        
        static void
       @@ -368,12 +368,12 @@ selection_to_primary(ltk_widget *self, ltk_key_event *event) {
                (void)event;
                ltk_entry *entry = LTK_CAST_ENTRY(self);
                if (entry->sel_end == entry->sel_start)
       -                return 0;
       +                return 1;
                txtbuf *primary = ltk_clipboard_get_primary_buffer(ltk_get_clipboard());
                txtbuf_clear(primary);
                txtbuf_appendn(primary, entry->text + entry->sel_start, entry->sel_end - entry->sel_start);
                ltk_clipboard_set_primary_selection_owner(ltk_get_clipboard());
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -381,12 +381,12 @@ selection_to_clipboard(ltk_widget *self, ltk_key_event *event) {
                (void)event;
                ltk_entry *entry = LTK_CAST_ENTRY(self);
                if (entry->sel_end == entry->sel_start)
       -                return 0;
       +                return 1;
                txtbuf *clip = ltk_clipboard_get_clipboard_buffer(ltk_get_clipboard());
                txtbuf_clear(clip);
                txtbuf_appendn(clip, entry->text + entry->sel_start, entry->sel_end - entry->sel_start);
                ltk_clipboard_set_clipboard_selection_owner(ltk_get_clipboard());
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -394,7 +394,7 @@ switch_selection_side(ltk_widget *self, ltk_key_event *event) {
                (void)event;
                ltk_entry *entry = LTK_CAST_ENTRY(self);
                entry->sel_side = !entry->sel_side;
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -404,7 +404,7 @@ paste_primary(ltk_widget *self, ltk_key_event *event) {
                txtbuf *buf = ltk_clipboard_get_primary_text(ltk_get_clipboard());
                if (buf)
                        insert_text(entry, buf->text, buf->len, 1);
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -414,7 +414,7 @@ paste_clipboard(ltk_widget *self, ltk_key_event *event) {
                txtbuf *buf = ltk_clipboard_get_clipboard_text(ltk_get_clipboard());
                if (buf)
                        insert_text(entry, buf->text, buf->len, 1);
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -422,7 +422,7 @@ expand_selection_left(ltk_widget *self, ltk_key_event *event) {
                (void)event;
                ltk_entry *entry = LTK_CAST_ENTRY(self);
                expand_selection(entry, -1);
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -430,7 +430,7 @@ expand_selection_right(ltk_widget *self, ltk_key_event *event) {
                (void)event;
                ltk_entry *entry = LTK_CAST_ENTRY(self);
                expand_selection(entry, 1);
       -        return 0;
       +        return 1;
        }
        
        static void
       @@ -457,7 +457,7 @@ delete_char_backwards(ltk_widget *self, ltk_key_event *event) {
                        size_t new = prev_utf8(entry->text, entry->pos);
                        delete_text(entry, new, entry->pos);
                }
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -470,7 +470,7 @@ delete_char_forwards(ltk_widget *self, ltk_key_event *event) {
                        size_t new = next_utf8(entry->text, entry->len, entry->pos);
                        delete_text(entry, entry->pos, new);
                }
       -        return 0;
       +        return 1;
        }
        
        static int
       @@ -481,7 +481,7 @@ select_all(ltk_widget *self, ltk_key_event *event) {
                if (entry->len)
                        selection_to_primary(LTK_CAST_WIDGET(entry), NULL);
                entry->sel_side = 0;
       -        return 0;
       +        return 1;
        }
        
        static void
       @@ -580,29 +580,16 @@ edit_external(ltk_widget *self, ltk_key_event *event) {
                        /* FIXME: change interface to not require length of cmd */
                        ltk_call_cmd(LTK_CAST_WIDGET(entry), config->line_editor, entry->text, entry->len);
                }
       -        return 0;
       +        return 1;
        }
        
       -/* FIXME: return values of callbacks are currently ignored - could this be used for anything useful? */
       -/* -> maybe if multiple bindings are configured for the same key? */
        static int
        ltk_entry_key_press(ltk_widget *self, ltk_key_event *event) {
                ltk_entry *entry = LTK_CAST_ENTRY(self);
       -        ltk_keypress_binding b;
       -        for (size_t i = 0; i < ltk_array_len(keypresses); i++) {
       -                b = ltk_array_get(keypresses, i).b;
       -                /* FIXME: change naming (rawtext, text, mapped...) */
       -                /* FIXME: a bit weird to mask out shift, but if that isn't done, it
       -                   would need to be included for all mappings with capital letters */
       -                if ((b.mods == event->modmask && b.sym != LTK_KEY_NONE && b.sym == event->sym) ||
       -                    (b.mods == (event->modmask & ~LTK_MOD_SHIFT) &&
       -                     ((b.text && event->mapped && !strcmp(b.text, event->mapped)) ||
       -                      (b.rawtext && event->text && !strcmp(b.rawtext, event->text))))) {
       -                        ltk_array_get(keypresses, i).cb.func(LTK_CAST_WIDGET(entry), event);
       -                        self->dirty = 1;
       -                        ltk_window_invalidate_widget_rect(self->window, self);
       -                        return 1;
       -                }
       +        if (ltk_widget_handle_keypress_bindings(self, event, keypresses, 0)) {
       +                self->dirty = 1;
       +                ltk_window_invalidate_widget_rect(self->window, self);
       +                return 1;
                }
                if (event->text && (event->modmask & (LTK_MOD_CTRL | LTK_MOD_ALT | LTK_MOD_SUPER)) == 0) {
                        /* FIXME: properly handle everything */
   DIR diff --git a/src/ltk/label.c b/src/ltk/label.c
       @@ -15,8 +15,8 @@
         */
        
        #include <stddef.h>
       -#include <stdint.h>
        
       +#include "config.h"
        #include "memory.h"
        #include "color.h"
        #include "rect.h"
   DIR diff --git a/src/ltk/label.h b/src/ltk/label.h
       @@ -18,7 +18,6 @@
        #define LTK_LABEL_H
        
        #include "text.h"
       -#include "graphics.h"
        #include "widget.h"
        #include "window.h"
        
   DIR diff --git a/src/ltk/menu.c b/src/ltk/menu.c
       @@ -26,6 +26,7 @@
        #include <limits.h>
        
        #include "event.h"
       +#include "config.h"
        #include "memory.h"
        #include "color.h"
        #include "rect.h"
   DIR diff --git a/src/ltk/menu.h b/src/ltk/menu.h
       @@ -19,7 +19,6 @@
        
        #include <stddef.h>
        
       -#include "graphics.h"
        #include "text.h"
        #include "widget.h"
        #include "window.h"
   DIR diff --git a/src/ltk/scrollbar.c b/src/ltk/scrollbar.c
       @@ -17,11 +17,13 @@
        #include <stddef.h>
        
        #include "event.h"
       +#include "config.h"
        #include "memory.h"
        #include "color.h"
        #include "rect.h"
        #include "widget.h"
        #include "util.h"
       +#include "graphics.h"
        #include "scrollbar.h"
        #include "eventdefs.h"
        
   DIR diff --git a/src/ltk/scrollbar.h b/src/ltk/scrollbar.h
       @@ -17,7 +17,6 @@
        #ifndef LTK_SCROLLBAR_H
        #define LTK_SCROLLBAR_H
        
       -#include "graphics.h"
        #include "widget.h"
        #include "window.h"
        
   DIR diff --git a/src/ltk/widget.c b/src/ltk/widget.c
       @@ -14,13 +14,16 @@
         * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
         */
        
       +#include <stddef.h>
        #include <string.h>
        
        #include "rect.h"
       +#include "config.h"
        #include "widget.h"
        #include "window.h"
        #include "memory.h"
        #include "array.h"
       +#include "eventdefs.h"
        
        LTK_ARRAY_INIT_FUNC_DECL_STATIC(signal, ltk_signal_callback_info)
        LTK_ARRAY_INIT_IMPL_STATIC(signal, ltk_signal_callback_info)
       @@ -309,3 +312,41 @@ ltk_widget_recalc_ideal_size(ltk_widget *widget) {
                if (widget->vtable->recalc_ideal_size)
                        widget->vtable->recalc_ideal_size(widget);
        }
       +
       +int
       +ltk_widget_handle_keypress_bindings(ltk_widget *widget, ltk_key_event *event, ltk_array(keypress) *keypresses, int handled) {
       +        if (!keypresses)
       +                return 0;
       +        ltk_keypress_binding *b;
       +        for (size_t i = 0; i < ltk_array_len(keypresses); i++) {
       +                b = &ltk_array_get(keypresses, i).b;
       +                if ((!(b->flags & LTK_KEY_BINDING_RUN_ALWAYS) && handled))
       +                        continue;
       +                /* FIXME: change naming (rawtext, text, mapped...) */
       +                /* FIXME: a bit weird to mask out shift, but if that isn't done, it
       +                   would need to be included for all mappings with capital letters */
       +                if ((b->mods == event->modmask && b->sym != LTK_KEY_NONE && b->sym == event->sym) ||
       +                    (b->mods == (event->modmask & ~LTK_MOD_SHIFT) &&
       +                     ((b->text && event->mapped && !strcmp(b->text, event->mapped)) ||
       +                      (b->rawtext && event->text && !strcmp(b->rawtext, event->text))))) {
       +                        handled |= ltk_array_get(keypresses, i).cb.func(widget, event);
       +                }
       +        }
       +        return handled;
       +}
       +
       +int
       +ltk_widget_handle_keyrelease_bindings(ltk_widget *widget, ltk_key_event *event, ltk_array(keyrelease) *keyreleases, int handled) {
       +        if (!keyreleases)
       +                return 0;
       +        ltk_keyrelease_binding *b = NULL;
       +        for (size_t i = 0; i < ltk_array_len(keyreleases); i++) {
       +                b = &ltk_array_get(keyreleases, i).b;
       +                if (b->mods != event->modmask || (!(b->flags & LTK_KEY_BINDING_RUN_ALWAYS) && handled)) {
       +                        continue;
       +                } else if (b->sym != LTK_KEY_NONE && event->sym == b->sym) {
       +                        handled |= ltk_array_get(keyreleases, i).cb.func(widget, event);
       +                }
       +        }
       +        return handled;
       +}
   DIR diff --git a/src/ltk/widget_internal.h b/src/ltk/widget_internal.h
       @@ -66,4 +66,7 @@ void ltk_window_get_keybinding_parseinfo(
        -> first option maybe just set callback, etc. of current cmd to NULL so widget can still be destroyed */
        int ltk_call_cmd(ltk_widget *caller, ltk_array(cmd) *cmd, const char *text, size_t textlen);
        
       +int ltk_widget_handle_keypress_bindings(ltk_widget *widget, ltk_key_event *event, ltk_array(keypress) *keypresses, int handled);
       +int ltk_widget_handle_keyrelease_bindings(ltk_widget *widget, ltk_key_event *event, ltk_array(keyrelease) *keyreleases, int handled);
       +
        #endif /* LTK_WIDGET_INTERNAL_H */
   DIR diff --git a/src/ltk/window.c b/src/ltk/window.c
       @@ -15,18 +15,19 @@
         * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
         */
        
       -#include <stdlib.h>
        #include <string.h>
        #include <math.h>
        
        #include "ltk.h"
        #include "util.h"
       +#include "color.h"
        #include "array.h"
        #include "widget.h"
        #include "window.h"
        #include "memory.h"
        #include "config.h"
        #include "eventdefs.h"
       +#include "widget_internal.h"
        
        #define MAX_WINDOW_FONT_SIZE 20000
        
       @@ -190,21 +191,7 @@ ltk_window_key_press_event(ltk_widget *self, ltk_key_event *event) {
                                }
                        }
                }
       -        if (!keypresses)
       -                return 1;
       -        ltk_keypress_binding *b = NULL;
       -        /* FIXME: move into separate function and share between window, entry, etc. */
       -        for (size_t i = 0; i < ltk_array_len(keypresses); i++) {
       -                b = &ltk_array_get(keypresses, i).b;
       -                if ((!(b->flags & LTK_KEY_BINDING_RUN_ALWAYS) && handled))
       -                        continue;
       -                if ((b->mods == event->modmask && b->sym != LTK_KEY_NONE && b->sym == event->sym) ||
       -                    (b->mods == (event->modmask & ~LTK_MOD_SHIFT) &&
       -                     ((b->text && event->mapped && !strcmp(b->text, event->mapped)) ||
       -                      (b->rawtext && event->text && !strcmp(b->rawtext, event->text))))) {
       -                        handled |= ltk_array_get(keypresses, i).cb.func(LTK_CAST_WIDGET(window), event);
       -                }
       -        }
       +        ltk_widget_handle_keypress_bindings(self, event, keypresses, handled);
                return 1;
        }
        
       @@ -224,17 +211,7 @@ ltk_window_key_release_event(ltk_widget *self, ltk_key_event *event) {
                                }
                        }
                }
       -        if (!keyreleases)
       -                return 1;
       -        ltk_keyrelease_binding *b = NULL;
       -        for (size_t i = 0; i < ltk_array_len(keyreleases); i++) {
       -                b = &ltk_array_get(keyreleases, i).b;
       -                if (b->mods != event->modmask || (!(b->flags & LTK_KEY_BINDING_RUN_ALWAYS) && handled)) {
       -                        continue;
       -                } else if (b->sym != LTK_KEY_NONE && event->sym == b->sym) {
       -                        handled |= ltk_array_get(keyreleases, i).cb.func(LTK_CAST_WIDGET(window), event);
       -                }
       -        }
       +        ltk_widget_handle_keyrelease_bindings(self, event, keyreleases, handled);
                return 1;
        }
        
   DIR diff --git a/src/ltk/window.h b/src/ltk/window.h
       @@ -18,8 +18,6 @@
        #define LTK_WINDOW_H
        
        #include <stddef.h>
       -#include "color.h"
       -#include "config.h"
        #include "event.h"
        #include "graphics.h"
        #include "rect.h"