]> git.armaanb.net Git - dmenu.git/commitdiff
add embedding support with -w option
authorQuentin Rameau <quinq@fifth.space>
Sat, 8 Oct 2016 12:08:28 +0000 (14:08 +0200)
committerHiltjo Posthuma <hiltjo@codemadness.org>
Fri, 14 Oct 2016 13:26:35 +0000 (15:26 +0200)
dmenu.1
dmenu.c

diff --git a/dmenu.1 b/dmenu.1
index 8bbd79d42a5e3395bc255e9ce27be21dcc6f358b..9eab758ca5b51a6b5ca1fc81d5ab095a1e3fde27 100644 (file)
--- a/dmenu.1
+++ b/dmenu.1
@@ -20,6 +20,8 @@ dmenu \- dynamic menu
 .IR color ]
 .RB [ \-sf
 .IR color ]
 .IR color ]
 .RB [ \-sf
 .IR color ]
+.RB [ \-w
+.IR windowid ]
 .P
 .BR dmenu_run " ..."
 .SH DESCRIPTION
 .P
 .BR dmenu_run " ..."
 .SH DESCRIPTION
@@ -75,6 +77,9 @@ defines the selected foreground color.
 .TP
 .B \-v
 prints version information to stdout, then exits.
 .TP
 .B \-v
 prints version information to stdout, then exits.
+.TP
+.BI \-w " windowid"
+embed into windowid.
 .SH USAGE
 dmenu is completely controlled by the keyboard.  Items are selected using the
 arrow keys, page up, page down, home, and end.
 .SH USAGE
 dmenu is completely controlled by the keyboard.  Items are selected using the
 arrow keys, page up, page down, home, and end.
diff --git a/dmenu.c b/dmenu.c
index ff7436936315e4cc6c00942fc74179b5e797254b..9278e916f6e4f6079e5c05b8abec274c457b394f 100644 (file)
--- a/dmenu.c
+++ b/dmenu.c
@@ -34,8 +34,8 @@ struct item {
 };
 
 static char text[BUFSIZ] = "";
 };
 
 static char text[BUFSIZ] = "";
+static char *embed;
 static int bh, mw, mh;
 static int bh, mw, mh;
-static int sw, sh; /* X display screen geometry width, height */
 static int inputw = 0, promptw;
 static int lrpad; /* sum of left and right padding */
 static size_t cursor;
 static int inputw = 0, promptw;
 static int lrpad; /* sum of left and right padding */
 static size_t cursor;
@@ -46,7 +46,7 @@ static int mon = -1, screen;
 
 static Atom clip, utf8;
 static Display *dpy;
 
 static Atom clip, utf8;
 static Display *dpy;
-static Window root, win;
+static Window root, parentwin, win;
 static XIC xic;
 
 static Drw *drw;
 static XIC xic;
 
 static Drw *drw;
@@ -174,12 +174,31 @@ drawmenu(void)
        drw_map(drw, win, 0, 0, mw, mh);
 }
 
        drw_map(drw, win, 0, 0, mw, mh);
 }
 
+static void
+grabfocus(void)
+{
+       struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000  };
+       Window focuswin;
+       int i, revertwin;
+
+       for (i = 0; i < 100; ++i) {
+               XGetInputFocus(dpy, &focuswin, &revertwin);
+               if (focuswin == win)
+                       return;
+               XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
+               nanosleep(&ts, NULL);
+       }
+       die("cannot grab focus");
+}
+
 static void
 grabkeyboard(void)
 {
        struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000  };
        int i;
 
 static void
 grabkeyboard(void)
 {
        struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000  };
        int i;
 
