summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ui.c81
1 files changed, 65 insertions, 16 deletions
diff --git a/ui.c b/ui.c
index 1913709..37c36b7 100644
--- a/ui.c
+++ b/ui.c
@@ -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);
-}