X-Git-Url: https://git.xinqibao.xyz/dmenu.git/blobdiff_plain/5e0156c0727fa8f225c3309f265da241a98edc08..dd29c5d48084ae0f61a43bfbd5119fb480d83fb7:/dmenu.c diff --git a/dmenu.c b/dmenu.c index dc1f236..841af4a 100644 --- a/dmenu.c +++ b/dmenu.c @@ -13,9 +13,10 @@ #endif #include "draw.h" -#define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ + * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) typedef struct Item Item; struct Item { @@ -58,6 +59,7 @@ static Item *items = NULL; static Item *matches, *matchend; static Item *prev, *curr, *next, *sel; static Window win; +static XIC xic; static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; static char *(*fstrstr)(const char *, const char *) = strstr; @@ -229,9 +231,13 @@ insert(const char *str, ssize_t n) { void keypress(XKeyEvent *ev) { char buf[32]; - KeySym ksym; + int len; + KeySym ksym = NoSymbol; + Status status; - XLookupString(ev, buf, sizeof buf, &ksym, NULL); + len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); + if(status == XBufferOverflow) + return; if(ev->state & ControlMask) { KeySym lower, upper; @@ -273,7 +279,7 @@ keypress(XKeyEvent *ev) { switch(ksym) { default: if(!iscntrl(*buf)) - insert(buf, strlen(buf)); + insert(buf, len); break; case XK_Delete: if(text[cursor] == '\0') @@ -461,7 +467,9 @@ void run(void) { XEvent ev; - while(!XNextEvent(dc->dpy, &ev)) + while(!XNextEvent(dc->dpy, &ev)) { + if(XFilterEvent(&ev, win)) + continue; switch(ev.type) { case Expose: if(ev.xexpose.count == 0) @@ -479,6 +487,7 @@ run(void) { XRaiseWindow(dc->dpy, win); break; } + } } void @@ -486,6 +495,7 @@ setup(void) { int x, y, screen = DefaultScreen(dc->dpy); Window root = RootWindow(dc->dpy, screen); XSetWindowAttributes swa; + XIM xim; #ifdef XINERAMA int n; XineramaScreenInfo *info; @@ -504,19 +514,28 @@ setup(void) { mh = (lines + 1) * bh; #ifdef XINERAMA if((info = XineramaQueryScreens(dc->dpy, &n))) { - int i, di; + int a, j, di, i = 0, area = 0; unsigned int du; - Window w, dw; + Window w, pw, dw, *dws; XWindowAttributes wa; XGetInputFocus(dc->dpy, &w, &di); - if(w != root && w != PointerRoot && w != None && XGetWindowAttributes(dc->dpy, w, &wa)) - XTranslateCoordinates(dc->dpy, w, root, wa.x, wa.y, &x, &y, &dw); - else - XQueryPointer(dc->dpy, root, &dw, &dw, &x, &y, &di, &di, &du); - for(i = 0; i < n-1; i++) - if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) - break; + if(w != root && w != PointerRoot && w != None) { + do { + if(XQueryTree(dc->dpy, (pw = w), &dw, &w, &dws, &du) && dws) + XFree(dws); + } while(w != root && w != pw); + if(XGetWindowAttributes(dc->dpy, pw, &wa)) + for(j = 0; j < n; j++) + if((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { + area = a; + i = j; + } + } + if(!area && XQueryPointer(dc->dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) + for(i = 0; i < n; i++) + if(INTERSECT(x, y, 1, 1, info[i])) + break; x = info[i].x_org; y = info[i].y_org + (topbar ? 0 : info[i].height - mh); mw = info[i].width; @@ -542,6 +561,11 @@ setup(void) { DefaultVisual(dc->dpy, screen), CWOverrideRedirect | CWBackPixmap | CWEventMask, &swa); + /* input methods */ + xim = XOpenIM(dc->dpy, NULL, NULL, NULL); + xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, win, XNFocusWindow, win, NULL); + XMapRaised(dc->dpy, win); resizedc(dc, mw, mh); drawmenu();