+       if (embed)
+               return;
        /* try to grab keyboard, we may have to wait for another process to ungrab */
        for (i = 0; i < 1000; i++) {
                if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
        /* try to grab keyboard, we may have to wait for another process to ungrab */
        for (i = 0; i < 1000; i++) {
                if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
@@ -497,6 +516,11 @@ run(void)
                        if (ev.xexpose.count == 0)
                                drw_map(drw, win, 0, 0, mw, mh);
                        break;
                        if (ev.xexpose.count == 0)
                                drw_map(drw, win, 0, 0, mw, mh);
                        break;
+               case FocusIn:
+                       /* regrab focus from parent window */
+                       if (ev.xfocus.window != win)
+                               grabfocus();
+                       break;
                case KeyPress:
                        keypress(&ev.xkey);
                        break;
                case KeyPress:
                        keypress(&ev.xkey);
                        break;
@@ -539,7 +563,7 @@ setup(void)
        lines = MAX(lines, 0);
        mh = (lines + 1) * bh;
 #ifdef XINERAMA
        lines = MAX(lines, 0);
        mh = (lines + 1) * bh;
 #ifdef XINERAMA
-       if ((info = XineramaQueryScreens(dpy, &n))) {
+       if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
                XGetInputFocus(dpy, &w, &di);
                if (mon >= 0 && mon < n)
                        i = mon;
                XGetInputFocus(dpy, &w, &di);
                if (mon >= 0 && mon < n)
                        i = mon;
@@ -570,9 +594,12 @@ setup(void)
        } else
 #endif
        {
        } else
 #endif
        {
+               if (!XGetWindowAttributes(dpy, parentwin, &wa))
+                       die("could not get embedding window attributes: 0x%lx",
+                           parentwin);
                x = 0;
                x = 0;
-               y = topbar ? 0 : sh - mh;
-               mw = sw;
+               y = topbar ? 0 : wa.height - mh;
+               mw = wa.width;
        }
        promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
        inputw = MIN(inputw, mw/3);
        }
        promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
        inputw = MIN(inputw, mw/3);
@@ -582,9 +609,8 @@ setup(void)
        swa.override_redirect = True;
        swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
        swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
        swa.override_redirect = True;
        swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
        swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
-       win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
-                           DefaultDepth(dpy, screen), CopyFromParent,
-                           DefaultVisual(dpy, screen),
+       win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
+                           CopyFromParent, CopyFromParent, CopyFromParent,
                            CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
 
        /* open input methods */
                            CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
 
        /* open input methods */
@@ -593,6 +619,15 @@ setup(void)
                        XNClientWindow, win, XNFocusWindow, win, NULL);
 
        XMapRaised(dpy, win);
                        XNClientWindow, win, XNFocusWindow, win, NULL);
 
        XMapRaised(dpy, win);
+       if (embed) {
+               XSelectInput(dpy, parentwin, FocusChangeMask);
+               if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
+                       for (i = 0; i < du && dws[i] != win; ++i)
+                               XSelectInput(dpy, dws[i], FocusChangeMask);
+                       XFree(dws);
+               }
+               grabfocus();
+       }
        drw_resize(drw, mw, mh);
        drawmenu();
 }
        drw_resize(drw, mw, mh);
        drawmenu();
 }
@@ -601,13 +636,14 @@ static void
 usage(void)
 {
        fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
 usage(void)
 {
        fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
-             "             [-nb color] [-nf color] [-sb color] [-sf color]\n", stderr);
+             "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
        exit(1);
 }
 
 int
 main(int argc, char *argv[])
 {
        exit(1);
 }
 
 int
 main(int argc, char *argv[])
 {
+       XWindowAttributes wa;
        int i, fast = 0;
 
        for (i = 1; i < argc; i++)
        int i, fast = 0;
 
        for (i = 1; i < argc; i++)
@@ -641,6 +677,8 @@ main(int argc, char *argv[])
                        colors[SchemeSel][ColBg] = argv[++i];
                else if (!strcmp(argv[i], "-sf"))  /* selected foreground color */
                        colors[SchemeSel][ColFg] = argv[++i];
                        colors[SchemeSel][ColBg] = argv[++i];
                else if (!strcmp(argv[i], "-sf"))  /* selected foreground color */
                        colors[SchemeSel][ColFg] = argv[++i];
+               else if (!strcmp(argv[i], "-w"))   /* embedding window id */
+                       embed = argv[++i];
                else
                        usage();
 
                else
                        usage();
 
@@ -650,9 +688,12 @@ main(int argc, char *argv[])
                die("cannot open display");
        screen = DefaultScreen(dpy);
        root = RootWindow(dpy, screen);
                die("cannot open display");
        screen = DefaultScreen(dpy);
        root = RootWindow(dpy, screen);
-       sw = DisplayWidth(dpy, screen);
-       sh = DisplayHeight(dpy, screen);
-       drw = drw_create(dpy, screen, root, sw, sh);
+       if (!embed || !(parentwin = strtol(embed, NULL, 0)))
+               parentwin = root;
+       if (!XGetWindowAttributes(dpy, parentwin, &wa))
+               die("could not get embedding window attributes: 0x%lx",
+                   parentwin);
+       drw = drw_create(dpy, screen, root, wa.width, wa.height);
        if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
                die("no fonts could be loaded.");
        lrpad = drw->fonts->h;
        if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
                die("no fonts could be loaded.");
        lrpad = drw->fonts->h;