URI: 
       tTurn the basic framework into a single .c and .h file pair - ltkx - GUI toolkit for X11 (WIP)
  HTML git clone git://lumidify.org/ltkx.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit a8d438e533db40481c75ddd952a14f14b6f68c94
   DIR parent 8a3b7084765b5ce72d0e55adf283e737a0049e03
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Thu,  5 Jan 2017 10:24:48 +0100
       
       Turn the basic framework into a single .c and .h file pair
       
       Diffstat:
         M Makefile                            |       2 +-
         D common.c                            |     208 -------------------------------
         D common.h                            |     187 -------------------------------
         M ltk.c                               |     328 +++++++++++++++++++++++++++++++
         M ltk.h                               |     246 ++++++++++++++++++++++++++++++-
         D theme.c                             |      64 -------------------------------
         D theme.h                             |      51 -------------------------------
         D window.c                            |     153 -------------------------------
         D window.h                            |      54 -------------------------------
       
       9 files changed, 571 insertions(+), 722 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       t@@ -1,7 +1,7 @@
        LIBS = -lX11 -lm -ldl
        STD = -std=c89
        FLAGS = -g -w -Wall -Werror -Wextra -pedantic
       -CFILES = ltk.c cJSON.c common.c grid.c window.c theme.c button.c test1.c
       +CFILES = ltk.c cJSON.c grid.c button.c test1.c
        
        all: test1.c
                gcc $(STD) $(FLAGS) $(LIBS) $(CFILES) -o test
   DIR diff --git a/common.c b/common.c
       t@@ -1,208 +0,0 @@
       -/*
       - * This file is part of the Lumidify ToolKit (LTK)
       - * Copyright (c) 2016, 2017 Lumidify Productions <lumidify@openmailbox.org>
       - *
       - * Permission is hereby granted, free of charge, to any person obtaining a copy
       - * of this software and associated documentation files (the "Software"), to deal
       - * in the Software without restriction, including without limitation the rights
       - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       - * copies of the Software, and to permit persons to whom the Software is
       - * furnished to do so, subject to the following conditions:
       - *
       - * The above copyright notice and this permission notice shall be included in all
       - * copies or substantial portions of the Software.
       - *
       - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       - * SOFTWARE.
       - */
       -
       -#include "ltk.h"
       -
       -char *ltk_read_file(const char *path)
       -{
       -    FILE *f;
       -    long len;
       -    char *file_contents;
       -    f = fopen(path, "rb");
       -    fseek(f, 0, SEEK_END);
       -    len = ftell(f);
       -    fseek(f, 0, SEEK_SET);
       -    file_contents = malloc(len + 1);
       -    fread(file_contents, 1, len, f);
       -    file_contents[len] = '\0';
       -    fclose(f);
       -
       -    return file_contents;
       -}
       -
       -int ltk_collide_rect(LtkRect rect, int x, int y)
       -{
       -    return (rect.x <= x && (rect.x + rect.w) >= x && rect.y <= y && (rect.y + rect.h) >= y);
       -}
       -
       -void ltk_remove_active_widget(void *widget)
       -{
       -    if (!widget) return;
       -    LtkWidget *parent = widget;
       -    LtkWidget *child;
       -    while (parent->active_widget)
       -    {
       -        child = parent->active_widget;
       -        child->state = LTK_NORMAL;
       -        child->draw(child);
       -        parent->active_widget = NULL;
       -        parent = child;
       -    }
       -}
       -
       -void ltk_change_active_widget_state(void *widget, LtkWidgetState state)
       -{
       -    if (!widget) return;
       -    LtkWidget *ptr = widget;
       -    while (ptr = ptr->active_widget)
       -    {
       -        ptr->state = state;
       -        ptr->draw(ptr);
       -    }
       -}
       -
       -void ltk_remove_hover_widget(void *widget)
       -{
       -    if (!widget) return;
       -    LtkWidget *parent = widget;
       -    LtkWidget *child;
       -    while (parent->hover_widget)
       -    {
       -        child = parent->hover_widget;
       -        child->state = child->state == LTK_HOVERACTIVE ? LTK_ACTIVE : LTK_NORMAL;
       -        child->draw(child);
       -        parent->hover_widget = NULL;
       -        parent = child;
       -    }
       -}
       -
       -LtkWidget ltk_create_widget(LtkWindow *window, void (*draw)(void *), void (*destroy)(void *), int needs_redraw)
       -{
       -    LtkWidget widget;
       -    widget.window = window;
       -    widget.active_widget = NULL;
       -    widget.hover_widget = NULL;
       -    widget.parent = NULL;
       -
       -    widget.key_press = NULL;
       -    widget.key_release = NULL;
       -    widget.mouse_press = NULL;
       -    widget.mouse_release = NULL;
       -    widget.motion_notify = NULL;
       -
       -    widget.resize = NULL;
       -    widget.draw = draw;
       -    widget.destroy = destroy;
       -
       -    widget.needs_redraw = needs_redraw;
       -    widget.state = LTK_NORMAL;
       -    widget.row = 0;
       -    widget.rect.x = 0;
       -    widget.rect.y = 0;
       -    widget.rect.w = 100;
       -    widget.rect.h = 100;
       -
       -    widget.row = NULL;
       -    widget.column = NULL;
       -    widget.row_span = NULL;
       -    widget.column_span = NULL;
       -    widget.sticky = NULL;
       -
       -    return widget;
       -}
       -
       -void ltk_mouse_press_event(void *widget, XEvent event)
       -{
       -    LtkWidget *ptr = widget;
       -    if (!ptr || ptr->state == LTK_DISABLED) return;
       -    if (event.xbutton.button == 1)
       -    {
       -        LtkWidget *parent = ptr->parent;
       -        if (parent)
       -        {
       -            ltk_remove_active_widget(parent);
       -            parent->active_widget = ptr;
       -        }
       -        ptr->state = LTK_PRESSED;
       -        if (ptr->needs_redraw) 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 == LTK_DISABLED) return;
       -    if (ptr->state == LTK_PRESSED)
       -    {
       -        ptr->state = LTK_HOVERACTIVE;
       -        if (ptr->needs_redraw) 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 == LTK_NORMAL || ptr->state == LTK_ACTIVE) &&
       -        (event.xmotion.state & Button1Mask) != Button1Mask)
       -    {
       -        ptr->state = ptr->state == LTK_ACTIVE ? LTK_HOVERACTIVE : LTK_HOVER;
       -        LtkWidget *parent = ptr->parent;
       -        if (parent)
       -        {
       -            ltk_remove_hover_widget(parent);
       -            parent->hover_widget = ptr;
       -        }
       -        if (ptr->needs_redraw) ptr->draw(ptr);
       -    }
       -    if (ptr->motion_notify)
       -    {
       -        ptr->motion_notify(ptr, event);
       -    }
       -}
       -
       -void ltk_handle_event(XEvent event)
       -{
       -    LtkWindow *window;
       -    LtkWidget *root_widget;
       -    HASH_FIND_INT(ltk_global->window_hash, &event.xany.window, window);
       -    if (!window) return;
       -    root_widget = window->root_widget;
       -    switch (event.type)
       -    {
       -    case KeyPress:
       -        break;
       -    case KeyRelease:
       -        break;
       -    case ButtonPress:
       -        if (root_widget) ltk_mouse_press_event(root_widget, event);
       -        break;
       -    case ButtonRelease:
       -        if (root_widget) ltk_mouse_release_event(root_widget, event);
       -        break;
       -    case MotionNotify:
       -        if (root_widget) ltk_motion_notify_event(root_widget, event);
       -        break;
       -    default:
       -        /* FIXME: users should be able to register other events like closing the window */
       -        if (window->other_event)
       -            window->other_event(window, event);
       -    }
       -}
   DIR diff --git a/common.h b/common.h
       t@@ -1,187 +0,0 @@
       -/*
       - * This file is part of the Lumidify ToolKit (LTK)
       - * Copyright (c) 2016, 2017 Lumidify Productions <lumidify@openmailbox.org>
       - *
       - * Permission is hereby granted, free of charge, to any person obtaining a copy
       - * of this software and associated documentation files (the "Software"), to deal
       - * in the Software without restriction, including without limitation the rights
       - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       - * copies of the Software, and to permit persons to whom the Software is
       - * furnished to do so, subject to the following conditions:
       - *
       - * The above copyright notice and this permission notice shall be included in all
       - * copies or substantial portions of the Software.
       - *
       - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       - * SOFTWARE.
       - */
       -
       -#ifndef _LTK_COMMON_H_
       -#define _LTK_COMMON_H_
       -
       -typedef struct LtkWidget LtkWidget;
       -typedef struct LtkWindow LtkWindow;
       -
       -/*
       - * Struct to represent a rectangle.
       - */
       -typedef struct
       -{
       -    int x;
       -    int y;
       -    int w;
       -    int h;
       -} LtkRect;
       -
       -typedef enum {
       -    LTK_STICKY_LEFT = 1 << 0,
       -    LTK_STICKY_RIGHT = 1 << 1,
       -    LTK_STICKY_TOP = 1 << 2,
       -    LTK_STICKY_BOTTOM = 1 << 3
       -} LtkStickyMask;
       -
       -/*
       - * An enumeration of all widget states.
       - */
       -typedef enum
       -{
       -    LTK_NORMAL = 0,
       -    LTK_HOVER = 1,
       -    LTK_PRESSED = 2,
       -    LTK_ACTIVE = 3,
       -    LTK_HOVERACTIVE = 4,
       -    LTK_DISABLED = 5
       -} LtkWidgetState;
       -
       -/*
       - * A struct to contain all basic widget information.
       - * First element of every widget so the widget can
       - * be cast to LtkWidget.
       - */
       -typedef struct LtkWidget
       -{
       -    /* The window the widget will be displayed on */
       -    LtkWindow *window;
       -    /* For container widgets; the widget that is currently active */
       -    struct LtkWidget *active_widget;
       -    /* For container widgets; the widget that is currently highlighted */
       -    struct LtkWidget *hover_widget;
       -    /* Parent widget */
       -    struct LtkWidget *parent;
       -
       -    /* 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)(void *);
       -    /* Function to destroy the widget */
       -    void (*destroy)(void *);
       -
       -    /* Position and size of the widget */
       -    LtkRect rect;
       -    /* Row of widget if gridded */
       -    unsigned int row;
       -    /* Column of widget if gridded */
       -    unsigned int column;
       -    /* Row span of widget if gridded */
       -    unsigned int row_span;
       -    /* Column span of widget if gridded */
       -    unsigned int column_span;
       -    /* Specifies if the widget needs to be redrawn after a state change */
       -    int needs_redraw : 1;
       -    /* State of the widget */
       -    LtkWidgetState state : 3;
       -    /* Similar to sticky in tk */
       -    unsigned short sticky : 4;
       -} LtkWidget;
       -
       -
       -/*
       - * Check if a rectangle collides with a point.
       - * rect: The rectangle.
       - * x: The x coordinate of the point.
       - * y: The y coordinate of the point.
       - */
       -int ltk_collide_rect(LtkRect rect, int x, int y);
       -
       -/*
       - * Read a file and return a null-terminated string with the contents.
       - * path: The path to the file.
       - */
       -char *ltk_read_file(const char *path);
       -
       -/*
       - * Recursively set the state of all active_widgets in 'widget' to 'state'.
       - */
       -void ltk_change_active_widget_state(void *widget, LtkWidgetState state);
       -
       -/*
       - * Recursively set the state of all active_widgets in 'widget' to LTK_NORMAL,
       - * redraw the widgets, and remove the references to them from their parents.
       - */
       -void ltk_remove_active_widget(void *widget);
       -
       -/*
       - * Recursively set the state of all hover_widgets in 'widget' to LTK_NORMAL or
       - * LTK_ACTIVE, redraw the widgets, and remove the references to them from their parents.
       - */
       -void ltk_remove_hover_widget(void *widget);
       -
       -/*
       - * Create a widget.
       - * window: The window the widget is to be shown on.
       - * draw: The function used to draw the widget.
       - * destroy: The function used to destroy the widget.
       - * needs_redraw: Flag to indicate if the widget needs to be
       - *               be redrawn when it is resized.
       - * Returns: The new LtkWidget.
       - */
       -LtkWidget ltk_create_widget(LtkWindow *window, void (*draw)(void *), void (*destroy)(void *), int needs_redraw);
       -
       -/*
       - * Handles mouse press events for all widgets and calls
       - * specific widget handlers if set.
       - * widget: Pointer to the widget the mouse is currrently on.
       - * event: The event to be handled.
       - */
       -void ltk_mouse_press_event(void *widget, XEvent event);
       -
       -/*
       - * Handles mouse release events for all widgets and calls
       - * specific widget handlers if set.
       - * widget: Pointer to the widget the mouse is currrently on.
       - * event: The event to be handled.
       - */
       -void ltk_mouse_release_event(void *widget, XEvent event);
       -
       -/*
       - * Handles mouse motion events for all widgets and calls
       - * specific widget handlers if set.
       - * widget: Pointer to the widget the mouse is currrently on.
       - * event: The event to be handled.
       - */
       -void ltk_motion_notify_event(void *widget, XEvent event);
       -
       -/*
       - * Handles all events and dispatches them to their
       - * respective handlers.
       - * event: The event to be handled.
       - */
       -void ltk_handle_event(XEvent event);
       -
       -#endif
   DIR diff --git a/ltk.c b/ltk.c
       t@@ -91,3 +91,330 @@ void ltk_mainloop(void)
                */
            }
        }
       +
       +LtkWindowTheme *ltk_parse_window_theme(cJSON *window_json)
       +{
       +    LtkWindowTheme *window_theme = malloc(sizeof(LtkWindowTheme));
       +    if (!window_theme) ltk_fatal("No memory for new LtkWindowTheme\n");
       +    cJSON *border_width = cJSON_GetObjectItem(window_json, "border-width");
       +    cJSON *fg = cJSON_GetObjectItem(window_json, "foreground");
       +    cJSON *bg = cJSON_GetObjectItem(window_json, "background");
       +    window_theme->border_width = border_width ? border_width->valueint : 0;
       +    window_theme->fg = ltk_create_xcolor(fg->valuestring);
       +    window_theme->bg = ltk_create_xcolor(bg->valuestring);
       +
       +    return window_theme;
       +}
       +
       +void ltk_redraw_window(LtkWindow *window)
       +{
       +    LtkWidget *ptr;
       +    if (!window)
       +    {
       +        return;
       +    }
       +    if (!window->root_widget)
       +    {
       +        return;
       +    }
       +    ptr = window->root_widget;
       +    ptr->draw(ptr);
       +}
       +
       +LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h)
       +{
       +    LtkWindow *window = malloc(sizeof(LtkWindow));
       +    if (!window) ltk_fatal("Not enough memory left for window!\n");
       +    LtkWindowTheme *wtheme = ltk_global->theme->window; /* For convenience */
       +    Display *display = ltk_global->display; /* For convenience */
       +    window->xwindow = XCreateSimpleWindow(display, DefaultRootWindow(display), x, y, w, h, wtheme->border_width, wtheme->fg.pixel, wtheme->bg.pixel);
       +    window->gc = XCreateGC(display, window->xwindow, 0, 0);
       +    XSetForeground(display, window->gc, wtheme->fg.pixel);
       +    XSetBackground(display, window->gc, wtheme->bg.pixel);
       +    XSetStandardProperties(display, window->xwindow, title, NULL, None, NULL, 0, NULL);
       +    XSetWMProtocols(display, window->xwindow, &ltk_global->wm_delete_msg, 1);
       +    window->root_widget = NULL;
       +
       +    window->other_event = &ltk_window_other_event;
       +
       +    window->rect.w = 0;
       +    window->rect.h = 0;
       +    window->rect.x = 0;
       +    window->rect.y = 0;
       +
       +    XClearWindow(display, window->xwindow);
       +    XMapRaised(display, window->xwindow);
       +    XSelectInput(display, window->xwindow, ExposureMask|KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|StructureNotifyMask|PointerMotionMask);
       +
       +    HASH_ADD_INT(ltk_global->window_hash, xwindow, window);
       +
       +    return window;
       +}
       +
       +void ltk_remove_window(LtkWindow *window)
       +{
       +    ltk_destroy_window(window);
       +    if (!ltk_global->window_hash) ltk_quit();
       +}
       +
       +void ltk_destroy_window(LtkWindow *window)
       +{
       +    HASH_DEL(ltk_global->window_hash, window);
       +    LtkWidget *ptr = window->root_widget;
       +    if (ptr) ptr->destroy(ptr);
       +    XDestroyWindow(ltk_global->display, window->xwindow);
       +    free(window);
       +}
       +
       +void ltk_window_other_event(void *widget, XEvent event)
       +{
       +    LtkWindow *window = widget;
       +    LtkWidget *ptr = window->root_widget;
       +    if (event.type == ConfigureNotify)
       +    {
       +        unsigned int w, h;
       +        w = event.xconfigure.width;
       +        h = event.xconfigure.height;
       +        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->resize(ptr);
       +            ltk_redraw_window(window);
       +        }
       +    }
       +    if (event.type == Expose && event.xexpose.count == 0)
       +    {
       +        ltk_redraw_window(window);
       +    }
       +    if (event.type == ClientMessage && event.xclient.data.l[0] == ltk_global->wm_delete_msg)
       +    {
       +        ltk_remove_window(window);
       +    }
       +}
       +
       +LtkTheme *ltk_load_theme(const char *path)
       +{
       +    char *file_contents = ltk_read_file(path);
       +
       +    cJSON *json = cJSON_Parse(file_contents);
       +    if (!json)
       +    {
       +        printf("Theme error before: [%s]\n", cJSON_GetErrorPtr());
       +        return NULL;
       +    }
       +    cJSON *button_json = cJSON_GetObjectItem(json, "button");
       +    if (!button_json)
       +    {
       +        printf("Theme error before: [%s]\n", cJSON_GetErrorPtr());
       +        return NULL;
       +    }
       +    cJSON *window_json = cJSON_GetObjectItem(json, "window");
       +    if (!window_json)
       +    {
       +        printf("Theme error before: [%s]\n", cJSON_GetErrorPtr());
       +        return NULL;
       +    }
       +
       +    LtkTheme *theme = malloc(sizeof(LtkTheme));
       +    theme->button = ltk_parse_button_theme(button_json);
       +    theme->window = ltk_parse_window_theme(window_json);
       +
       +    free(file_contents);
       +    cJSON_Delete(json);
       +
       +    return theme;
       +}
       +
       +void ltk_destroy_theme(LtkTheme *theme)
       +{
       +    free(theme->button);
       +    free(theme->window);
       +    free(theme);
       +}
       +
       +char *ltk_read_file(const char *path)
       +{
       +    FILE *f;
       +    long len;
       +    char *file_contents;
       +    f = fopen(path, "rb");
       +    fseek(f, 0, SEEK_END);
       +    len = ftell(f);
       +    fseek(f, 0, SEEK_SET);
       +    file_contents = malloc(len + 1);
       +    fread(file_contents, 1, len, f);
       +    file_contents[len] = '\0';
       +    fclose(f);
       +
       +    return file_contents;
       +}
       +
       +int ltk_collide_rect(LtkRect rect, int x, int y)
       +{
       +    return (rect.x <= x && (rect.x + rect.w) >= x && rect.y <= y && (rect.y + rect.h) >= y);
       +}
       +
       +void ltk_remove_active_widget(void *widget)
       +{
       +    if (!widget) return;
       +    LtkWidget *parent = widget;
       +    LtkWidget *child;
       +    while (parent->active_widget)
       +    {
       +        child = parent->active_widget;
       +        child->state = LTK_NORMAL;
       +        child->draw(child);
       +        parent->active_widget = NULL;
       +        parent = child;
       +    }
       +}
       +
       +void ltk_change_active_widget_state(void *widget, LtkWidgetState state)
       +{
       +    if (!widget) return;
       +    LtkWidget *ptr = widget;
       +    while (ptr = ptr->active_widget)
       +    {
       +        ptr->state = state;
       +        ptr->draw(ptr);
       +    }
       +}
       +
       +void ltk_remove_hover_widget(void *widget)
       +{
       +    if (!widget) return;
       +    LtkWidget *parent = widget;
       +    LtkWidget *child;
       +    while (parent->hover_widget)
       +    {
       +        child = parent->hover_widget;
       +        child->state = child->state == LTK_HOVERACTIVE ? LTK_ACTIVE : LTK_NORMAL;
       +        child->draw(child);
       +        parent->hover_widget = NULL;
       +        parent = child;
       +    }
       +}
       +
       +LtkWidget ltk_create_widget(LtkWindow *window, void (*draw)(void *), void (*destroy)(void *), int needs_redraw)
       +{
       +    LtkWidget widget;
       +    widget.window = window;
       +    widget.active_widget = NULL;
       +    widget.hover_widget = NULL;
       +    widget.parent = NULL;
       +
       +    widget.key_press = NULL;
       +    widget.key_release = NULL;
       +    widget.mouse_press = NULL;
       +    widget.mouse_release = NULL;
       +    widget.motion_notify = NULL;
       +
       +    widget.resize = NULL;
       +    widget.draw = draw;
       +    widget.destroy = destroy;
       +
       +    widget.needs_redraw = needs_redraw;
       +    widget.state = LTK_NORMAL;
       +    widget.row = 0;
       +    widget.rect.x = 0;
       +    widget.rect.y = 0;
       +    widget.rect.w = 100;
       +    widget.rect.h = 100;
       +
       +    widget.row = NULL;
       +    widget.column = NULL;
       +    widget.row_span = NULL;
       +    widget.column_span = NULL;
       +    widget.sticky = NULL;
       +
       +    return widget;
       +}
       +
       +void ltk_mouse_press_event(void *widget, XEvent event)
       +{
       +    LtkWidget *ptr = widget;
       +    if (!ptr || ptr->state == LTK_DISABLED) return;
       +    if (event.xbutton.button == 1)
       +    {
       +        LtkWidget *parent = ptr->parent;
       +        if (parent)
       +        {
       +            ltk_remove_active_widget(parent);
       +            parent->active_widget = ptr;
       +        }
       +        ptr->state = LTK_PRESSED;
       +        if (ptr->needs_redraw) 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 == LTK_DISABLED) return;
       +    if (ptr->state == LTK_PRESSED)
       +    {
       +        ptr->state = LTK_HOVERACTIVE;
       +        if (ptr->needs_redraw) 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 == LTK_NORMAL || ptr->state == LTK_ACTIVE) &&
       +        (event.xmotion.state & Button1Mask) != Button1Mask)
       +    {
       +        ptr->state = ptr->state == LTK_ACTIVE ? LTK_HOVERACTIVE : LTK_HOVER;
       +        LtkWidget *parent = ptr->parent;
       +        if (parent)
       +        {
       +            ltk_remove_hover_widget(parent);
       +            parent->hover_widget = ptr;
       +        }
       +        if (ptr->needs_redraw) ptr->draw(ptr);
       +    }
       +    if (ptr->motion_notify)
       +    {
       +        ptr->motion_notify(ptr, event);
       +    }
       +}
       +
       +void ltk_handle_event(XEvent event)
       +{
       +    LtkWindow *window;
       +    LtkWidget *root_widget;
       +    HASH_FIND_INT(ltk_global->window_hash, &event.xany.window, window);
       +    if (!window) return;
       +    root_widget = window->root_widget;
       +    switch (event.type)
       +    {
       +    case KeyPress:
       +        break;
       +    case KeyRelease:
       +        break;
       +    case ButtonPress:
       +        if (root_widget) ltk_mouse_press_event(root_widget, event);
       +        break;
       +    case ButtonRelease:
       +        if (root_widget) ltk_mouse_release_event(root_widget, event);
       +        break;
       +    case MotionNotify:
       +        if (root_widget) ltk_motion_notify_event(root_widget, event);
       +        break;
       +    default:
       +        /* FIXME: users should be able to register other events like closing the window */
       +        if (window->other_event)
       +            window->other_event(window, event);
       +    }
       +}
       +\ No newline at end of file
   DIR diff --git a/ltk.h b/ltk.h
       t@@ -30,11 +30,134 @@
        #include <X11/Xutil.h>
        #include "cJSON.h"
        #include "uthash.h"
       -#include "common.h"
       -#include "window.h"
       -#include "theme.h"
       -#include "grid.h"
       +
       +/*
       + * Struct to represent a rectangle.
       + */
       +typedef struct
       +{
       +    int x;
       +    int y;
       +    int w;
       +    int h;
       +} LtkRect;
       +
       +typedef enum {
       +    LTK_STICKY_LEFT = 1 << 0,
       +    LTK_STICKY_RIGHT = 1 << 1,
       +    LTK_STICKY_TOP = 1 << 2,
       +    LTK_STICKY_BOTTOM = 1 << 3
       +} LtkStickyMask;
       +
       +/*
       + * An enumeration of all widget states.
       + */
       +typedef enum
       +{
       +    LTK_NORMAL = 0,
       +    LTK_HOVER = 1,
       +    LTK_PRESSED = 2,
       +    LTK_ACTIVE = 3,
       +    LTK_HOVERACTIVE = 4,
       +    LTK_DISABLED = 5
       +} LtkWidgetState;
       +
       +typedef struct LtkWindow LtkWindow;
       +
       +/*
       + * A struct to contain all basic widget information.
       + * First element of every widget so the widget can
       + * be cast to LtkWidget.
       + */
       +typedef struct LtkWidget
       +{
       +    /* The window the widget will be displayed on */
       +    LtkWindow *window;
       +    /* For container widgets; the widget that is currently active */
       +    struct LtkWidget *active_widget;
       +    /* For container widgets; the widget that is currently highlighted */
       +    struct LtkWidget *hover_widget;
       +    /* Parent widget */
       +    struct LtkWidget *parent;
       +
       +    /* 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)(void *);
       +    /* Function to destroy the widget */
       +    void (*destroy)(void *);
       +
       +    /* Position and size of the widget */
       +    LtkRect rect;
       +    /* Row of widget if gridded */
       +    unsigned int row;
       +    /* Column of widget if gridded */
       +    unsigned int column;
       +    /* Row span of widget if gridded */
       +    unsigned int row_span;
       +    /* Column span of widget if gridded */
       +    unsigned int column_span;
       +    /* Specifies if the widget needs to be redrawn after a state change */
       +    int needs_redraw : 1;
       +    /* State of the widget */
       +    LtkWidgetState state : 3;
       +    /* Similar to sticky in tk */
       +    unsigned short sticky : 4;
       +} LtkWidget;
       +
       +/*
       + * Struct to represent a window.
       + */
       +typedef struct LtkWindow
       +{
       +    Window xwindow;
       +    GC gc;
       +    void *root_widget;
       +    void (*other_event)(void *, XEvent event);
       +    LtkRect rect;
       +    UT_hash_handle hh;
       +} LtkWindow;
       +
       +/*
       + * Struct to represent the border width,
       + * foreground color, and background color
       + * of a window.
       + */
       +typedef struct LtkWindowTheme
       +{
       +    int border_width;
       +    XColor fg;
       +    XColor bg;
       +} LtkWindowTheme;
       +
        #include "button.h"
       +#include "grid.h"
       +
       +/*
       + * Struct to contain all styles needed by LTK.
       + */
       +typedef struct
       +{
       +    LtkWindowTheme *window;
       +    LtkButtonTheme *button;
       +} LtkTheme;
       +
       +/*
       + * Load a theme from a JSON file.
       + * path: The path to the file.
       + */
       +LtkTheme *ltk_load_theme(const char *path);
        
        /*
         * Struct to contain all global information.
       t@@ -80,4 +203,119 @@ XColor ltk_create_xcolor(const char *hex);
         */
        void ltk_mainloop(void);
        
       +/*
       + * Create a window.
       + * title: The title of the window.
       + * x: The x position of the window.
       + * y: The y position of the window.
       + * w: The width of the window.
       + * h: The height of the window.
       + */
       +LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h);
       +
       +/*
       + * Redraw the widgets in a window.
       + * window: The window to redraw.
       + */
       +void ltk_redraw_window(LtkWindow *window);
       +
       +/*
       + * Destroy a window and quit the application
       + * if no windows are left.
       + * window: The window to remove.
       + */
       +void ltk_remove_window(LtkWindow *window);
       +
       +/*
       + * Destroy a window, freeing its memory.
       + * window: The window to destroy.
       + */
       +void ltk_destroy_window(LtkWindow *window);
       +
       +/*
       + * Handles any event other than mouse or keyboard events.
       + * widget: Pointer to the window.
       + * event: The XEvent to be handled.
       + */
       +void ltk_window_other_event(void *widget, XEvent event);
       +
       +/*
       + * Destroy an LtkTheme struct.
       + * theme: Pointer to the struct.
       + */
       +void ltk_destroy_theme(LtkTheme *theme);
       +
       +/*
       + * Check if a rectangle collides with a point.
       + * rect: The rectangle.
       + * x: The x coordinate of the point.
       + * y: The y coordinate of the point.
       + */
       +int ltk_collide_rect(LtkRect rect, int x, int y);
       +
       +/*
       + * Read a file and return a null-terminated string with the contents.
       + * path: The path to the file.
       + */
       +char *ltk_read_file(const char *path);
       +
       +/*
       + * Recursively set the state of all active_widgets in 'widget' to 'state'.
       + */
       +void ltk_change_active_widget_state(void *widget, LtkWidgetState state);
       +
       +/*
       + * Recursively set the state of all active_widgets in 'widget' to LTK_NORMAL,
       + * redraw the widgets, and remove the references to them from their parents.
       + */
       +void ltk_remove_active_widget(void *widget);
       +
       +/*
       + * Recursively set the state of all hover_widgets in 'widget' to LTK_NORMAL or
       + * LTK_ACTIVE, redraw the widgets, and remove the references to them from their parents.
       + */
       +void ltk_remove_hover_widget(void *widget);
       +
       +/*
       + * Create a widget.
       + * window: The window the widget is to be shown on.
       + * draw: The function used to draw the widget.
       + * destroy: The function used to destroy the widget.
       + * needs_redraw: Flag to indicate if the widget needs to be
       + *               be redrawn when it is resized.
       + * Returns: The new LtkWidget.
       + */
       +LtkWidget ltk_create_widget(LtkWindow *window, void (*draw)(void *), void (*destroy)(void *), int needs_redraw);
       +
       +/*
       + * Handles mouse press events for all widgets and calls
       + * specific widget handlers if set.
       + * widget: Pointer to the widget the mouse is currrently on.
       + * event: The event to be handled.
       + */
       +void ltk_mouse_press_event(void *widget, XEvent event);
       +
       +/*
       + * Handles mouse release events for all widgets and calls
       + * specific widget handlers if set.
       + * widget: Pointer to the widget the mouse is currrently on.
       + * event: The event to be handled.
       + */
       +void ltk_mouse_release_event(void *widget, XEvent event);
       +
       +/*
       + * Handles mouse motion events for all widgets and calls
       + * specific widget handlers if set.
       + * widget: Pointer to the widget the mouse is currrently on.
       + * event: The event to be handled.
       + */
       +void ltk_motion_notify_event(void *widget, XEvent event);
       +
       +/*
       + * Handles all events and dispatches them to their
       + * respective handlers.
       + * event: The event to be handled.
       + */
       +void ltk_handle_event(XEvent event);
       +
        #endif
   DIR diff --git a/theme.c b/theme.c
       t@@ -1,64 +0,0 @@
       -/*
       - * This file is part of the Lumidify ToolKit (LTK)
       - * Copyright (c) 2016, 2017 Lumidify Productions <lumidify@openmailbox.org>
       - *
       - * Permission is hereby granted, free of charge, to any person obtaining a copy
       - * of this software and associated documentation files (the "Software"), to deal
       - * in the Software without restriction, including without limitation the rights
       - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       - * copies of the Software, and to permit persons to whom the Software is
       - * furnished to do so, subject to the following conditions:
       - *
       - * The above copyright notice and this permission notice shall be included in all
       - * copies or substantial portions of the Software.
       - *
       - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       - * SOFTWARE.
       - */
       -
       -#include "ltk.h"
       -
       -LtkTheme *ltk_load_theme(const char *path)
       -{
       -    char *file_contents = ltk_read_file(path);
       -
       -    cJSON *json = cJSON_Parse(file_contents);
       -    if (!json)
       -    {
       -        printf("Theme error before: [%s]\n", cJSON_GetErrorPtr());
       -        return NULL;
       -    }
       -    cJSON *button_json = cJSON_GetObjectItem(json, "button");
       -    if (!button_json)
       -    {
       -        printf("Theme error before: [%s]\n", cJSON_GetErrorPtr());
       -        return NULL;
       -    }
       -    cJSON *window_json = cJSON_GetObjectItem(json, "window");
       -    if (!window_json)
       -    {
       -        printf("Theme error before: [%s]\n", cJSON_GetErrorPtr());
       -        return NULL;
       -    }
       -
       -    LtkTheme *theme = malloc(sizeof(LtkTheme));
       -    theme->button = ltk_parse_button_theme(button_json);
       -    theme->window = ltk_parse_window_theme(window_json);
       -
       -    free(file_contents);
       -    cJSON_Delete(json);
       -
       -    return theme;
       -}
       -
       -void ltk_destroy_theme(LtkTheme *theme)
       -{
       -    free(theme->button);
       -    free(theme->window);
       -    free(theme);
       -}
   DIR diff --git a/theme.h b/theme.h
       t@@ -1,51 +0,0 @@
       -/*
       - * This file is part of the Lumidify ToolKit (LTK)
       - * Copyright (c) 2016, 2017 Lumidify Productions <lumidify@openmailbox.org>
       - *
       - * Permission is hereby granted, free of charge, to any person obtaining a copy
       - * of this software and associated documentation files (the "Software"), to deal
       - * in the Software without restriction, including without limitation the rights
       - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       - * copies of the Software, and to permit persons to whom the Software is
       - * furnished to do so, subject to the following conditions:
       - *
       - * The above copyright notice and this permission notice shall be included in all
       - * copies or substantial portions of the Software.
       - *
       - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       - * SOFTWARE.
       - */
       -
       -#ifndef _LTK_THEME_H_
       -#define _LTK_THEME_H_
       -
       -typedef struct LtkWindowTheme LtkWindowTheme;
       -typedef struct LtkButtonTheme LtkButtonTheme;
       -
       -/*
       - * Struct to contain all styles needed by LTK.
       - */
       -typedef struct
       -{
       -    LtkWindowTheme *window;
       -    LtkButtonTheme *button;
       -} LtkTheme;
       -
       -/*
       - * Load a theme from a JSON file.
       - * path: The path to the file.
       - */
       -LtkTheme *ltk_load_theme(const char *path);
       -
       -/*
       - * Destroy an LtkTheme struct.
       - * theme: Pointer to the struct.
       - */
       -void ltk_destroy_theme(LtkTheme *theme);
       -
       -#endif
   DIR diff --git a/window.c b/window.c
       t@@ -1,153 +0,0 @@
       -/*
       - * This file is part of the Lumidify ToolKit (LTK)
       - * Copyright (c) 2016, 2017 Lumidify Productions <lumidify@openmailbox.org>
       - *
       - * Permission is hereby granted, free of charge, to any person obtaining a copy
       - * of this software and associated documentation files (the "Software"), to deal
       - * in the Software without restriction, including without limitation the rights
       - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       - * copies of the Software, and to permit persons to whom the Software is
       - * furnished to do so, subject to the following conditions:
       - *
       - * The above copyright notice and this permission notice shall be included in all
       - * copies or substantial portions of the Software.
       - *
       - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       - * SOFTWARE.
       - */
       -
       -#include "ltk.h"
       -
       -LtkWindowTheme *ltk_parse_window_theme(cJSON *window_json)
       -{
       -    LtkWindowTheme *window_theme = malloc(sizeof(LtkWindowTheme));
       -    if (!window_theme) ltk_fatal("No memory for new LtkWindowTheme\n");
       -    cJSON *border_width = cJSON_GetObjectItem(window_json, "border-width");
       -    cJSON *fg = cJSON_GetObjectItem(window_json, "foreground");
       -    cJSON *bg = cJSON_GetObjectItem(window_json, "background");
       -    window_theme->border_width = border_width ? border_width->valueint : 0;
       -    window_theme->fg = ltk_create_xcolor(fg->valuestring);
       -    window_theme->bg = ltk_create_xcolor(bg->valuestring);
       -
       -    return window_theme;
       -}
       -
       -void ltk_redraw_window(LtkWindow *window)
       -{
       -    LtkWidget *ptr;
       -    if (!window)
       -    {
       -        return;
       -    }
       -    if (!window->root_widget)
       -    {
       -        return;
       -    }
       -    ptr = window->root_widget;
       -    ptr->draw(ptr);
       -}
       -
       -LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h)
       -{
       -    LtkWindow *window = malloc(sizeof(LtkWindow));
       -    if (!window) ltk_fatal("Not enough memory left for window!\n");
       -    LtkWindowTheme *wtheme = ltk_global->theme->window; /* For convenience */
       -    Display *display = ltk_global->display; /* For convenience */
       -    window->xwindow = XCreateSimpleWindow(display, DefaultRootWindow(display), x, y, w, h, wtheme->border_width, wtheme->fg.pixel, wtheme->bg.pixel);
       -    window->gc = XCreateGC(display, window->xwindow, 0, 0);
       -    XSetForeground(display, window->gc, wtheme->fg.pixel);
       -    XSetBackground(display, window->gc, wtheme->bg.pixel);
       -    XSetStandardProperties(display, window->xwindow, title, NULL, None, NULL, 0, NULL);
       -    XSetWMProtocols(display, window->xwindow, &ltk_global->wm_delete_msg, 1);
       -    window->root_widget = NULL;
       -
       -    window->other_event = &ltk_window_other_event;
       -
       -    window->rect.w = 0;
       -    window->rect.h = 0;
       -    window->rect.x = 0;
       -    window->rect.y = 0;
       -
       -    XClearWindow(display, window->xwindow);
       -    XMapRaised(display, window->xwindow);
       -    XSelectInput(display, window->xwindow, ExposureMask|KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|StructureNotifyMask|PointerMotionMask);
       -
       -    HASH_ADD_INT(ltk_global->window_hash, xwindow, window);
       -
       -    return window;
       -}
       -
       -void ltk_remove_window(LtkWindow *window)
       -{
       -    ltk_destroy_window(window);
       -    if (!ltk_global->window_hash) ltk_quit();
       -}
       -
       -void ltk_destroy_window(LtkWindow *window)
       -{
       -    HASH_DEL(ltk_global->window_hash, window);
       -    LtkWidget *ptr = window->root_widget;
       -    if (ptr) ptr->destroy(ptr);
       -    XDestroyWindow(ltk_global->display, window->xwindow);
       -    free(window);
       -}
       -
       -void ltk_window_other_event(void *widget, XEvent event)
       -{
       -    LtkWindow *window = widget;
       -    LtkWidget *ptr = window->root_widget;
       -    if (event.type == ConfigureNotify)
       -    {
       -        unsigned int w, h;
       -        w = event.xconfigure.width;
       -        h = event.xconfigure.height;
       -        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->resize(ptr);
       -            ltk_redraw_window(window);
       -        }
       -    }
       -    if (event.type == Expose && event.xexpose.count == 0)
       -    {
       -        ltk_redraw_window(window);
       -    }
       -    if (event.type == ClientMessage && event.xclient.data.l[0] == ltk_global->wm_delete_msg)
       -    {
       -        ltk_remove_window(window);
       -    }
       -}
       -
       -/*
       -void ltk_resize_window(Uint32 id, int w, int h)
       -{
       -    LtkWindow *window;
       -    LtkWidget *ptr;
       -    HASH_FIND_INT(ltk_window_hash, &id, window);
       -    if (!window)
       -    {
       -        return;
       -    }
       -    ptr = window->root_widget;
       -    if (!ptr)
       -    {
       -        return;
       -    }
       -    ptr->rect.w = w;
       -    ptr->rect.h = h;
       -    ptr->resize(ptr);
       -}
       -
       -void ltk_window_set_root_widget(LtkWindow *window, void *root_widget)
       -{
       -    window->root_widget = root_widget;
       -}
       -*/
   DIR diff --git a/window.h b/window.h
       t@@ -1,54 +0,0 @@
       -/*
       - * This file is part of the Lumidify ToolKit (LTK)
       - * Copyright (c) 2016, 2017 Lumidify Productions <lumidify@openmailbox.org>
       - *
       - * Permission is hereby granted, free of charge, to any person obtaining a copy
       - * of this software and associated documentation files (the "Software"), to deal
       - * in the Software without restriction, including without limitation the rights
       - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       - * copies of the Software, and to permit persons to whom the Software is
       - * furnished to do so, subject to the following conditions:
       - *
       - * The above copyright notice and this permission notice shall be included in all
       - * copies or substantial portions of the Software.
       - *
       - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       - * SOFTWARE.
       - */
       -
       -#ifndef _LTK_WINDOW_H_
       -#define _LTK_WINDOW_H_
       -
       -#include <X11/Xlib.h>
       -#include "event.h"
       -
       -typedef struct LtkWindow
       -{
       -    Window xwindow;
       -    GC gc;
       -    void *root_widget;
       -    void (*other_event)(void *, XEvent event);
       -    LtkRect rect;
       -    UT_hash_handle hh;
       -} LtkWindow;
       -
       -typedef struct LtkWindowTheme
       -{
       -    int border_width;
       -    XColor fg;
       -    XColor bg;
       -} LtkWindowTheme;
       -
       -LtkWindow *ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h);
       -void ltk_redraw_window(LtkWindow *window);
       -void ltk_destroy_window(LtkWindow *window);
       -void ltk_window_key_event(void *widget, XEvent event);
       -void ltk_window_mouse_event(void *widget, XEvent event);
       -void ltk_window_other_event(void *widget, XEvent event);
       -
       -#endif