Mercurial > vim
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 */ |