--- rxvt-unicode/src/rxvttoolkit.C 2011/02/11 01:24:46 1.115 +++ rxvt-unicode/src/rxvttoolkit.C 2014/11/02 15:52:39 1.144 @@ -3,11 +3,12 @@ *----------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. - * Copyright (c) 2003-2007 Marc Lehmann + * Copyright (c) 2003-2011 Marc Lehmann + * Copyright (c) 2011 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -67,7 +68,7 @@ "WM_LOCALE_NAME", "XIM_SERVERS", #endif -#ifdef ENABLE_TRANSPARENCY +#if HAVE_IMG || ENABLE_PERL "_XROOTPMAP_ID", "ESETROOT_PMAP_ID", #endif @@ -154,7 +155,7 @@ ///////////////////////////////////////////////////////////////////////////// -#ifdef USE_XIM +#if USE_XIM static void #if XIMCB_PROTO_BROKEN @@ -261,21 +262,41 @@ cmap = DefaultColormapOfScreen (screen); } +#if ENABLE_FRILLS + void -rxvt_screen::select_visual (int bitdepth) +rxvt_screen::select_visual (int id) { -#if XFT XVisualInfo vinfo; + vinfo.visualid = id; + int n; - if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo)) + if (XVisualInfo *vi = XGetVisualInfo (dpy, VisualIDMask, &vinfo, &n)) { - depth = bitdepth; - visual = vinfo.visual; - cmap = XCreateColormap (dpy, display->root, visual, AllocNone); + depth = vi->depth; + visual = vi->visual; + + XFree (vi); + + cmap = XCreateColormap (dpy, display->root, visual, AllocNone); } -#endif + else + rxvt_warn ("no visual found for requested id 0x%02x, using default visual.\n", id); +} + +void +rxvt_screen::select_depth (int bitdepth) +{ + XVisualInfo vinfo; + + if (XMatchVisualInfo (dpy, display->screen, bitdepth, TrueColor, &vinfo)) + select_visual (vinfo.visualid); + else + rxvt_warn ("no visual found for requested depth %d, using default visual.\n", bitdepth); } +#endif + void rxvt_screen::clear () { @@ -431,10 +452,11 @@ #ifdef LOCAL_X_IS_UNIX if (id[0] == ':') { - if (!(val = rxvt_temp_buf (5 + strlen (id) + 1))) - return false; + char *val = rxvt_temp_buf (5 + strlen (id) + 1); + strcpy (val, "unix/"); strcat (val, id); + dpy = XOpenDisplay (val); } else @@ -450,7 +472,7 @@ screen = DefaultScreen (dpy); root = DefaultRootWindow (dpy); - assert (ARRAY_LENGTH(xa_names) == NUM_XA); + assert (ecb_array_length (xa_names) == NUM_XA); XInternAtoms (dpy, (char **)xa_names, NUM_XA, False, xa); XrmSetDatabase (dpy, get_resources (false)); @@ -466,6 +488,25 @@ XUnloadFont (dpy, f); #endif + flags = 0; +#if XRENDER + int major, minor; + if (XRenderQueryVersion (dpy, &major, &minor)) + if (major > 0 || (major == 0 && minor >= 11)) + { + flags |= DISPLAY_HAS_RENDER; + + if (XFilters *filters = XRenderQueryFilters (dpy, root)) + { + for (int i = 0; i < filters->nfilter; i++) + if (!strcmp (filters->filter [i], FilterConvolution)) + flags |= DISPLAY_HAS_RENDER_CONV; + + XFree (filters); + } + } +#endif + int fd = XConnectionNumber (dpy); // try to detect whether we have a local connection. @@ -512,14 +553,14 @@ #endif x_ev.stop (); flush_ev.stop (); -#ifdef USE_XIM +#if USE_XIM xims.clear (); #endif XrmDestroyDatabase (XrmGetDatabase (dpy)); XCloseDisplay (dpy); } -#ifdef USE_XIM +#if USE_XIM void rxvt_display::im_change_cb () { for (im_watcher **i = imw.begin (); i != imw.end (); ++i) @@ -565,7 +606,7 @@ XEvent xev; XNextEvent (dpy, &xev); -#ifdef USE_XIM +#if USE_XIM if (!XFilterEvent (&xev, None)) { if (xev.type == PropertyNotify @@ -583,7 +624,7 @@ else if (xw[i]->window == xev.xany.window) xw[i]->call (xev); } -#ifdef USE_XIM +#if USE_XIM } #endif } @@ -624,7 +665,7 @@ cur_owner = owner; } -#ifdef USE_XIM +#if USE_XIM void rxvt_display::reg (im_watcher *w) { @@ -669,6 +710,28 @@ return XInternAtom (dpy, name, False); } +Pixmap +rxvt_display::get_pixmap_property (Atom property) +{ + Pixmap pixmap = None; + + int aformat; + unsigned long nitems, bytes_after; + Atom atype; + unsigned char *prop; + int result = XGetWindowProperty (dpy, root, property, + 0L, 1L, False, XA_PIXMAP, &atype, &aformat, + &nitems, &bytes_after, &prop); + if (result == Success) + { + if (atype == XA_PIXMAP) + pixmap = *(Pixmap *)prop; + XFree (prop); + } + + return pixmap; +} + ///////////////////////////////////////////////////////////////////////////// template class refcache; @@ -687,7 +750,7 @@ rxvt_color::alloc (rxvt_screen *screen, const rgba &color) { //TODO: only supports 24 bit - int alpha = color.a >= 0xff00 ? 0xffff : color.a; + unsigned int alpha = color.a >= 0xff00 ? 0xffff : color.a; #if XFT XRenderPictFormat *format; @@ -704,10 +767,16 @@ c.color.blue = color.b; c.color.alpha = alpha; - c.pixel = insert_component (color.r, format->direct.redMask , format->direct.red ) - | insert_component (color.g, format->direct.greenMask, format->direct.green) - | insert_component (color.b, format->direct.blueMask , format->direct.blue ) - | insert_component (alpha , format->direct.alphaMask, format->direct.alpha); + // Xft wants premultiplied alpha, but abuses the alpha channel + // as blend factor, and doesn't allow us to set the alpha channel + c.color.red = c.color.red * alpha / 0xffff; + c.color.green = c.color.green * alpha / 0xffff; + c.color.blue = c.color.blue * alpha / 0xffff; + + c.pixel = insert_component (c.color.red , format->direct.redMask , format->direct.red ) + | insert_component (c.color.green, format->direct.greenMask, format->direct.green) + | insert_component (c.color.blue , format->direct.blueMask , format->direct.blue ) + | insert_component (alpha , format->direct.alphaMask, format->direct.alpha); return true; } @@ -720,7 +789,8 @@ d.blue = color.b; d.alpha = alpha; - return XftColorAllocValue (screen->dpy, screen->visual, screen->cmap, &d, &c); + if (XftColorAllocValue (screen->dpy, screen->visual, screen->cmap, &d, &c)) + return true; } #else c.red = color.r; @@ -729,20 +799,20 @@ if (screen->visual->c_class == TrueColor) { - c.pixel = (color.r >> (16 - rxvt_popcount (screen->visual->red_mask )) << rxvt_ctz (screen->visual->red_mask )) - | (color.g >> (16 - rxvt_popcount (screen->visual->green_mask)) << rxvt_ctz (screen->visual->green_mask)) - | (color.b >> (16 - rxvt_popcount (screen->visual->blue_mask )) << rxvt_ctz (screen->visual->blue_mask )); + c.pixel = (color.r >> (16 - ecb_popcount32 (screen->visual->red_mask )) << ecb_ctz32 (screen->visual->red_mask )) + | (color.g >> (16 - ecb_popcount32 (screen->visual->green_mask)) << ecb_ctz32 (screen->visual->green_mask)) + | (color.b >> (16 - ecb_popcount32 (screen->visual->blue_mask )) << ecb_ctz32 (screen->visual->blue_mask )); return true; } else if (XAllocColor (screen->dpy, screen->cmap, &c)) return true; - else - c.pixel = (color.r + color.g + color.b) > 128*3 - ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->dpy)) - : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->dpy)); #endif + c.pixel = (color.r + color.g + color.b) > 128*3 + ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->dpy)) + : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->dpy)); + return false; } @@ -836,7 +906,7 @@ } void -rxvt_color::get (rgba &color) +rxvt_color::get (rgba &color) const { #if XFT color.r = c.color.red; @@ -852,7 +922,7 @@ } void -rxvt_color::get (XColor &color) +rxvt_color::get (XColor &color) const { rgba c; get (c); @@ -893,8 +963,8 @@ ); } -rxvt_selection::rxvt_selection (rxvt_display *disp, int selnum, Time tm, Window win, Atom prop, sel_cb cb, void *ptr) -: display (disp), request_time (tm), request_win (win), request_prop (prop), request_cb (cb), user_data (ptr) +rxvt_selection::rxvt_selection (rxvt_display *disp, int selnum, Time tm, Window win, Atom prop, rxvt_term *term) +: display (disp), request_time (tm), request_win (win), request_prop (prop), term (term) { assert (selnum >= Sel_Primary && selnum <= Sel_Clipboard); @@ -905,6 +975,39 @@ incr_buf = 0; incr_buf_size = incr_buf_fill = 0; selection_wait = Sel_normal; + selection_type = selnum; + cb_sv = 0; +} + +void +rxvt_selection::stop () +{ + free (incr_buf); + incr_buf = 0; + timer_ev.stop (); + x_ev.stop (display); +} + +rxvt_selection::~rxvt_selection () +{ + stop (); +} + +void +rxvt_selection::run () +{ + int selnum = selection_type; + +#if ENABLE_FRILLS + if (selnum == Sel_Primary && display->selection_owner) + { + /* internal selection */ + char *str = rxvt_wcstombs (display->selection_owner->selection.text, display->selection_owner->selection.len); + finish (str, strlen (str)); + free (str); + return; + } +#endif #if X_HAVE_UTF8_STRING selection_type = Sel_UTF8String; @@ -920,18 +1023,24 @@ handle_selection (display->root, XA_CUT_BUFFER0, false); } -rxvt_selection::~rxvt_selection () -{ - stop (); -} - void -rxvt_selection::stop () +rxvt_selection::finish (char *data, unsigned int len) { - free (incr_buf); - incr_buf = 0; - timer_ev.stop (); - x_ev.stop (display); + if (!cb_sv) + { + if (data) + term->paste (data, len); + + term->selection_req = 0; + delete this; + } +#if ENABLE_PERL + else + { + stop (); // we do not really trust perl callbacks + rxvt_perl.selection_finish (this, data, len); + } +#endif } bool @@ -1106,8 +1215,7 @@ if (selection_wait == Sel_normal) { - stop (); - request_cb (data, data_len, this, user_data); + finish (data, data_len); free (data); } } @@ -1118,8 +1226,7 @@ if (selection_wait == Sel_incr) rxvt_warn ("data loss: timeout on INCR selection paste, ignoring.\n"); - stop (); - request_cb (NULL, 0, this, user_data); + finish (); } void @@ -1136,8 +1243,7 @@ case SelectionNotify: if (selection_wait == Sel_normal - && xev.xselection.time == request_time - && xev.xselection.property == request_prop) + && xev.xselection.time == request_time) { timer_ev.stop (); handle_selection (xev.xselection.requestor, xev.xselection.property, true);