diff --git a/libs/x11/client.c b/libs/x11/client.c index d296538..0f338cc 100644 --- a/libs/x11/client.c +++ b/libs/x11/client.c @@ -210,3 +210,43 @@ void resizeclient(void) { XMoveResizeWindow(dpy, win, x + sp, y + vp, mw - 2 * sp - borderwidth * 2, mh); drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh); } + +void xinitvisual(void) { + XVisualInfo *infos; + XRenderPictFormat *fmt; + int nitems; + int i; + + // visual properties + XVisualInfo tpl = { + .screen = screen, + .depth = 32, + .class = TrueColor + }; + + long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; + + infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); + visual = NULL; + + // create colormap + for(i = 0; i < nitems; i ++) { + fmt = XRenderFindVisualFormat(dpy, infos[i].visual); + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { + visual = infos[i].visual; + depth = infos[i].depth; + cmap = XCreateColormap(dpy, root, visual, AllocNone); + useargb = 1; + break; + } + } + + XFree(infos); + + // no alpha, reset to default + if (!visual || !alpha) { + visual = DefaultVisual(dpy, screen); + depth = DefaultDepth(dpy, screen); + cmap = DefaultColormap(dpy, screen); + } +} diff --git a/libs/x11/client.h b/libs/x11/client.h index e220cf8..f8d6a5a 100644 --- a/libs/x11/client.h +++ b/libs/x11/client.h @@ -8,3 +8,4 @@ static void set_prop(void); static void resizeclient(void); static void store_image_vars(void); static void set_mode(void); +static void xinitvisual(void); diff --git a/libs/x11/clipboard.c b/libs/x11/clipboard.c new file mode 100644 index 0000000..f6e59ed --- /dev/null +++ b/libs/x11/clipboard.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ + +void pastesel_x11(void) { + char *p, *q; + int di; + unsigned long dl; + Atom da; + + // we have been given the current selection, now insert it into input + if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, + utf8, &da, &di, &dl, &dl, (unsigned char **)&p) + == Success && p) { + insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); // insert selection + XFree(p); + } + + // draw the menu + drawmenu(); +} diff --git a/libs/x11/clipboard.h b/libs/x11/clipboard.h new file mode 100644 index 0000000..43622ee --- /dev/null +++ b/libs/x11/clipboard.h @@ -0,0 +1,3 @@ +/* See LICENSE file for copyright and license details. */ + +static void pastesel_x11(void); diff --git a/libs/x11/focus.c b/libs/x11/focus.c new file mode 100644 index 0000000..196efca --- /dev/null +++ b/libs/x11/focus.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ + +void grabfocus_x11(void) { + struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; + Window focuswin; + int i, revertwin; + XWindowAttributes wa; + + XSync(dpy, False); + XGetWindowAttributes(dpy, win, &wa); + + for (i = 0; i < 100; ++i) { + XGetInputFocus(dpy, &focuswin, &revertwin); + if (focuswin == win) + return; + + // if it's a client, we can't just steal all the input for ourselves + if (managed) { + if (wa.map_state == IsViewable) { + XTextProperty prop; + char *windowtitle = prompt != NULL ? prompt : "spmenu"; + Xutf8TextListToTextProperty(dpy, &windowtitle, 1, XUTF8StringStyle, &prop); + XSetWMName(dpy, win, &prop); + XSetTextProperty(dpy, win, &prop, XInternAtom(dpy, "_NET_WM_NAME", False)); + XFree(prop.value); + } + } else { // spmenu is not managed, and is very greedy + if (wa.map_state == IsViewable) // it must be viewable first, otherwise we get a BadMatch error + XSetInputFocus(dpy, win, RevertToParent, CurrentTime); + } + + nanosleep(&ts, NULL); + } + + die("spmenu: cannot grab focus"); // not possible to grab focus, abort immediately +} diff --git a/libs/x11/focus.h b/libs/x11/focus.h new file mode 100644 index 0000000..1ba9fc9 --- /dev/null +++ b/libs/x11/focus.h @@ -0,0 +1,3 @@ +/* See LICENSE file for copyright and license details. */ + +static void grabfocus_x11(void); diff --git a/libs/x11/inc.c b/libs/x11/inc.c index 00fb203..c4ef14e 100644 --- a/libs/x11/inc.c +++ b/libs/x11/inc.c @@ -7,3 +7,5 @@ #include "client.h" #include "client.c" #include "init.c" +#include "focus.c" +#include "clipboard.c" diff --git a/libs/x11/inc.h b/libs/x11/inc.h index b17c739..8f718b3 100644 --- a/libs/x11/inc.h +++ b/libs/x11/inc.h @@ -6,3 +6,5 @@ #include "xim.h" #include "key.h" #include "mouse.h" +#include "focus.h" +#include "clipboard.h" diff --git a/libs/x11/init.c b/libs/x11/init.c index ad93f68..319254a 100644 --- a/libs/x11/init.c +++ b/libs/x11/init.c @@ -174,3 +174,9 @@ void handle_x11(void) { xinitvisual(); // init visual and create drawable after drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); } + +void cleanup_x11(Display *disp) { + XUngrabKey(disp, AnyKey, AnyModifier, root); + XSync(disp, False); + XCloseDisplay(disp); +} diff --git a/libs/x11/init.h b/libs/x11/init.h index fc1315d..488df3b 100644 --- a/libs/x11/init.h +++ b/libs/x11/init.h @@ -7,4 +7,5 @@ static Window root, parentwin, win; static void setupdisplay(void); static void set_screen(Display *disp); static void handle_x11(void); +static void cleanup_x11(Display *disp); static Display * opendisplay(char *disp); diff --git a/spmenu.c b/spmenu.c index 2f717c2..085633e 100644 --- a/spmenu.c +++ b/spmenu.c @@ -180,9 +180,9 @@ static int ignoreconfmouse = 0; // same for mouse static int ignoreglobalmouse = 0; // same for mouse // colors -static int useargb = 0; -static Visual *visual; +static int useargb; static int depth; +static Visual *visual; static Colormap cmap; static Drw *drw; static Clr **scheme; @@ -195,10 +195,9 @@ static void recalculatenumbers(void); static void insert(const char *str, ssize_t n); static void cleanup(void); static void navigatehistfile(int dir); -static void grabfocus(void); static void pastesel(void); +static void grabfocus(void); static void appenditem(struct item *item, struct item **list, struct item **last); -static void xinitvisual(void); static int max_textw(void); static size_t nextrune(int inc); static char * cistrstr(const char *s, const char *sub); @@ -351,8 +350,6 @@ void cleanup(void) { cleanupimage(); // function frees images #endif - XUngrabKey(dpy, AnyKey, AnyModifier, root); // ungrab keys - // free color scheme for (i = 0; i < LENGTH(colors) + 1; i++) free(scheme[i]); @@ -363,8 +360,7 @@ void cleanup(void) { // free drawing and close the display drw_free(drw); - XSync(dpy, False); - XCloseDisplay(dpy); + cleanup_x11(dpy); free(sel_index); } @@ -386,38 +382,7 @@ char * cistrstr(const char *h, const char *n) { } void grabfocus(void) { - struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; - Window focuswin; - int i, revertwin; - XWindowAttributes wa; - - XSync(dpy, False); - XGetWindowAttributes(dpy, win, &wa); - - for (i = 0; i < 100; ++i) { - XGetInputFocus(dpy, &focuswin, &revertwin); - if (focuswin == win) - return; - - // if it's a client, we can't just steal all the input for ourselves - if (managed) { - if (wa.map_state == IsViewable) { - XTextProperty prop; - char *windowtitle = prompt != NULL ? prompt : "spmenu"; - Xutf8TextListToTextProperty(dpy, &windowtitle, 1, XUTF8StringStyle, &prop); - XSetWMName(dpy, win, &prop); - XSetTextProperty(dpy, win, &prop, XInternAtom(dpy, "_NET_WM_NAME", False)); - XFree(prop.value); - } - } else { // spmenu is not managed, and is very greedy - if (wa.map_state == IsViewable) // it must be viewable first, otherwise we get a BadMatch error - XSetInputFocus(dpy, win, RevertToParent, CurrentTime); - } - - nanosleep(&ts, NULL); - } - - die("spmenu: cannot grab focus"); // not possible to grab focus, abort immediately + grabfocus_x11(); } void insert(const char *str, ssize_t n) { @@ -455,61 +420,7 @@ size_t nextrune(int inc) { } void pastesel(void) { - char *p, *q; - int di; - unsigned long dl; - Atom da; - - // we have been given the current selection, now insert it into input - if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, - utf8, &da, &di, &dl, &dl, (unsigned char **)&p) - == Success && p) { - insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); // insert selection - XFree(p); - } - - // draw the menu - drawmenu(); -} - -void xinitvisual(void) { - XVisualInfo *infos; - XRenderPictFormat *fmt; - int nitems; - int i; - - // visual properties - XVisualInfo tpl = { - .screen = screen, - .depth = 32, - .class = TrueColor - }; - - long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; - - infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); - visual = NULL; - - // create colormap - for(i = 0; i < nitems; i ++) { - fmt = XRenderFindVisualFormat(dpy, infos[i].visual); - if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { - visual = infos[i].visual; - depth = infos[i].depth; - cmap = XCreateColormap(dpy, root, visual, AllocNone); - useargb = 1; - break; - } - } - - XFree(infos); - - // no alpha, reset to default - if (!visual || !alpha) { - visual = DefaultVisual(dpy, screen); - depth = DefaultDepth(dpy, screen); - cmap = DefaultColormap(dpy, screen); - } + pastesel_x11(); } int main(int argc, char *argv[]) {