ltkx

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltkx.git
Log | Files | Refs | README | LICENSE

commit f8162695f7e3ea7d517610987a5fbc614f515878
parent 0d6981b3dbd7dbfcc80fe517414fac3da70822b4
Author: lumidify <nobody@lumidify.org>
Date:   Sun,  1 Jan 2017 18:48:28 +0100

Update event system

Diffstat:
MREADME.md | 4++--
Mbutton.c | 63++++++++++++---------------------------------------------------
Mbutton.h | 3+--
Mcommon.c | 4++--
Mcommon.h | 1+
Mevent.c | 30++++++++++++++++++++----------
Mevent.h | 2+-
Mgrid.c | 117+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mgrid.h | 5+++--
Mtest1.c | 19+++----------------
Athemes/default.ini | 21+++++++++++++++++++++
Mwidget.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mwidget.h | 31+++++++++++++++++++++----------
Mwindow.c | 34++++++----------------------------
Mwindow.h | 4+---
15 files changed, 218 insertions(+), 177 deletions(-)

diff --git a/README.md b/README.md @@ -6,6 +6,6 @@ Please do not attempt to actually use any of the code. ## Licenses of Other Libraries Used -[uthash](https://troydhanson.github.io/uthash/): [BSD Revised](https://troydhanson.github.io/uthash/license.html) +[uthash](https://troydhanson.github.io/uthash/) by Troy D. Hanson: [BSD Revised](https://troydhanson.github.io/uthash/license.html) -[cJSON](https://github.com/DaveGamble/cJSON): [MIT/X](https://github.com/DaveGamble/cJSON/blob/master/LICENSE) +[cJSON](https://github.com/DaveGamble/cJSON) by Dave Gamble: [MIT/X](https://github.com/DaveGamble/cJSON/blob/master/LICENSE) diff --git a/button.c b/button.c @@ -154,6 +154,7 @@ void ltk_draw_button(void *widget) } XSetForeground(ltk_global->display, window->gc, fill_color.pixel); XFillRectangle(ltk_global->display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h); + if (border_width < 1) return; XSetForeground(ltk_global->display, window->gc, border_color.pixel); XSetLineAttributes(ltk_global->display, window->gc, border_width, LineSolid, CapButt, JoinMiter); XDrawRectangle(ltk_global->display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h); @@ -173,11 +174,15 @@ LtkButton *ltk_create_button(LtkWindow *window, const char *text, void (*callbac button->widget.parent = NULL; button->widget.active_widget = NULL; button->widget.hover_widget = NULL; - button->widget.key_func = &ltk_button_key_event; - button->widget.mouse_func = &ltk_button_mouse_event; - button->widget.update_function = NULL; - button->widget.draw_function = &ltk_draw_button; - button->widget.destroy_function = &ltk_destroy_button; + button->widget.key_press = NULL; + button->widget.key_release = NULL; + button->widget.mouse_press = NULL; + button->widget.mouse_release = &ltk_button_mouse_release; + button->widget.motion_notify = NULL; + button->widget.resize = NULL; + button->widget.draw = &ltk_draw_button; + button->widget.destroy = &ltk_destroy_button; + button->widget.redraw_state = 1; button->widget.rect.x = 0; button->widget.rect.y = 0; /* For testing, will default to size of text once text is implemented */ @@ -206,52 +211,8 @@ void ltk_button_key_event(void *widget, XEvent event) { } -void ltk_button_mouse_event(void *widget, XEvent event) + +void ltk_button_mouse_release(void *widget, XEvent event) { LtkButton *button = widget; - if (button->widget.state == DISABLED) - { - return; - } - if (event.type == ButtonPress && event.xbutton.button == 1) - { - LtkWidget *parent = button->widget.parent; - if (parent) - { - ltk_remove_active_widget(parent); - parent->active_widget = button; - } - button->widget.state = PRESSED; - ltk_draw_button(button); - } - else if (event.type == ButtonRelease) - { - if (button->widget.state == PRESSED) - { - button->widget.state = HOVERACTIVE; - ltk_draw_button(button); - } - } - else if (event.type == MotionNotify) - { - if (button->widget.state == NORMAL || button->widget.state == ACTIVE) - { - if (button->widget.state == ACTIVE) - { - button->widget.state = HOVERACTIVE; - } - else - { - button->widget.state = HOVER; - } - LtkWidget *parent = button->widget.parent; - LtkWidget *hover_widget; - if (parent) - { - ltk_remove_hover_widget(parent); - parent->hover_widget = button; - } - ltk_draw_button(button); - } - } } diff --git a/button.h b/button.h @@ -72,7 +72,6 @@ LtkButton *ltk_create_button(LtkWindow *window, const char *text, void (*callbac void ltk_button_key_event(void *widget, XEvent event); void ltk_button_mouse_event(void *widget, XEvent event); void ltk_destroy_button(void *widget); -void ltk_button_key_event(void *widget, XEvent event); -void ltk_button_mouse_event(void *widget, XEvent event); +void ltk_button_mouse_release(void *widget, XEvent event); #endif diff --git a/common.c b/common.c @@ -56,7 +56,7 @@ void ltk_remove_active_widget(void *widget) { child = parent->active_widget; child->state = NORMAL; - child->draw_function(child); + child->draw(child); parent->active_widget = NULL; parent = child; } @@ -73,7 +73,7 @@ void ltk_remove_hover_widget(void *widget) { child = parent->hover_widget; child->state = child->state == HOVERACTIVE ? ACTIVE : NORMAL; - child->draw_function(child); + child->draw(child); parent->hover_widget = NULL; parent = child; } diff --git a/common.h b/common.h @@ -24,6 +24,7 @@ #ifndef _LTK_COMMON_H_ #define _LTK_COMMON_H_ +typedef void (*LTK_VOID_FUNC)(void *); typedef struct LtkWidget LtkWidget; typedef enum diff --git a/event.c b/event.c @@ -26,17 +26,27 @@ void ltk_handle_event(XEvent event) { LtkWindow *window; + LtkWidget *root_widget; HASH_FIND_INT(ltk_global->window_hash, &event.xany.window, window); - if ((event.type == KeyPress || event.type == KeyRelease) && window->key_func) + root_widget = window->root_widget; + if (!root_widget) return; + switch (event.type) { - window->key_func(window, event); - } - else if ((event.type == ButtonPress || event.type == ButtonRelease || event.type == MotionNotify) && window->mouse_func) - { - window->mouse_func(window, event); - } - else if (window->other_func) - { - window->other_func(window, event); + case KeyPress: + break; + case KeyRelease: + break; + case ButtonPress: + ltk_mouse_press_event(root_widget, event); + break; + case ButtonRelease: + ltk_mouse_release_event(root_widget, event); + break; + case MotionNotify: + ltk_motion_notify_event(root_widget, event); + break; + default: + if (window->other_event) + window->other_event(window, event); } } diff --git a/event.h b/event.h @@ -26,6 +26,6 @@ #ifndef _LTK_EVENT_H_ #define _LTK_EVENT_H_ -typedef void (*LTK_EVENT_FUNC)(void *widget, XEvent event); +typedef void (*LTK_EVENT_FUNC)(void *, XEvent); #endif diff --git a/grid.c b/grid.c @@ -42,12 +42,9 @@ void ltk_draw_grid(LtkGrid *grid) int i; for (i = 0; i < grid->rows * grid->columns; i++) { - if (!grid->widget_grid[i]) - { - continue; - } + if (!grid->widget_grid[i]) continue; LtkWidget *ptr = grid->widget_grid[i]; - ptr->draw_function(ptr); + ptr->draw(ptr); } } @@ -57,11 +54,15 @@ LtkGrid *ltk_create_grid(LtkWindow *window, int rows, int columns) grid->widget.window = window; grid->widget.parent = NULL; - grid->widget.key_func = &ltk_grid_key_event; - grid->widget.mouse_func = &ltk_grid_mouse_event; - grid->widget.update_function = &ltk_recalculate_grid; - grid->widget.draw_function = &ltk_draw_grid; - grid->widget.destroy_function = &ltk_destroy_grid; + grid->widget.mouse_press = &ltk_grid_mouse_press; + grid->widget.mouse_release = &ltk_grid_mouse_release; + grid->widget.motion_notify = &ltk_grid_motion_notify; + grid->widget.key_press = NULL; + grid->widget.key_release = NULL; + grid->widget.resize = &ltk_recalculate_grid; + grid->widget.draw = &ltk_draw_grid; + grid->widget.destroy = &ltk_destroy_grid; + grid->widget.redraw_state = 0; grid->widget.rect.x = 0; grid->widget.rect.y = 0; grid->widget.rect.w = 0; @@ -113,7 +114,7 @@ void ltk_destroy_grid(void *widget) if (grid->widget_grid[i]) { ptr = grid->widget_grid[i]; - ptr->destroy_function(ptr); + ptr->destroy(ptr); } } free(grid->widget_grid); @@ -203,9 +204,9 @@ void ltk_recalculate_grid(void *widget) } if (orig_width != ptr->rect.w || orig_height != ptr->rect.h) { - if (ptr->update_function) + if (ptr->resize) { - ptr->update_function(ptr); + ptr->resize(ptr); } } @@ -246,10 +247,12 @@ void ltk_grid_widget(void *ptr, LtkGrid *grid, int row, int column, int row_span widget->column = column; widget->row_span = row_span; widget->column_span = column_span; - if (grid->column_weights[column] == 0 && widget->rect.w > grid->column_widths[column]) { + if (grid->column_weights[column] == 0 && widget->rect.w > grid->column_widths[column]) + { grid->column_widths[column] = widget->rect.w; } - if (grid->row_weights[row] == 0 && widget->rect.h > grid->row_heights[row]) { + if (grid->row_weights[row] == 0 && widget->rect.h > grid->row_heights[row]) + { grid->row_heights[row] = widget->rect.h; } grid->widget_grid[widget->row * grid->columns + widget->column] = widget; @@ -257,57 +260,71 @@ void ltk_grid_widget(void *ptr, LtkGrid *grid, int row, int column, int row_span ltk_recalculate_grid(grid); } -void ltk_grid_key_event(void *widget, XEvent event) -{ - LtkGrid *grid = widget; - LtkWidget *ptr = grid->widget.active_widget; - if (ptr && ptr->key_func) - { - ptr->key_func(ptr, event); - } -} - -void ltk_grid_mouse_event(void *widget, XEvent event) +int ltk_grid_find_nearest_column(LtkGrid *grid, int x) { - LtkGrid *grid = widget; - LtkWidget *ptr; int i; - int x, y; - int row, column; - if (event.type == ButtonPress || event.type == ButtonRelease) - { - x = event.xbutton.x; - y = event.xbutton.y; - } - else if (event.type == MotionNotify) - { - x = event.xmotion.x; - y = event.xmotion.y; - } for (i = 0; i < grid->columns; i++) { if (grid->column_pos[i] <= x && grid->column_pos[i + 1] >= x) { - column = i; + return i; } } +} + +int ltk_grid_find_nearest_row(LtkGrid *grid, int y) +{ + int i; for (i = 0; i < grid->rows; i++) { if (grid->row_pos[i] <= y && grid->row_pos[i + 1] >= y) { - row = i; + return i; } } - ptr = grid->widget_grid[row * grid->columns + column]; - if (ptr && ptr->mouse_func) +} + +ltk_grid_mouse_press(void *widget, XEvent event) +{ + LtkGrid *grid = widget; + int x = event.xbutton.x; + int y = event.xbutton.y; + int row = ltk_grid_find_nearest_row(grid, y); + int column = ltk_grid_find_nearest_column(grid, x); + LtkWidget *ptr = grid->widget_grid[row * grid->columns + column]; + if (ptr && ltk_collide_rect(ptr->rect, x, y)) + { + ltk_mouse_press_event(ptr, event); + } +} + +ltk_grid_mouse_release(void *widget, XEvent event) +{ + LtkGrid *grid = widget; + int x = event.xbutton.x; + int y = event.xbutton.y; + int row = ltk_grid_find_nearest_row(grid, y); + int column = ltk_grid_find_nearest_column(grid, x); + LtkWidget *ptr = grid->widget_grid[row * grid->columns + column]; + if (ptr && ltk_collide_rect(ptr->rect, x, y)) + { + ltk_mouse_release_event(ptr, event); + } +} + +ltk_grid_motion_notify(void *widget, XEvent event) +{ + LtkGrid *grid = widget; + int x = event.xbutton.x; + int y = event.xbutton.y; + int row = ltk_grid_find_nearest_row(grid, y); + int column = ltk_grid_find_nearest_column(grid, x); + LtkWidget *ptr = grid->widget_grid[row * grid->columns + column]; + if (ptr) { if (ltk_collide_rect(ptr->rect, x, y)) - { - ptr->mouse_func(ptr, event); - } - else if (grid->widget.hover_widget) - { + ltk_motion_notify_event(ptr, event); + else ltk_remove_hover_widget(grid); - } } } diff --git a/grid.h b/grid.h @@ -46,8 +46,9 @@ void ltk_draw_grid(LtkGrid *grid); LtkGrid *ltk_create_grid(LtkWindow *window, int rows, int columns); void ltk_destroy_grid(void *widget); void ltk_recalculate_grid(void *widget); -void ltk_grid_key_event(void *widget, XEvent event); -void ltk_grid_mouse_event(void *widget, XEvent event); void ltk_grid_widget(void *ptr, LtkGrid *grid, int row, int column, int rowspan, int columnspan, int sticky[4]); +void ltk_grid_mouse_press(void *widget, XEvent event); +void ltk_grid_mouse_release(void *widget, XEvent event); +void ltk_grid_motion_notify(void *widget, XEvent event); #endif diff --git a/test1.c b/test1.c @@ -1,21 +1,8 @@ #include "ltk.h" -void bob(void *window, XEvent event) +void bob1(void) { - KeySym key; - char text[255]; - if (XLookupString(&event.xkey, text, 255, &key, 0) == 1) - { - if (text[0] == 'q') - { - ltk_quit(); - } - } -} - -void bob1(void *window, XEvent event) -{ - printf("mouse\n"); + printf("bob\n"); } int main(int argc, char *argv[]) @@ -28,7 +15,7 @@ int main(int argc, char *argv[]) ltk_set_row_weight(grid1, 1, 1); ltk_set_column_weight(grid1, 0, 1); ltk_set_column_weight(grid1, 1, 1); - LtkButton *button1 = ltk_create_button(window1, "I'm a button!", NULL); + LtkButton *button1 = ltk_create_button(window1, "I'm a button!", &bob1); int sticky1[4] = {0, 1, 0, 1}; ltk_grid_widget(button1, grid1, 0, 0, 1, 1, sticky1); LtkButton *button2 = ltk_create_button(window1, "I'm a button!", NULL); diff --git a/themes/default.ini b/themes/default.ini @@ -0,0 +1,21 @@ +[window] +border_width = 0 +background = #000000 +foreground = #FFFFFF + +[button] +border_width = 2 +font_size = 20 +border_color = #339999 +fill_color = #113355 +pad_left = 5 +pad_right = 5 +pad_top = 5 +pad_bottom = 5 +fill_color_hover = 738194 +border_color_pressed = #FFFFFF +fill_color_pressed = 113355 +border_color_active = #FFFFFF +fill_color_active = #113355 +border_color_disabled = #FFFFFF +fill_color_disabled = #292929 diff --git a/widget.c b/widget.c @@ -21,3 +21,60 @@ * SOFTWARE. */ +#include "ltk.h" + +void ltk_mouse_press_event(void *widget, XEvent event) +{ + LtkWidget *ptr = widget; + if (!ptr || ptr->state == DISABLED) return; + if (event.xbutton.button == 1) + { + LtkWidget *parent = ptr->parent; + if (parent) + { + ltk_remove_active_widget(parent); + parent->active_widget = ptr; + } + ptr->state = PRESSED; + if (ptr->redraw_state) ptr->draw(ptr); + } + if (ptr->mouse_press) + { + ptr->mouse_press(ptr, event); + } +} + +void ltk_mouse_release_event(void *widget, XEvent event) +{ + LtkWidget *ptr = widget; + if (!ptr || ptr->state == DISABLED) return; + if (ptr->state == PRESSED) + { + ptr->state = HOVERACTIVE; + if (ptr->redraw_state) ptr->draw(ptr); + } + if (ptr->mouse_release) + { + ptr->mouse_release(ptr, event); + } +} + +void ltk_motion_notify_event(void *widget, XEvent event) +{ + LtkWidget *ptr = widget; + if (!ptr || ptr->state == NORMAL || ptr->state == ACTIVE) + { + ptr->state = ptr->state == ACTIVE ? HOVERACTIVE : HOVER; + LtkWidget *parent = ptr->parent; + if (parent) + { + ltk_remove_hover_widget(parent); + parent->hover_widget = ptr; + } + if (ptr->redraw_state) ptr->draw(ptr); + } + if (ptr->motion_notify) + { + ptr->motion_notify(ptr, event); + } +} diff --git a/widget.h b/widget.h @@ -38,18 +38,29 @@ typedef struct LtkWidget void *hover_widget; /* Parent widget */ void *parent; - /* Function to be called on a KeyPress or KeyRelease event */ - LTK_EVENT_FUNC key_func; - /* Function to be called on a ButtonPress, ButtonRelease, or MotionNotify event */ - LTK_EVENT_FUNC mouse_func; - /* For container widgets; function to be called when the widget is resized */ - void (*update_function)(void *); + + /* Called on KeyPress events */ + void (*key_press)(void *, XEvent event); + /* Called on KeyRelease events */ + void (*key_release)(void *, XEvent event); + /* Called on ButtonPress events */ + void (*mouse_press)(void *, XEvent event); + /* Called on ButtonRelease event */ + void (*mouse_release)(void *, XEvent event); + /* Called on MotionNotify events */ + void (*motion_notify)(void *, XEvent event); + + /* Function to update the widget after its LtkRect has been modified */ + void (*resize)(void *); /* Function to draw the widget */ - void (*draw_function)(void *); - /* State of the widget; NORMAL, PRESSED, ACTIVE, HOVER, or DISABLED */ + void (*draw)(void *); + /* Function to destroy the widget */ + void (*destroy)(void *); + + /* Specifies if the widget needs to be redrawn after a state change */ + int redraw_state; + /* State of the widget */ LtkWidgetState state; - /* Function to destroy the widget; used by containers to destroy child widgets */ - void (*destroy_function)(void *); /* Position and size of the widget */ LtkRect rect; /* Row of widget if gridded */ diff --git a/window.c b/window.c @@ -49,7 +49,7 @@ void ltk_redraw_window(LtkWindow *window) return; } ptr = window->root_widget; - ptr->draw_function(ptr); + ptr->draw(ptr); } LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h) @@ -65,9 +65,7 @@ LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, un XSetStandardProperties(display, window->xwindow, title, NULL, None, NULL, 0, NULL); window->root_widget = NULL; - window->key_func = &ltk_window_key_event; - window->mouse_func = &ltk_window_mouse_event; - window->other_func = &ltk_window_other_event; + window->other_event = &ltk_window_other_event; window->rect.w = 0; window->rect.h = 0; @@ -88,31 +86,11 @@ void ltk_destroy_window(LtkWindow *window) LtkWidget *ptr = window->root_widget; if (ptr) { - ptr->destroy_function(ptr); + ptr->destroy(ptr); } free(window); } -void ltk_window_key_event(void *widget, XEvent event) -{ - LtkWindow *window = widget; - LtkWidget *ptr = window->root_widget; - if (ptr && ptr->key_func) - { - ptr->key_func(ptr, event); - } -} - -void ltk_window_mouse_event(void *widget, XEvent event) -{ - LtkWindow *window = widget; - LtkWidget *ptr = window->root_widget; - if (ptr && ptr->mouse_func) - { - ptr->mouse_func(ptr, event); - } -} - void ltk_window_other_event(void *widget, XEvent event) { LtkWindow *window = widget; @@ -122,13 +100,13 @@ void ltk_window_other_event(void *widget, XEvent event) unsigned int w, h; w = event.xconfigure.width; h = event.xconfigure.height; - if (ptr && ptr->update_function && (window->rect.w != w || window->rect.h != h)) + if (ptr && ptr->resize && (window->rect.w != w || window->rect.h != h)) { window->rect.w = w; window->rect.h = h; ptr->rect.w = w; ptr->rect.h = h; - ptr->update_function(ptr); + ptr->resize(ptr); ltk_redraw_window(window); } } @@ -155,7 +133,7 @@ void ltk_resize_window(Uint32 id, int w, int h) } ptr->rect.w = w; ptr->rect.h = h; - ptr->update_function(ptr); + ptr->resize(ptr); } void ltk_window_set_root_widget(LtkWindow *window, void *root_widget) diff --git a/window.h b/window.h @@ -32,9 +32,7 @@ typedef struct LtkWindow Window xwindow; GC gc; void *root_widget; - LTK_EVENT_FUNC key_func; /* Called on any keyboard event */ - LTK_EVENT_FUNC mouse_func; /* Called on any mouse event */ - LTK_EVENT_FUNC other_func; /* Called on any other event */ + void (*other_event)(void *, XEvent event); LtkRect rect; UT_hash_handle hh; } LtkWindow;