]> git.mdlowis.com Git - projs/tide.git/commitdiff
added event handling scaffolding ui-rearch
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 25 Mar 2022 20:07:02 +0000 (16:07 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 25 Mar 2022 20:07:02 +0000 (16:07 -0400)
src/uitest/main.c
src/uitest/ui.h
src/uitest/ui_window.c
src/uitest/x11.c

index 76fbabf1c2e93f73673d25805b705e0bad40129e..febf2efacbfc31d1b754a67b8da3f92e7f4c0bb2 100644 (file)
@@ -1,10 +1,13 @@
 #include <stdc.h>
+
 #include "ui.h"
+#define INCLUDE_DEFS
+#include "config.h"
 
 int main(int argc, char** argv)
 {
     UIWidget* win = UI_MakeWindow(640, 480);
     UI_ShowWindow(win);
-    sleep(60);
+    UI_StartEventLoop(NULL);
     return 0;
 }
index 2f773817e4952fd2d9d763b37eb0d4da959d68f0..a06d75fe1c228171d3d525b8598f9234ba85ff2b 100644 (file)
@@ -14,6 +14,7 @@ enum {
 };
 
 typedef struct XConf {
+    Atom XA_DELETE, XA_GOTO;
     Bool error;
     int state, fd, screen, mods;
     Window root;
@@ -33,91 +34,93 @@ extern XConf X;
 //    CLIPBOARD = 1
 //};
 //
-///* key definitions */
-//enum Keys {
-//    /* Define some runes in the private use area of unicode to represent
-//     * special keys */
-//    KEY_F1     = (0xE000+0),
-//    KEY_F2     = (0xE000+1),
-//    KEY_F3     = (0xE000+2),
-//    KEY_F4     = (0xE000+3),
-//    KEY_F5     = (0xE000+4),
-//    KEY_F6     = (0xE000+5),
-//    KEY_F7     = (0xE000+6),
-//    KEY_F8     = (0xE000+7),
-//    KEY_F9     = (0xE000+8),
-//    KEY_F10    = (0xE000+9),
-//    KEY_F11    = (0xE000+10),
-//    KEY_F12    = (0xE000+11),
-//    KEY_INSERT = (0xE000+12),
-//    KEY_DELETE = (0xE000+13),
-//    KEY_HOME   = (0xE000+14),
-//    KEY_END    = (0xE000+15),
-//    KEY_PGUP   = (0xE000+16),
-//    KEY_PGDN   = (0xE000+17),
-//    KEY_UP     = (0xE000+18),
-//    KEY_DOWN   = (0xE000+19),
-//    KEY_RIGHT  = (0xE000+20),
-//    KEY_LEFT   = (0xE000+21),
-//
-//    /* ASCII Control Characters */
-//    KEY_CTRL_TILDE       = 0x00,
-//    KEY_CTRL_2           = 0x00,
-//    KEY_CTRL_A           = 0x01,
-//    KEY_CTRL_B           = 0x02,
-//    KEY_CTRL_C           = 0x03,
-//    KEY_CTRL_D           = 0x04,
-//    KEY_CTRL_E           = 0x05,
-//    KEY_CTRL_F           = 0x06,
-//    KEY_CTRL_G           = 0x07,
-//    KEY_BACKSPACE        = 0x08,
-//    KEY_CTRL_H           = 0x08,
-//    KEY_TAB              = 0x09,
-//    KEY_CTRL_I           = 0x09,
-//    KEY_CTRL_J           = 0x0A,
-//    KEY_CTRL_K           = 0x0B,
-//    KEY_CTRL_L           = 0x0C,
-//    KEY_ENTER            = 0x0D,
-//    KEY_CTRL_M           = 0x0D,
-//    KEY_CTRL_N           = 0x0E,
-//    KEY_CTRL_O           = 0x0F,
-//    KEY_CTRL_P           = 0x10,
-//    KEY_CTRL_Q           = 0x11,
-//    KEY_CTRL_R           = 0x12,
-//    KEY_CTRL_S           = 0x13,
-//    KEY_CTRL_T           = 0x14,
-//    KEY_CTRL_U           = 0x15,
-//    KEY_CTRL_V           = 0x16,
-//    KEY_CTRL_W           = 0x17,
-//    KEY_CTRL_X           = 0x18,
-//    KEY_CTRL_Y           = 0x19,
-//    KEY_CTRL_Z           = 0x1A,
-//    KEY_ESCAPE           = 0x1B,
-//    KEY_CTRL_LSQ_BRACKET = 0x1B,
-//    KEY_CTRL_3           = 0x1B,
-//    KEY_CTRL_4           = 0x1C,
-//    KEY_CTRL_BACKSLASH   = 0x1C,
-//    KEY_CTRL_5           = 0x1D,
-//    KEY_CTRL_RSQ_BRACKET = 0x1D,
-//    KEY_CTRL_6           = 0x1E,
-//    KEY_CTRL_7           = 0x1F,
-//    KEY_CTRL_SLASH       = 0x1F,
-//    KEY_CTRL_UNDERSCORE  = 0x1F,
-//};
-//
-///* Key modifier masks */
-//enum {
-//    ModNone       = 0,
-//    ModShift      = (1 << 0),
-//    ModCapsLock   = (1 << 1),
-//    ModCtrl       = (1 << 2),
-//    ModAlt        = (1 << 3),
-//    ModNumLock    = (1 << 4),
-//    ModScrollLock = (1 << 5),
-//    ModWindows    = (1 << 6),
-//    ModOneOrMore  = (ModCtrl|ModAlt),
-//    ModAny        = -1
-//};
+/* key definitions */
+enum Keys {
+    RUNE_ERR = 0xFFFD,
+
+    /* Define some runes in the private use area of unicode to represent
+     * special keys */
+    KEY_F1     = (0xE000+0),
+    KEY_F2     = (0xE000+1),
+    KEY_F3     = (0xE000+2),
+    KEY_F4     = (0xE000+3),
+    KEY_F5     = (0xE000+4),
+    KEY_F6     = (0xE000+5),
+    KEY_F7     = (0xE000+6),
+    KEY_F8     = (0xE000+7),
+    KEY_F9     = (0xE000+8),
+    KEY_F10    = (0xE000+9),
+    KEY_F11    = (0xE000+10),
+    KEY_F12    = (0xE000+11),
+    KEY_INSERT = (0xE000+12),
+    KEY_DELETE = (0xE000+13),
+    KEY_HOME   = (0xE000+14),
+    KEY_END    = (0xE000+15),
+    KEY_PGUP   = (0xE000+16),
+    KEY_PGDN   = (0xE000+17),
+    KEY_UP     = (0xE000+18),
+    KEY_DOWN   = (0xE000+19),
+    KEY_RIGHT  = (0xE000+20),
+    KEY_LEFT   = (0xE000+21),
+
+    /* ASCII Control Characters */
+    KEY_CTRL_TILDE       = 0x00,
+    KEY_CTRL_2           = 0x00,
+    KEY_CTRL_A           = 0x01,
+    KEY_CTRL_B           = 0x02,
+    KEY_CTRL_C           = 0x03,
+    KEY_CTRL_D           = 0x04,
+    KEY_CTRL_E           = 0x05,
+    KEY_CTRL_F           = 0x06,
+    KEY_CTRL_G           = 0x07,
+    KEY_BACKSPACE        = 0x08,
+    KEY_CTRL_H           = 0x08,
+    KEY_TAB              = 0x09,
+    KEY_CTRL_I           = 0x09,
+    KEY_CTRL_J           = 0x0A,
+    KEY_CTRL_K           = 0x0B,
+    KEY_CTRL_L           = 0x0C,
+    KEY_ENTER            = 0x0D,
+    KEY_CTRL_M           = 0x0D,
+    KEY_CTRL_N           = 0x0E,
+    KEY_CTRL_O           = 0x0F,
+    KEY_CTRL_P           = 0x10,
+    KEY_CTRL_Q           = 0x11,
+    KEY_CTRL_R           = 0x12,
+    KEY_CTRL_S           = 0x13,
+    KEY_CTRL_T           = 0x14,
+    KEY_CTRL_U           = 0x15,
+    KEY_CTRL_V           = 0x16,
+    KEY_CTRL_W           = 0x17,
+    KEY_CTRL_X           = 0x18,
+    KEY_CTRL_Y           = 0x19,
+    KEY_CTRL_Z           = 0x1A,
+    KEY_ESCAPE           = 0x1B,
+    KEY_CTRL_LSQ_BRACKET = 0x1B,
+    KEY_CTRL_3           = 0x1B,
+    KEY_CTRL_4           = 0x1C,
+    KEY_CTRL_BACKSLASH   = 0x1C,
+    KEY_CTRL_5           = 0x1D,
+    KEY_CTRL_RSQ_BRACKET = 0x1D,
+    KEY_CTRL_6           = 0x1E,
+    KEY_CTRL_7           = 0x1F,
+    KEY_CTRL_SLASH       = 0x1F,
+    KEY_CTRL_UNDERSCORE  = 0x1F,
+};
+
+/* Key modifier masks */
+enum {
+    ModNone       = 0,
+    ModShift      = (1 << 0),
+    ModCapsLock   = (1 << 1),
+    ModCtrl       = (1 << 2),
+    ModAlt        = (1 << 3),
+    ModNumLock    = (1 << 4),
+    ModScrollLock = (1 << 5),
+    ModWindows    = (1 << 6),
+    ModOneOrMore  = (ModCtrl|ModAlt),
+    ModAny        = -1
+};
 //
 //typedef struct {
 //    int mods;
@@ -188,9 +191,10 @@ typedef struct {
 struct UIWidget;
 
 typedef struct {
+    void (*clientmsg)(struct UIWidget* widget, long type, long value);
     void (*resize)(struct UIWidget* widget, long maxw, long maxh);
-    void (*draw)(struct UIWidget* widget, long maxw, long maxh);
-    long (*process)(struct UIWidget* widget, UIEvent* ev);
+    void (*redraw)(struct UIWidget* widget, long maxw, long maxh);
+    void (*keypress)(struct UIWidget* widget, long mods, long key);
 } UIWidgetFuncs;
 
 typedef struct UIWidget {
@@ -203,6 +207,7 @@ typedef struct UIWidget {
 
 UIWidget* UI_MakeWindow(long width, long height);
 UIWidget* UI_MakeDialog(void);
-void UI_StartEventLoop(void (*)(UIWidget*, UIEvent*));
+void UI_StartEventLoop(void (*onevent)(int fd, int events));
+int UI_MonitorDescriptor(int fd);
 void UI_ShowWindow(UIWidget* w);
 void UI_HideWindow(UIWidget* w);
index 3a169f3c89ebc738aaa07a7a2179db04975d4d12..a3dfa2f1bab86043e324a8f77e3c1b252202041c 100644 (file)
@@ -1,5 +1,12 @@
 #include <stdc.h>
+#include <poll.h>
+
 #include "ui.h"
+#include "config.h"
+
+#ifndef MAX_DESCRIPTORS
+#define MAX_DESCRIPTORS 256
+#endif
 
 typedef struct UIWindow {
     UIWidget widget;
@@ -7,11 +14,166 @@ typedef struct UIWindow {
     struct UIWindow* next;
 } UIWindow;
 
-UIWindow* WindowList = NULL;
+static int Num_Descriptors = 0;
+static struct pollfd Descriptors[MAX_DESCRIPTORS];
+static UIWindow* WindowList = NULL;
+
+static UIWindow* get_window(Window id)
+{
+    UIWindow* win = WindowList;
+    for (; win && win->xwin.winid != id; win = win->next);
+    return win;
+}
+
+static void xkeypress(XEvent* e)
+{
+    /* map special keys to a special section of unicode for "private use" */
+    static uint32_t keymap[256] = {
+        /* Function keys */
+        [0xBE] = KEY_F1, [0xBF] = KEY_F2,  [0xC0] = KEY_F3,  [0xC1] = KEY_F4,
+        [0xC2] = KEY_F5, [0xC3] = KEY_F6,  [0xC4] = KEY_F7,  [0xC5] = KEY_F8,
+        [0xC6] = KEY_F9, [0xC7] = KEY_F10, [0xC8] = KEY_F11, [0xC9] = KEY_F12,
+        /* Navigation keys */
+        [0x50] = KEY_HOME,  [0x51] = KEY_LEFT, [0x52] = KEY_UP,
+        [0x53] = KEY_RIGHT, [0x54] = KEY_DOWN, [0x55] = KEY_PGUP,
+        [0x56] = KEY_PGDN,  [0x57] = KEY_END,
+        /* Control keys */
+        [0x08] = '\b', [0x09] = '\t', [0x0d] = '\n', [0x0a] = '\n',
+        /* Miscellaneous */
+        [0x63] = KEY_INSERT, [0x1B] = KEY_ESCAPE, [0xFF] = KEY_DELETE,
+    };
+
+    uint32_t rune;
+    char buf[8];
+    KeySym key;
+    Status status;
+
+    UIWindow* win = get_window(e->xany.window);
+    if (win && win->widget.funcs->keypress)
+    {
+        printf("%s(%lu)\n", __func__, win->xwin.winid);
+
+        /* Read the key string */
+        if (win->xwin.xic)
+        {
+            Xutf8LookupString(
+                win->xwin.xic, &(e->xkey), buf, sizeof(buf), &key, &status);
+        }
+        else
+        {
+            XLookupString(&(e->xkey), buf, sizeof(buf), &key, 0);
+        }
+
+        /* if it's ascii, just return it */
+        if (key >= 0x20 && key <= 0x7F)
+        {
+            rune = (uint32_t)key;
+        }
+        else
+        {
+            /* lookup the key by keysym */
+            key = ((key & 0xFF00) == 0xFF00 ? keymap[key & 0xFF] : key);
+            rune = (!key ? RUNE_ERR : key);
+        }
+
+        if (key != RUNE_ERR)
+        {
+            int mods = e->xkey.state & (ModCtrl|ModShift|ModAlt);
+            win->widget.funcs->keypress(&(win->widget), mods, tolower(rune));
+        }
+
+        printf("key: 0x%x\n", rune);
+    }
+}
+
+static void xmousebtn(XEvent* e)
+{
+    UIWindow* win = get_window(e->xany.window);
+    if (win)
+    {
+        printf("%s(%lu)\n", __func__, win->xwin.winid);
+    }
+}
+
+static void xbtnmotion(XEvent* e)
+{
+    UIWindow* win = get_window(e->xany.window);
+    if (win)
+    {
+        printf("%s(%lu)\n", __func__, win->xwin.winid);
+    }
+}
+
+static void xclientmsg(XEvent* e)
+{
+    UIWindow* win = get_window(e->xany.window);
+    if (win)
+    {
+        printf("%s(%lu)\n", __func__, win->xwin.winid);
+
+        if ((Atom)(e->xclient.data.l[0]) == X.XA_DELETE)
+        {
+//            win_quit();
+        }
+        else if (e->xclient.message_type == X.XA_GOTO)
+        {
+//            x11_seturgent(x, 1);
+//            win_setln(e->xclient.data.l[0]);
+        }
+    }
+}
+
+static void xresize(XEvent* e)
+{
+    UIWindow* win = get_window(e->xany.window);
+    if (win)
+    {
+        printf("%s(%lu)\n", __func__, win->xwin.winid);
+    }
+}
+
+static void xmapnotify(XEvent* e)
+{
+    UIWindow* win = get_window(e->xany.window);
+    if (win)
+    {
+        printf("%s(%lu)\n", __func__, win->xwin.winid);
+    }
+}
+
+static void xenternotify(XEvent* e)
+{
+    UIWindow* win = get_window(e->xany.window);
+    if (win)
+    {
+        printf("%s(%lu)\n", __func__, win->xwin.winid);
+    }
+}
+
+static void xinit(void)
+{
+    static int initialized = 0;
+    if (!initialized) {
+        X11_Init();
+        X.eventfns[KeyPress] = xkeypress;
+        X.eventfns[ButtonPress] = xmousebtn;
+        X.eventfns[ButtonRelease] = xmousebtn;
+        X.eventfns[MotionNotify] = xbtnmotion;
+        X.eventfns[ClientMessage] = xclientmsg;
+        X.eventfns[ConfigureNotify] = xresize;
+        X.eventfns[MapNotify] = xmapnotify;
+        X.eventfns[EnterNotify] = xenternotify;
+        X.XA_DELETE = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
+        X.XA_GOTO = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
+        Num_Descriptors = 0;
+        UI_MonitorDescriptor(ConnectionNumber(X.display));
+        initialized = 1;
+    }
+}
 
 UIWindow* make_window(void)
 {
-    if (!WindowList) { X11_Init(); }
+    xinit();
     UIWindow* win = calloc(1, sizeof(UIWindow));
     win->next = WindowList;
     WindowList = win;
@@ -32,10 +194,94 @@ UIWidget* UI_MakeDialog(void)
     return &(win->widget);
 }
 
-//void UI_StartEventLoop(void (*)(UIWidget*, UIEvent*))
-//{
-//    /* TODO: implement event loop */
-//}
+static void process_xevents(int events)
+{
+    if (events & (POLLHUP|POLLERR))
+    {
+        /* kill X connection and cleanup windows */
+    }
+    else if (events & POLLIN)
+    {
+        /* process the entire event queue */
+        while (XEventsQueued(X.display, QueuedAfterReading))
+        {
+            for (XEvent e; XPending(X.display);)
+            {
+                XNextEvent(X.display, &e);
+                if (!XFilterEvent(&e, None) && X.eventfns[e.type])
+                {
+                    X.eventfns[e.type](&e);
+                }
+            }
+        }
+    }
+    else
+    {
+        /* do nothing */
+    }
+}
+
+
+static void process_descriptor(int fd, int events, void (*onevent)(int fd, int events))
+{
+    if (events)
+    {
+        int xfd = ConnectionNumber(X.display);
+        if (fd == xfd)
+        {
+            process_xevents(events);
+        }
+        else
+        {
+            onevent(fd, events);
+        }
+    }
+}
+
+void UI_StartEventLoop(void (*onevent)(int fd, int events))
+{
+    int maxcount = 1000 / Timeout;
+    int count = 0;
+
+    XSync(X.display, False);
+    while (Num_Descriptors)
+    {
+        /* Clear previous statuses in prep */
+        for (int i = 0; i < Num_Descriptors; i++)
+        {
+            Descriptors[Num_Descriptors].events = 0;
+        }
+
+        /* Poll the descriptor list until there is something to do */
+        long ret = poll(Descriptors, Num_Descriptors, Timeout);
+
+        /* Process the list of descriptors */
+        for (int i = 0; i < Num_Descriptors; i++)
+        {
+            process_descriptor(Descriptors[i].fd, Descriptors[i].revents, onevent);
+        }
+
+//        bool ready = poll_descriptors(Timeout);
+//        count += (ready ? -count : 1);
+//        if (count < maxcount)
+//        {
+//            xupdate(NULL);
+//        }
+    }
+}
+
+int UI_MonitorDescriptor(int fd)
+{
+    int success = -1;
+    if (Num_Descriptors < MAX_DESCRIPTORS)
+    {
+        Descriptors[Num_Descriptors].fd = fd;
+        Descriptors[Num_Descriptors].events = POLLIN|POLLOUT;
+        Num_Descriptors++;
+        success = 0;
+    }
+    return success;
+}
 
 void UI_ShowWindow(UIWidget* w)
 {
index a4154785b7c06d08b0231022c6dfbce5189e8953..6caa967a1a12bb733aa858740d39872eb556e956 100644 (file)
@@ -1,4 +1,5 @@
 #include <stdc.h>
+#include <locale.h>
 #include "ui.h"
 #include "config.h"
 
@@ -13,27 +14,6 @@ static int onerror(Display* disp, XErrorEvent* ev)
     return 0;
 }
 
-static void xkeypress(XEvent* e)
-{}
-
-static void xmousebtn(XEvent* e)
-{}
-
-static void xbtnmotion(XEvent* e)
-{}
-
-static void xclientmsg(XEvent* e)
-{}
-
-static void xresize(XEvent* e)
-{}
-
-static void xmapnotify(XEvent* e)
-{}
-
-static void xenternotify(XEvent* e)
-{}
-
 int X11_Init(void)
 {
     int ret = -1;
@@ -53,16 +33,6 @@ int X11_Init(void)
         X.depth    = DefaultDepth(X.display, X.screen);
         X.state    = RUNNING;
         XSetErrorHandler(onerror);
-
-        /* register event handlers */
-        X.eventfns[KeyPress] = xkeypress;
-        X.eventfns[ButtonPress] = xmousebtn;
-        X.eventfns[ButtonRelease] = xmousebtn;
-        X.eventfns[MotionNotify] = xbtnmotion;
-        X.eventfns[ClientMessage] = xclientmsg;
-        X.eventfns[ConfigureNotify] = xresize;
-        X.eventfns[MapNotify] = xmapnotify;
-        X.eventfns[EnterNotify] = xenternotify;
         ret = 0;
     }
 
@@ -155,7 +125,7 @@ void X11_ShowWindow(XWindow* w)
         }
         if (ev.type == ConfigureNotify)
         {
-            xresize(&ev);
+            X.eventfns[ConfigureNotify](&ev);
         }
     }
     while (ev.type != MapNotify);