comparison src/gui_x11.c @ 9634:86d470495333 v7.4.2094

commit https://github.com/vim/vim/commit/4658228262f491fcb582d531d4e8e5754b0d5e83 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jul 23 14:35:12 2016 +0200 patch 7.4.2094 Problem: The color allocation in X11 is overly complicated. Solution: Remove find_closest_color(), XAllocColor() already does this. (Kazunobu Kuriyama)
author Christian Brabandt <cb@256bit.org>
date Sat, 23 Jul 2016 14:45:05 +0200
parents 0c7f47088e55
children ccb6461b82df
comparison
equal deleted inserted replaced
9633:c2fba797633f 9634:86d470495333
69 #ifdef FEAT_GUI_ATHENA 69 #ifdef FEAT_GUI_ATHENA
70 # define DFLT_MENU_BG_COLOR "gray77" 70 # define DFLT_MENU_BG_COLOR "gray77"
71 # define DFLT_MENU_FG_COLOR "black" 71 # define DFLT_MENU_FG_COLOR "black"
72 # define DFLT_SCROLL_BG_COLOR "gray60" 72 # define DFLT_SCROLL_BG_COLOR "gray60"
73 # define DFLT_SCROLL_FG_COLOR "gray77" 73 # define DFLT_SCROLL_FG_COLOR "gray77"
74 # define DFLT_TOOLTIP_BG_COLOR "#ffffffff9191" 74 # define DFLT_TOOLTIP_BG_COLOR "#ffff91"
75 # define DFLT_TOOLTIP_FG_COLOR "#000000000000" 75 # define DFLT_TOOLTIP_FG_COLOR "#000000"
76 #else 76 #else
77 /* use the default (CDE) colors */ 77 /* use the default (CDE) colors */
78 # define DFLT_MENU_BG_COLOR "" 78 # define DFLT_MENU_BG_COLOR ""
79 # define DFLT_MENU_FG_COLOR "" 79 # define DFLT_MENU_FG_COLOR ""
80 # define DFLT_SCROLL_BG_COLOR "" 80 # define DFLT_SCROLL_BG_COLOR ""
81 # define DFLT_SCROLL_FG_COLOR "" 81 # define DFLT_SCROLL_FG_COLOR ""
82 # define DFLT_TOOLTIP_BG_COLOR "#ffffffff9191" 82 # define DFLT_TOOLTIP_BG_COLOR "#ffff91"
83 # define DFLT_TOOLTIP_FG_COLOR "#000000000000" 83 # define DFLT_TOOLTIP_FG_COLOR "#000000"
84 #endif 84 #endif
85 85
86 Widget vimShell = (Widget)0; 86 Widget vimShell = (Widget)0;
87 87
88 static Atom wm_atoms[2]; /* Window Manager Atoms */ 88 static Atom wm_atoms[2]; /* Window Manager Atoms */
134 134
135 #if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) 135 #if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU)
136 static XButtonPressedEvent last_mouse_event; 136 static XButtonPressedEvent last_mouse_event;
137 #endif 137 #endif
138 138
139 static int find_closest_color(Colormap colormap, XColor *colorPtr);
140 static void gui_x11_timer_cb(XtPointer timed_out, XtIntervalId *interval_id); 139 static void gui_x11_timer_cb(XtPointer timed_out, XtIntervalId *interval_id);
141 static void gui_x11_visibility_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum); 140 static void gui_x11_visibility_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum);
142 static void gui_x11_expose_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum); 141 static void gui_x11_expose_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum);
143 static void gui_x11_resize_window_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum); 142 static void gui_x11_resize_window_cb(Widget w, XtPointer dud, XEvent *event, Boolean *dum);
144 static void gui_x11_focus_change_cb(Widget w, XtPointer data, XEvent *event, Boolean *dum); 143 static void gui_x11_focus_change_cb(Widget w, XtPointer data, XEvent *event, Boolean *dum);
2240 /* 2239 /*
2241 * Return the Pixel value (color) for the given color name. 2240 * Return the Pixel value (color) for the given color name.
2242 * Return INVALCOLOR for error. 2241 * Return INVALCOLOR for error.
2243 */ 2242 */
2244 guicolor_T 2243 guicolor_T
2245 gui_mch_get_color(char_u *reqname) 2244 gui_mch_get_color(char_u *name)
2246 { 2245 {
2247 int i; 2246 guicolor_T requested;
2248 char_u *name = reqname; 2247 XColor available;
2249 Colormap colormap; 2248 Colormap colormap;
2250 XColor color; 2249 #define COLORSPECBUFSIZE 8 /* space enough to hold "#RRGGBB" */
2251 static char *(vimnames[][2]) = 2250 char spec[COLORSPECBUFSIZE];
2252 {
2253 /* A number of colors that some X11 systems don't have */
2254 {"LightRed", "#FFBBBB"},
2255 {"LightGreen", "#88FF88"},
2256 {"LightMagenta","#FFBBFF"},
2257 {"DarkCyan", "#008888"},
2258 {"DarkBlue", "#0000BB"},
2259 {"DarkRed", "#BB0000"},
2260 {"DarkMagenta", "#BB00BB"},
2261 {"DarkGrey", "#BBBBBB"},
2262 {"DarkYellow", "#BBBB00"},
2263 {"Gray10", "#1A1A1A"},
2264 {"Grey10", "#1A1A1A"},
2265 {"Gray20", "#333333"},
2266 {"Grey20", "#333333"},
2267 {"Gray30", "#4D4D4D"},
2268 {"Grey30", "#4D4D4D"},
2269 {"Gray40", "#666666"},
2270 {"Grey40", "#666666"},
2271 {"Gray50", "#7F7F7F"},
2272 {"Grey50", "#7F7F7F"},
2273 {"Gray60", "#999999"},
2274 {"Grey60", "#999999"},
2275 {"Gray70", "#B3B3B3"},
2276 {"Grey70", "#B3B3B3"},
2277 {"Gray80", "#CCCCCC"},
2278 {"Grey80", "#CCCCCC"},
2279 {"Gray90", "#E5E5E5"},
2280 {"Grey90", "#E5E5E5"},
2281 {NULL, NULL}
2282 };
2283 2251
2284 /* can't do this when GUI not running */ 2252 /* can't do this when GUI not running */
2285 if (!gui.in_use || *reqname == NUL) 2253 if (!gui.in_use || name == NULL || *name == NUL)
2286 return INVALCOLOR; 2254 return INVALCOLOR;
2287 2255
2288 colormap = DefaultColormap(gui.dpy, XDefaultScreen(gui.dpy)); 2256 requested = gui_get_color_cmn(name);
2289 2257 if (requested == INVALCOLOR)
2290 /* Do this twice if the name isn't recognized. */ 2258 return INVALCOLOR;
2291 while (name != NULL) 2259
2292 { 2260 vim_snprintf(spec, COLORSPECBUFSIZE, "#%.2x%.2x%.2x",
2293 i = XParseColor(gui.dpy, colormap, (char *)name, &color); 2261 (requested & 0xff0000) >> 16,
2294 2262 (requested & 0xff00) >> 8,
2295 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 2263 requested & 0xff);
2296 if (i == 0) 2264 #undef COLORSPECBUFSIZE
2297 { 2265 colormap = DefaultColormap(gui.dpy, DefaultScreen(gui.dpy));
2298 char *old; 2266 if (XParseColor(gui.dpy, colormap, (char *)spec, &available) != 0
2299 2267 && XAllocColor(gui.dpy, colormap, &available) != 0)
2300 /* The X11 system is trying to resolve named colors only by names 2268 return (guicolor_T)available.pixel;
2301 * corresponding to the current locale language. But Vim scripts
2302 * usually contain the English color names. Therefore we have to
2303 * try a second time here with the native "C" locale set.
2304 * Hopefully, restoring the old locale this way works on all
2305 * systems...
2306 */
2307 old = setlocale(LC_ALL, NULL);
2308 if (old != NULL && STRCMP(old, "C") != 0)
2309 {
2310 old = (char *)vim_strsave((char_u *)old);
2311 setlocale(LC_ALL, "C");
2312 i = XParseColor(gui.dpy, colormap, (char *)name, &color);
2313 setlocale(LC_ALL, old);
2314 vim_free(old);
2315 }
2316 }
2317 #endif
2318 if (i != 0 && (XAllocColor(gui.dpy, colormap, &color) != 0
2319 || find_closest_color(colormap, &color) == OK))
2320 return (guicolor_T)color.pixel;
2321
2322 /* check for a few builtin names */
2323 for (i = 0; ; ++i)
2324 {
2325 if (vimnames[i][0] == NULL)
2326 {
2327 name = NULL;
2328 break;
2329 }
2330 if (STRICMP(name, vimnames[i][0]) == 0)
2331 {
2332 name = (char_u *)vimnames[i][1];
2333 break;
2334 }
2335 }
2336 }
2337 2269
2338 return INVALCOLOR; 2270 return INVALCOLOR;
2339 }
2340
2341 /*
2342 * Find closest color for "colorPtr" in "colormap". set "colorPtr" to the
2343 * resulting color.
2344 * Based on a similar function in TCL.
2345 * Return FAIL if not able to find or allocate a color.
2346 */
2347 static int
2348 find_closest_color(Colormap colormap, XColor *colorPtr)
2349 {
2350 double tmp, distance, closestDistance;
2351 int i, closest, numFound, cmap_size;
2352 XColor *colortable;
2353 XVisualInfo template, *visInfoPtr;
2354
2355 template.visualid = XVisualIDFromVisual(DefaultVisual(gui.dpy,
2356 XDefaultScreen(gui.dpy)));
2357 visInfoPtr = XGetVisualInfo(gui.dpy, (long)VisualIDMask,
2358 &template, &numFound);
2359 if (numFound < 1)
2360 /* FindClosestColor couldn't lookup visual */
2361 return FAIL;
2362
2363 cmap_size = visInfoPtr->colormap_size;
2364 XFree((char *)visInfoPtr);
2365 colortable = (XColor *)alloc((unsigned)(cmap_size * sizeof(XColor)));
2366 if (!colortable)
2367 return FAIL; /* out of memory */
2368
2369 for (i = 0; i < cmap_size; i++)
2370 colortable[i].pixel = (unsigned long)i;
2371 XQueryColors(gui.dpy, colormap, colortable, cmap_size);
2372
2373 /*
2374 * Find the color that best approximates the desired one, then
2375 * try to allocate that color. If that fails, it must mean that
2376 * the color was read-write (so we can't use it, since it's owner
2377 * might change it) or else it was already freed. Try again,
2378 * over and over again, until something succeeds.
2379 */
2380 closestDistance = 1e30;
2381 closest = 0;
2382 for (i = 0; i < cmap_size; i++)
2383 {
2384 /*
2385 * Use Euclidean distance in RGB space, weighted by Y (of YIQ)
2386 * as the objective function; this accounts for differences
2387 * in the color sensitivity of the eye.
2388 */
2389 tmp = .30 * (((int)colorPtr->red) - (int)colortable[i].red);
2390 distance = tmp * tmp;
2391 tmp = .61 * (((int)colorPtr->green) - (int)colortable[i].green);
2392 distance += tmp * tmp;
2393 tmp = .11 * (((int)colorPtr->blue) - (int)colortable[i].blue);
2394 distance += tmp * tmp;
2395 if (distance < closestDistance)
2396 {
2397 closest = i;
2398 closestDistance = distance;
2399 }
2400 }
2401
2402 if (XAllocColor(gui.dpy, colormap, &colortable[closest]) != 0)
2403 {
2404 gui.color_approx = TRUE;
2405 *colorPtr = colortable[closest];
2406 }
2407
2408 vim_free(colortable);
2409 return OK;
2410 } 2271 }
2411 2272
2412 /* 2273 /*
2413 * Set the current text foreground color. 2274 * Set the current text foreground color.
2414 */ 2275 */