1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // see below for copyright information on the second portion of this file
7 #include <X11/extensions/XShm.h>
8 #include <X11/keysymdef.h>
9 #include <X11/keysym.h>
10 #include <X11/cursorfont.h>
11 #include <X11/Xutil.h>
12 #include <X11/Xatom.h>
13 #include <X11/Xmu/StdCmap.h>
15 #include <java/lang/String.h>
16 #include <org/xwt/Surface.h>
17 #include <org/xwt/Picture.h>
18 #include <org/xwt/Box.h>
19 #include <org/xwt/plat/X11.h>
20 #include <org/xwt/plat/X11$X11Surface.h>
21 #include <org/xwt/plat/X11$X11Picture.h>
22 #include <org/xwt/plat/X11$X11PixelBuffer.h>
23 #include <org/xwt/util/Semaphore.h>
24 #include <org/xwt/Platform.h>
25 #include <java/lang/Long.h>
26 #include <java/util/Hashtable.h>
27 #include <org/xwt/util/Log.h>
29 #include <java/lang/System.h>
30 #include <java/io/PrintStream.h>
32 // static (per-xserver) data
33 static Visual* visual;
34 static Colormap s_colormap;
35 static XStandardColormap* colormap_info;
36 static XShmSegmentInfo shm_info;
37 static Window selectionWindow;
38 static int shm_supported = 0;
39 static int shm_pixmaps_supported;
40 static int screen_num;
41 static int colorDepth = 0;
42 static Display* display;
43 static int shm_size = 0;
45 #define min(a, b) ((a) < (b) ? (a) : (b))
46 #define max(a, b) ((a) < (b) ? (b) : (a))
48 // X11PixelBuffer //////////////////////////////////////////////////////////////////////
50 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
51 static void ensureShmSize(int size) {
52 if (size > shm_size) {
54 XShmDetach(display, &shm_info);
55 shmdt(shm_info.shmaddr);
56 shmctl(shm_info.shmid, IPC_RMID, 0);
58 shm_size = 3 * size / 2;
59 shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
60 shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
61 shm_info.readOnly = False;
62 XSync(display, False);
63 shmctl(shm_info.shmid, IPC_RMID, 0);
64 XShmAttach(display, &shm_info);
65 XSync(display, False);
69 void org::xwt::plat::X11$X11PixelBuffer::fastDrawPicture(org::xwt::Picture* s,
70 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
71 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
73 if (source->doublebuf->stipple != NULL) {
74 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
75 XSetClipOrigin(display, (*((GC*)clipped_gc)), cx1 - dx, cy1 - dy);
77 XSetClipMask(display, (*((GC*)clipped_gc)), None);
80 *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)),
81 cx1 - dx, cy1 - dy, cx2 - cx1, cy2 - cy1, cx1, cy1);
84 void org::xwt::plat::X11$X11PixelBuffer::slowDrawPicture(org::xwt::Picture* s,
85 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2,
86 jint rgb, jboolean alphaOnly) {
88 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
91 // FASTEST: shared pixmap; twiddle bits in video ram directly
93 XSync(display, False); // ensure that all pending operations have rendered
94 xi = (XImage*)fake_ximage;
96 // MEDIUM: write to a shared ximage, then ask the server to do the blit
97 } else if (shm_supported) {
98 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, cx2 - cx1, cy2 - cy1);
99 ensureShmSize(xi->bytes_per_line * xi->height);
100 xi->data = shm_info.shmaddr;
101 XShmGetImage(display, (*((Pixmap*)pm)), xi, cx1, cy1, AllPlanes);
103 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
105 xi = XGetImage(display, (*((Pixmap*)pm)), cx1, cy1, cx2 - cx1, cy2 - cy1, AllPlanes, ZPixmap);
108 int* sourcedata = (int*)elements(source->data);
109 for(int y=cy1; y < cy2; y++) {
111 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
112 (shared_pixmap ? cx1 * (xi->bits_per_pixel / 8) : - 1 * cy1 * xi->bytes_per_line);
114 for(int x=cx1; x < cx2; x++, current_pixel += xi->bits_per_pixel / 8) {
115 int source_x = x - dx;
116 int source_y = y - dy;
118 // FEATURE: be smarter here; can we do something better for the alphaonly case?
119 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
120 int alpha = (sourcepixel & 0xFF000000) >> 24;
121 if (alphaOnly) sourcepixel = rgb;
122 int source_red = (sourcepixel & 0x00FF0000) >> 16;
123 int source_green = (sourcepixel & 0x0000FF00) >> 8;
124 int source_blue = (sourcepixel & 0x000000FF);
125 int red = 0, blue = 0, green = 0;
127 if (alpha == 0x00) continue;
129 switch (xi->bits_per_pixel) {
130 case 8: targetpixel = (int)(*current_pixel); break;
132 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
134 // FIXME assumes endianness...
135 case 24: targetpixel =
136 (((int)*current_pixel) << 16) |
137 (((int)*(current_pixel + 1)) << 8) |
138 (((int)*(current_pixel + 2))); break;
139 case 32: targetpixel = *((int*)current_pixel); break;
140 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
142 targetpixel -= colormap_info->base_pixel;
144 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
145 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
146 red = targetpixel / colormap_info->red_mult;
147 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
148 blue = (targetpixel-red * colormap_info->red_mult-green * colormap_info->green_mult)/colormap_info->blue_mult;
150 blue = targetpixel / colormap_info->blue_mult;
151 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
152 red = (targetpixel-blue * colormap_info->blue_mult-green * colormap_info->green_mult)/colormap_info->red_mult;
155 red = ((source_red * (colormap_info->red_max) * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
156 green = ((source_green * (colormap_info->green_max) * alpha)+(green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
157 blue = ((source_blue * (colormap_info->blue_max) * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
159 (red * colormap_info->red_mult) +
160 (green * colormap_info->green_mult) +
161 (blue * colormap_info->blue_mult) +
162 colormap_info->base_pixel;
163 switch (xi->bits_per_pixel) {
164 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
165 case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
167 int offset = (int)current_pixel & 0x3;
168 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
169 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
170 uint64_t* base = (uint64_t*)(current_pixel - offset);
171 *base = (*base & ~mask) | dest;
174 case 32: *((uint32_t*)current_pixel) = destpixel; break;
175 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
181 // do nothing, we wrote directly to video memory
183 } else if (shm_supported) {
184 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1, False);
188 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1);
193 void org::xwt::plat::X11$X11PixelBuffer::finalize() {
195 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
196 XShmDetach(display, sinfo);
197 shmdt(sinfo->shmaddr);
198 shmctl(sinfo->shmid, IPC_RMID, 0);
199 XDestroyImage((XImage*)fake_ximage);
203 XFreePixmap(display, *((Pixmap*)stipple));
206 XFreePixmap(display, *((Pixmap*)pm));
207 XFreeGC(display, *((GC*)gc));
208 XFreeGC(display, *((GC*)clipped_gc));
211 void org::xwt::plat::X11$X11PixelBuffer::natInit() {
213 if (width == 0 || height == 0) return;
214 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
215 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
218 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
220 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
221 shm_segment = (gnu::gcj::RawData*)sinfo;
222 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
223 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
224 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
225 sinfo->readOnly = False;
226 XShmAttach(display, sinfo);
227 XSync(display, False);
228 shmctl(sinfo->shmid, IPC_RMID, 0);
229 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
230 XSync(display, False);
233 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
234 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
235 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
236 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
239 vm.graphics_exposures = 0;
240 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
241 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
244 void org::xwt::plat::X11$X11PixelBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
246 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
247 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
250 xi.data = (char*)malloc((width + 1) * height);
257 xi.byte_order = LSBFirst;
259 xi.bytes_per_line = (width / 8) + 1;
260 xi.bits_per_pixel = 1;
262 jint* d = (jint*)elements(xpi->data);
263 memset(xi.data, 0xFF, (width + 1) * height);
264 for(int x=0; x<width; x++)
265 for (int y=0; y<height; y++)
266 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
268 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
271 vm.graphics_exposures = 0;
272 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
274 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
277 void org::xwt::plat::X11$X11Surface::blit(org::xwt::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
278 org::xwt::plat::X11$X11PixelBuffer *xdb = (org::xwt::plat::X11$X11PixelBuffer*)db;
279 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
283 void org::xwt::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
288 if (x < clipx) { w -= (clipx - x); x = clipx; }
289 if (y < clipy) { h -= (clipy - y); y = clipy; }
290 if (x + w > clipx + clipw) w = (clipx + clipw - x);
291 if (y + h > clipy + cliph) h = (cliph + clipy - y);
293 XSetForeground(display, (*((GC*)gc)),
294 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
295 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
296 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
297 colormap_info->base_pixel
300 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
304 // X11Surface //////////////////////////////////////////////////////////////////////
306 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
307 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
308 org::xwt::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
309 p->buildPixelBuffer(1);
311 memset(&xwmh, 0, sizeof(XWMHints));
312 xwmh.flags |= IconPixmapHint | IconMaskHint;
313 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
314 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
315 XSetWMHints(display, (*((Window*)window)), &xwmh);
316 p->doublebuf = old_dbuf;
319 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
320 int len = min(JvGetStringUTFLength(s), 1024);
322 JvGetStringUTFRegion(s, 0, len, buf);
326 tp.value = (unsigned char*)buf;
328 tp.encoding = XA_STRING;
330 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
331 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
334 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
336 hints.min_width = minw;
337 hints.min_height = minh;
338 hints.max_width = maxw;
339 hints.max_height = maxh;
340 hints.flags = PMinSize | PMaxSize;
341 XSetWMNormalHints(display, (*((Window*)window)), &hints);
344 void org::xwt::plat::X11$X11Surface::_setSize (jint width, jint height) {
345 if (width <= 0 || height <= 0) return;
346 XResizeWindow(display, (*((Window*)window)), width, height);
350 void org::xwt::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
351 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
352 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
354 void org::xwt::plat::X11$X11Surface::_dispose() {
355 // without this we get phantom messages after the window is gone
356 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
357 XDestroyWindow(display, (*((Window*)window)));
360 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
361 if (i) XUnmapWindow(display, (*((Window*)window)));
362 else XMapRaised(display, (*((Window*)window)));
366 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
367 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
368 else XMapRaised(display, (*((Window*)window)));
372 void org::xwt::plat::X11$X11Surface::natInit() {
373 XSetWindowAttributes xswa;
374 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
375 xswa.bit_gravity = NorthWestGravity;
376 xswa.colormap = s_colormap;
377 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
378 KeyPressMask | KeyReleaseMask | ButtonPressMask |
379 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
380 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
381 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
382 colorDepth, InputOutput, CopyFromParent,
383 CWColormap | CWBitGravity | CWEventMask, &xswa);
386 // I don't know why this works....
387 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
388 XChangeProperty(display, (*((Window*)window)),
389 XInternAtom(display, "_MOTIF_WM_HINTS", False),
390 XInternAtom(display, "_MOTIF_WM_HINTS", False),
398 tp.value = (unsigned char*)"XWT";
400 tp.encoding = XA_STRING;
402 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
404 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
405 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
407 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
408 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
411 XMapRaised(display, (*((Window*)window)));
414 waitForCreation->block();
415 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
418 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
419 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
422 vm.graphics_exposures = 0;
423 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
427 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
429 XEvent* e = (XEvent*)ev;
430 if (e->type == Expose) {
431 XExposeEvent *expose = (XExposeEvent*)(e);
432 Dirty(expose->x, expose->y, expose->width, expose->height);
434 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
435 } else if (e->type == UnmapNotify) { Minimized(1);
436 } else if (e->type == FocusIn) { Focused(1);
437 } else if (e->type == FocusOut) { Focused(0);
438 } else if (e->type == ClientMessage) {
439 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
441 } else if (e->type == KeyPress || e->type == KeyRelease) {
442 XKeyEvent *xbe = (XKeyEvent*)(e);
444 // drop faked KeyRelease events generated by the X server's autorepeat
445 if (e->type == KeyRelease) {
447 XQueryKeymap(display, depressed);
448 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
454 unsigned int savestate = xbe->state;
455 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
456 XLookupString(xbe, s, 20, NULL, NULL);
457 xbe->state = savestate;
459 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
463 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
465 case XK_BackSpace: s = "back_space"; break;
466 case XK_Tab: s = "tab"; break;
467 case XK_Linefeed: s = "enter"; break;
468 case XK_Return: s = "enter"; break;
469 case XK_Scroll_Lock: s = "scroll_lock"; break;
470 case XK_Escape: s = "escape"; break;
471 case XK_Insert: s = "insert"; break;
472 case XK_Delete: s = "delete"; break;
473 case XK_Home: s = "home"; break;
474 case XK_Left: s = "left"; break;
475 case XK_Up: s = "up"; break;
476 case XK_Right: s = "right"; break;
477 case XK_Down: s = "down"; break;
478 case XK_Page_Up: s = "page_up"; break;
479 case XK_Page_Down: s = "page_down"; break;
480 case XK_End: s = "end"; break;
481 case XK_Num_Lock: s = "num_lock"; break;
482 case XK_KP_Tab: s = "tab"; break;
483 case XK_KP_Enter: s = "enter"; break;
484 case XK_KP_F1: s = "f1"; break;
485 case XK_KP_F2: s = "f2"; break;
486 case XK_KP_F3: s = "f3"; break;
487 case XK_KP_F4: s = "f4"; break;
488 case XK_KP_Home: s = "home"; break;
489 case XK_KP_Left: s = "left"; break;
490 case XK_KP_Up: s = "up"; break;
491 case XK_KP_Right: s = "right"; break;
492 case XK_KP_Down: s = "down"; break;
493 case XK_KP_Page_Up: s = "page_up"; break;
494 case XK_KP_Page_Down: s = "page_down"; break;
495 case XK_KP_End: s = "end"; break;
496 case XK_KP_Insert: s = "insert"; break;
497 case XK_KP_Delete: s = "delete"; break;
498 case XK_F1: s = "f1"; break;
499 case XK_F2: s = "f2"; break;
500 case XK_F3: s = "f3"; break;
501 case XK_F4: s = "f4"; break;
502 case XK_F5: s = "f5"; break;
503 case XK_F6: s = "f6"; break;
504 case XK_F7: s = "f7"; break;
505 case XK_F8: s = "f8"; break;
506 case XK_F9: s = "f9"; break;
507 case XK_F10: s = "f10"; break;
508 case XK_F11: s = "f11"; break;
509 case XK_F12: s = "f12"; break;
510 case XK_Shift_L: s = "shift"; break;
511 case XK_Shift_R: s = "shift"; break;
512 case XK_Control_L: s = "control"; break;
513 case XK_Control_R: s = "control"; break;
514 case XK_Meta_L: s = "alt"; break;
515 case XK_Meta_R: s = "alt"; break;
516 case XK_Alt_L: s = "alt"; break;
517 case XK_Alt_R: s = "alt"; break;
522 jstring s2 = JvNewStringLatin1(s);
523 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
524 if (e->type == KeyRelease) KeyReleased(s2);
526 } else if (e->type == ButtonPress) {
527 XButtonEvent* xbe = (XButtonEvent*)(e);
528 if (xbe->button == 2) xbe->button = 3;
529 else if (xbe->button == 3) xbe->button = 2;
532 } else if (e->type == ButtonRelease) {
533 XButtonEvent* xbe = (XButtonEvent*)(e);
534 if (xbe->button == 2) xbe->button = 3;
535 else if (xbe->button == 3) xbe->button = 2;
536 Release(xbe->button);
538 } else if (e->type == MotionNotify) {
539 XMotionEvent* xme = (XMotionEvent*)(e);
540 Move(xme->x, xme->y);
542 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
543 XCrossingEvent* xce = (XCrossingEvent*)(e);
544 Move(xce->x, xce->y);
546 } else if (e->type == ConfigureNotify) {
549 XConfigureEvent* xce = (XConfigureEvent*)(e);
550 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
551 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
552 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
557 static jstring crosshair, east, hand, move, north, northeast, northwest,
558 south, southeast, southwest, text, west, wait_string;
559 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
560 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
561 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
563 void org::xwt::plat::X11$X11Surface::syncCursor() {
566 if (cursor->equals(crosshair)) curs = crosshair_cursor;
567 else if (cursor->equals(east)) curs = east_cursor;
568 else if (cursor->equals(hand)) curs = hand_cursor;
569 else if (cursor->equals(move)) curs = move_cursor;
570 else if (cursor->equals(north)) curs = north_cursor;
571 else if (cursor->equals(northeast)) curs = northeast_cursor;
572 else if (cursor->equals(northwest)) curs = northwest_cursor;
573 else if (cursor->equals(south)) curs = south_cursor;
574 else if (cursor->equals(southeast)) curs = southeast_cursor;
575 else if (cursor->equals(southwest)) curs = southwest_cursor;
576 else if (cursor->equals(text)) curs = text_cursor;
577 else if (cursor->equals(west)) curs = west_cursor;
578 else if (cursor->equals(wait_string)) curs = wait_cursor;
579 else curs = default_cursor;
581 XDefineCursor(display, (*((Window*)window)), curs);
586 // X11 ///////////////////////////////////////////////////////////////////
588 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
589 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
591 static void dispatchSelectionEvent(XEvent* e) {
592 if (e->type == SelectionNotify) {
593 XSelectionEvent* xsn = (XSelectionEvent*)(e);
594 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
598 unsigned long numitems;
600 unsigned long bytes_after;
601 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
602 True, AnyPropertyType, &returntype, &returnformat,
603 &numitems, &bytes_after, &ret);
604 org::xwt::plat::X11::clipboard =
605 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
607 org::xwt::plat::X11::waiting_for_selection_event->release();
609 } else if (e->type == SelectionRequest) {
610 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
612 xsn.type = SelectionNotify;
613 xsn.serial = xsr->serial;
614 xsn.send_event = True;
615 xsn.display = display;
616 xsn.requestor = xsr->requestor;
617 xsn.selection = xsr->selection;
618 xsn.target = xsr->target;
619 xsn.property = xsr->property;
620 xsn.time = xsr->time;
622 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
624 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
627 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
628 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
632 void org::xwt::plat::X11::eventThread() {
635 XNextEvent(display, &e);
636 if (e.type == SelectionNotify || e.type == SelectionRequest) {
637 dispatchSelectionEvent(&e);
639 org::xwt::plat::X11$X11Surface* surface =
640 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
641 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
646 jstring org::xwt::plat::X11::_getClipBoard() {
647 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
649 org::xwt::plat::X11::waiting_for_selection_event->block();
653 void org::xwt::plat::X11::_setClipBoard(jstring s) {
655 int len = JvGetStringUTFLength(clipboard);
657 JvGetStringUTFRegion(clipboard, 0, len, buf);
659 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
662 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
663 int errorHandler(Display* d, XErrorEvent* e) {
664 // this error handler is only installed during the initial
665 // test to see if shm is present
669 void org::xwt::plat::X11::natInit() {
672 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
674 char* DISPLAY = getenv("DISPLAY");
675 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
676 display = XOpenDisplay(DISPLAY);
679 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
681 screen_num = XDefaultScreen(display);
682 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
683 shm_info.shmaddr = NULL;
685 // FIXME: SHM doesn't work on Darwin
686 //shm_supported = (XShmQueryExtension(display) == True);
688 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
689 XShmSegmentInfo sinfo;
690 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
691 sinfo.readOnly = False;
692 // if the server is remote, this will trigger the error handler
693 XShmAttach(display, &sinfo);
694 XSync(display, False);
695 XSetErrorHandler(oldHandler);
699 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
701 crosshair = JvNewStringLatin1("crosshair");
702 east = JvNewStringLatin1("east");
703 hand = JvNewStringLatin1("hand");
704 move = JvNewStringLatin1("move");
705 north = JvNewStringLatin1("north");
706 northeast = JvNewStringLatin1("northeast");
707 northwest = JvNewStringLatin1("northwest");
708 south = JvNewStringLatin1("south");
709 southeast = JvNewStringLatin1("southeast");
710 southwest = JvNewStringLatin1("southwest");
711 text = JvNewStringLatin1("text");
712 west = JvNewStringLatin1("west");
713 wait_string = JvNewStringLatin1("wait");
714 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
715 east_cursor = XCreateFontCursor(display, XC_right_side);
716 hand_cursor = XCreateFontCursor(display, XC_hand2);
717 move_cursor = XCreateFontCursor(display, XC_fleur);
718 north_cursor = XCreateFontCursor(display, XC_top_side);
719 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
720 northwest_cursor = XCreateFontCursor(display, XC_left_side);
721 south_cursor = XCreateFontCursor(display, XC_bottom_side);
722 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
723 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
724 text_cursor = XCreateFontCursor(display, XC_xterm);
725 west_cursor = XCreateFontCursor(display, XC_right_side);
726 wait_cursor = XCreateFontCursor(display, XC_watch);
727 default_cursor = XCreateFontCursor(display, XC_left_ptr);
729 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
730 visual = DefaultVisual(display, screen_num);
732 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
733 org::xwt::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
734 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
735 org::xwt::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
736 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
737 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
738 org::xwt::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
740 // FIXME: don't know why (True, False) is the best solution...
741 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
742 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
744 XStandardColormap* best_map_info = NULL;
746 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
747 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
748 if (!best_map_info->colormap)
749 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
750 if (best_map_info->red_max == 0)
751 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
752 s_colormap = best_map_info->colormap;
753 colormap_info = best_map_info;
755 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
756 org::xwt::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
757 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
758 org::xwt::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
759 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
760 org::xwt::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
761 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
762 org::xwt::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
767 //////////////////////////////////////////////////////////////////////////////
768 //////////////////////////////////////////////////////////////////////////////
769 //////////////////////////////////////////////////////////////////////////////
770 //////////////////////////////////////////////////////////////////////////////
772 // Everything below this point was taken, cut-and-paste, from the //
773 // source for libXmu. It implements the official 'standard colormap //
774 // creation algorithm. I made some small changes to //
775 // XmuDeleteStandardColormap //
777 //////////////////////////////////////////////////////////////////////////////
778 //////////////////////////////////////////////////////////////////////////////
779 //////////////////////////////////////////////////////////////////////////////
780 //////////////////////////////////////////////////////////////////////////////
782 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
786 Copyright 1989, 1998 The Open Group
788 Permission to use, copy, modify, distribute, and sell this software and its
789 documentation for any purpose is hereby granted without fee, provided that
790 the above copyright notice appear in all copies and that both that
791 copyright notice and this permission notice appear in supporting
794 The above copyright notice and this permission notice shall be included in
795 all copies or substantial portions of the Software.
797 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
798 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
799 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
800 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
801 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
802 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
804 Except as contained in this notice, the name of The Open Group shall not be
805 used in advertising or otherwise to promote the sale, use or other dealings
806 in this Software without prior written authorization from The Open Group.
809 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
812 * Author: Donna Converse, MIT X Consortium
816 #include <X11/Xlib.h>
817 #include <X11/Xatom.h>
818 #include <X11/Xutil.h>
819 #include <X11/Xmu/StdCmap.h>
825 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
828 * To create a standard colormap if one does not currently exist, or
829 * replace the currently existing standard colormap, use
830 * XmuLookupStandardColormap().
832 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
833 * will determine the best allocation for the property under the specified
834 * visual, and determine the whether to create a new colormap or to use
835 * the default colormap of the screen. It will call XmuStandardColormap()
836 * to create the standard colormap.
838 * If replace is true, any previous definition of the property will be
839 * replaced. If retain is true, the property and the colormap will be
840 * made permanent for the duration of the server session. However,
841 * pre-existing property definitions which are not replaced cannot be made
842 * permanent by a call to XmuLookupStandardColormap(); a request to retain
843 * resources pertains to newly created resources.
845 * Returns 0 on failure, non-zero on success. A request to create a
846 * standard colormap upon a visual which cannot support such a map is
847 * considered a failure. An example of this would be requesting any
848 * standard colormap property on a monochrome visual, or, requesting an
849 * RGB_BEST_MAP on a display whose colormap size is 16.
853 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
854 unsigned int depth, Atom property,
855 Bool replace, Bool retain)
857 * dpy - specifies X server connection
858 * screen - specifies screen of display
859 * visualid - specifies the visual type
860 * depth - specifies the visual type
861 * property - a standard colormap property
862 * replace - specifies whether to replace
863 * retain - specifies whether to retain
866 Display *odpy; /* original display connection */
867 XStandardColormap *colormap;
868 XVisualInfo vinfo_template, *vinfo; /* visual */
870 unsigned long r_max, g_max, b_max; /* allocation */
872 Colormap cmap; /* colormap ID */
876 /* Match the requested visual */
878 vinfo_template.visualid = visualid;
879 vinfo_template.screen = screen;
880 vinfo_template.depth = depth;
881 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
882 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
886 /* Monochrome visuals have no standard maps */
888 if (vinfo->colormap_size <= 2) {
889 XFree((char *) vinfo);
893 /* If the requested property already exists on this screen, and,
894 * if the replace flag has not been set to true, return success.
895 * lookup() will remove a pre-existing map if replace is true.
898 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
899 replace) && !replace) {
900 XFree((char *) vinfo);
904 /* Determine the best allocation for this property under the requested
905 * visualid and depth, and determine whether or not to use the default
906 * colormap of the screen.
909 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
910 XFree((char *) vinfo);
914 cmap = (property == XA_RGB_DEFAULT_MAP &&
915 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
916 ? DefaultColormap(dpy, screen) : None;
918 /* If retaining resources, open a new connection to the same server */
922 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
923 XFree((char *) vinfo);
928 /* Create the standard colormap */
930 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
931 cmap, r_max, g_max, b_max);
933 /* Set the standard colormap property */
938 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
940 /* Someone has defined the property since we last looked.
941 * Since we will not replace it, release our own resources.
942 * If this is the default map, our allocations will be freed
943 * when this connection closes.
945 if (colormap->killid == ReleaseByFreeingColormap)
946 XFreeColormap(dpy, colormap->colormap);
948 XSetCloseDownMode(dpy, RetainPermanent);
951 XFree((char *) colormap);
957 XFree((char *) vinfo);
961 /***************************************************************************/
963 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
964 * the visualid is used to determine whether the indicated standard colormap
965 * exists. If the map exists and replace is true, delete the resources used
966 * by the map and remove the property. Return true if the map exists,
967 * or did exist and was deleted; return false if the map was not found.
969 * Note that this is not the way that a Status return is normally used.
971 * If new is not NULL, new points to an XStandardColormap structure which
972 * describes a standard colormap of the specified property. It will be made
973 * a standard colormap of the screen if none already exists, or if replace
978 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
979 XStandardColormap *cnew, Bool replace)
981 * dpy - specifies display connection
982 * screen - specifies screen number
983 * visualid - specifies visualid for std map
984 * property - specifies colormap property name
985 * cnew - specifies a standard colormap
986 * replace - specifies whether to replace
991 XStandardColormap *stdcmaps, *s;
992 Window win = RootWindow(dpy, screen);
994 /* The property does not already exist */
996 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
998 XSetRGBColormaps(dpy, win, cnew, 1, property);
1002 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1004 if (property != XA_RGB_DEFAULT_MAP) {
1006 XmuDeleteStandardColormap(dpy, screen, property);
1008 XSetRGBColormaps(dpy, win, cnew, 1, property);
1010 XFree((char *)stdcmaps);
1014 /* The property exists and is RGB_DEFAULT_MAP */
1016 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1019 /* No RGB_DEFAULT_MAP property matches the given visualid */
1023 XStandardColormap *m, *maps;
1025 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1026 (XStandardColormap)));
1028 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1029 m->colormap = maps->colormap;
1030 m->red_max = maps->red_max;
1031 m->red_mult = maps->red_mult;
1032 m->green_max = maps->green_max;
1033 m->green_mult = maps->green_mult;
1034 m->blue_max = maps->blue_max;
1035 m->blue_mult = maps->blue_mult;
1036 m->base_pixel = maps->base_pixel;
1037 m->visualid = maps->visualid;
1038 m->killid = maps->killid;
1040 m->colormap = cnew->colormap;
1041 m->red_max = cnew->red_max;
1042 m->red_mult = cnew->red_mult;
1043 m->green_max = cnew->green_max;
1044 m->green_mult = cnew->green_mult;
1045 m->blue_max = cnew->blue_max;
1046 m->blue_mult = cnew->blue_mult;
1047 m->base_pixel = cnew->base_pixel;
1048 m->visualid = cnew->visualid;
1049 m->killid = cnew->killid;
1051 XSetRGBColormaps(dpy, win, s, ++count, property);
1054 XFree((char *) stdcmaps);
1058 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1061 /* Free old resources first - we may need them, particularly in
1062 * the default colormap of the screen. However, because of this,
1063 * it is possible that we will destroy the old resource and fail
1064 * to create a new one if XmuStandardColormap() fails.
1068 XmuDeleteStandardColormap(dpy, screen, property);
1070 XSetRGBColormaps(dpy, win, cnew, 1, property);
1073 XStandardColormap *map;
1075 /* s still points to the matching standard colormap */
1077 if (s->killid == ReleaseByFreeingColormap) {
1078 if ((s->colormap != None) &&
1079 (s->colormap != DefaultColormap(dpy, screen)))
1080 XFreeColormap(dpy, s->colormap);
1082 else if (s->killid != None)
1083 XKillClient(dpy, s->killid);
1085 map = (cnew) ? cnew : stdcmaps + --count;
1087 s->colormap = map->colormap;
1088 s->red_max = map->red_max;
1089 s->red_mult = map->red_mult;
1090 s->green_max = map->green_max;
1091 s->green_mult = map->green_mult;
1092 s->blue_max = map->blue_max;
1093 s->blue_mult = map->blue_mult;
1094 s->visualid = map->visualid;
1095 s->killid = map->killid;
1097 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1100 XFree((char *) stdcmaps);
1104 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1108 Copyright 1989, 1994, 1998 The Open Group
1110 Permission to use, copy, modify, distribute, and sell this software and its
1111 documentation for any purpose is hereby granted without fee, provided that
1112 the above copyright notice appear in all copies and that both that
1113 copyright notice and this permission notice appear in supporting
1116 The above copyright notice and this permission notice shall be included in
1117 all copies or substantial portions of the Software.
1119 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1120 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1121 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1122 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1123 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1124 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1126 Except as contained in this notice, the name of The Open Group shall not be
1127 used in advertising or otherwise to promote the sale, use or other dealings
1128 in this Software without prior written authorization from The Open Group.
1131 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1134 * Author: Donna Converse, MIT X Consortium
1137 #include <X11/Xlib.h>
1138 #include <X11/Xatom.h>
1139 #include <X11/Xutil.h>
1140 #include <X11/Xmu/StdCmap.h>
1143 #define lowbit(x) ((x) & (~(x) + 1))
1148 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1150 static int default_allocation(XVisualInfo*, unsigned long*,
1151 unsigned long*, unsigned long*);
1152 static void gray_allocation(int, unsigned long*, unsigned long*,
1154 static int icbrt(int);
1155 static int icbrt_with_bits(int, int);
1156 static int icbrt_with_guess(int, int);
1158 /* To determine the best allocation of reds, greens, and blues in a
1159 * standard colormap, use XmuGetColormapAllocation.
1160 * vinfo specifies visual information for a chosen visual
1161 * property specifies one of the standard colormap property names
1162 * red_max returns maximum red value
1163 * green_max returns maximum green value
1164 * blue_max returns maximum blue value
1166 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1167 * It is assumed that the visual is appropriate for the colormap property.
1171 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1172 unsigned long *red_max,
1173 unsigned long *green_max,
1174 unsigned long *blue_max)
1178 if (vinfo->colormap_size <= 2)
1183 case XA_RGB_DEFAULT_MAP:
1184 status = default_allocation(vinfo, red_max, green_max, blue_max);
1186 case XA_RGB_BEST_MAP:
1187 best_allocation(vinfo, red_max, green_max, blue_max);
1189 case XA_RGB_GRAY_MAP:
1190 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1192 case XA_RGB_RED_MAP:
1193 *red_max = vinfo->colormap_size - 1;
1194 *green_max = *blue_max = 0;
1196 case XA_RGB_GREEN_MAP:
1197 *green_max = vinfo->colormap_size - 1;
1198 *red_max = *blue_max = 0;
1200 case XA_RGB_BLUE_MAP:
1201 *blue_max = vinfo->colormap_size - 1;
1202 *red_max = *green_max = 0;
1210 /****************************************************************************/
1211 /* Determine the appropriate color allocations of a gray scale.
1213 * Keith Packard, MIT X Consortium
1217 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1218 unsigned long *blue_max)
1220 *red_max = (n * 30) / 100;
1221 *green_max = (n * 59) / 100;
1222 *blue_max = (n * 11) / 100;
1223 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1226 /****************************************************************************/
1227 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1228 * If a map has less than a minimum number of definable entries, we do not
1229 * produce an allocation for an RGB_DEFAULT_MAP.
1231 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1232 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1233 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1234 * Maximum green and maximum blue values are identical to maximum red.
1235 * This leaves at least 125 cells which clients can allocate.
1237 * Return 0 if an allocation has been determined, non-zero otherwise.
1241 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1242 unsigned long *green, unsigned long *blue)
1244 int ngrays; /* number of gray cells */
1246 switch (vinfo->c_class)
1250 if (vinfo->colormap_size > 65000)
1251 /* intended for displays with 16 planes */
1252 *red = *green = *blue = (unsigned long) 27;
1253 else if (vinfo->colormap_size > 4000)
1254 /* intended for displays with 12 planes */
1255 *red = *green = *blue = (unsigned long) 12;
1256 else if (vinfo->colormap_size < 250)
1259 /* intended for displays with 8 planes */
1260 *red = *green = *blue = (unsigned long)
1261 (icbrt(vinfo->colormap_size - 125) - 1);
1266 if (vinfo->colormap_size < 10)
1268 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1273 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1274 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1275 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1280 if (vinfo->colormap_size > 65000)
1282 else if (vinfo->colormap_size > 4000)
1284 else if (vinfo->colormap_size < 250)
1288 gray_allocation(ngrays, red, green, blue);
1297 /****************************************************************************/
1298 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1300 * For a DirectColor or TrueColor visual, the allocation is determined
1301 * by the red_mask, green_mask, and blue_mask members of the visual info.
1303 * Otherwise, if the colormap size is an integral power of 2, determine
1304 * the allocation according to the number of bits given to each color,
1305 * with green getting more than red, and red more than blue, if there
1306 * are to be inequities in the distribution. If the colormap size is
1307 * not an integral power of 2, let n = the number of colormap entries.
1308 * Then maximum red value = floor(cube_root(n)) - 1;
1309 * maximum blue value = floor(cube_root(n)) - 1;
1310 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1311 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1312 * defineable colormap entries.
1316 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1317 unsigned long *blue)
1320 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1322 *red = vinfo->red_mask;
1323 while ((*red & 01) == 0)
1325 *green = vinfo->green_mask;
1326 while ((*green & 01) == 0)
1328 *blue = vinfo->blue_mask;
1329 while ((*blue & 01) == 0)
1334 register int bits, n;
1336 /* Determine n such that n is the least integral power of 2 which is
1337 * greater than or equal to the number of entries in the colormap.
1341 while (vinfo->colormap_size > n)
1347 /* If the number of entries in the colormap is a power of 2, determine
1348 * the allocation by "dealing" the bits, first to green, then red, then
1349 * blue. If not, find the maximum integral red, green, and blue values
1350 * which, when multiplied together, do not exceed the number of
1354 if (n == vinfo->colormap_size)
1356 register int r, g, b;
1358 g = b + ((bits % 3) ? 1 : 0);
1359 r = b + (((bits % 3) == 2) ? 1 : 0);
1366 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1368 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1378 * integer cube roots by Newton's method
1380 * Stephen Gildea, MIT X Consortium, July 1991
1386 register int bits = 0;
1387 register unsigned n = a;
1394 return icbrt_with_bits(a, bits);
1399 icbrt_with_bits(int a, int bits)
1400 /* bits - log 2 of a */
1402 return icbrt_with_guess(a, a>>2*bits/3);
1405 #ifdef _X_ROOT_STATS
1406 int icbrt_loopcount;
1409 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1411 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1414 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1415 * Only works for positive integers (since that's all we need).
1416 * We actually return floor(cbrt(a)) because that's what we need here, too.
1420 icbrt_with_guess(int a, int guess)
1424 #ifdef _X_ROOT_STATS
1425 icbrt_loopcount = 0;
1433 #ifdef _X_ROOT_STATS
1436 delta = (guess - a/(guess*guess))/3;
1438 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1441 } while (delta != 0);
1443 if (guess*guess*guess > a)
1450 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1454 Copyright 1989, 1998 The Open Group
1456 Permission to use, copy, modify, distribute, and sell this software and its
1457 documentation for any purpose is hereby granted without fee, provided that
1458 the above copyright notice appear in all copies and that both that
1459 copyright notice and this permission notice appear in supporting
1462 The above copyright notice and this permission notice shall be included in
1463 all copies or substantial portions of the Software.
1465 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1466 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1467 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1468 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1469 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1470 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1472 Except as contained in this notice, the name of The Open Group shall not be
1473 used in advertising or otherwise to promote the sale, use or other dealings
1474 in this Software without prior written authorization from The Open Group.
1477 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1480 * Author: Donna Converse, MIT X Consortium
1484 #include <X11/Xlib.h>
1485 #include <X11/Xatom.h>
1486 #include <X11/Xutil.h>
1487 #include <X11/Xmu/StdCmap.h>
1489 #define lowbit(x) ((x) & (~(x) + 1))
1494 /* argument restrictions */
1495 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1496 unsigned long, Atom);
1499 * To create any one standard colormap, use XmuStandardColormap().
1501 * Create a standard colormap for the given screen, visualid, and visual
1502 * depth, with the given red, green, and blue maximum values, with the
1503 * given standard property name. Return a pointer to an XStandardColormap
1504 * structure which describes the newly created colormap, upon success.
1505 * Upon failure, return NULL.
1507 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1509 * Resources created by this function are not made permanent; that is the
1510 * caller's responsibility.
1514 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1515 unsigned int depth, Atom property, Colormap cmap,
1516 unsigned long red_max, unsigned long green_max,
1517 unsigned long blue_max)
1519 * dpy - specifies X server connection
1520 * screen - specifies display screen
1521 * visualid - identifies the visual type
1522 * depth - identifies the visual type
1523 * property - a standard colormap property
1524 * cmap - specifies colormap ID or None
1525 * red_max, green_max, blue_max - allocations
1528 XStandardColormap *stdcmap;
1530 XVisualInfo vinfo_template, *vinfo;
1534 /* Match the required visual information to an actual visual */
1535 vinfo_template.visualid = visualid;
1536 vinfo_template.screen = screen;
1537 vinfo_template.depth = depth;
1538 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1539 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1542 /* Check the validity of the combination of visual characteristics,
1543 * allocation, and colormap property. Create an XStandardColormap
1547 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1548 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1549 XFree((char *) vinfo);
1553 /* Fill in the XStandardColormap structure */
1555 if (cmap == DefaultColormap(dpy, screen)) {
1556 /* Allocating out of the default map, cannot use XFreeColormap() */
1557 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1558 0, 0, InputOnly, vinfo->visual,
1560 (XSetWindowAttributes *)NULL);
1561 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1562 XDestroyWindow(dpy, win);
1563 stdcmap->colormap = cmap;
1565 stdcmap->killid = ReleaseByFreeingColormap;
1566 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1567 vinfo->visual, AllocNone);
1569 stdcmap->red_max = red_max;
1570 stdcmap->green_max = green_max;
1571 stdcmap->blue_max = blue_max;
1572 if (property == XA_RGB_GRAY_MAP)
1573 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1574 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1575 stdcmap->red_mult = lowbit(vinfo->red_mask);
1576 stdcmap->green_mult = lowbit(vinfo->green_mask);
1577 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1579 stdcmap->red_mult = (red_max > 0)
1580 ? (green_max + 1) * (blue_max + 1) : 0;
1581 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1582 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1584 stdcmap->base_pixel = 0; /* base pixel may change */
1585 stdcmap->visualid = vinfo->visualid;
1587 /* Make the colormap */
1589 status = XmuCreateColormap(dpy, stdcmap);
1593 XFree((char *) vinfo);
1596 /* Free the colormap or the pixmap, if we created one */
1597 if (stdcmap->killid == ReleaseByFreeingColormap)
1598 XFreeColormap(dpy, stdcmap->colormap);
1599 else if (stdcmap->killid != None)
1600 XFreePixmap(dpy, stdcmap->killid);
1602 XFree((char *) stdcmap);
1603 return (XStandardColormap *) NULL;
1608 /****************************************************************************/
1610 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1611 unsigned long blue_max, Atom property)
1613 * vinfo - specifies visual
1614 * red_max, green_max, blue_max - specifies alloc
1615 * property - specifies property name
1618 unsigned long ncolors; /* number of colors requested */
1620 /* Determine that the number of colors requested is <= map size */
1622 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1625 mask = vinfo->red_mask;
1630 mask = vinfo->green_mask;
1633 if (green_max > mask)
1635 mask = vinfo->blue_mask;
1638 if (blue_max > mask)
1640 } else if (property == XA_RGB_GRAY_MAP) {
1641 ncolors = red_max + green_max + blue_max + 1;
1642 if (ncolors > vinfo->colormap_size)
1645 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1646 if (ncolors > vinfo->colormap_size)
1650 /* Determine that the allocation and visual make sense for the property */
1654 case XA_RGB_DEFAULT_MAP:
1655 if (red_max == 0 || green_max == 0 || blue_max == 0)
1658 case XA_RGB_RED_MAP:
1662 case XA_RGB_GREEN_MAP:
1666 case XA_RGB_BLUE_MAP:
1670 case XA_RGB_BEST_MAP:
1671 if (red_max == 0 || green_max == 0 || blue_max == 0)
1674 case XA_RGB_GRAY_MAP:
1675 if (red_max == 0 || blue_max == 0 || green_max == 0)
1685 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1689 Copyright 1989, 1998 The Open Group
1691 Permission to use, copy, modify, distribute, and sell this software and its
1692 documentation for any purpose is hereby granted without fee, provided that
1693 the above copyright notice appear in all copies and that both that
1694 copyright notice and this permission notice appear in supporting
1697 The above copyright notice and this permission notice shall be included in
1698 all copies or substantial portions of the Software.
1700 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1701 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1702 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1703 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1704 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1705 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1707 Except as contained in this notice, the name of The Open Group shall not be
1708 used in advertising or otherwise to promote the sale, use or other dealings
1709 in this Software without prior written authorization from The Open Group.
1712 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1715 * Author: Donna Converse, MIT X Consortium
1719 * CreateCmap.c - given a standard colormap description, make the map.
1724 #include <X11/Xlib.h>
1725 #include <X11/Xutil.h>
1726 #include <X11/Xmu/StdCmap.h>
1731 /* allocate entire map Read Only */
1732 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1734 /* allocate a cell, prefer Read Only */
1735 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1736 XColor*, unsigned long);
1738 /* allocate a cell Read Write */
1739 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1742 static int compare(_Xconst void*, _Xconst void*);
1744 /* find contiguous sequence of cells */
1745 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1747 /* frees resources before quitting */
1748 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1750 /* create a map in a RO visual type */
1751 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1753 /* create a map in a RW visual type */
1754 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1756 #define lowbit(x) ((x) & (~(x) + 1))
1757 #define TRUEMATCH(mult,max,mask) \
1758 (colormap->max * colormap->mult <= vinfo->mask && \
1759 lowbit(vinfo->mask) == colormap->mult)
1762 * To create any one colormap which is described by an XStandardColormap
1763 * structure, use XmuCreateColormap().
1765 * Return 0 on failure, non-zero on success.
1766 * Resources created by this function are not made permanent.
1767 * No argument error checking is provided. Use at your own risk.
1769 * All colormaps are created with read only allocations, with the exception
1770 * of read only allocations of colors in the default map or otherwise
1771 * which fail to return the expected pixel value, and these are individually
1772 * defined as read/write allocations. This is done so that all the cells
1773 * defined in the default map are contiguous, for use in image processing.
1774 * This typically happens with White and Black in the default map.
1776 * Colormaps of static visuals are considered to be successfully created if
1777 * the map of the static visual matches the definition given in the
1778 * standard colormap structure.
1782 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1783 /* dpy - specifies the connection under which the map is created
1784 * colormap - specifies the map to be created, and returns, particularly
1785 * if the map is created as a subset of the default colormap
1786 * of the screen, the base_pixel of the map.
1789 XVisualInfo vinfo_template; /* template visual information */
1790 XVisualInfo *vinfo; /* matching visual information */
1791 XVisualInfo *vpointer; /* for freeing the entire list */
1792 long vinfo_mask; /* specifies the visual mask value */
1793 int n; /* number of matching visuals */
1796 vinfo_template.visualid = colormap->visualid;
1797 vinfo_mask = VisualIDMask;
1798 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1801 /* A visual id may be valid on multiple screens. Also, there may
1802 * be multiple visuals with identical visual ids at different depths.
1803 * If the colormap is the Default Colormap, use the Default Visual.
1804 * Otherwise, arbitrarily, use the deepest visual.
1810 register int screen_number;
1814 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1815 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1821 for (i=0; i < n; i++, vinfo++) {
1822 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1827 XVisualInfo *v = NULL;
1829 for (i=0; i < n; i++, vinfo++)
1830 if (vinfo->depth > maxdepth) {
1831 maxdepth = vinfo->depth;
1838 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1839 vinfo->c_class == GrayScale)
1840 status = readwrite_map(dpy, vinfo, colormap);
1841 else if (vinfo->c_class == TrueColor)
1842 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1843 TRUEMATCH(green_mult, green_max, green_mask) &&
1844 TRUEMATCH(blue_mult, blue_max, blue_mask);
1846 status = readonly_map(dpy, vinfo, colormap);
1848 XFree((char *) vpointer);
1852 /****************************************************************************/
1854 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1856 register unsigned long i, n; /* index counters */
1857 unsigned long ncolors; /* number of colors to be defined */
1858 int npixels; /* number of pixels allocated R/W */
1859 int first_index; /* first index of pixels to use */
1860 int remainder; /* first index of remainder */
1861 XColor color; /* the definition of a color */
1862 unsigned long *pixels; /* array of colormap pixels */
1863 unsigned long delta;
1866 /* Determine ncolors, the number of colors to be defined.
1867 * Insure that 1 < ncolors <= the colormap size.
1869 if (vinfo->c_class == DirectColor) {
1870 ncolors = colormap->red_max;
1871 if (colormap->green_max > ncolors)
1872 ncolors = colormap->green_max;
1873 if (colormap->blue_max > ncolors)
1874 ncolors = colormap->blue_max;
1876 delta = lowbit(vinfo->red_mask) +
1877 lowbit(vinfo->green_mask) +
1878 lowbit(vinfo->blue_mask);
1880 ncolors = colormap->red_max * colormap->red_mult +
1881 colormap->green_max * colormap->green_mult +
1882 colormap->blue_max * colormap->blue_mult + 1;
1885 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1887 /* Allocate Read/Write as much of the colormap as we can possibly get.
1888 * Then insure that the pixels we were allocated are given in
1889 * monotonically increasing order, using a quicksort. Next, insure
1890 * that our allocation includes a subset of contiguous pixels at least
1891 * as long as the number of colors to be defined. Now we know that
1892 * these conditions are met:
1893 * 1) There are no free cells in the colormap.
1894 * 2) We have a contiguous sequence of pixels, monotonically
1895 * increasing, of length >= the number of colors requested.
1897 * One cell at a time, we will free, compute the next color value,
1898 * then allocate read only. This takes a long time.
1899 * This is done to insure that cells are allocated read only in the
1900 * contiguous order which we prefer. If the server has a choice of
1901 * cells to grant to an allocation request, the server may give us any
1902 * cell, so that is why we do these slow gymnastics.
1905 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1906 sizeof(unsigned long))) == NULL)
1909 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1910 vinfo->colormap_size, ncolors)) == 0) {
1911 free((char *) pixels);
1915 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1917 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1919 /* can't find enough contiguous cells, give up */
1920 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1922 free((char *) pixels);
1925 colormap->base_pixel = pixels[first_index];
1927 /* construct a gray map */
1928 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1929 colormap->blue_mult == 1)
1930 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1933 color.blue = color.green = color.red =
1934 (unsigned short) ((i * 65535) / (colormap->red_max +
1935 colormap->green_max +
1936 colormap->blue_max));
1938 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1943 /* construct a red ramp map */
1944 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1945 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1948 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1949 color.green = color.blue = 0;
1951 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1956 /* construct a green ramp map */
1957 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1958 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1961 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1962 color.red = color.blue = 0;
1964 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1969 /* construct a blue ramp map */
1970 else if (colormap->red_max == 0 && colormap->green_max == 0)
1971 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1974 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1975 color.red = color.green = 0;
1977 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1982 /* construct a standard red green blue cube map */
1985 #define calc(max,mult) (((n / colormap->mult) % \
1986 (colormap->max + 1)) * 65535) / colormap->max
1988 for (n=0, i=0; i < ncolors; i++, n += delta)
1990 color.pixel = n + colormap->base_pixel;
1991 color.red = calc(red_max, red_mult);
1992 color.green = calc(green_max, green_mult);
1993 color.blue = calc(blue_max, blue_mult);
1994 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2000 /* We have a read-only map defined. Now free unused cells,
2001 * first those occuring before the contiguous sequence begins,
2002 * then any following the contiguous sequence.
2006 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2009 XFreeColors(dpy, colormap->colormap,
2010 &(pixels[first_index + ncolors]), remainder,
2013 free((char *) pixels);
2018 /****************************************************************************/
2020 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2022 * dpy - the X server connection
2023 * cmap - specifies colormap ID
2024 * pixels - returns pixel allocations
2025 * m - specifies colormap size
2026 * n - specifies number of colors
2031 /* first try to allocate the entire colormap */
2032 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2033 (unsigned) 0, pixels, (unsigned) m))
2036 /* Allocate all available cells in the colormap, using a binary
2037 * algorithm to discover how many cells we can allocate in the colormap.
2041 p = n + ((m - n + 1) / 2);
2042 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2043 (unsigned) 0, pixels, (unsigned) p)) {
2047 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2058 /****************************************************************************/
2060 contiguous(unsigned long pixels[], int npixels, int ncolors,
2061 unsigned long delta, int *first, int *rem)
2062 /* pixels - specifies allocated pixels
2063 * npixels - specifies count of alloc'd pixels
2064 * ncolors - specifies needed sequence length
2065 * delta - between pixels
2066 * first - returns first index of sequence
2067 * rem - returns first index after sequence, or 0, if none follow
2070 register int i = 1; /* walking index into the pixel array */
2071 register int count = 1; /* length of sequence discovered so far */
2074 if (npixels == ncolors) {
2079 while (count < ncolors && ncolors - count <= *rem)
2081 if (pixels[i-1] + delta == pixels[i])
2090 if (count != ncolors)
2096 /****************************************************************************/
2098 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2099 int npixels, XColor *color, unsigned long p)
2101 unsigned long pixel;
2104 /* Free the read/write allocation of one cell in the colormap.
2105 * Request a read only allocation of one cell in the colormap.
2106 * If the read only allocation cannot be granted, give up, because
2107 * there must be no free cells in the colormap.
2108 * If the read only allocation is granted, but gives us a cell which
2109 * is not the one that we just freed, it is probably the case that
2110 * we are trying allocate White or Black or some other color which
2111 * already has a read-only allocation in the map. So we try to
2112 * allocate the previously freed cell with a read/write allocation,
2113 * because we want contiguous cells for image processing algorithms.
2116 pixel = color->pixel;
2117 request.red = color->red;
2118 request.green = color->green;
2119 request.blue = color->blue;
2121 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2122 if (! XAllocColor(dpy, cmap, color)
2123 || (color->pixel != pixel &&
2124 (!RWcell(dpy, cmap, color, &request, &pixel))))
2126 free_cells(dpy, cmap, pixels, npixels, (int)p);
2133 /****************************************************************************/
2135 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2138 * pixels - to be freed
2139 * npixels - original number allocated
2142 /* One of the npixels allocated has already been freed.
2143 * p is the index of the freed pixel.
2144 * First free the pixels preceeding p, and there are p of them;
2145 * then free the pixels following p, there are npixels - p - 1 of them.
2147 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2148 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2149 free((char *) pixels);
2153 /****************************************************************************/
2155 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2156 unsigned long *pixel)
2158 unsigned long n = *pixel;
2160 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2161 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2162 (unsigned) 0, pixel, (unsigned) 1))
2166 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2169 color->pixel = *pixel;
2170 color->flags = DoRed | DoGreen | DoBlue;
2171 color->red = request->red;
2172 color->green = request->green;
2173 color->blue = request->blue;
2174 XStoreColors(dpy, cmap, color, 1);
2179 /****************************************************************************/
2181 compare(_Xconst void *e1, _Xconst void *e2)
2183 return ((int)(*(long *)e1 - *(long *)e2));
2187 /****************************************************************************/
2189 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2194 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2195 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2197 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2199 color.pixel = (unsigned long) i;
2200 color.red = (unsigned short)
2201 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2203 if (vinfo->c_class == StaticColor) {
2204 color.green = (unsigned short)
2205 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2206 65535) / colormap->green_max);
2207 color.blue = (unsigned short)
2208 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2210 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2211 color.green = color.blue = color.red;
2213 XAllocColor(dpy, colormap->colormap, &color);
2214 if (color.pixel != (unsigned long) i)
2221 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2225 Copyright 1989, 1998 The Open Group
2227 Permission to use, copy, modify, distribute, and sell this software and its
2228 documentation for any purpose is hereby granted without fee, provided that
2229 the above copyright notice appear in all copies and that both that
2230 copyright notice and this permission notice appear in supporting
2233 The above copyright notice and this permission notice shall be included in
2234 all copies or substantial portions of the Software.
2236 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2237 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2238 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2239 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2240 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2241 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2243 Except as contained in this notice, the name of The Open Group shall not be
2244 used in advertising or otherwise to promote the sale, use or other dealings
2245 in this Software without prior written authorization from The Open Group.
2248 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2251 * Author: Donna Converse, MIT X Consortium
2254 #include <X11/Xlib.h>
2255 #include <X11/Xutil.h>
2256 #include <X11/Xmu/StdCmap.h>
2258 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2260 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2261 * XmuDeleteStandardColormap() will remove the specified property from the
2262 * specified screen, releasing any resources used by the colormap(s) of the
2263 * property if possible.
2267 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2268 /* dpy; - specifies the X server to connect to
2269 * screen - specifies the screen of the display
2270 * property - specifies the standard colormap property
2273 XStandardColormap *stdcmaps, *s;
2276 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2279 for (s=stdcmaps; count > 0; count--, s++) {
2280 if ((s->killid == ReleaseByFreeingColormap) &&
2281 (s->colormap != None) &&
2282 (s->colormap != DefaultColormap(dpy, screen))) {
2284 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2285 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2287 XFreeColormap(dpy, s->colormap);
2289 XSetErrorHandler(oldHandler);
2292 } else if (s->killid != None) {
2293 XKillClient(dpy, s->killid);
2296 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2297 XFree((char *) stdcmaps);