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;
130 switch (xi->bits_per_pixel) {
131 case 8: targetpixel = (int)(*current_pixel); break;
132 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
133 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
134 case 32: targetpixel = *((int*)current_pixel); break;
135 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
138 targetpixel -= colormap_info->base_pixel;
140 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
141 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
142 red = targetpixel / colormap_info->red_mult;
143 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
144 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
146 blue = targetpixel / colormap_info->blue_mult;
147 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
148 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
152 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
153 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
154 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
155 uint32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
156 blue * colormap_info->blue_mult + colormap_info->base_pixel;
158 switch (xi->bits_per_pixel) {
159 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
160 case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
162 int offset = (int)current_pixel & 0x3;
163 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
164 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
165 uint64_t* base = (uint64_t*)(current_pixel - offset);
166 *base = (*base & ~mask) | dest;
169 case 32: *((uint32_t*)current_pixel) = destpixel; break;
170 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
176 // do nothing, we wrote directly to video memory
178 } else if (shm_supported) {
179 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1, False);
183 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1);
188 void org::xwt::plat::X11$X11PixelBuffer::finalize() {
190 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
191 XShmDetach(display, sinfo);
192 shmdt(sinfo->shmaddr);
193 shmctl(sinfo->shmid, IPC_RMID, 0);
194 XDestroyImage((XImage*)fake_ximage);
198 XFreePixmap(display, *((Pixmap*)stipple));
201 XFreePixmap(display, *((Pixmap*)pm));
202 XFreeGC(display, *((GC*)gc));
203 XFreeGC(display, *((GC*)clipped_gc));
206 void org::xwt::plat::X11$X11PixelBuffer::natInit() {
208 if (width == 0 || height == 0) return;
209 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
210 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
213 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
215 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
216 shm_segment = (gnu::gcj::RawData*)sinfo;
217 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
218 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
219 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
220 sinfo->readOnly = False;
221 XShmAttach(display, sinfo);
222 XSync(display, False);
223 shmctl(sinfo->shmid, IPC_RMID, 0);
224 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
225 XSync(display, False);
228 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
229 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
230 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
231 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
234 vm.graphics_exposures = 0;
235 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
236 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
239 void org::xwt::plat::X11$X11PixelBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
241 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
242 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
245 xi.data = (char*)malloc((width + 1) * height);
252 xi.byte_order = LSBFirst;
254 xi.bytes_per_line = (width / 8) + 1;
255 xi.bits_per_pixel = 1;
257 jint* d = (jint*)elements(xpi->data);
258 memset(xi.data, 0xFF, (width + 1) * height);
259 for(int x=0; x<width; x++)
260 for (int y=0; y<height; y++)
261 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
263 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
266 vm.graphics_exposures = 0;
267 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
269 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
272 void org::xwt::plat::X11$X11Surface::blit(org::xwt::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
273 org::xwt::plat::X11$X11PixelBuffer *xdb = (org::xwt::plat::X11$X11PixelBuffer*)db;
274 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
278 void org::xwt::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
283 if (x < clipx) { w -= (clipx - x); x = clipx; }
284 if (y < clipy) { h -= (clipy - y); y = clipy; }
285 if (x + w > clipx + clipw) w = (clipx + clipw - x);
286 if (y + h > clipy + cliph) h = (cliph + clipy - y);
288 XSetForeground(display, (*((GC*)gc)),
289 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
290 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
291 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
292 colormap_info->base_pixel
295 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
299 // X11Surface //////////////////////////////////////////////////////////////////////
301 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
302 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
303 org::xwt::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
304 p->buildPixelBuffer(1);
306 memset(&xwmh, 0, sizeof(XWMHints));
307 xwmh.flags |= IconPixmapHint | IconMaskHint;
308 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
309 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
310 XSetWMHints(display, (*((Window*)window)), &xwmh);
311 p->doublebuf = old_dbuf;
314 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
315 int len = min(JvGetStringUTFLength(s), 1024);
317 JvGetStringUTFRegion(s, 0, len, buf);
321 tp.value = (unsigned char*)buf;
323 tp.encoding = XA_STRING;
325 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
326 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
329 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
331 hints.min_width = minw;
332 hints.min_height = minh;
333 hints.max_width = maxw;
334 hints.max_height = maxh;
335 hints.flags = PMinSize | PMaxSize;
336 XSetWMNormalHints(display, (*((Window*)window)), &hints);
339 void org::xwt::plat::X11$X11Surface::_setSize (jint width, jint height) {
340 if (width <= 0 || height <= 0) return;
341 XResizeWindow(display, (*((Window*)window)), width, height);
345 void org::xwt::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
346 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
347 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
349 void org::xwt::plat::X11$X11Surface::_dispose() {
350 // without this we get phantom messages after the window is gone
351 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
352 XDestroyWindow(display, (*((Window*)window)));
355 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
356 if (i) XUnmapWindow(display, (*((Window*)window)));
357 else XMapRaised(display, (*((Window*)window)));
361 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
362 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
363 else XMapRaised(display, (*((Window*)window)));
367 void org::xwt::plat::X11$X11Surface::natInit() {
368 XSetWindowAttributes xswa;
369 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
370 xswa.bit_gravity = NorthWestGravity;
371 xswa.colormap = s_colormap;
372 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
373 KeyPressMask | KeyReleaseMask | ButtonPressMask |
374 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
375 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
376 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
377 colorDepth, InputOutput, CopyFromParent,
378 CWColormap | CWBitGravity | CWEventMask, &xswa);
381 // I don't know why this works....
382 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
383 XChangeProperty(display, (*((Window*)window)),
384 XInternAtom(display, "_MOTIF_WM_HINTS", False),
385 XInternAtom(display, "_MOTIF_WM_HINTS", False),
393 tp.value = (unsigned char*)"XWT";
395 tp.encoding = XA_STRING;
397 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
399 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
400 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
402 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
403 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
406 XMapRaised(display, (*((Window*)window)));
409 waitForCreation->block();
410 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
413 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
414 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
417 vm.graphics_exposures = 0;
418 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
422 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
424 XEvent* e = (XEvent*)ev;
425 if (e->type == Expose) {
426 XExposeEvent *expose = (XExposeEvent*)(e);
427 Dirty(expose->x, expose->y, expose->width, expose->height);
429 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
430 } else if (e->type == UnmapNotify) { Minimized(1);
431 } else if (e->type == FocusIn) { Focused(1);
432 } else if (e->type == FocusOut) { Focused(0);
433 } else if (e->type == ClientMessage) {
434 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
436 } else if (e->type == KeyPress || e->type == KeyRelease) {
437 XKeyEvent *xbe = (XKeyEvent*)(e);
439 // drop faked KeyRelease events generated by the X server's autorepeat
440 if (e->type == KeyRelease) {
442 XQueryKeymap(display, depressed);
443 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
449 unsigned int savestate = xbe->state;
450 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
451 XLookupString(xbe, s, 20, NULL, NULL);
452 xbe->state = savestate;
454 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
458 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
460 case XK_BackSpace: s = "back_space"; break;
461 case XK_Tab: s = "tab"; break;
462 case XK_Linefeed: s = "enter"; break;
463 case XK_Return: s = "enter"; break;
464 case XK_Scroll_Lock: s = "scroll_lock"; break;
465 case XK_Escape: s = "escape"; break;
466 case XK_Insert: s = "insert"; break;
467 case XK_Delete: s = "delete"; break;
468 case XK_Home: s = "home"; break;
469 case XK_Left: s = "left"; break;
470 case XK_Up: s = "up"; break;
471 case XK_Right: s = "right"; break;
472 case XK_Down: s = "down"; break;
473 case XK_Page_Up: s = "page_up"; break;
474 case XK_Page_Down: s = "page_down"; break;
475 case XK_End: s = "end"; break;
476 case XK_Num_Lock: s = "num_lock"; break;
477 case XK_KP_Tab: s = "tab"; break;
478 case XK_KP_Enter: s = "enter"; break;
479 case XK_KP_F1: s = "f1"; break;
480 case XK_KP_F2: s = "f2"; break;
481 case XK_KP_F3: s = "f3"; break;
482 case XK_KP_F4: s = "f4"; break;
483 case XK_KP_Home: s = "home"; break;
484 case XK_KP_Left: s = "left"; break;
485 case XK_KP_Up: s = "up"; break;
486 case XK_KP_Right: s = "right"; break;
487 case XK_KP_Down: s = "down"; break;
488 case XK_KP_Page_Up: s = "page_up"; break;
489 case XK_KP_Page_Down: s = "page_down"; break;
490 case XK_KP_End: s = "end"; break;
491 case XK_KP_Insert: s = "insert"; break;
492 case XK_KP_Delete: s = "delete"; break;
493 case XK_F1: s = "f1"; break;
494 case XK_F2: s = "f2"; break;
495 case XK_F3: s = "f3"; break;
496 case XK_F4: s = "f4"; break;
497 case XK_F5: s = "f5"; break;
498 case XK_F6: s = "f6"; break;
499 case XK_F7: s = "f7"; break;
500 case XK_F8: s = "f8"; break;
501 case XK_F9: s = "f9"; break;
502 case XK_F10: s = "f10"; break;
503 case XK_F11: s = "f11"; break;
504 case XK_F12: s = "f12"; break;
505 case XK_Shift_L: s = "shift"; break;
506 case XK_Shift_R: s = "shift"; break;
507 case XK_Control_L: s = "control"; break;
508 case XK_Control_R: s = "control"; break;
509 case XK_Meta_L: s = "alt"; break;
510 case XK_Meta_R: s = "alt"; break;
511 case XK_Alt_L: s = "alt"; break;
512 case XK_Alt_R: s = "alt"; break;
517 jstring s2 = JvNewStringLatin1(s);
518 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
519 if (e->type == KeyRelease) KeyReleased(s2);
521 } else if (e->type == ButtonPress) {
522 XButtonEvent* xbe = (XButtonEvent*)(e);
523 if (xbe->button == 2) xbe->button = 3;
524 else if (xbe->button == 3) xbe->button = 2;
527 } else if (e->type == ButtonRelease) {
528 XButtonEvent* xbe = (XButtonEvent*)(e);
529 if (xbe->button == 2) xbe->button = 3;
530 else if (xbe->button == 3) xbe->button = 2;
531 Release(xbe->button);
533 } else if (e->type == MotionNotify) {
534 XMotionEvent* xme = (XMotionEvent*)(e);
535 Move(xme->x, xme->y);
537 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
538 XCrossingEvent* xce = (XCrossingEvent*)(e);
539 Move(xce->x, xce->y);
541 } else if (e->type == ConfigureNotify) {
544 XConfigureEvent* xce = (XConfigureEvent*)(e);
545 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
546 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
547 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
552 static jstring crosshair, east, hand, move, north, northeast, northwest,
553 south, southeast, southwest, text, west, wait_string;
554 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
555 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
556 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
558 void org::xwt::plat::X11$X11Surface::syncCursor() {
561 if (cursor->equals(crosshair)) curs = crosshair_cursor;
562 else if (cursor->equals(east)) curs = east_cursor;
563 else if (cursor->equals(hand)) curs = hand_cursor;
564 else if (cursor->equals(move)) curs = move_cursor;
565 else if (cursor->equals(north)) curs = north_cursor;
566 else if (cursor->equals(northeast)) curs = northeast_cursor;
567 else if (cursor->equals(northwest)) curs = northwest_cursor;
568 else if (cursor->equals(south)) curs = south_cursor;
569 else if (cursor->equals(southeast)) curs = southeast_cursor;
570 else if (cursor->equals(southwest)) curs = southwest_cursor;
571 else if (cursor->equals(text)) curs = text_cursor;
572 else if (cursor->equals(west)) curs = west_cursor;
573 else if (cursor->equals(wait_string)) curs = wait_cursor;
574 else curs = default_cursor;
576 XDefineCursor(display, (*((Window*)window)), curs);
581 // X11 ///////////////////////////////////////////////////////////////////
583 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
584 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
586 static void dispatchSelectionEvent(XEvent* e) {
587 if (e->type == SelectionNotify) {
588 XSelectionEvent* xsn = (XSelectionEvent*)(e);
589 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
593 unsigned long numitems;
595 unsigned long bytes_after;
596 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
597 True, AnyPropertyType, &returntype, &returnformat,
598 &numitems, &bytes_after, &ret);
599 org::xwt::plat::X11::clipboard =
600 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
602 org::xwt::plat::X11::waiting_for_selection_event->release();
604 } else if (e->type == SelectionRequest) {
605 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
607 xsn.type = SelectionNotify;
608 xsn.serial = xsr->serial;
609 xsn.send_event = True;
610 xsn.display = display;
611 xsn.requestor = xsr->requestor;
612 xsn.selection = xsr->selection;
613 xsn.target = xsr->target;
614 xsn.property = xsr->property;
615 xsn.time = xsr->time;
617 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
619 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
622 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
623 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
627 void org::xwt::plat::X11::eventThread() {
630 XNextEvent(display, &e);
631 if (e.type == SelectionNotify || e.type == SelectionRequest) {
632 dispatchSelectionEvent(&e);
634 org::xwt::plat::X11$X11Surface* surface =
635 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
636 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
641 jstring org::xwt::plat::X11::_getClipBoard() {
642 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
644 org::xwt::plat::X11::waiting_for_selection_event->block();
648 void org::xwt::plat::X11::_setClipBoard(jstring s) {
650 int len = JvGetStringUTFLength(clipboard);
652 JvGetStringUTFRegion(clipboard, 0, len, buf);
654 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
657 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
658 int errorHandler(Display* d, XErrorEvent* e) {
659 // this error handler is only installed during the initial
660 // test to see if shm is present
664 void org::xwt::plat::X11::natInit() {
667 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
669 char* DISPLAY = getenv("DISPLAY");
670 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
671 display = XOpenDisplay(DISPLAY);
674 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
676 screen_num = XDefaultScreen(display);
677 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
678 shm_info.shmaddr = NULL;
680 // FIXME: SHM doesn't work on Darwin
681 //shm_supported = (XShmQueryExtension(display) == True);
683 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
684 XShmSegmentInfo sinfo;
685 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
686 sinfo.readOnly = False;
687 // if the server is remote, this will trigger the error handler
688 XShmAttach(display, &sinfo);
689 XSync(display, False);
690 XSetErrorHandler(oldHandler);
694 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
696 crosshair = JvNewStringLatin1("crosshair");
697 east = JvNewStringLatin1("east");
698 hand = JvNewStringLatin1("hand");
699 move = JvNewStringLatin1("move");
700 north = JvNewStringLatin1("north");
701 northeast = JvNewStringLatin1("northeast");
702 northwest = JvNewStringLatin1("northwest");
703 south = JvNewStringLatin1("south");
704 southeast = JvNewStringLatin1("southeast");
705 southwest = JvNewStringLatin1("southwest");
706 text = JvNewStringLatin1("text");
707 west = JvNewStringLatin1("west");
708 wait_string = JvNewStringLatin1("wait");
709 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
710 east_cursor = XCreateFontCursor(display, XC_right_side);
711 hand_cursor = XCreateFontCursor(display, XC_hand2);
712 move_cursor = XCreateFontCursor(display, XC_fleur);
713 north_cursor = XCreateFontCursor(display, XC_top_side);
714 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
715 northwest_cursor = XCreateFontCursor(display, XC_left_side);
716 south_cursor = XCreateFontCursor(display, XC_bottom_side);
717 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
718 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
719 text_cursor = XCreateFontCursor(display, XC_xterm);
720 west_cursor = XCreateFontCursor(display, XC_right_side);
721 wait_cursor = XCreateFontCursor(display, XC_watch);
722 default_cursor = XCreateFontCursor(display, XC_left_ptr);
724 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
725 visual = DefaultVisual(display, screen_num);
727 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
728 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
729 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
730 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
731 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
732 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
733 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
735 // FIXME: don't know why (True, False) is the best solution...
736 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
737 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
739 XStandardColormap* best_map_info = NULL;
741 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
742 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
743 if (!best_map_info->colormap)
744 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
745 if (best_map_info->red_max == 0)
746 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
747 s_colormap = best_map_info->colormap;
748 colormap_info = best_map_info;
750 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
751 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
752 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
753 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
754 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
755 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
756 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
757 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
762 //////////////////////////////////////////////////////////////////////////////
763 //////////////////////////////////////////////////////////////////////////////
764 //////////////////////////////////////////////////////////////////////////////
765 //////////////////////////////////////////////////////////////////////////////
767 // Everything below this point was taken, cut-and-paste, from the //
768 // source for libXmu. It implements the official 'standard colormap //
769 // creation algorithm. I made some small changes to //
770 // XmuDeleteStandardColormap //
772 //////////////////////////////////////////////////////////////////////////////
773 //////////////////////////////////////////////////////////////////////////////
774 //////////////////////////////////////////////////////////////////////////////
775 //////////////////////////////////////////////////////////////////////////////
777 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
781 Copyright 1989, 1998 The Open Group
783 Permission to use, copy, modify, distribute, and sell this software and its
784 documentation for any purpose is hereby granted without fee, provided that
785 the above copyright notice appear in all copies and that both that
786 copyright notice and this permission notice appear in supporting
789 The above copyright notice and this permission notice shall be included in
790 all copies or substantial portions of the Software.
792 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
793 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
794 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
795 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
796 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
797 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
799 Except as contained in this notice, the name of The Open Group shall not be
800 used in advertising or otherwise to promote the sale, use or other dealings
801 in this Software without prior written authorization from The Open Group.
804 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
807 * Author: Donna Converse, MIT X Consortium
811 #include <X11/Xlib.h>
812 #include <X11/Xatom.h>
813 #include <X11/Xutil.h>
814 #include <X11/Xmu/StdCmap.h>
820 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
823 * To create a standard colormap if one does not currently exist, or
824 * replace the currently existing standard colormap, use
825 * XmuLookupStandardColormap().
827 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
828 * will determine the best allocation for the property under the specified
829 * visual, and determine the whether to create a new colormap or to use
830 * the default colormap of the screen. It will call XmuStandardColormap()
831 * to create the standard colormap.
833 * If replace is true, any previous definition of the property will be
834 * replaced. If retain is true, the property and the colormap will be
835 * made permanent for the duration of the server session. However,
836 * pre-existing property definitions which are not replaced cannot be made
837 * permanent by a call to XmuLookupStandardColormap(); a request to retain
838 * resources pertains to newly created resources.
840 * Returns 0 on failure, non-zero on success. A request to create a
841 * standard colormap upon a visual which cannot support such a map is
842 * considered a failure. An example of this would be requesting any
843 * standard colormap property on a monochrome visual, or, requesting an
844 * RGB_BEST_MAP on a display whose colormap size is 16.
848 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
849 unsigned int depth, Atom property,
850 Bool replace, Bool retain)
852 * dpy - specifies X server connection
853 * screen - specifies screen of display
854 * visualid - specifies the visual type
855 * depth - specifies the visual type
856 * property - a standard colormap property
857 * replace - specifies whether to replace
858 * retain - specifies whether to retain
861 Display *odpy; /* original display connection */
862 XStandardColormap *colormap;
863 XVisualInfo vinfo_template, *vinfo; /* visual */
865 unsigned long r_max, g_max, b_max; /* allocation */
867 Colormap cmap; /* colormap ID */
871 /* Match the requested visual */
873 vinfo_template.visualid = visualid;
874 vinfo_template.screen = screen;
875 vinfo_template.depth = depth;
876 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
877 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
881 /* Monochrome visuals have no standard maps */
883 if (vinfo->colormap_size <= 2) {
884 XFree((char *) vinfo);
888 /* If the requested property already exists on this screen, and,
889 * if the replace flag has not been set to true, return success.
890 * lookup() will remove a pre-existing map if replace is true.
893 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
894 replace) && !replace) {
895 XFree((char *) vinfo);
899 /* Determine the best allocation for this property under the requested
900 * visualid and depth, and determine whether or not to use the default
901 * colormap of the screen.
904 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
905 XFree((char *) vinfo);
909 cmap = (property == XA_RGB_DEFAULT_MAP &&
910 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
911 ? DefaultColormap(dpy, screen) : None;
913 /* If retaining resources, open a new connection to the same server */
917 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
918 XFree((char *) vinfo);
923 /* Create the standard colormap */
925 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
926 cmap, r_max, g_max, b_max);
928 /* Set the standard colormap property */
933 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
935 /* Someone has defined the property since we last looked.
936 * Since we will not replace it, release our own resources.
937 * If this is the default map, our allocations will be freed
938 * when this connection closes.
940 if (colormap->killid == ReleaseByFreeingColormap)
941 XFreeColormap(dpy, colormap->colormap);
943 XSetCloseDownMode(dpy, RetainPermanent);
946 XFree((char *) colormap);
952 XFree((char *) vinfo);
956 /***************************************************************************/
958 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
959 * the visualid is used to determine whether the indicated standard colormap
960 * exists. If the map exists and replace is true, delete the resources used
961 * by the map and remove the property. Return true if the map exists,
962 * or did exist and was deleted; return false if the map was not found.
964 * Note that this is not the way that a Status return is normally used.
966 * If new is not NULL, new points to an XStandardColormap structure which
967 * describes a standard colormap of the specified property. It will be made
968 * a standard colormap of the screen if none already exists, or if replace
973 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
974 XStandardColormap *cnew, Bool replace)
976 * dpy - specifies display connection
977 * screen - specifies screen number
978 * visualid - specifies visualid for std map
979 * property - specifies colormap property name
980 * cnew - specifies a standard colormap
981 * replace - specifies whether to replace
986 XStandardColormap *stdcmaps, *s;
987 Window win = RootWindow(dpy, screen);
989 /* The property does not already exist */
991 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
993 XSetRGBColormaps(dpy, win, cnew, 1, property);
997 /* The property exists and is not describing the RGB_DEFAULT_MAP */
999 if (property != XA_RGB_DEFAULT_MAP) {
1001 XmuDeleteStandardColormap(dpy, screen, property);
1003 XSetRGBColormaps(dpy, win, cnew, 1, property);
1005 XFree((char *)stdcmaps);
1009 /* The property exists and is RGB_DEFAULT_MAP */
1011 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1014 /* No RGB_DEFAULT_MAP property matches the given visualid */
1018 XStandardColormap *m, *maps;
1020 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1021 (XStandardColormap)));
1023 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1024 m->colormap = maps->colormap;
1025 m->red_max = maps->red_max;
1026 m->red_mult = maps->red_mult;
1027 m->green_max = maps->green_max;
1028 m->green_mult = maps->green_mult;
1029 m->blue_max = maps->blue_max;
1030 m->blue_mult = maps->blue_mult;
1031 m->base_pixel = maps->base_pixel;
1032 m->visualid = maps->visualid;
1033 m->killid = maps->killid;
1035 m->colormap = cnew->colormap;
1036 m->red_max = cnew->red_max;
1037 m->red_mult = cnew->red_mult;
1038 m->green_max = cnew->green_max;
1039 m->green_mult = cnew->green_mult;
1040 m->blue_max = cnew->blue_max;
1041 m->blue_mult = cnew->blue_mult;
1042 m->base_pixel = cnew->base_pixel;
1043 m->visualid = cnew->visualid;
1044 m->killid = cnew->killid;
1046 XSetRGBColormaps(dpy, win, s, ++count, property);
1049 XFree((char *) stdcmaps);
1053 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1056 /* Free old resources first - we may need them, particularly in
1057 * the default colormap of the screen. However, because of this,
1058 * it is possible that we will destroy the old resource and fail
1059 * to create a new one if XmuStandardColormap() fails.
1063 XmuDeleteStandardColormap(dpy, screen, property);
1065 XSetRGBColormaps(dpy, win, cnew, 1, property);
1068 XStandardColormap *map;
1070 /* s still points to the matching standard colormap */
1072 if (s->killid == ReleaseByFreeingColormap) {
1073 if ((s->colormap != None) &&
1074 (s->colormap != DefaultColormap(dpy, screen)))
1075 XFreeColormap(dpy, s->colormap);
1077 else if (s->killid != None)
1078 XKillClient(dpy, s->killid);
1080 map = (cnew) ? cnew : stdcmaps + --count;
1082 s->colormap = map->colormap;
1083 s->red_max = map->red_max;
1084 s->red_mult = map->red_mult;
1085 s->green_max = map->green_max;
1086 s->green_mult = map->green_mult;
1087 s->blue_max = map->blue_max;
1088 s->blue_mult = map->blue_mult;
1089 s->visualid = map->visualid;
1090 s->killid = map->killid;
1092 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1095 XFree((char *) stdcmaps);
1099 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1103 Copyright 1989, 1994, 1998 The Open Group
1105 Permission to use, copy, modify, distribute, and sell this software and its
1106 documentation for any purpose is hereby granted without fee, provided that
1107 the above copyright notice appear in all copies and that both that
1108 copyright notice and this permission notice appear in supporting
1111 The above copyright notice and this permission notice shall be included in
1112 all copies or substantial portions of the Software.
1114 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1115 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1116 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1117 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1118 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1119 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1121 Except as contained in this notice, the name of The Open Group shall not be
1122 used in advertising or otherwise to promote the sale, use or other dealings
1123 in this Software without prior written authorization from The Open Group.
1126 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1129 * Author: Donna Converse, MIT X Consortium
1132 #include <X11/Xlib.h>
1133 #include <X11/Xatom.h>
1134 #include <X11/Xutil.h>
1135 #include <X11/Xmu/StdCmap.h>
1138 #define lowbit(x) ((x) & (~(x) + 1))
1143 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1145 static int default_allocation(XVisualInfo*, unsigned long*,
1146 unsigned long*, unsigned long*);
1147 static void gray_allocation(int, unsigned long*, unsigned long*,
1149 static int icbrt(int);
1150 static int icbrt_with_bits(int, int);
1151 static int icbrt_with_guess(int, int);
1153 /* To determine the best allocation of reds, greens, and blues in a
1154 * standard colormap, use XmuGetColormapAllocation.
1155 * vinfo specifies visual information for a chosen visual
1156 * property specifies one of the standard colormap property names
1157 * red_max returns maximum red value
1158 * green_max returns maximum green value
1159 * blue_max returns maximum blue value
1161 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1162 * It is assumed that the visual is appropriate for the colormap property.
1166 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1167 unsigned long *red_max,
1168 unsigned long *green_max,
1169 unsigned long *blue_max)
1173 if (vinfo->colormap_size <= 2)
1178 case XA_RGB_DEFAULT_MAP:
1179 status = default_allocation(vinfo, red_max, green_max, blue_max);
1181 case XA_RGB_BEST_MAP:
1182 best_allocation(vinfo, red_max, green_max, blue_max);
1184 case XA_RGB_GRAY_MAP:
1185 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1187 case XA_RGB_RED_MAP:
1188 *red_max = vinfo->colormap_size - 1;
1189 *green_max = *blue_max = 0;
1191 case XA_RGB_GREEN_MAP:
1192 *green_max = vinfo->colormap_size - 1;
1193 *red_max = *blue_max = 0;
1195 case XA_RGB_BLUE_MAP:
1196 *blue_max = vinfo->colormap_size - 1;
1197 *red_max = *green_max = 0;
1205 /****************************************************************************/
1206 /* Determine the appropriate color allocations of a gray scale.
1208 * Keith Packard, MIT X Consortium
1212 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1213 unsigned long *blue_max)
1215 *red_max = (n * 30) / 100;
1216 *green_max = (n * 59) / 100;
1217 *blue_max = (n * 11) / 100;
1218 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1221 /****************************************************************************/
1222 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1223 * If a map has less than a minimum number of definable entries, we do not
1224 * produce an allocation for an RGB_DEFAULT_MAP.
1226 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1227 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1228 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1229 * Maximum green and maximum blue values are identical to maximum red.
1230 * This leaves at least 125 cells which clients can allocate.
1232 * Return 0 if an allocation has been determined, non-zero otherwise.
1236 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1237 unsigned long *green, unsigned long *blue)
1239 int ngrays; /* number of gray cells */
1241 switch (vinfo->c_class)
1245 if (vinfo->colormap_size > 65000)
1246 /* intended for displays with 16 planes */
1247 *red = *green = *blue = (unsigned long) 27;
1248 else if (vinfo->colormap_size > 4000)
1249 /* intended for displays with 12 planes */
1250 *red = *green = *blue = (unsigned long) 12;
1251 else if (vinfo->colormap_size < 250)
1254 /* intended for displays with 8 planes */
1255 *red = *green = *blue = (unsigned long)
1256 (icbrt(vinfo->colormap_size - 125) - 1);
1261 if (vinfo->colormap_size < 10)
1263 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1268 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1269 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1270 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1275 if (vinfo->colormap_size > 65000)
1277 else if (vinfo->colormap_size > 4000)
1279 else if (vinfo->colormap_size < 250)
1283 gray_allocation(ngrays, red, green, blue);
1292 /****************************************************************************/
1293 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1295 * For a DirectColor or TrueColor visual, the allocation is determined
1296 * by the red_mask, green_mask, and blue_mask members of the visual info.
1298 * Otherwise, if the colormap size is an integral power of 2, determine
1299 * the allocation according to the number of bits given to each color,
1300 * with green getting more than red, and red more than blue, if there
1301 * are to be inequities in the distribution. If the colormap size is
1302 * not an integral power of 2, let n = the number of colormap entries.
1303 * Then maximum red value = floor(cube_root(n)) - 1;
1304 * maximum blue value = floor(cube_root(n)) - 1;
1305 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1306 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1307 * defineable colormap entries.
1311 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1312 unsigned long *blue)
1315 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1317 *red = vinfo->red_mask;
1318 while ((*red & 01) == 0)
1320 *green = vinfo->green_mask;
1321 while ((*green & 01) == 0)
1323 *blue = vinfo->blue_mask;
1324 while ((*blue & 01) == 0)
1329 register int bits, n;
1331 /* Determine n such that n is the least integral power of 2 which is
1332 * greater than or equal to the number of entries in the colormap.
1336 while (vinfo->colormap_size > n)
1342 /* If the number of entries in the colormap is a power of 2, determine
1343 * the allocation by "dealing" the bits, first to green, then red, then
1344 * blue. If not, find the maximum integral red, green, and blue values
1345 * which, when multiplied together, do not exceed the number of
1349 if (n == vinfo->colormap_size)
1351 register int r, g, b;
1353 g = b + ((bits % 3) ? 1 : 0);
1354 r = b + (((bits % 3) == 2) ? 1 : 0);
1361 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1363 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1373 * integer cube roots by Newton's method
1375 * Stephen Gildea, MIT X Consortium, July 1991
1381 register int bits = 0;
1382 register unsigned n = a;
1389 return icbrt_with_bits(a, bits);
1394 icbrt_with_bits(int a, int bits)
1395 /* bits - log 2 of a */
1397 return icbrt_with_guess(a, a>>2*bits/3);
1400 #ifdef _X_ROOT_STATS
1401 int icbrt_loopcount;
1404 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1406 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1409 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1410 * Only works for positive integers (since that's all we need).
1411 * We actually return floor(cbrt(a)) because that's what we need here, too.
1415 icbrt_with_guess(int a, int guess)
1419 #ifdef _X_ROOT_STATS
1420 icbrt_loopcount = 0;
1428 #ifdef _X_ROOT_STATS
1431 delta = (guess - a/(guess*guess))/3;
1433 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1436 } while (delta != 0);
1438 if (guess*guess*guess > a)
1445 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1449 Copyright 1989, 1998 The Open Group
1451 Permission to use, copy, modify, distribute, and sell this software and its
1452 documentation for any purpose is hereby granted without fee, provided that
1453 the above copyright notice appear in all copies and that both that
1454 copyright notice and this permission notice appear in supporting
1457 The above copyright notice and this permission notice shall be included in
1458 all copies or substantial portions of the Software.
1460 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1461 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1462 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1463 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1464 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1465 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1467 Except as contained in this notice, the name of The Open Group shall not be
1468 used in advertising or otherwise to promote the sale, use or other dealings
1469 in this Software without prior written authorization from The Open Group.
1472 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1475 * Author: Donna Converse, MIT X Consortium
1479 #include <X11/Xlib.h>
1480 #include <X11/Xatom.h>
1481 #include <X11/Xutil.h>
1482 #include <X11/Xmu/StdCmap.h>
1484 #define lowbit(x) ((x) & (~(x) + 1))
1489 /* argument restrictions */
1490 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1491 unsigned long, Atom);
1494 * To create any one standard colormap, use XmuStandardColormap().
1496 * Create a standard colormap for the given screen, visualid, and visual
1497 * depth, with the given red, green, and blue maximum values, with the
1498 * given standard property name. Return a pointer to an XStandardColormap
1499 * structure which describes the newly created colormap, upon success.
1500 * Upon failure, return NULL.
1502 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1504 * Resources created by this function are not made permanent; that is the
1505 * caller's responsibility.
1509 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1510 unsigned int depth, Atom property, Colormap cmap,
1511 unsigned long red_max, unsigned long green_max,
1512 unsigned long blue_max)
1514 * dpy - specifies X server connection
1515 * screen - specifies display screen
1516 * visualid - identifies the visual type
1517 * depth - identifies the visual type
1518 * property - a standard colormap property
1519 * cmap - specifies colormap ID or None
1520 * red_max, green_max, blue_max - allocations
1523 XStandardColormap *stdcmap;
1525 XVisualInfo vinfo_template, *vinfo;
1529 /* Match the required visual information to an actual visual */
1530 vinfo_template.visualid = visualid;
1531 vinfo_template.screen = screen;
1532 vinfo_template.depth = depth;
1533 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1534 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1537 /* Check the validity of the combination of visual characteristics,
1538 * allocation, and colormap property. Create an XStandardColormap
1542 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1543 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1544 XFree((char *) vinfo);
1548 /* Fill in the XStandardColormap structure */
1550 if (cmap == DefaultColormap(dpy, screen)) {
1551 /* Allocating out of the default map, cannot use XFreeColormap() */
1552 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1553 0, 0, InputOnly, vinfo->visual,
1555 (XSetWindowAttributes *)NULL);
1556 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1557 XDestroyWindow(dpy, win);
1558 stdcmap->colormap = cmap;
1560 stdcmap->killid = ReleaseByFreeingColormap;
1561 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1562 vinfo->visual, AllocNone);
1564 stdcmap->red_max = red_max;
1565 stdcmap->green_max = green_max;
1566 stdcmap->blue_max = blue_max;
1567 if (property == XA_RGB_GRAY_MAP)
1568 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1569 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1570 stdcmap->red_mult = lowbit(vinfo->red_mask);
1571 stdcmap->green_mult = lowbit(vinfo->green_mask);
1572 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1574 stdcmap->red_mult = (red_max > 0)
1575 ? (green_max + 1) * (blue_max + 1) : 0;
1576 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1577 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1579 stdcmap->base_pixel = 0; /* base pixel may change */
1580 stdcmap->visualid = vinfo->visualid;
1582 /* Make the colormap */
1584 status = XmuCreateColormap(dpy, stdcmap);
1588 XFree((char *) vinfo);
1591 /* Free the colormap or the pixmap, if we created one */
1592 if (stdcmap->killid == ReleaseByFreeingColormap)
1593 XFreeColormap(dpy, stdcmap->colormap);
1594 else if (stdcmap->killid != None)
1595 XFreePixmap(dpy, stdcmap->killid);
1597 XFree((char *) stdcmap);
1598 return (XStandardColormap *) NULL;
1603 /****************************************************************************/
1605 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1606 unsigned long blue_max, Atom property)
1608 * vinfo - specifies visual
1609 * red_max, green_max, blue_max - specifies alloc
1610 * property - specifies property name
1613 unsigned long ncolors; /* number of colors requested */
1615 /* Determine that the number of colors requested is <= map size */
1617 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1620 mask = vinfo->red_mask;
1625 mask = vinfo->green_mask;
1628 if (green_max > mask)
1630 mask = vinfo->blue_mask;
1633 if (blue_max > mask)
1635 } else if (property == XA_RGB_GRAY_MAP) {
1636 ncolors = red_max + green_max + blue_max + 1;
1637 if (ncolors > vinfo->colormap_size)
1640 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1641 if (ncolors > vinfo->colormap_size)
1645 /* Determine that the allocation and visual make sense for the property */
1649 case XA_RGB_DEFAULT_MAP:
1650 if (red_max == 0 || green_max == 0 || blue_max == 0)
1653 case XA_RGB_RED_MAP:
1657 case XA_RGB_GREEN_MAP:
1661 case XA_RGB_BLUE_MAP:
1665 case XA_RGB_BEST_MAP:
1666 if (red_max == 0 || green_max == 0 || blue_max == 0)
1669 case XA_RGB_GRAY_MAP:
1670 if (red_max == 0 || blue_max == 0 || green_max == 0)
1680 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1684 Copyright 1989, 1998 The Open Group
1686 Permission to use, copy, modify, distribute, and sell this software and its
1687 documentation for any purpose is hereby granted without fee, provided that
1688 the above copyright notice appear in all copies and that both that
1689 copyright notice and this permission notice appear in supporting
1692 The above copyright notice and this permission notice shall be included in
1693 all copies or substantial portions of the Software.
1695 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1696 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1697 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1698 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1699 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1700 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1702 Except as contained in this notice, the name of The Open Group shall not be
1703 used in advertising or otherwise to promote the sale, use or other dealings
1704 in this Software without prior written authorization from The Open Group.
1707 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1710 * Author: Donna Converse, MIT X Consortium
1714 * CreateCmap.c - given a standard colormap description, make the map.
1719 #include <X11/Xlib.h>
1720 #include <X11/Xutil.h>
1721 #include <X11/Xmu/StdCmap.h>
1726 /* allocate entire map Read Only */
1727 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1729 /* allocate a cell, prefer Read Only */
1730 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1731 XColor*, unsigned long);
1733 /* allocate a cell Read Write */
1734 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1737 static int compare(_Xconst void*, _Xconst void*);
1739 /* find contiguous sequence of cells */
1740 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1742 /* frees resources before quitting */
1743 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1745 /* create a map in a RO visual type */
1746 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1748 /* create a map in a RW visual type */
1749 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1751 #define lowbit(x) ((x) & (~(x) + 1))
1752 #define TRUEMATCH(mult,max,mask) \
1753 (colormap->max * colormap->mult <= vinfo->mask && \
1754 lowbit(vinfo->mask) == colormap->mult)
1757 * To create any one colormap which is described by an XStandardColormap
1758 * structure, use XmuCreateColormap().
1760 * Return 0 on failure, non-zero on success.
1761 * Resources created by this function are not made permanent.
1762 * No argument error checking is provided. Use at your own risk.
1764 * All colormaps are created with read only allocations, with the exception
1765 * of read only allocations of colors in the default map or otherwise
1766 * which fail to return the expected pixel value, and these are individually
1767 * defined as read/write allocations. This is done so that all the cells
1768 * defined in the default map are contiguous, for use in image processing.
1769 * This typically happens with White and Black in the default map.
1771 * Colormaps of static visuals are considered to be successfully created if
1772 * the map of the static visual matches the definition given in the
1773 * standard colormap structure.
1777 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1778 /* dpy - specifies the connection under which the map is created
1779 * colormap - specifies the map to be created, and returns, particularly
1780 * if the map is created as a subset of the default colormap
1781 * of the screen, the base_pixel of the map.
1784 XVisualInfo vinfo_template; /* template visual information */
1785 XVisualInfo *vinfo; /* matching visual information */
1786 XVisualInfo *vpointer; /* for freeing the entire list */
1787 long vinfo_mask; /* specifies the visual mask value */
1788 int n; /* number of matching visuals */
1791 vinfo_template.visualid = colormap->visualid;
1792 vinfo_mask = VisualIDMask;
1793 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1796 /* A visual id may be valid on multiple screens. Also, there may
1797 * be multiple visuals with identical visual ids at different depths.
1798 * If the colormap is the Default Colormap, use the Default Visual.
1799 * Otherwise, arbitrarily, use the deepest visual.
1805 register int screen_number;
1809 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1810 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1816 for (i=0; i < n; i++, vinfo++) {
1817 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1822 XVisualInfo *v = NULL;
1824 for (i=0; i < n; i++, vinfo++)
1825 if (vinfo->depth > maxdepth) {
1826 maxdepth = vinfo->depth;
1833 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1834 vinfo->c_class == GrayScale)
1835 status = readwrite_map(dpy, vinfo, colormap);
1836 else if (vinfo->c_class == TrueColor)
1837 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1838 TRUEMATCH(green_mult, green_max, green_mask) &&
1839 TRUEMATCH(blue_mult, blue_max, blue_mask);
1841 status = readonly_map(dpy, vinfo, colormap);
1843 XFree((char *) vpointer);
1847 /****************************************************************************/
1849 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1851 register unsigned long i, n; /* index counters */
1852 unsigned long ncolors; /* number of colors to be defined */
1853 int npixels; /* number of pixels allocated R/W */
1854 int first_index; /* first index of pixels to use */
1855 int remainder; /* first index of remainder */
1856 XColor color; /* the definition of a color */
1857 unsigned long *pixels; /* array of colormap pixels */
1858 unsigned long delta;
1861 /* Determine ncolors, the number of colors to be defined.
1862 * Insure that 1 < ncolors <= the colormap size.
1864 if (vinfo->c_class == DirectColor) {
1865 ncolors = colormap->red_max;
1866 if (colormap->green_max > ncolors)
1867 ncolors = colormap->green_max;
1868 if (colormap->blue_max > ncolors)
1869 ncolors = colormap->blue_max;
1871 delta = lowbit(vinfo->red_mask) +
1872 lowbit(vinfo->green_mask) +
1873 lowbit(vinfo->blue_mask);
1875 ncolors = colormap->red_max * colormap->red_mult +
1876 colormap->green_max * colormap->green_mult +
1877 colormap->blue_max * colormap->blue_mult + 1;
1880 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1882 /* Allocate Read/Write as much of the colormap as we can possibly get.
1883 * Then insure that the pixels we were allocated are given in
1884 * monotonically increasing order, using a quicksort. Next, insure
1885 * that our allocation includes a subset of contiguous pixels at least
1886 * as long as the number of colors to be defined. Now we know that
1887 * these conditions are met:
1888 * 1) There are no free cells in the colormap.
1889 * 2) We have a contiguous sequence of pixels, monotonically
1890 * increasing, of length >= the number of colors requested.
1892 * One cell at a time, we will free, compute the next color value,
1893 * then allocate read only. This takes a long time.
1894 * This is done to insure that cells are allocated read only in the
1895 * contiguous order which we prefer. If the server has a choice of
1896 * cells to grant to an allocation request, the server may give us any
1897 * cell, so that is why we do these slow gymnastics.
1900 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1901 sizeof(unsigned long))) == NULL)
1904 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1905 vinfo->colormap_size, ncolors)) == 0) {
1906 free((char *) pixels);
1910 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1912 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1914 /* can't find enough contiguous cells, give up */
1915 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1917 free((char *) pixels);
1920 colormap->base_pixel = pixels[first_index];
1922 /* construct a gray map */
1923 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1924 colormap->blue_mult == 1)
1925 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1928 color.blue = color.green = color.red =
1929 (unsigned short) ((i * 65535) / (colormap->red_max +
1930 colormap->green_max +
1931 colormap->blue_max));
1933 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1938 /* construct a red ramp map */
1939 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1940 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1943 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1944 color.green = color.blue = 0;
1946 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1951 /* construct a green ramp map */
1952 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1953 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1956 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1957 color.red = color.blue = 0;
1959 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1964 /* construct a blue ramp map */
1965 else if (colormap->red_max == 0 && colormap->green_max == 0)
1966 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1969 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1970 color.red = color.green = 0;
1972 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1977 /* construct a standard red green blue cube map */
1980 #define calc(max,mult) (((n / colormap->mult) % \
1981 (colormap->max + 1)) * 65535) / colormap->max
1983 for (n=0, i=0; i < ncolors; i++, n += delta)
1985 color.pixel = n + colormap->base_pixel;
1986 color.red = calc(red_max, red_mult);
1987 color.green = calc(green_max, green_mult);
1988 color.blue = calc(blue_max, blue_mult);
1989 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1995 /* We have a read-only map defined. Now free unused cells,
1996 * first those occuring before the contiguous sequence begins,
1997 * then any following the contiguous sequence.
2001 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2004 XFreeColors(dpy, colormap->colormap,
2005 &(pixels[first_index + ncolors]), remainder,
2008 free((char *) pixels);
2013 /****************************************************************************/
2015 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2017 * dpy - the X server connection
2018 * cmap - specifies colormap ID
2019 * pixels - returns pixel allocations
2020 * m - specifies colormap size
2021 * n - specifies number of colors
2026 /* first try to allocate the entire colormap */
2027 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2028 (unsigned) 0, pixels, (unsigned) m))
2031 /* Allocate all available cells in the colormap, using a binary
2032 * algorithm to discover how many cells we can allocate in the colormap.
2036 p = n + ((m - n + 1) / 2);
2037 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2038 (unsigned) 0, pixels, (unsigned) p)) {
2042 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2053 /****************************************************************************/
2055 contiguous(unsigned long pixels[], int npixels, int ncolors,
2056 unsigned long delta, int *first, int *rem)
2057 /* pixels - specifies allocated pixels
2058 * npixels - specifies count of alloc'd pixels
2059 * ncolors - specifies needed sequence length
2060 * delta - between pixels
2061 * first - returns first index of sequence
2062 * rem - returns first index after sequence, or 0, if none follow
2065 register int i = 1; /* walking index into the pixel array */
2066 register int count = 1; /* length of sequence discovered so far */
2069 if (npixels == ncolors) {
2074 while (count < ncolors && ncolors - count <= *rem)
2076 if (pixels[i-1] + delta == pixels[i])
2085 if (count != ncolors)
2091 /****************************************************************************/
2093 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2094 int npixels, XColor *color, unsigned long p)
2096 unsigned long pixel;
2099 /* Free the read/write allocation of one cell in the colormap.
2100 * Request a read only allocation of one cell in the colormap.
2101 * If the read only allocation cannot be granted, give up, because
2102 * there must be no free cells in the colormap.
2103 * If the read only allocation is granted, but gives us a cell which
2104 * is not the one that we just freed, it is probably the case that
2105 * we are trying allocate White or Black or some other color which
2106 * already has a read-only allocation in the map. So we try to
2107 * allocate the previously freed cell with a read/write allocation,
2108 * because we want contiguous cells for image processing algorithms.
2111 pixel = color->pixel;
2112 request.red = color->red;
2113 request.green = color->green;
2114 request.blue = color->blue;
2116 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2117 if (! XAllocColor(dpy, cmap, color)
2118 || (color->pixel != pixel &&
2119 (!RWcell(dpy, cmap, color, &request, &pixel))))
2121 free_cells(dpy, cmap, pixels, npixels, (int)p);
2128 /****************************************************************************/
2130 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2133 * pixels - to be freed
2134 * npixels - original number allocated
2137 /* One of the npixels allocated has already been freed.
2138 * p is the index of the freed pixel.
2139 * First free the pixels preceeding p, and there are p of them;
2140 * then free the pixels following p, there are npixels - p - 1 of them.
2142 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2143 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2144 free((char *) pixels);
2148 /****************************************************************************/
2150 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2151 unsigned long *pixel)
2153 unsigned long n = *pixel;
2155 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2156 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2157 (unsigned) 0, pixel, (unsigned) 1))
2161 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2164 color->pixel = *pixel;
2165 color->flags = DoRed | DoGreen | DoBlue;
2166 color->red = request->red;
2167 color->green = request->green;
2168 color->blue = request->blue;
2169 XStoreColors(dpy, cmap, color, 1);
2174 /****************************************************************************/
2176 compare(_Xconst void *e1, _Xconst void *e2)
2178 return ((int)(*(long *)e1 - *(long *)e2));
2182 /****************************************************************************/
2184 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2189 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2190 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2192 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2194 color.pixel = (unsigned long) i;
2195 color.red = (unsigned short)
2196 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2198 if (vinfo->c_class == StaticColor) {
2199 color.green = (unsigned short)
2200 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2201 65535) / colormap->green_max);
2202 color.blue = (unsigned short)
2203 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2205 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2206 color.green = color.blue = color.red;
2208 XAllocColor(dpy, colormap->colormap, &color);
2209 if (color.pixel != (unsigned long) i)
2216 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2220 Copyright 1989, 1998 The Open Group
2222 Permission to use, copy, modify, distribute, and sell this software and its
2223 documentation for any purpose is hereby granted without fee, provided that
2224 the above copyright notice appear in all copies and that both that
2225 copyright notice and this permission notice appear in supporting
2228 The above copyright notice and this permission notice shall be included in
2229 all copies or substantial portions of the Software.
2231 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2232 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2233 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2234 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2235 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2236 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2238 Except as contained in this notice, the name of The Open Group shall not be
2239 used in advertising or otherwise to promote the sale, use or other dealings
2240 in this Software without prior written authorization from The Open Group.
2243 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2246 * Author: Donna Converse, MIT X Consortium
2249 #include <X11/Xlib.h>
2250 #include <X11/Xutil.h>
2251 #include <X11/Xmu/StdCmap.h>
2253 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2255 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2256 * XmuDeleteStandardColormap() will remove the specified property from the
2257 * specified screen, releasing any resources used by the colormap(s) of the
2258 * property if possible.
2262 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2263 /* dpy; - specifies the X server to connect to
2264 * screen - specifies the screen of the display
2265 * property - specifies the standard colormap property
2268 XStandardColormap *stdcmaps, *s;
2271 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2274 for (s=stdcmaps; count > 0; count--, s++) {
2275 if ((s->killid == ReleaseByFreeingColormap) &&
2276 (s->colormap != None) &&
2277 (s->colormap != DefaultColormap(dpy, screen))) {
2279 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2280 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2282 XFreeColormap(dpy, s->colormap);
2284 XSetErrorHandler(oldHandler);
2287 } else if (s->killid != None) {
2288 XKillClient(dpy, s->killid);
2291 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2292 XFree((char *) stdcmaps);