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>
17 #include <sys/types.h>
21 #include <java/lang/String.h>
22 #include <org/xwt/Surface.h>
23 #include <org/xwt/Picture.h>
24 #include <org/xwt/Box.h>
25 #include <org/xwt/plat/X11.h>
26 #include <org/xwt/plat/X11$X11Surface.h>
27 #include <org/xwt/plat/X11$X11Picture.h>
28 #include <org/xwt/plat/X11$X11DoubleBuffer.h>
29 #include <org/xwt/util/Semaphore.h>
30 #include <org/xwt/Platform.h>
31 #include <java/lang/Long.h>
32 #include <java/util/Hashtable.h>
33 #include <org/xwt/util/Log.h>
35 #include <java/lang/System.h>
36 #include <java/io/PrintStream.h>
40 // static (per-xserver) data
41 static Visual* visual;
42 static Colormap s_colormap;
43 static XStandardColormap* colormap_info;
44 static XShmSegmentInfo shm_info;
45 static Window selectionWindow;
46 static int shm_supported;
47 static int shm_pixmaps_supported;
48 static int screen_num;
49 static int colorDepth = 0;
50 static Display* display;
51 static int shm_size = 0;
53 #define min(a, b) ((a) < (b) ? (a) : (b))
54 #define max(a, b) ((a) < (b) ? (b) : (a))
56 // X11DoubleBuffer //////////////////////////////////////////////////////////////////////
58 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
59 static void ensureShmSize(int size) {
60 if (size > shm_size) {
62 XShmDetach(display, &shm_info);
63 shmdt(shm_info.shmaddr);
64 shmctl(shm_info.shmid, IPC_RMID, 0);
66 shm_size = 3 * size / 2;
67 shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
68 shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
69 shm_info.readOnly = False;
70 XSync(display, False);
71 shmctl(shm_info.shmid, IPC_RMID, 0);
72 XShmAttach(display, &shm_info);
73 XSync(display, False);
77 void org::xwt::plat::X11$X11DoubleBuffer::fastDrawPicture(org::xwt::Picture* s,
78 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
79 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
81 // it's safe to clip manually since we no that no scaling will be done
82 if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
83 if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
84 if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
85 if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
86 if (dx1 > clipx + clipw) return;
87 if (dy1 > clipy + cliph) return;
88 if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
90 if (source->doublebuf->stipple != NULL) {
91 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
92 XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
94 XSetClipMask(display, (*((GC*)clipped_gc)), None);
96 XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
99 void org::xwt::plat::X11$X11DoubleBuffer::slowDrawPicture(org::xwt::Picture* s,
100 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
102 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
105 // FASTEST: shared pixmap; twiddle bits in video ram directly
107 XSync(display, False); // ensure that all pending operations have rendered
108 xi = (XImage*)fake_ximage;
110 // MEDIUM: write to a shared ximage, then ask the server to do the blit
111 } else if (shm_supported) {
112 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1);
113 ensureShmSize(xi->bytes_per_line * xi->height);
114 xi->data = shm_info.shmaddr;
115 XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes);
117 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
119 xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
122 int* sourcedata = (int*)elements(source->data);
123 for(int y=max(dy1, clipy); y<min(dy2, clipy + cliph); y++) {
125 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
126 (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line);
128 for(int x=max(dx1, clipx); x<min(dx2, clipx + clipw); x++, current_pixel += xi->bits_per_pixel / 8) {
129 int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
130 int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
132 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
133 int alpha = (sourcepixel & 0xFF000000) >> 24;
134 int source_red = (sourcepixel & 0x00FF0000) >> 16;
135 int source_green = (sourcepixel & 0x0000FF00) >> 8;
136 int source_blue = (sourcepixel & 0x000000FF);
137 int red = 0, blue = 0, green = 0;
139 if (alpha == 0x00) continue;
142 switch (xi->bits_per_pixel) {
143 case 8: targetpixel = (int)(*current_pixel); break;
144 case 16: targetpixel = (int)(*((u_int16_t*)current_pixel)); break;
145 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
146 case 32: targetpixel = *((int*)current_pixel); break;
147 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
150 targetpixel -= colormap_info->base_pixel;
152 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
153 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
154 red = targetpixel / colormap_info->red_mult;
155 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
156 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
158 blue = targetpixel / colormap_info->blue_mult;
159 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
160 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
164 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
165 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
166 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
167 u_int32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
168 blue * colormap_info->blue_mult + colormap_info->base_pixel;
170 switch (xi->bits_per_pixel) {
171 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
172 case 16: *((u_int16_t*)current_pixel) = (u_int16_t)destpixel; break;
174 int offset = (int)current_pixel & 0x3;
175 u_int64_t dest = ((u_int64_t)destpixel) << (8 * offset);
176 u_int64_t mask = ((u_int64_t)0xffffff) << (8 * offset);
177 u_int64_t* base = (u_int64_t*)(current_pixel - offset);
178 *base = (*base & ~mask) | dest;
181 case 32: *((u_int32_t*)current_pixel) = destpixel; break;
182 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
188 // do nothing, we wrote directly to video memory
190 } else if (shm_supported) {
191 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
195 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
200 void org::xwt::plat::X11$X11DoubleBuffer::finalize() {
202 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
203 XShmDetach(display, sinfo);
204 shmdt(sinfo->shmaddr);
205 shmctl(sinfo->shmid, IPC_RMID, 0);
206 XDestroyImage((XImage*)fake_ximage);
210 XFreePixmap(display, *((Pixmap*)stipple));
213 XFreePixmap(display, *((Pixmap*)pm));
214 XFreeGC(display, *((GC*)gc));
215 XFreeGC(display, *((GC*)clipped_gc));
218 void org::xwt::plat::X11$X11DoubleBuffer::natInit() {
220 if (width == 0 || height == 0) return;
221 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
222 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
225 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
227 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
228 shm_segment = (gnu::gcj::RawData*)sinfo;
229 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
230 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
231 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
232 sinfo->readOnly = False;
233 XShmAttach(display, sinfo);
234 XSync(display, False);
235 shmctl(sinfo->shmid, IPC_RMID, 0);
236 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
237 XSync(display, False);
240 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
241 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
242 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
243 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
246 vm.graphics_exposures = 0;
247 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
248 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
251 void org::xwt::plat::X11$X11DoubleBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
253 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
254 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
257 xi.data = (char*)malloc((width + 1) * height);
264 xi.byte_order = LSBFirst;
266 xi.bytes_per_line = (width / 8) + 1;
267 xi.bits_per_pixel = 1;
269 jint* d = (jint*)elements(xpi->data);
270 memset(xi.data, 0xFF, (width + 1) * height);
271 for(int x=0; x<width; x++)
272 for (int y=0; y<height; y++)
273 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
275 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
278 vm.graphics_exposures = 0;
279 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
281 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
284 void org::xwt::plat::X11$X11Surface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
285 org::xwt::plat::X11$X11DoubleBuffer *xdb = (org::xwt::plat::X11$X11DoubleBuffer*)db;
286 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
290 void org::xwt::plat::X11$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
295 if (x < clipx) { w -= (clipx - x); x = clipx; }
296 if (y < clipy) { h -= (clipy - y); y = clipy; }
297 if (x + w > clipx + clipw) w = (clipx + clipw - x);
298 if (y + h > clipy + cliph) h = (cliph + clipy - y);
300 XSetForeground(display, (*((GC*)gc)),
301 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
302 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
303 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
304 colormap_info->base_pixel
307 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
310 void org::xwt::plat::X11$X11DoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
313 rect.x = clipx, rect.y = clipy; rect.width = clipw; rect.height = cliph;
314 XSetClipMask(display, (*((GC*)clipped_gc)), None);
315 XSetClipRectangles(display, (*((GC*)clipped_gc)), 0, 0, &rect, 1, YSorted);
316 XSetForeground(display, (*((GC*)clipped_gc)),
317 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
318 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
319 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
320 colormap_info->base_pixel
324 int len = min(1024, JvGetStringUTFLength(text));
326 JvGetStringUTFRegion(text, 0, len, buf);
329 // Build the XTextItem structure
331 textitem.chars = buf;
332 textitem.nchars = len;
334 textitem.font = ((XFontStruct*)org::xwt::plat::X11::fontToXFont(font))->fid;
337 XDrawText(display, (*((Pixmap*)pm)), (*((GC*)clipped_gc)), x, y, &textitem, 1);
341 // X11Surface //////////////////////////////////////////////////////////////////////
343 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
344 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
345 org::xwt::plat::X11$X11DoubleBuffer* old_dbuf = p->doublebuf;
346 p->buildDoubleBuffer(1);
348 memset(&xwmh, 0, sizeof(XWMHints));
349 xwmh.flags |= IconPixmapHint | IconMaskHint;
350 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
351 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
352 XSetWMHints(display, (*((Window*)window)), &xwmh);
353 p->doublebuf = old_dbuf;
356 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
357 int len = min(JvGetStringUTFLength(s), 1024);
359 JvGetStringUTFRegion(s, 0, len, buf);
363 tp.value = (unsigned char*)buf;
365 tp.encoding = XA_STRING;
367 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
368 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
371 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
373 hints.min_width = minw;
374 hints.min_height = minh;
375 hints.max_width = maxw;
376 hints.max_height = maxh;
377 hints.flags = PMinSize | PMaxSize;
378 XSetWMNormalHints(display, (*((Window*)window)), &hints);
381 void org::xwt::plat::X11$X11Surface::setSize (jint width, jint height) {
382 if (width <= 0 || height <= 0) return;
383 XResizeWindow(display, (*((Window*)window)), width, height);
387 void org::xwt::plat::X11$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
388 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
389 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
391 void org::xwt::plat::X11$X11Surface::_dispose() {
392 // without this we get phantom messages after the window is gone
393 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
394 XDestroyWindow(display, (*((Window*)window)));
397 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
398 if (i) XUnmapWindow(display, (*((Window*)window)));
399 else XMapRaised(display, (*((Window*)window)));
403 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
404 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
405 else XMapRaised(display, (*((Window*)window)));
409 void org::xwt::plat::X11$X11Surface::natInit() {
410 XSetWindowAttributes xswa;
411 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
412 xswa.bit_gravity = NorthWestGravity;
413 xswa.colormap = s_colormap;
414 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
415 KeyPressMask | KeyReleaseMask | ButtonPressMask |
416 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
417 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
418 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
419 colorDepth, InputOutput, CopyFromParent,
420 CWColormap | CWBitGravity | CWEventMask, &xswa);
423 // I don't know why this works....
424 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
425 XChangeProperty(display, (*((Window*)window)),
426 XInternAtom(display, "_MOTIF_WM_HINTS", False),
427 XInternAtom(display, "_MOTIF_WM_HINTS", False),
435 tp.value = (unsigned char*)"XWT";
437 tp.encoding = XA_STRING;
439 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
441 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
442 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
444 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
445 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
448 XMapRaised(display, (*((Window*)window)));
451 waitForCreation->block();
452 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
455 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
456 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
459 vm.graphics_exposures = 0;
460 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
464 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
466 XEvent* e = (XEvent*)ev;
467 if (e->type == Expose) {
468 XExposeEvent *expose = (XExposeEvent*)(e);
469 Dirty(expose->x, expose->y, expose->width, expose->height);
471 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
472 } else if (e->type == UnmapNotify) { Minimized(1);
473 } else if (e->type == FocusIn) { Focused(1);
474 } else if (e->type == FocusOut) { Focused(0);
475 } else if (e->type == ClientMessage) {
476 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
478 } else if (e->type == KeyPress || e->type == KeyRelease) {
479 XKeyEvent *xbe = (XKeyEvent*)(e);
481 // drop faked KeyRelease events generated by the X server's autorepeat
482 if (e->type == KeyRelease) {
484 XQueryKeymap(display, depressed);
485 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
491 unsigned int savestate = xbe->state;
492 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
493 XLookupString(xbe, s, 20, NULL, NULL);
494 xbe->state = savestate;
496 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
500 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
502 case XK_BackSpace: s = "back_space"; break;
503 case XK_Tab: s = "tab"; break;
504 case XK_Linefeed: s = "enter"; break;
505 case XK_Return: s = "enter"; break;
506 case XK_Scroll_Lock: s = "scroll_lock"; break;
507 case XK_Escape: s = "escape"; break;
508 case XK_Insert: s = "insert"; break;
509 case XK_Delete: s = "delete"; break;
510 case XK_Home: s = "home"; break;
511 case XK_Left: s = "left"; break;
512 case XK_Up: s = "up"; break;
513 case XK_Right: s = "right"; break;
514 case XK_Down: s = "down"; break;
515 case XK_Page_Up: s = "page_up"; break;
516 case XK_Page_Down: s = "page_down"; break;
517 case XK_End: s = "end"; break;
518 case XK_Num_Lock: s = "num_lock"; break;
519 case XK_KP_Tab: s = "tab"; break;
520 case XK_KP_Enter: s = "enter"; break;
521 case XK_KP_F1: s = "f1"; break;
522 case XK_KP_F2: s = "f2"; break;
523 case XK_KP_F3: s = "f3"; break;
524 case XK_KP_F4: s = "f4"; break;
525 case XK_KP_Home: s = "home"; break;
526 case XK_KP_Left: s = "left"; break;
527 case XK_KP_Up: s = "up"; break;
528 case XK_KP_Right: s = "right"; break;
529 case XK_KP_Down: s = "down"; break;
530 case XK_KP_Page_Up: s = "page_up"; break;
531 case XK_KP_Page_Down: s = "page_down"; break;
532 case XK_KP_End: s = "end"; break;
533 case XK_KP_Insert: s = "insert"; break;
534 case XK_KP_Delete: s = "delete"; break;
535 case XK_F1: s = "f1"; break;
536 case XK_F2: s = "f2"; break;
537 case XK_F3: s = "f3"; break;
538 case XK_F4: s = "f4"; break;
539 case XK_F5: s = "f5"; break;
540 case XK_F6: s = "f6"; break;
541 case XK_F7: s = "f7"; break;
542 case XK_F8: s = "f8"; break;
543 case XK_F9: s = "f9"; break;
544 case XK_F10: s = "f10"; break;
545 case XK_F11: s = "f11"; break;
546 case XK_F12: s = "f12"; break;
547 case XK_Shift_L: s = "shift"; break;
548 case XK_Shift_R: s = "shift"; break;
549 case XK_Control_L: s = "control"; break;
550 case XK_Control_R: s = "control"; break;
551 case XK_Meta_L: s = "alt"; break;
552 case XK_Meta_R: s = "alt"; break;
553 case XK_Alt_L: s = "alt"; break;
554 case XK_Alt_R: s = "alt"; break;
559 jstring s2 = JvNewStringLatin1(s);
560 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
561 if (e->type == KeyRelease) KeyReleased(s2);
563 } else if (e->type == ButtonPress) {
564 XButtonEvent* xbe = (XButtonEvent*)(e);
565 if (xbe->button == 2) xbe->button = 3;
566 else if (xbe->button == 3) xbe->button = 2;
569 } else if (e->type == ButtonRelease) {
570 XButtonEvent* xbe = (XButtonEvent*)(e);
571 if (xbe->button == 2) xbe->button = 3;
572 else if (xbe->button == 3) xbe->button = 2;
573 Release(xbe->button);
575 } else if (e->type == MotionNotify) {
576 XMotionEvent* xme = (XMotionEvent*)(e);
577 Move(xme->x, xme->y);
579 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
580 XCrossingEvent* xce = (XCrossingEvent*)(e);
581 Move(xce->x, xce->y);
583 } else if (e->type == ConfigureNotify) {
586 XConfigureEvent* xce = (XConfigureEvent*)(e);
587 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
588 if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
589 if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
594 static jstring crosshair, east, hand, move, north, northeast, northwest,
595 south, southeast, southwest, text, west, wait_string;
596 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
597 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
598 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
600 void org::xwt::plat::X11$X11Surface::syncCursor() {
603 if (cursor->equals(crosshair)) curs = crosshair_cursor;
604 else if (cursor->equals(east)) curs = east_cursor;
605 else if (cursor->equals(hand)) curs = hand_cursor;
606 else if (cursor->equals(move)) curs = move_cursor;
607 else if (cursor->equals(north)) curs = north_cursor;
608 else if (cursor->equals(northeast)) curs = northeast_cursor;
609 else if (cursor->equals(northwest)) curs = northwest_cursor;
610 else if (cursor->equals(south)) curs = south_cursor;
611 else if (cursor->equals(southeast)) curs = southeast_cursor;
612 else if (cursor->equals(southwest)) curs = southwest_cursor;
613 else if (cursor->equals(text)) curs = text_cursor;
614 else if (cursor->equals(west)) curs = west_cursor;
615 else if (cursor->equals(wait_string)) curs = wait_cursor;
616 else curs = default_cursor;
618 XDefineCursor(display, (*((Window*)window)), curs);
623 // X11 ///////////////////////////////////////////////////////////////////
625 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
626 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
628 static void dispatchSelectionEvent(XEvent* e) {
629 if (e->type == SelectionNotify) {
630 XSelectionEvent* xsn = (XSelectionEvent*)(e);
631 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
635 unsigned long numitems;
637 unsigned long bytes_after;
638 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
639 True, AnyPropertyType, &returntype, &returnformat,
640 &numitems, &bytes_after, &ret);
641 org::xwt::plat::X11::clipboard =
642 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
644 org::xwt::plat::X11::waiting_for_selection_event->release();
646 } else if (e->type == SelectionRequest) {
647 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
649 xsn.type = SelectionNotify;
650 xsn.serial = xsr->serial;
651 xsn.send_event = True;
652 xsn.display = display;
653 xsn.requestor = xsr->requestor;
654 xsn.selection = xsr->selection;
655 xsn.target = xsr->target;
656 xsn.property = xsr->property;
657 xsn.time = xsr->time;
659 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
661 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
664 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
665 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
669 void org::xwt::plat::X11::eventThread() {
672 XNextEvent(display, &e);
673 if (e.type == SelectionNotify || e.type == SelectionRequest) {
674 dispatchSelectionEvent(&e);
676 org::xwt::plat::X11$X11Surface* surface =
677 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
678 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
683 jstring org::xwt::plat::X11::_getClipBoard() {
684 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
686 org::xwt::plat::X11::waiting_for_selection_event->block();
690 void org::xwt::plat::X11::_setClipBoard(jstring s) {
692 int len = JvGetStringUTFLength(clipboard);
694 JvGetStringUTFRegion(clipboard, 0, len, buf);
696 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
699 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
700 int errorHandler(Display* d, XErrorEvent* e) {
701 // this error handler is only installed during the initial
702 // test to see if shm is present
706 void org::xwt::plat::X11::natInit() {
709 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
711 display = XOpenDisplay(NULL);
712 screen_num = XDefaultScreen(display);
713 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
714 shm_info.shmaddr = NULL;
716 shm_supported = (XShmQueryExtension(display) == True);
718 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
719 XShmSegmentInfo sinfo;
720 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
721 sinfo.readOnly = False;
722 // if the server is remote, this will trigger the error handler
723 XShmAttach(display, &sinfo);
724 XSync(display, False);
725 XSetErrorHandler(oldHandler);
729 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
731 crosshair = JvNewStringLatin1("crosshair");
732 east = JvNewStringLatin1("east");
733 hand = JvNewStringLatin1("hand");
734 move = JvNewStringLatin1("move");
735 north = JvNewStringLatin1("north");
736 northeast = JvNewStringLatin1("northeast");
737 northwest = JvNewStringLatin1("northwest");
738 south = JvNewStringLatin1("south");
739 southeast = JvNewStringLatin1("southeast");
740 southwest = JvNewStringLatin1("southwest");
741 text = JvNewStringLatin1("text");
742 west = JvNewStringLatin1("west");
743 wait_string = JvNewStringLatin1("wait");
744 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
745 east_cursor = XCreateFontCursor(display, XC_right_side);
746 hand_cursor = XCreateFontCursor(display, XC_hand2);
747 move_cursor = XCreateFontCursor(display, XC_fleur);
748 north_cursor = XCreateFontCursor(display, XC_top_side);
749 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
750 northwest_cursor = XCreateFontCursor(display, XC_left_side);
751 south_cursor = XCreateFontCursor(display, XC_bottom_side);
752 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
753 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
754 text_cursor = XCreateFontCursor(display, XC_xterm);
755 west_cursor = XCreateFontCursor(display, XC_right_side);
756 wait_cursor = XCreateFontCursor(display, XC_watch);
757 default_cursor = XCreateFontCursor(display, XC_left_ptr);
759 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
760 visual = DefaultVisual(display, screen_num);
762 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
763 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
764 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
765 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
766 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
767 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
768 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
770 // FIXME: don't know why (True, False) is the best solution...
771 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
772 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
774 XStandardColormap* best_map_info = NULL;
776 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
777 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
778 if (!best_map_info->colormap)
779 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
780 if (best_map_info->red_max == 0)
781 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
782 s_colormap = best_map_info->colormap;
783 colormap_info = best_map_info;
785 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
786 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
787 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
788 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
789 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
790 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
791 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
792 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
795 JArray<java::lang::String*>* org::xwt::plat::X11::listNativeFonts() {
797 char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
798 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
799 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
800 for(int i=0; i<numfonts; i++)
801 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
805 gnu::gcj::RawData* org::xwt::plat::X11::fontStringToStruct(jstring s) {
806 int len = min(1024, JvGetStringUTFLength(s));
808 JvGetStringUTFRegion(s, 0, len, buf);
810 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
813 jint org::xwt::plat::X11::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
814 jint org::xwt::plat::X11::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
815 jint org::xwt::plat::X11::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
816 if (text == NULL) return 0;
817 int len = JvGetStringUTFLength(text);
819 JvGetStringUTFRegion(text, 0, len, buf);
821 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
825 //////////////////////////////////////////////////////////////////////////////
826 //////////////////////////////////////////////////////////////////////////////
827 //////////////////////////////////////////////////////////////////////////////
828 //////////////////////////////////////////////////////////////////////////////
830 // Everything below this point was taken, cut-and-paste, from the //
831 // source for libXmu. It implements the official 'standard colormap //
832 // creation algorithm. I made some small changes to //
833 // XmuDeleteStandardColormap //
835 //////////////////////////////////////////////////////////////////////////////
836 //////////////////////////////////////////////////////////////////////////////
837 //////////////////////////////////////////////////////////////////////////////
838 //////////////////////////////////////////////////////////////////////////////
840 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
844 Copyright 1989, 1998 The Open Group
846 Permission to use, copy, modify, distribute, and sell this software and its
847 documentation for any purpose is hereby granted without fee, provided that
848 the above copyright notice appear in all copies and that both that
849 copyright notice and this permission notice appear in supporting
852 The above copyright notice and this permission notice shall be included in
853 all copies or substantial portions of the Software.
855 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
856 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
857 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
858 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
859 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
860 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
862 Except as contained in this notice, the name of The Open Group shall not be
863 used in advertising or otherwise to promote the sale, use or other dealings
864 in this Software without prior written authorization from The Open Group.
867 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
870 * Author: Donna Converse, MIT X Consortium
874 #include <X11/Xlib.h>
875 #include <X11/Xatom.h>
876 #include <X11/Xutil.h>
877 #include <X11/Xmu/StdCmap.h>
883 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
886 * To create a standard colormap if one does not currently exist, or
887 * replace the currently existing standard colormap, use
888 * XmuLookupStandardColormap().
890 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
891 * will determine the best allocation for the property under the specified
892 * visual, and determine the whether to create a new colormap or to use
893 * the default colormap of the screen. It will call XmuStandardColormap()
894 * to create the standard colormap.
896 * If replace is true, any previous definition of the property will be
897 * replaced. If retain is true, the property and the colormap will be
898 * made permanent for the duration of the server session. However,
899 * pre-existing property definitions which are not replaced cannot be made
900 * permanent by a call to XmuLookupStandardColormap(); a request to retain
901 * resources pertains to newly created resources.
903 * Returns 0 on failure, non-zero on success. A request to create a
904 * standard colormap upon a visual which cannot support such a map is
905 * considered a failure. An example of this would be requesting any
906 * standard colormap property on a monochrome visual, or, requesting an
907 * RGB_BEST_MAP on a display whose colormap size is 16.
911 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
912 unsigned int depth, Atom property,
913 Bool replace, Bool retain)
915 * dpy - specifies X server connection
916 * screen - specifies screen of display
917 * visualid - specifies the visual type
918 * depth - specifies the visual type
919 * property - a standard colormap property
920 * replace - specifies whether to replace
921 * retain - specifies whether to retain
924 Display *odpy; /* original display connection */
925 XStandardColormap *colormap;
926 XVisualInfo vinfo_template, *vinfo; /* visual */
928 unsigned long r_max, g_max, b_max; /* allocation */
930 Colormap cmap; /* colormap ID */
934 /* Match the requested visual */
936 vinfo_template.visualid = visualid;
937 vinfo_template.screen = screen;
938 vinfo_template.depth = depth;
939 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
940 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
944 /* Monochrome visuals have no standard maps */
946 if (vinfo->colormap_size <= 2) {
947 XFree((char *) vinfo);
951 /* If the requested property already exists on this screen, and,
952 * if the replace flag has not been set to true, return success.
953 * lookup() will remove a pre-existing map if replace is true.
956 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
957 replace) && !replace) {
958 XFree((char *) vinfo);
962 /* Determine the best allocation for this property under the requested
963 * visualid and depth, and determine whether or not to use the default
964 * colormap of the screen.
967 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
968 XFree((char *) vinfo);
972 cmap = (property == XA_RGB_DEFAULT_MAP &&
973 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
974 ? DefaultColormap(dpy, screen) : None;
976 /* If retaining resources, open a new connection to the same server */
980 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
981 XFree((char *) vinfo);
986 /* Create the standard colormap */
988 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
989 cmap, r_max, g_max, b_max);
991 /* Set the standard colormap property */
996 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
998 /* Someone has defined the property since we last looked.
999 * Since we will not replace it, release our own resources.
1000 * If this is the default map, our allocations will be freed
1001 * when this connection closes.
1003 if (colormap->killid == ReleaseByFreeingColormap)
1004 XFreeColormap(dpy, colormap->colormap);
1005 } else if (retain) {
1006 XSetCloseDownMode(dpy, RetainPermanent);
1009 XFree((char *) colormap);
1015 XFree((char *) vinfo);
1019 /***************************************************************************/
1021 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1022 * the visualid is used to determine whether the indicated standard colormap
1023 * exists. If the map exists and replace is true, delete the resources used
1024 * by the map and remove the property. Return true if the map exists,
1025 * or did exist and was deleted; return false if the map was not found.
1027 * Note that this is not the way that a Status return is normally used.
1029 * If new is not NULL, new points to an XStandardColormap structure which
1030 * describes a standard colormap of the specified property. It will be made
1031 * a standard colormap of the screen if none already exists, or if replace
1036 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1037 XStandardColormap *cnew, Bool replace)
1039 * dpy - specifies display connection
1040 * screen - specifies screen number
1041 * visualid - specifies visualid for std map
1042 * property - specifies colormap property name
1043 * cnew - specifies a standard colormap
1044 * replace - specifies whether to replace
1049 XStandardColormap *stdcmaps, *s;
1050 Window win = RootWindow(dpy, screen);
1052 /* The property does not already exist */
1054 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1056 XSetRGBColormaps(dpy, win, cnew, 1, property);
1060 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1062 if (property != XA_RGB_DEFAULT_MAP) {
1064 XmuDeleteStandardColormap(dpy, screen, property);
1066 XSetRGBColormaps(dpy, win, cnew, 1, property);
1068 XFree((char *)stdcmaps);
1072 /* The property exists and is RGB_DEFAULT_MAP */
1074 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1077 /* No RGB_DEFAULT_MAP property matches the given visualid */
1081 XStandardColormap *m, *maps;
1083 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1084 (XStandardColormap)));
1086 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1087 m->colormap = maps->colormap;
1088 m->red_max = maps->red_max;
1089 m->red_mult = maps->red_mult;
1090 m->green_max = maps->green_max;
1091 m->green_mult = maps->green_mult;
1092 m->blue_max = maps->blue_max;
1093 m->blue_mult = maps->blue_mult;
1094 m->base_pixel = maps->base_pixel;
1095 m->visualid = maps->visualid;
1096 m->killid = maps->killid;
1098 m->colormap = cnew->colormap;
1099 m->red_max = cnew->red_max;
1100 m->red_mult = cnew->red_mult;
1101 m->green_max = cnew->green_max;
1102 m->green_mult = cnew->green_mult;
1103 m->blue_max = cnew->blue_max;
1104 m->blue_mult = cnew->blue_mult;
1105 m->base_pixel = cnew->base_pixel;
1106 m->visualid = cnew->visualid;
1107 m->killid = cnew->killid;
1109 XSetRGBColormaps(dpy, win, s, ++count, property);
1112 XFree((char *) stdcmaps);
1116 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1119 /* Free old resources first - we may need them, particularly in
1120 * the default colormap of the screen. However, because of this,
1121 * it is possible that we will destroy the old resource and fail
1122 * to create a new one if XmuStandardColormap() fails.
1126 XmuDeleteStandardColormap(dpy, screen, property);
1128 XSetRGBColormaps(dpy, win, cnew, 1, property);
1131 XStandardColormap *map;
1133 /* s still points to the matching standard colormap */
1135 if (s->killid == ReleaseByFreeingColormap) {
1136 if ((s->colormap != None) &&
1137 (s->colormap != DefaultColormap(dpy, screen)))
1138 XFreeColormap(dpy, s->colormap);
1140 else if (s->killid != None)
1141 XKillClient(dpy, s->killid);
1143 map = (cnew) ? cnew : stdcmaps + --count;
1145 s->colormap = map->colormap;
1146 s->red_max = map->red_max;
1147 s->red_mult = map->red_mult;
1148 s->green_max = map->green_max;
1149 s->green_mult = map->green_mult;
1150 s->blue_max = map->blue_max;
1151 s->blue_mult = map->blue_mult;
1152 s->visualid = map->visualid;
1153 s->killid = map->killid;
1155 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1158 XFree((char *) stdcmaps);
1162 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1166 Copyright 1989, 1994, 1998 The Open Group
1168 Permission to use, copy, modify, distribute, and sell this software and its
1169 documentation for any purpose is hereby granted without fee, provided that
1170 the above copyright notice appear in all copies and that both that
1171 copyright notice and this permission notice appear in supporting
1174 The above copyright notice and this permission notice shall be included in
1175 all copies or substantial portions of the Software.
1177 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1178 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1179 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1180 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1181 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1182 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1184 Except as contained in this notice, the name of The Open Group shall not be
1185 used in advertising or otherwise to promote the sale, use or other dealings
1186 in this Software without prior written authorization from The Open Group.
1189 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1192 * Author: Donna Converse, MIT X Consortium
1195 #include <X11/Xlib.h>
1196 #include <X11/Xatom.h>
1197 #include <X11/Xutil.h>
1198 #include <X11/Xmu/StdCmap.h>
1201 #define lowbit(x) ((x) & (~(x) + 1))
1206 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1208 static int default_allocation(XVisualInfo*, unsigned long*,
1209 unsigned long*, unsigned long*);
1210 static void gray_allocation(int, unsigned long*, unsigned long*,
1212 static int icbrt(int);
1213 static int icbrt_with_bits(int, int);
1214 static int icbrt_with_guess(int, int);
1216 /* To determine the best allocation of reds, greens, and blues in a
1217 * standard colormap, use XmuGetColormapAllocation.
1218 * vinfo specifies visual information for a chosen visual
1219 * property specifies one of the standard colormap property names
1220 * red_max returns maximum red value
1221 * green_max returns maximum green value
1222 * blue_max returns maximum blue value
1224 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1225 * It is assumed that the visual is appropriate for the colormap property.
1229 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1230 unsigned long *red_max,
1231 unsigned long *green_max,
1232 unsigned long *blue_max)
1236 if (vinfo->colormap_size <= 2)
1241 case XA_RGB_DEFAULT_MAP:
1242 status = default_allocation(vinfo, red_max, green_max, blue_max);
1244 case XA_RGB_BEST_MAP:
1245 best_allocation(vinfo, red_max, green_max, blue_max);
1247 case XA_RGB_GRAY_MAP:
1248 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1250 case XA_RGB_RED_MAP:
1251 *red_max = vinfo->colormap_size - 1;
1252 *green_max = *blue_max = 0;
1254 case XA_RGB_GREEN_MAP:
1255 *green_max = vinfo->colormap_size - 1;
1256 *red_max = *blue_max = 0;
1258 case XA_RGB_BLUE_MAP:
1259 *blue_max = vinfo->colormap_size - 1;
1260 *red_max = *green_max = 0;
1268 /****************************************************************************/
1269 /* Determine the appropriate color allocations of a gray scale.
1271 * Keith Packard, MIT X Consortium
1275 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1276 unsigned long *blue_max)
1278 *red_max = (n * 30) / 100;
1279 *green_max = (n * 59) / 100;
1280 *blue_max = (n * 11) / 100;
1281 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1284 /****************************************************************************/
1285 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1286 * If a map has less than a minimum number of definable entries, we do not
1287 * produce an allocation for an RGB_DEFAULT_MAP.
1289 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1290 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1291 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1292 * Maximum green and maximum blue values are identical to maximum red.
1293 * This leaves at least 125 cells which clients can allocate.
1295 * Return 0 if an allocation has been determined, non-zero otherwise.
1299 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1300 unsigned long *green, unsigned long *blue)
1302 int ngrays; /* number of gray cells */
1304 switch (vinfo->c_class)
1308 if (vinfo->colormap_size > 65000)
1309 /* intended for displays with 16 planes */
1310 *red = *green = *blue = (unsigned long) 27;
1311 else if (vinfo->colormap_size > 4000)
1312 /* intended for displays with 12 planes */
1313 *red = *green = *blue = (unsigned long) 12;
1314 else if (vinfo->colormap_size < 250)
1317 /* intended for displays with 8 planes */
1318 *red = *green = *blue = (unsigned long)
1319 (icbrt(vinfo->colormap_size - 125) - 1);
1324 if (vinfo->colormap_size < 10)
1326 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1331 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1332 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1333 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1338 if (vinfo->colormap_size > 65000)
1340 else if (vinfo->colormap_size > 4000)
1342 else if (vinfo->colormap_size < 250)
1346 gray_allocation(ngrays, red, green, blue);
1355 /****************************************************************************/
1356 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1358 * For a DirectColor or TrueColor visual, the allocation is determined
1359 * by the red_mask, green_mask, and blue_mask members of the visual info.
1361 * Otherwise, if the colormap size is an integral power of 2, determine
1362 * the allocation according to the number of bits given to each color,
1363 * with green getting more than red, and red more than blue, if there
1364 * are to be inequities in the distribution. If the colormap size is
1365 * not an integral power of 2, let n = the number of colormap entries.
1366 * Then maximum red value = floor(cube_root(n)) - 1;
1367 * maximum blue value = floor(cube_root(n)) - 1;
1368 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1369 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1370 * defineable colormap entries.
1374 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1375 unsigned long *blue)
1378 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1380 *red = vinfo->red_mask;
1381 while ((*red & 01) == 0)
1383 *green = vinfo->green_mask;
1384 while ((*green & 01) == 0)
1386 *blue = vinfo->blue_mask;
1387 while ((*blue & 01) == 0)
1392 register int bits, n;
1394 /* Determine n such that n is the least integral power of 2 which is
1395 * greater than or equal to the number of entries in the colormap.
1399 while (vinfo->colormap_size > n)
1405 /* If the number of entries in the colormap is a power of 2, determine
1406 * the allocation by "dealing" the bits, first to green, then red, then
1407 * blue. If not, find the maximum integral red, green, and blue values
1408 * which, when multiplied together, do not exceed the number of
1412 if (n == vinfo->colormap_size)
1414 register int r, g, b;
1416 g = b + ((bits % 3) ? 1 : 0);
1417 r = b + (((bits % 3) == 2) ? 1 : 0);
1424 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1426 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1436 * integer cube roots by Newton's method
1438 * Stephen Gildea, MIT X Consortium, July 1991
1444 register int bits = 0;
1445 register unsigned n = a;
1452 return icbrt_with_bits(a, bits);
1457 icbrt_with_bits(int a, int bits)
1458 /* bits - log 2 of a */
1460 return icbrt_with_guess(a, a>>2*bits/3);
1463 #ifdef _X_ROOT_STATS
1464 int icbrt_loopcount;
1467 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1469 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1472 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1473 * Only works for positive integers (since that's all we need).
1474 * We actually return floor(cbrt(a)) because that's what we need here, too.
1478 icbrt_with_guess(int a, int guess)
1482 #ifdef _X_ROOT_STATS
1483 icbrt_loopcount = 0;
1491 #ifdef _X_ROOT_STATS
1494 delta = (guess - a/(guess*guess))/3;
1496 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1499 } while (delta != 0);
1501 if (guess*guess*guess > a)
1508 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1512 Copyright 1989, 1998 The Open Group
1514 Permission to use, copy, modify, distribute, and sell this software and its
1515 documentation for any purpose is hereby granted without fee, provided that
1516 the above copyright notice appear in all copies and that both that
1517 copyright notice and this permission notice appear in supporting
1520 The above copyright notice and this permission notice shall be included in
1521 all copies or substantial portions of the Software.
1523 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1524 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1525 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1526 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1527 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1528 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1530 Except as contained in this notice, the name of The Open Group shall not be
1531 used in advertising or otherwise to promote the sale, use or other dealings
1532 in this Software without prior written authorization from The Open Group.
1535 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1538 * Author: Donna Converse, MIT X Consortium
1542 #include <X11/Xlib.h>
1543 #include <X11/Xatom.h>
1544 #include <X11/Xutil.h>
1545 #include <X11/Xmu/StdCmap.h>
1547 #define lowbit(x) ((x) & (~(x) + 1))
1552 /* argument restrictions */
1553 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1554 unsigned long, Atom);
1557 * To create any one standard colormap, use XmuStandardColormap().
1559 * Create a standard colormap for the given screen, visualid, and visual
1560 * depth, with the given red, green, and blue maximum values, with the
1561 * given standard property name. Return a pointer to an XStandardColormap
1562 * structure which describes the newly created colormap, upon success.
1563 * Upon failure, return NULL.
1565 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1567 * Resources created by this function are not made permanent; that is the
1568 * caller's responsibility.
1572 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1573 unsigned int depth, Atom property, Colormap cmap,
1574 unsigned long red_max, unsigned long green_max,
1575 unsigned long blue_max)
1577 * dpy - specifies X server connection
1578 * screen - specifies display screen
1579 * visualid - identifies the visual type
1580 * depth - identifies the visual type
1581 * property - a standard colormap property
1582 * cmap - specifies colormap ID or None
1583 * red_max, green_max, blue_max - allocations
1586 XStandardColormap *stdcmap;
1588 XVisualInfo vinfo_template, *vinfo;
1592 /* Match the required visual information to an actual visual */
1593 vinfo_template.visualid = visualid;
1594 vinfo_template.screen = screen;
1595 vinfo_template.depth = depth;
1596 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1597 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1600 /* Check the validity of the combination of visual characteristics,
1601 * allocation, and colormap property. Create an XStandardColormap
1605 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1606 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1607 XFree((char *) vinfo);
1611 /* Fill in the XStandardColormap structure */
1613 if (cmap == DefaultColormap(dpy, screen)) {
1614 /* Allocating out of the default map, cannot use XFreeColormap() */
1615 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1616 0, 0, InputOnly, vinfo->visual,
1618 (XSetWindowAttributes *)NULL);
1619 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1620 XDestroyWindow(dpy, win);
1621 stdcmap->colormap = cmap;
1623 stdcmap->killid = ReleaseByFreeingColormap;
1624 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1625 vinfo->visual, AllocNone);
1627 stdcmap->red_max = red_max;
1628 stdcmap->green_max = green_max;
1629 stdcmap->blue_max = blue_max;
1630 if (property == XA_RGB_GRAY_MAP)
1631 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1632 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1633 stdcmap->red_mult = lowbit(vinfo->red_mask);
1634 stdcmap->green_mult = lowbit(vinfo->green_mask);
1635 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1637 stdcmap->red_mult = (red_max > 0)
1638 ? (green_max + 1) * (blue_max + 1) : 0;
1639 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1640 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1642 stdcmap->base_pixel = 0; /* base pixel may change */
1643 stdcmap->visualid = vinfo->visualid;
1645 /* Make the colormap */
1647 status = XmuCreateColormap(dpy, stdcmap);
1651 XFree((char *) vinfo);
1654 /* Free the colormap or the pixmap, if we created one */
1655 if (stdcmap->killid == ReleaseByFreeingColormap)
1656 XFreeColormap(dpy, stdcmap->colormap);
1657 else if (stdcmap->killid != None)
1658 XFreePixmap(dpy, stdcmap->killid);
1660 XFree((char *) stdcmap);
1661 return (XStandardColormap *) NULL;
1666 /****************************************************************************/
1668 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1669 unsigned long blue_max, Atom property)
1671 * vinfo - specifies visual
1672 * red_max, green_max, blue_max - specifies alloc
1673 * property - specifies property name
1676 unsigned long ncolors; /* number of colors requested */
1678 /* Determine that the number of colors requested is <= map size */
1680 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1683 mask = vinfo->red_mask;
1688 mask = vinfo->green_mask;
1691 if (green_max > mask)
1693 mask = vinfo->blue_mask;
1696 if (blue_max > mask)
1698 } else if (property == XA_RGB_GRAY_MAP) {
1699 ncolors = red_max + green_max + blue_max + 1;
1700 if (ncolors > vinfo->colormap_size)
1703 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1704 if (ncolors > vinfo->colormap_size)
1708 /* Determine that the allocation and visual make sense for the property */
1712 case XA_RGB_DEFAULT_MAP:
1713 if (red_max == 0 || green_max == 0 || blue_max == 0)
1716 case XA_RGB_RED_MAP:
1720 case XA_RGB_GREEN_MAP:
1724 case XA_RGB_BLUE_MAP:
1728 case XA_RGB_BEST_MAP:
1729 if (red_max == 0 || green_max == 0 || blue_max == 0)
1732 case XA_RGB_GRAY_MAP:
1733 if (red_max == 0 || blue_max == 0 || green_max == 0)
1743 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1747 Copyright 1989, 1998 The Open Group
1749 Permission to use, copy, modify, distribute, and sell this software and its
1750 documentation for any purpose is hereby granted without fee, provided that
1751 the above copyright notice appear in all copies and that both that
1752 copyright notice and this permission notice appear in supporting
1755 The above copyright notice and this permission notice shall be included in
1756 all copies or substantial portions of the Software.
1758 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1759 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1760 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1761 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1762 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1763 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1765 Except as contained in this notice, the name of The Open Group shall not be
1766 used in advertising or otherwise to promote the sale, use or other dealings
1767 in this Software without prior written authorization from The Open Group.
1770 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1773 * Author: Donna Converse, MIT X Consortium
1777 * CreateCmap.c - given a standard colormap description, make the map.
1782 #include <X11/Xlib.h>
1783 #include <X11/Xutil.h>
1784 #include <X11/Xmu/StdCmap.h>
1789 /* allocate entire map Read Only */
1790 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1792 /* allocate a cell, prefer Read Only */
1793 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1794 XColor*, unsigned long);
1796 /* allocate a cell Read Write */
1797 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1800 static int compare(_Xconst void*, _Xconst void*);
1802 /* find contiguous sequence of cells */
1803 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1805 /* frees resources before quitting */
1806 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1808 /* create a map in a RO visual type */
1809 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1811 /* create a map in a RW visual type */
1812 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1814 #define lowbit(x) ((x) & (~(x) + 1))
1815 #define TRUEMATCH(mult,max,mask) \
1816 (colormap->max * colormap->mult <= vinfo->mask && \
1817 lowbit(vinfo->mask) == colormap->mult)
1820 * To create any one colormap which is described by an XStandardColormap
1821 * structure, use XmuCreateColormap().
1823 * Return 0 on failure, non-zero on success.
1824 * Resources created by this function are not made permanent.
1825 * No argument error checking is provided. Use at your own risk.
1827 * All colormaps are created with read only allocations, with the exception
1828 * of read only allocations of colors in the default map or otherwise
1829 * which fail to return the expected pixel value, and these are individually
1830 * defined as read/write allocations. This is done so that all the cells
1831 * defined in the default map are contiguous, for use in image processing.
1832 * This typically happens with White and Black in the default map.
1834 * Colormaps of static visuals are considered to be successfully created if
1835 * the map of the static visual matches the definition given in the
1836 * standard colormap structure.
1840 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1841 /* dpy - specifies the connection under which the map is created
1842 * colormap - specifies the map to be created, and returns, particularly
1843 * if the map is created as a subset of the default colormap
1844 * of the screen, the base_pixel of the map.
1847 XVisualInfo vinfo_template; /* template visual information */
1848 XVisualInfo *vinfo; /* matching visual information */
1849 XVisualInfo *vpointer; /* for freeing the entire list */
1850 long vinfo_mask; /* specifies the visual mask value */
1851 int n; /* number of matching visuals */
1854 vinfo_template.visualid = colormap->visualid;
1855 vinfo_mask = VisualIDMask;
1856 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1859 /* A visual id may be valid on multiple screens. Also, there may
1860 * be multiple visuals with identical visual ids at different depths.
1861 * If the colormap is the Default Colormap, use the Default Visual.
1862 * Otherwise, arbitrarily, use the deepest visual.
1868 register int screen_number;
1872 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1873 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1879 for (i=0; i < n; i++, vinfo++) {
1880 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1885 XVisualInfo *v = NULL;
1887 for (i=0; i < n; i++, vinfo++)
1888 if (vinfo->depth > maxdepth) {
1889 maxdepth = vinfo->depth;
1896 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1897 vinfo->c_class == GrayScale)
1898 status = readwrite_map(dpy, vinfo, colormap);
1899 else if (vinfo->c_class == TrueColor)
1900 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1901 TRUEMATCH(green_mult, green_max, green_mask) &&
1902 TRUEMATCH(blue_mult, blue_max, blue_mask);
1904 status = readonly_map(dpy, vinfo, colormap);
1906 XFree((char *) vpointer);
1910 /****************************************************************************/
1912 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1914 register unsigned long i, n; /* index counters */
1915 unsigned long ncolors; /* number of colors to be defined */
1916 int npixels; /* number of pixels allocated R/W */
1917 int first_index; /* first index of pixels to use */
1918 int remainder; /* first index of remainder */
1919 XColor color; /* the definition of a color */
1920 unsigned long *pixels; /* array of colormap pixels */
1921 unsigned long delta;
1924 /* Determine ncolors, the number of colors to be defined.
1925 * Insure that 1 < ncolors <= the colormap size.
1927 if (vinfo->c_class == DirectColor) {
1928 ncolors = colormap->red_max;
1929 if (colormap->green_max > ncolors)
1930 ncolors = colormap->green_max;
1931 if (colormap->blue_max > ncolors)
1932 ncolors = colormap->blue_max;
1934 delta = lowbit(vinfo->red_mask) +
1935 lowbit(vinfo->green_mask) +
1936 lowbit(vinfo->blue_mask);
1938 ncolors = colormap->red_max * colormap->red_mult +
1939 colormap->green_max * colormap->green_mult +
1940 colormap->blue_max * colormap->blue_mult + 1;
1943 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1945 /* Allocate Read/Write as much of the colormap as we can possibly get.
1946 * Then insure that the pixels we were allocated are given in
1947 * monotonically increasing order, using a quicksort. Next, insure
1948 * that our allocation includes a subset of contiguous pixels at least
1949 * as long as the number of colors to be defined. Now we know that
1950 * these conditions are met:
1951 * 1) There are no free cells in the colormap.
1952 * 2) We have a contiguous sequence of pixels, monotonically
1953 * increasing, of length >= the number of colors requested.
1955 * One cell at a time, we will free, compute the next color value,
1956 * then allocate read only. This takes a long time.
1957 * This is done to insure that cells are allocated read only in the
1958 * contiguous order which we prefer. If the server has a choice of
1959 * cells to grant to an allocation request, the server may give us any
1960 * cell, so that is why we do these slow gymnastics.
1963 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1964 sizeof(unsigned long))) == NULL)
1967 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1968 vinfo->colormap_size, ncolors)) == 0) {
1969 free((char *) pixels);
1973 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1975 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1977 /* can't find enough contiguous cells, give up */
1978 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1980 free((char *) pixels);
1983 colormap->base_pixel = pixels[first_index];
1985 /* construct a gray map */
1986 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1987 colormap->blue_mult == 1)
1988 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1991 color.blue = color.green = color.red =
1992 (unsigned short) ((i * 65535) / (colormap->red_max +
1993 colormap->green_max +
1994 colormap->blue_max));
1996 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2001 /* construct a red ramp map */
2002 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2003 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2006 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2007 color.green = color.blue = 0;
2009 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2014 /* construct a green ramp map */
2015 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2016 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2019 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2020 color.red = color.blue = 0;
2022 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2027 /* construct a blue ramp map */
2028 else if (colormap->red_max == 0 && colormap->green_max == 0)
2029 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2032 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2033 color.red = color.green = 0;
2035 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2040 /* construct a standard red green blue cube map */
2043 #define calc(max,mult) (((n / colormap->mult) % \
2044 (colormap->max + 1)) * 65535) / colormap->max
2046 for (n=0, i=0; i < ncolors; i++, n += delta)
2048 color.pixel = n + colormap->base_pixel;
2049 color.red = calc(red_max, red_mult);
2050 color.green = calc(green_max, green_mult);
2051 color.blue = calc(blue_max, blue_mult);
2052 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2058 /* We have a read-only map defined. Now free unused cells,
2059 * first those occuring before the contiguous sequence begins,
2060 * then any following the contiguous sequence.
2064 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2067 XFreeColors(dpy, colormap->colormap,
2068 &(pixels[first_index + ncolors]), remainder,
2071 free((char *) pixels);
2076 /****************************************************************************/
2078 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2080 * dpy - the X server connection
2081 * cmap - specifies colormap ID
2082 * pixels - returns pixel allocations
2083 * m - specifies colormap size
2084 * n - specifies number of colors
2089 /* first try to allocate the entire colormap */
2090 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2091 (unsigned) 0, pixels, (unsigned) m))
2094 /* Allocate all available cells in the colormap, using a binary
2095 * algorithm to discover how many cells we can allocate in the colormap.
2099 p = n + ((m - n + 1) / 2);
2100 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2101 (unsigned) 0, pixels, (unsigned) p)) {
2105 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2116 /****************************************************************************/
2118 contiguous(unsigned long pixels[], int npixels, int ncolors,
2119 unsigned long delta, int *first, int *rem)
2120 /* pixels - specifies allocated pixels
2121 * npixels - specifies count of alloc'd pixels
2122 * ncolors - specifies needed sequence length
2123 * delta - between pixels
2124 * first - returns first index of sequence
2125 * rem - returns first index after sequence, or 0, if none follow
2128 register int i = 1; /* walking index into the pixel array */
2129 register int count = 1; /* length of sequence discovered so far */
2132 if (npixels == ncolors) {
2137 while (count < ncolors && ncolors - count <= *rem)
2139 if (pixels[i-1] + delta == pixels[i])
2148 if (count != ncolors)
2154 /****************************************************************************/
2156 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2157 int npixels, XColor *color, unsigned long p)
2159 unsigned long pixel;
2162 /* Free the read/write allocation of one cell in the colormap.
2163 * Request a read only allocation of one cell in the colormap.
2164 * If the read only allocation cannot be granted, give up, because
2165 * there must be no free cells in the colormap.
2166 * If the read only allocation is granted, but gives us a cell which
2167 * is not the one that we just freed, it is probably the case that
2168 * we are trying allocate White or Black or some other color which
2169 * already has a read-only allocation in the map. So we try to
2170 * allocate the previously freed cell with a read/write allocation,
2171 * because we want contiguous cells for image processing algorithms.
2174 pixel = color->pixel;
2175 request.red = color->red;
2176 request.green = color->green;
2177 request.blue = color->blue;
2179 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2180 if (! XAllocColor(dpy, cmap, color)
2181 || (color->pixel != pixel &&
2182 (!RWcell(dpy, cmap, color, &request, &pixel))))
2184 free_cells(dpy, cmap, pixels, npixels, (int)p);
2191 /****************************************************************************/
2193 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2196 * pixels - to be freed
2197 * npixels - original number allocated
2200 /* One of the npixels allocated has already been freed.
2201 * p is the index of the freed pixel.
2202 * First free the pixels preceeding p, and there are p of them;
2203 * then free the pixels following p, there are npixels - p - 1 of them.
2205 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2206 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2207 free((char *) pixels);
2211 /****************************************************************************/
2213 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2214 unsigned long *pixel)
2216 unsigned long n = *pixel;
2218 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2219 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2220 (unsigned) 0, pixel, (unsigned) 1))
2224 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2227 color->pixel = *pixel;
2228 color->flags = DoRed | DoGreen | DoBlue;
2229 color->red = request->red;
2230 color->green = request->green;
2231 color->blue = request->blue;
2232 XStoreColors(dpy, cmap, color, 1);
2237 /****************************************************************************/
2239 compare(_Xconst void *e1, _Xconst void *e2)
2241 return ((int)(*(long *)e1 - *(long *)e2));
2245 /****************************************************************************/
2247 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2252 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2253 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2255 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2257 color.pixel = (unsigned long) i;
2258 color.red = (unsigned short)
2259 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2261 if (vinfo->c_class == StaticColor) {
2262 color.green = (unsigned short)
2263 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2264 65535) / colormap->green_max);
2265 color.blue = (unsigned short)
2266 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2268 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2269 color.green = color.blue = color.red;
2271 XAllocColor(dpy, colormap->colormap, &color);
2272 if (color.pixel != (unsigned long) i)
2279 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2283 Copyright 1989, 1998 The Open Group
2285 Permission to use, copy, modify, distribute, and sell this software and its
2286 documentation for any purpose is hereby granted without fee, provided that
2287 the above copyright notice appear in all copies and that both that
2288 copyright notice and this permission notice appear in supporting
2291 The above copyright notice and this permission notice shall be included in
2292 all copies or substantial portions of the Software.
2294 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2295 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2296 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2297 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2298 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2299 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2301 Except as contained in this notice, the name of The Open Group shall not be
2302 used in advertising or otherwise to promote the sale, use or other dealings
2303 in this Software without prior written authorization from The Open Group.
2306 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2309 * Author: Donna Converse, MIT X Consortium
2312 #include <X11/Xlib.h>
2313 #include <X11/Xutil.h>
2314 #include <X11/Xmu/StdCmap.h>
2316 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2318 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2319 * XmuDeleteStandardColormap() will remove the specified property from the
2320 * specified screen, releasing any resources used by the colormap(s) of the
2321 * property if possible.
2325 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2326 /* dpy; - specifies the X server to connect to
2327 * screen - specifies the screen of the display
2328 * property - specifies the standard colormap property
2331 XStandardColormap *stdcmaps, *s;
2334 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2337 for (s=stdcmaps; count > 0; count--, s++) {
2338 if ((s->killid == ReleaseByFreeingColormap) &&
2339 (s->colormap != None) &&
2340 (s->colormap != DefaultColormap(dpy, screen))) {
2342 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2343 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2345 XFreeColormap(dpy, s->colormap);
2347 XSetErrorHandler(oldHandler);
2350 } else if (s->killid != None) {
2351 XKillClient(dpy, s->killid);
2354 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2355 XFree((char *) stdcmaps);