diff options
| -rw-r--r-- | ui.c | 81 |
1 files changed, 65 insertions, 16 deletions
@@ -5,6 +5,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/XKBlib.h> +#include <X11/Xresource.h> #include <stdio.h> #include "ui.h" @@ -12,8 +13,14 @@ static Display *dsp; static Window win; +static XrmDatabase db; +static XIM im; +static XIC ic; static int scr; +static XPoint ic_pos; +static XVaNestedList ic_pos_list; + static unsigned long fg, bg; static unsigned long selfg, selbg; static unsigned long inpfg, inpbg; @@ -42,11 +49,22 @@ color(const char *name) return px; } +static inline void +set_ic_pos(const char *s, int i) +{ + int w = XTextWidth(ft_inp, s, i); + ic_pos.x = 16 + w; + ic_pos.y = 24; + XSetICValues(ic, /* XNFocusWindow, win, */ XNPreeditAttributes, ic_pos_list, NULL); + XSetICFocus(ic); +} + void ui_init(int argc, char **argv, UiOpts opt) { dsp = XOpenDisplay(NULL); scr = DefaultScreen(dsp); + db = XrmGetDatabase(dsp); fg = BlackPixel(dsp, scr); bg = color("lavender"); @@ -64,24 +82,39 @@ ui_init(int argc, char **argv, UiOpts opt) szhint.height = 250; szhint.flags = PSize; - win = XCreateSimpleWindow( + win = XCreateWindow( dsp, DefaultRootWindow(dsp), szhint.x, szhint.y, szhint.width, szhint.height, - 2 /* border width */, - fg, bg); + 0, XDefaultDepth(dsp, scr), + InputOutput, + XDefaultVisual(dsp, scr), + CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask | CWColormap, + &(XSetWindowAttributes) { + .background_pixel = bg, + .border_pixel = fg, + .bit_gravity = NorthWestGravity, + .event_mask = KeyPressMask | KeyReleaseMask | ExposureMask + }); /* TODO: replace with modern XSetWMProperties */ + + /* char title[] = "xmenu"; XSetStandardProperties(dsp, win, title, title, None, argv, argc, &szhint); + */ + + XSetWMProperties(dsp, win, NULL, NULL, argv, argc, + &szhint, &(XWMHints) { .flags = InputHint, .input = 1 }, + &(XClassHint) { "xmenu", "xmenu" }); gc = XCreateGC(dsp, win, 0, 0); XSetBackground(dsp, gc, bg); XSetForeground(dsp, gc, fg); - XSelectInput(dsp, win, KeyPressMask | ExposureMask); + //XSelectInput(dsp, win, KeyPressMask | ExposureMask); wm_delete_window = XInternAtom(dsp, "WM_DELETE_WINDOW", False); XSetWMProtocols(dsp, win, &wm_delete_window, 1); @@ -110,9 +143,31 @@ ui_init(int argc, char **argv, UiOpts opt) (scr_width - w - 32) / 2, (scr_height - h - 32) / 2 ); + + im = XOpenIM(dsp, NULL, NULL, NULL); + ic = XCreateIC(im, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, win, + NULL); + + ic_pos_list = XVaCreateNestedList(0, XNSpotLocation, &ic_pos, NULL); + set_ic_pos("", 0); XMapRaised(dsp, win); } +void +ui_fini(void) +{ + XFree(ic_pos_list); + XDestroyIC(ic); + XCloseIM(im); + XFreeFont(dsp, ft_opt); + XFreeFont(dsp, ft_inp); + XFreeGC(dsp, gc); + XDestroyWindow(dsp, win); + XCloseDisplay(dsp); +} + UiKey xksym_to_uik(KeySym sym) { @@ -150,18 +205,21 @@ ui_wait_event(UiEvent *e) { XEvent ev; KeySym sym; + Status status; loop: XNextEvent(dsp, &ev); + if (XFilterEvent(&ev, None)) + goto loop; switch (ev.type) { case KeyPress: e->type = UI_KEY_DOWN; - e->key.strn = XLookupString(&ev.xkey, e->key.str, 10, &sym, 0); + e->key.strn = Xutf8LookupString(ic, &ev.xkey, e->key.str, sizeof(e->key.str), &sym, &status); e->key.key = xksym_to_uik(sym); e->key.mod = xkstate_to_uim(ev.xkey.state); return 1; case KeyRelease: e->type = UI_KEY_UP; - e->key.strn = XLookupString(&ev.xkey, e->key.str, 10, &sym, 0); + e->key.strn = Xutf8LookupString(ic, &ev.xkey, e->key.str, sizeof(e->key.str), &sym, &status); e->key.key = xksym_to_uik(sym); return 1; case Expose: @@ -185,6 +243,7 @@ ui_draw(Str input, int inpi, int seli, UiOpts o) XWindowAttributes attr; XClearWindow(dsp, win); XGetWindowAttributes(dsp, win, &attr); + set_ic_pos(input.s, inpi); /* draw input */ @@ -242,13 +301,3 @@ ui_draw(Str input, int inpi, int seli, UiOpts o) y += 24; } } - -void -ui_fini(void) -{ - XFreeFont(dsp, ft_opt); - XFreeFont(dsp, ft_inp); - XFreeGC(dsp, gc); - XDestroyWindow(dsp, win); - XCloseDisplay(dsp); -} |
