};
typedef struct XConf {
+ Atom XA_DELETE, XA_GOTO;
Bool error;
int state, fd, screen, mods;
Window root;
// 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;
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 {
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);
#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;
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;
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)
{