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>
38 // static (per-xserver) data
39 static Visual* visual;
40 static Colormap s_colormap;
41 static XStandardColormap* colormap_info;
42 static XShmSegmentInfo shm_info;
43 static Window selectionWindow;
44 static int shm_supported;
45 static int shm_pixmaps_supported;
46 static int screen_num;
47 static int colorDepth = 0;
48 static Display* display;
49 static int shm_size = 0;
51 #define min(a, b) ((a) < (b) ? (a) : (b))
52 #define max(a, b) ((a) < (b) ? (b) : (a))
54 // X11DoubleBuffer //////////////////////////////////////////////////////////////////////
56 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
57 static void ensureShmSize(int size) {
58 if (size > shm_size) {
60 XShmDetach(display, &shm_info);
61 shmdt(shm_info.shmaddr);
62 shmctl(shm_info.shmid, IPC_RMID, 0);
64 shm_size = 3 * size / 2;
65 shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
66 shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
67 shm_info.readOnly = False;
68 XSync(display, False);
69 shmctl(shm_info.shmid, IPC_RMID, 0);
70 XShmAttach(display, &shm_info);
71 XSync(display, False);
75 void org::xwt::plat::X11$X11DoubleBuffer::fastDrawPicture(org::xwt::Picture* s,
76 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
77 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
79 // it's safe to clip manually since we no that no scaling will be done
80 if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
81 if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
82 if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
83 if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
84 if (dx1 > clipx + clipw) return;
85 if (dy1 > clipy + cliph) return;
86 if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
88 if (source->doublebuf->stipple != NULL) {
89 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
90 XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
92 XSetClipMask(display, (*((GC*)clipped_gc)), None);
94 XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
97 void org::xwt::plat::X11$X11DoubleBuffer::slowDrawPicture(org::xwt::Picture* s,
98 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
100 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
103 // FASTEST: shared pixmap; twiddle bits in video ram directly
105 XSync(display, False); // ensure that all pending operations have rendered
106 xi = (XImage*)fake_ximage;
108 // MEDIUM: write to a shared ximage, then ask the server to do the blit
109 } else if (shm_supported) {
110 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1);
111 ensureShmSize(xi->bytes_per_line * xi->height);
112 xi->data = shm_info.shmaddr;
113 XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes);
115 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
117 xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
120 int* sourcedata = (int*)elements(source->data);
121 for(int y=max(dy1, clipy); y<min(dy2, clipy + cliph); y++) {
123 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
124 (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line);
126 for(int x=max(dx1, clipx); x<min(dx2, clipx + clipw); x++, current_pixel += xi->bits_per_pixel / 8) {
127 int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
128 int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
130 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
131 int alpha = (sourcepixel & 0xFF000000) >> 24;
132 int source_red = (sourcepixel & 0x00FF0000) >> 16;
133 int source_green = (sourcepixel & 0x0000FF00) >> 8;
134 int source_blue = (sourcepixel & 0x000000FF);
135 int red = 0, blue = 0, green = 0;
137 if (alpha == 0x00) continue;
140 switch (xi->bits_per_pixel) {
141 case 8: targetpixel = (int)(*current_pixel); break;
142 case 16: targetpixel = (int)(*((u_int16_t*)current_pixel)); break;
143 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
144 case 32: targetpixel = *((int*)current_pixel); break;
145 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
148 targetpixel -= colormap_info->base_pixel;
150 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
151 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
152 red = targetpixel / colormap_info->red_mult;
153 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
154 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
156 blue = targetpixel / colormap_info->blue_mult;
157 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
158 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
162 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
163 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
164 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
165 u_int32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
166 blue * colormap_info->blue_mult + colormap_info->base_pixel;
168 switch (xi->bits_per_pixel) {
169 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
170 case 16: *((u_int16_t*)current_pixel) = (u_int16_t)destpixel; break;
172 int offset = (int)current_pixel & 0x3;
173 u_int64_t dest = ((u_int64_t)destpixel) << (8 * offset);
174 u_int64_t mask = ((u_int64_t)0xffffff) << (8 * offset);
175 u_int64_t* base = (u_int64_t*)(current_pixel - offset);
176 *base = (*base & ~mask) | dest;
179 case 32: *((u_int32_t*)current_pixel) = destpixel; break;
180 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
186 // do nothing, we wrote directly to video memory
188 } else if (shm_supported) {
189 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
193 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
198 void org::xwt::plat::X11$X11DoubleBuffer::finalize() {
200 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
201 XShmDetach(display, sinfo);
202 shmdt(sinfo->shmaddr);
203 shmctl(sinfo->shmid, IPC_RMID, 0);
204 XDestroyImage((XImage*)fake_ximage);
208 XFreePixmap(display, *((Pixmap*)stipple));
211 XFreePixmap(display, *((Pixmap*)pm));
212 XFreeGC(display, *((GC*)gc));
213 XFreeGC(display, *((GC*)clipped_gc));
216 void org::xwt::plat::X11$X11DoubleBuffer::natInit() {
218 if (width == 0 || height == 0) return;
219 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
220 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
223 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
225 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
226 shm_segment = (gnu::gcj::RawData*)sinfo;
227 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
228 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
229 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
230 sinfo->readOnly = False;
231 XShmAttach(display, sinfo);
232 XSync(display, False);
233 shmctl(sinfo->shmid, IPC_RMID, 0);
234 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
235 XSync(display, False);
238 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
239 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
240 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
241 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
244 vm.graphics_exposures = 0;
245 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
246 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
249 void org::xwt::plat::X11$X11DoubleBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
251 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
252 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
255 xi.data = (char*)malloc((width + 1) * height);
262 xi.byte_order = LSBFirst;
264 xi.bytes_per_line = (width / 8) + 1;
265 xi.bits_per_pixel = 1;
267 jint* d = (jint*)elements(xpi->data);
268 memset(xi.data, 0xFF, (width + 1) * height);
269 for(int x=0; x<width; x++)
270 for (int y=0; y<height; y++)
271 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
273 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
276 vm.graphics_exposures = 0;
277 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
279 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
282 void org::xwt::plat::X11$X11Surface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
283 org::xwt::plat::X11$X11DoubleBuffer *xdb = (org::xwt::plat::X11$X11DoubleBuffer*)db;
284 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
288 void org::xwt::plat::X11$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
293 if (x < clipx) { w -= (clipx - x); x = clipx; }
294 if (y < clipy) { h -= (clipy - y); y = clipy; }
295 if (x + w > clipx + clipw) w = (clipx + clipw - x);
296 if (y + h > clipy + cliph) h = (cliph + clipy - y);
298 XSetForeground(display, (*((GC*)gc)),
299 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
300 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
301 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
302 colormap_info->base_pixel
305 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
308 void org::xwt::plat::X11$X11DoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
311 rect.x = clipx, rect.y = clipy; rect.width = clipw; rect.height = cliph;
312 XSetClipMask(display, (*((GC*)clipped_gc)), None);
313 XSetClipRectangles(display, (*((GC*)clipped_gc)), 0, 0, &rect, 1, YSorted);
314 XSetForeground(display, (*((GC*)clipped_gc)),
315 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
316 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
317 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
318 colormap_info->base_pixel
322 int len = min(1024, JvGetStringUTFLength(text));
324 JvGetStringUTFRegion(text, 0, len, buf);
327 // Build the XTextItem structure
329 textitem.chars = buf;
330 textitem.nchars = len;
332 textitem.font = ((XFontStruct*)org::xwt::plat::X11::fontToXFont(font))->fid;
335 XDrawText(display, (*((Pixmap*)pm)), (*((GC*)clipped_gc)), x, y, &textitem, 1);
339 // X11Surface //////////////////////////////////////////////////////////////////////
341 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
342 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
343 org::xwt::plat::X11$X11DoubleBuffer* old_dbuf = p->doublebuf;
344 p->buildDoubleBuffer(1);
346 memset(&xwmh, 0, sizeof(XWMHints));
347 xwmh.flags |= IconPixmapHint | IconMaskHint;
348 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
349 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
350 XSetWMHints(display, (*((Window*)window)), &xwmh);
351 p->doublebuf = old_dbuf;
354 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
355 int len = min(JvGetStringUTFLength(s), 1024);
357 JvGetStringUTFRegion(s, 0, len, buf);
361 tp.value = (unsigned char*)buf;
363 tp.encoding = XA_STRING;
365 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
366 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
369 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
371 hints.min_width = minw;
372 hints.min_height = minh;
373 hints.max_width = maxw;
374 hints.max_height = maxh;
375 hints.flags = PMinSize | PMaxSize;
376 XSetWMNormalHints(display, (*((Window*)window)), &hints);
379 void org::xwt::plat::X11$X11Surface::setSize (jint width, jint height) {
380 if (width <= 0 || height <= 0) return;
381 XResizeWindow(display, (*((Window*)window)), width, height);
385 void org::xwt::plat::X11$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
386 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
387 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
389 void org::xwt::plat::X11$X11Surface::_dispose() {
390 // without this we get phantom messages after the window is gone
391 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
392 XDestroyWindow(display, (*((Window*)window)));
395 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
396 if (i) XUnmapWindow(display, (*((Window*)window)));
397 else XMapRaised(display, (*((Window*)window)));
401 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
402 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
403 else XMapRaised(display, (*((Window*)window)));
407 void org::xwt::plat::X11$X11Surface::natInit() {
408 XSetWindowAttributes xswa;
409 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
410 xswa.bit_gravity = NorthWestGravity;
411 xswa.colormap = s_colormap;
412 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
413 KeyPressMask | KeyReleaseMask | ButtonPressMask |
414 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
415 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
416 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
417 colorDepth, InputOutput, CopyFromParent,
418 CWColormap | CWBitGravity | CWEventMask, &xswa);
421 // I don't know why this works....
422 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
423 XChangeProperty(display, (*((Window*)window)),
424 XInternAtom(display, "_MOTIF_WM_HINTS", False),
425 XInternAtom(display, "_MOTIF_WM_HINTS", False),
433 tp.value = (unsigned char*)"XWT";
435 tp.encoding = XA_STRING;
437 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
439 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
440 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
442 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
443 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
446 XMapRaised(display, (*((Window*)window)));
449 waitForCreation->block();
450 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
453 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
454 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
457 vm.graphics_exposures = 0;
458 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
462 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
464 XEvent* e = (XEvent*)ev;
465 if (e->type == Expose) {
466 XExposeEvent *expose = (XExposeEvent*)(e);
467 Dirty(expose->x, expose->y, expose->width, expose->height);
469 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
470 } else if (e->type == UnmapNotify) { Minimized(1);
471 } else if (e->type == FocusIn) { Focused(1);
472 } else if (e->type == FocusOut) { Focused(0);
473 } else if (e->type == ClientMessage) {
474 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
476 } else if (e->type == KeyPress || e->type == KeyRelease) {
477 XKeyEvent *xbe = (XKeyEvent*)(e);
479 // drop faked KeyRelease events generated by the X server's autorepeat
480 if (e->type == KeyRelease) {
482 XQueryKeymap(display, depressed);
483 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
489 unsigned int savestate = xbe->state;
490 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
491 XLookupString(xbe, s, 20, NULL, NULL);
492 xbe->state = savestate;
494 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
498 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
500 case XK_BackSpace: s = "back_space"; break;
501 case XK_Tab: s = "tab"; break;
502 case XK_Linefeed: s = "enter"; break;
503 case XK_Return: s = "enter"; break;
504 case XK_Scroll_Lock: s = "scroll_lock"; break;
505 case XK_Escape: s = "escape"; break;
506 case XK_Insert: s = "insert"; break;
507 case XK_Delete: s = "delete"; break;
508 case XK_Home: s = "home"; break;
509 case XK_Left: s = "left"; break;
510 case XK_Up: s = "up"; break;
511 case XK_Right: s = "right"; break;
512 case XK_Down: s = "down"; break;
513 case XK_Page_Up: s = "page_up"; break;
514 case XK_Page_Down: s = "page_down"; break;
515 case XK_End: s = "end"; break;
516 case XK_Num_Lock: s = "num_lock"; break;
517 case XK_KP_Tab: s = "tab"; break;
518 case XK_KP_Enter: s = "enter"; break;
519 case XK_KP_F1: s = "f1"; break;
520 case XK_KP_F2: s = "f2"; break;
521 case XK_KP_F3: s = "f3"; break;
522 case XK_KP_F4: s = "f4"; break;
523 case XK_KP_Home: s = "home"; break;
524 case XK_KP_Left: s = "left"; break;
525 case XK_KP_Up: s = "up"; break;
526 case XK_KP_Right: s = "right"; break;
527 case XK_KP_Down: s = "down"; break;
528 case XK_KP_Page_Up: s = "page_up"; break;
529 case XK_KP_Page_Down: s = "page_down"; break;
530 case XK_KP_End: s = "end"; break;
531 case XK_KP_Insert: s = "insert"; break;
532 case XK_KP_Delete: s = "delete"; break;
533 case XK_F1: s = "f1"; break;
534 case XK_F2: s = "f2"; break;
535 case XK_F3: s = "f3"; break;
536 case XK_F4: s = "f4"; break;
537 case XK_F5: s = "f5"; break;
538 case XK_F6: s = "f6"; break;
539 case XK_F7: s = "f7"; break;
540 case XK_F8: s = "f8"; break;
541 case XK_F9: s = "f9"; break;
542 case XK_F10: s = "f10"; break;
543 case XK_F11: s = "f11"; break;
544 case XK_F12: s = "f12"; break;
545 case XK_Shift_L: s = "shift"; break;
546 case XK_Shift_R: s = "shift"; break;
547 case XK_Control_L: s = "control"; break;
548 case XK_Control_R: s = "control"; break;
549 case XK_Meta_L: s = "alt"; break;
550 case XK_Meta_R: s = "alt"; break;
551 case XK_Alt_L: s = "alt"; break;
552 case XK_Alt_R: s = "alt"; break;
557 jstring s2 = JvNewStringLatin1(s);
558 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
559 if (e->type == KeyRelease) KeyReleased(s2);
561 } else if (e->type == ButtonPress) {
562 XButtonEvent* xbe = (XButtonEvent*)(e);
563 if (xbe->button == 2) xbe->button = 3;
564 else if (xbe->button == 3) xbe->button = 2;
567 } else if (e->type == ButtonRelease) {
568 XButtonEvent* xbe = (XButtonEvent*)(e);
569 if (xbe->button == 2) xbe->button = 3;
570 else if (xbe->button == 3) xbe->button = 2;
571 Release(xbe->button);
573 } else if (e->type == MotionNotify) {
574 XMotionEvent* xme = (XMotionEvent*)(e);
575 Move(xme->x, xme->y);
577 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
578 XCrossingEvent* xce = (XCrossingEvent*)(e);
579 Move(xce->x, xce->y);
581 } else if (e->type == ConfigureNotify) {
584 XConfigureEvent* xce = (XConfigureEvent*)(e);
585 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
586 if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
587 if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
592 static jstring crosshair, east, hand, move, north, northeast, northwest,
593 south, southeast, southwest, text, west, wait_string;
594 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
595 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
596 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
598 void org::xwt::plat::X11$X11Surface::syncCursor() {
601 if (cursor->equals(crosshair)) curs = crosshair_cursor;
602 else if (cursor->equals(east)) curs = east_cursor;
603 else if (cursor->equals(hand)) curs = hand_cursor;
604 else if (cursor->equals(move)) curs = move_cursor;
605 else if (cursor->equals(north)) curs = north_cursor;
606 else if (cursor->equals(northeast)) curs = northeast_cursor;
607 else if (cursor->equals(northwest)) curs = northwest_cursor;
608 else if (cursor->equals(south)) curs = south_cursor;
609 else if (cursor->equals(southeast)) curs = southeast_cursor;
610 else if (cursor->equals(southwest)) curs = southwest_cursor;
611 else if (cursor->equals(text)) curs = text_cursor;
612 else if (cursor->equals(west)) curs = west_cursor;
613 else if (cursor->equals(wait_string)) curs = wait_cursor;
614 else curs = default_cursor;
616 XDefineCursor(display, (*((Window*)window)), curs);
621 // X11 ///////////////////////////////////////////////////////////////////
623 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
624 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
626 static void dispatchSelectionEvent(XEvent* e) {
627 if (e->type == SelectionNotify) {
628 XSelectionEvent* xsn = (XSelectionEvent*)(e);
629 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
633 unsigned long numitems;
635 unsigned long bytes_after;
636 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
637 True, AnyPropertyType, &returntype, &returnformat,
638 &numitems, &bytes_after, &ret);
639 org::xwt::plat::X11::clipboard =
640 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
642 org::xwt::plat::X11::waiting_for_selection_event->release();
644 } else if (e->type == SelectionRequest) {
645 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
647 xsn.type = SelectionNotify;
648 xsn.serial = xsr->serial;
649 xsn.send_event = True;
650 xsn.display = display;
651 xsn.requestor = xsr->requestor;
652 xsn.selection = xsr->selection;
653 xsn.target = xsr->target;
654 xsn.property = xsr->property;
655 xsn.time = xsr->time;
657 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
659 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
662 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
663 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
667 void org::xwt::plat::X11::eventThread() {
670 XNextEvent(display, &e);
671 if (e.type == SelectionNotify || e.type == SelectionRequest) {
672 dispatchSelectionEvent(&e);
674 org::xwt::plat::X11$X11Surface* surface =
675 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
676 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
681 jstring org::xwt::plat::X11::_getClipBoard() {
682 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
684 org::xwt::plat::X11::waiting_for_selection_event->block();
688 void org::xwt::plat::X11::_setClipBoard(jstring s) {
690 int len = JvGetStringUTFLength(clipboard);
692 JvGetStringUTFRegion(clipboard, 0, len, buf);
694 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
697 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
698 int errorHandler(Display* d, XErrorEvent* e) {
699 // this error handler is only installed during the initial
700 // test to see if shm is present
704 void org::xwt::plat::X11::natInit() {
707 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
709 display = XOpenDisplay(NULL);
710 screen_num = XDefaultScreen(display);
711 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
712 shm_info.shmaddr = NULL;
714 shm_supported = (XShmQueryExtension(display) == True);
716 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
717 XShmSegmentInfo sinfo;
718 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
719 sinfo.readOnly = False;
720 // if the server is remote, this will trigger the error handler
721 XShmAttach(display, &sinfo);
722 XSync(display, False);
723 XSetErrorHandler(oldHandler);
727 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
729 crosshair = JvNewStringLatin1("crosshair");
730 east = JvNewStringLatin1("east");
731 hand = JvNewStringLatin1("hand");
732 move = JvNewStringLatin1("move");
733 north = JvNewStringLatin1("north");
734 northeast = JvNewStringLatin1("northeast");
735 northwest = JvNewStringLatin1("northwest");
736 south = JvNewStringLatin1("south");
737 southeast = JvNewStringLatin1("southeast");
738 southwest = JvNewStringLatin1("southwest");
739 text = JvNewStringLatin1("text");
740 west = JvNewStringLatin1("west");
741 wait_string = JvNewStringLatin1("wait");
742 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
743 east_cursor = XCreateFontCursor(display, XC_right_side);
744 hand_cursor = XCreateFontCursor(display, XC_hand2);
745 move_cursor = XCreateFontCursor(display, XC_fleur);
746 north_cursor = XCreateFontCursor(display, XC_top_side);
747 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
748 northwest_cursor = XCreateFontCursor(display, XC_left_side);
749 south_cursor = XCreateFontCursor(display, XC_bottom_side);
750 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
751 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
752 text_cursor = XCreateFontCursor(display, XC_xterm);
753 west_cursor = XCreateFontCursor(display, XC_right_side);
754 wait_cursor = XCreateFontCursor(display, XC_watch);
755 default_cursor = XCreateFontCursor(display, XC_left_ptr);
757 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
758 visual = DefaultVisual(display, screen_num);
760 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
761 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
762 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
763 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
764 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
765 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
766 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
768 // FIXME: don't know why (True, False) is the best solution...
769 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
770 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
772 XStandardColormap* best_map_info = NULL;
774 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
775 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
776 if (!best_map_info->colormap)
777 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
778 if (best_map_info->red_max == 0)
779 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
780 s_colormap = best_map_info->colormap;
781 colormap_info = best_map_info;
783 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
784 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
785 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
786 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
787 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
788 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
789 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
790 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
793 JArray<java::lang::String*>* org::xwt::plat::X11::listNativeFonts() {
795 char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
796 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
797 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
798 for(int i=0; i<numfonts; i++)
799 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
803 gnu::gcj::RawData* org::xwt::plat::X11::fontStringToStruct(jstring s) {
804 int len = min(1024, JvGetStringUTFLength(s));
806 JvGetStringUTFRegion(s, 0, len, buf);
808 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
811 jint org::xwt::plat::X11::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
812 jint org::xwt::plat::X11::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
813 jint org::xwt::plat::X11::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
814 if (text == NULL) return 0;
815 int len = JvGetStringUTFLength(text);
817 JvGetStringUTFRegion(text, 0, len, buf);
819 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
823 //////////////////////////////////////////////////////////////////////////////
824 //////////////////////////////////////////////////////////////////////////////
825 //////////////////////////////////////////////////////////////////////////////
826 //////////////////////////////////////////////////////////////////////////////
828 // Everything below this point was taken, cut-and-paste, from the //
829 // source for libXmu. It implements the official 'standard colormap //
830 // creation algorithm. I made some small changes to //
831 // XmuDeleteStandardColormap //
833 //////////////////////////////////////////////////////////////////////////////
834 //////////////////////////////////////////////////////////////////////////////
835 //////////////////////////////////////////////////////////////////////////////
836 //////////////////////////////////////////////////////////////////////////////
838 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
842 Copyright 1989, 1998 The Open Group
844 Permission to use, copy, modify, distribute, and sell this software and its
845 documentation for any purpose is hereby granted without fee, provided that
846 the above copyright notice appear in all copies and that both that
847 copyright notice and this permission notice appear in supporting
850 The above copyright notice and this permission notice shall be included in
851 all copies or substantial portions of the Software.
853 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
854 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
855 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
856 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
857 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
858 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
860 Except as contained in this notice, the name of The Open Group shall not be
861 used in advertising or otherwise to promote the sale, use or other dealings
862 in this Software without prior written authorization from The Open Group.
865 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
868 * Author: Donna Converse, MIT X Consortium
872 #include <X11/Xlib.h>
873 #include <X11/Xatom.h>
874 #include <X11/Xutil.h>
875 #include <X11/Xmu/StdCmap.h>
881 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
884 * To create a standard colormap if one does not currently exist, or
885 * replace the currently existing standard colormap, use
886 * XmuLookupStandardColormap().
888 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
889 * will determine the best allocation for the property under the specified
890 * visual, and determine the whether to create a new colormap or to use
891 * the default colormap of the screen. It will call XmuStandardColormap()
892 * to create the standard colormap.
894 * If replace is true, any previous definition of the property will be
895 * replaced. If retain is true, the property and the colormap will be
896 * made permanent for the duration of the server session. However,
897 * pre-existing property definitions which are not replaced cannot be made
898 * permanent by a call to XmuLookupStandardColormap(); a request to retain
899 * resources pertains to newly created resources.
901 * Returns 0 on failure, non-zero on success. A request to create a
902 * standard colormap upon a visual which cannot support such a map is
903 * considered a failure. An example of this would be requesting any
904 * standard colormap property on a monochrome visual, or, requesting an
905 * RGB_BEST_MAP on a display whose colormap size is 16.
909 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
910 unsigned int depth, Atom property,
911 Bool replace, Bool retain)
913 * dpy - specifies X server connection
914 * screen - specifies screen of display
915 * visualid - specifies the visual type
916 * depth - specifies the visual type
917 * property - a standard colormap property
918 * replace - specifies whether to replace
919 * retain - specifies whether to retain
922 Display *odpy; /* original display connection */
923 XStandardColormap *colormap;
924 XVisualInfo vinfo_template, *vinfo; /* visual */
926 unsigned long r_max, g_max, b_max; /* allocation */
928 Colormap cmap; /* colormap ID */
932 /* Match the requested visual */
934 vinfo_template.visualid = visualid;
935 vinfo_template.screen = screen;
936 vinfo_template.depth = depth;
937 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
938 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
942 /* Monochrome visuals have no standard maps */
944 if (vinfo->colormap_size <= 2) {
945 XFree((char *) vinfo);
949 /* If the requested property already exists on this screen, and,
950 * if the replace flag has not been set to true, return success.
951 * lookup() will remove a pre-existing map if replace is true.
954 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
955 replace) && !replace) {
956 XFree((char *) vinfo);
960 /* Determine the best allocation for this property under the requested
961 * visualid and depth, and determine whether or not to use the default
962 * colormap of the screen.
965 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
966 XFree((char *) vinfo);
970 cmap = (property == XA_RGB_DEFAULT_MAP &&
971 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
972 ? DefaultColormap(dpy, screen) : None;
974 /* If retaining resources, open a new connection to the same server */
978 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
979 XFree((char *) vinfo);
984 /* Create the standard colormap */
986 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
987 cmap, r_max, g_max, b_max);
989 /* Set the standard colormap property */
994 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
996 /* Someone has defined the property since we last looked.
997 * Since we will not replace it, release our own resources.
998 * If this is the default map, our allocations will be freed
999 * when this connection closes.
1001 if (colormap->killid == ReleaseByFreeingColormap)
1002 XFreeColormap(dpy, colormap->colormap);
1003 } else if (retain) {
1004 XSetCloseDownMode(dpy, RetainPermanent);
1007 XFree((char *) colormap);
1013 XFree((char *) vinfo);
1017 /***************************************************************************/
1019 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1020 * the visualid is used to determine whether the indicated standard colormap
1021 * exists. If the map exists and replace is true, delete the resources used
1022 * by the map and remove the property. Return true if the map exists,
1023 * or did exist and was deleted; return false if the map was not found.
1025 * Note that this is not the way that a Status return is normally used.
1027 * If new is not NULL, new points to an XStandardColormap structure which
1028 * describes a standard colormap of the specified property. It will be made
1029 * a standard colormap of the screen if none already exists, or if replace
1034 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1035 XStandardColormap *cnew, Bool replace)
1037 * dpy - specifies display connection
1038 * screen - specifies screen number
1039 * visualid - specifies visualid for std map
1040 * property - specifies colormap property name
1041 * cnew - specifies a standard colormap
1042 * replace - specifies whether to replace
1047 XStandardColormap *stdcmaps, *s;
1048 Window win = RootWindow(dpy, screen);
1050 /* The property does not already exist */
1052 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1054 XSetRGBColormaps(dpy, win, cnew, 1, property);
1058 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1060 if (property != XA_RGB_DEFAULT_MAP) {
1062 XmuDeleteStandardColormap(dpy, screen, property);
1064 XSetRGBColormaps(dpy, win, cnew, 1, property);
1066 XFree((char *)stdcmaps);
1070 /* The property exists and is RGB_DEFAULT_MAP */
1072 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1075 /* No RGB_DEFAULT_MAP property matches the given visualid */
1079 XStandardColormap *m, *maps;
1081 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1082 (XStandardColormap)));
1084 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1085 m->colormap = maps->colormap;
1086 m->red_max = maps->red_max;
1087 m->red_mult = maps->red_mult;
1088 m->green_max = maps->green_max;
1089 m->green_mult = maps->green_mult;
1090 m->blue_max = maps->blue_max;
1091 m->blue_mult = maps->blue_mult;
1092 m->base_pixel = maps->base_pixel;
1093 m->visualid = maps->visualid;
1094 m->killid = maps->killid;
1096 m->colormap = cnew->colormap;
1097 m->red_max = cnew->red_max;
1098 m->red_mult = cnew->red_mult;
1099 m->green_max = cnew->green_max;
1100 m->green_mult = cnew->green_mult;
1101 m->blue_max = cnew->blue_max;
1102 m->blue_mult = cnew->blue_mult;
1103 m->base_pixel = cnew->base_pixel;
1104 m->visualid = cnew->visualid;
1105 m->killid = cnew->killid;
1107 XSetRGBColormaps(dpy, win, s, ++count, property);
1110 XFree((char *) stdcmaps);
1114 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1117 /* Free old resources first - we may need them, particularly in
1118 * the default colormap of the screen. However, because of this,
1119 * it is possible that we will destroy the old resource and fail
1120 * to create a new one if XmuStandardColormap() fails.
1124 XmuDeleteStandardColormap(dpy, screen, property);
1126 XSetRGBColormaps(dpy, win, cnew, 1, property);
1129 XStandardColormap *map;
1131 /* s still points to the matching standard colormap */
1133 if (s->killid == ReleaseByFreeingColormap) {
1134 if ((s->colormap != None) &&
1135 (s->colormap != DefaultColormap(dpy, screen)))
1136 XFreeColormap(dpy, s->colormap);
1138 else if (s->killid != None)
1139 XKillClient(dpy, s->killid);
1141 map = (cnew) ? cnew : stdcmaps + --count;
1143 s->colormap = map->colormap;
1144 s->red_max = map->red_max;
1145 s->red_mult = map->red_mult;
1146 s->green_max = map->green_max;
1147 s->green_mult = map->green_mult;
1148 s->blue_max = map->blue_max;
1149 s->blue_mult = map->blue_mult;
1150 s->visualid = map->visualid;
1151 s->killid = map->killid;
1153 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1156 XFree((char *) stdcmaps);
1160 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1164 Copyright 1989, 1994, 1998 The Open Group
1166 Permission to use, copy, modify, distribute, and sell this software and its
1167 documentation for any purpose is hereby granted without fee, provided that
1168 the above copyright notice appear in all copies and that both that
1169 copyright notice and this permission notice appear in supporting
1172 The above copyright notice and this permission notice shall be included in
1173 all copies or substantial portions of the Software.
1175 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1176 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1177 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1178 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1179 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1180 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1182 Except as contained in this notice, the name of The Open Group shall not be
1183 used in advertising or otherwise to promote the sale, use or other dealings
1184 in this Software without prior written authorization from The Open Group.
1187 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1190 * Author: Donna Converse, MIT X Consortium
1193 #include <X11/Xlib.h>
1194 #include <X11/Xatom.h>
1195 #include <X11/Xutil.h>
1196 #include <X11/Xmu/StdCmap.h>
1199 #define lowbit(x) ((x) & (~(x) + 1))
1204 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1206 static int default_allocation(XVisualInfo*, unsigned long*,
1207 unsigned long*, unsigned long*);
1208 static void gray_allocation(int, unsigned long*, unsigned long*,
1210 static int icbrt(int);
1211 static int icbrt_with_bits(int, int);
1212 static int icbrt_with_guess(int, int);
1214 /* To determine the best allocation of reds, greens, and blues in a
1215 * standard colormap, use XmuGetColormapAllocation.
1216 * vinfo specifies visual information for a chosen visual
1217 * property specifies one of the standard colormap property names
1218 * red_max returns maximum red value
1219 * green_max returns maximum green value
1220 * blue_max returns maximum blue value
1222 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1223 * It is assumed that the visual is appropriate for the colormap property.
1227 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1228 unsigned long *red_max,
1229 unsigned long *green_max,
1230 unsigned long *blue_max)
1234 if (vinfo->colormap_size <= 2)
1239 case XA_RGB_DEFAULT_MAP:
1240 status = default_allocation(vinfo, red_max, green_max, blue_max);
1242 case XA_RGB_BEST_MAP:
1243 best_allocation(vinfo, red_max, green_max, blue_max);
1245 case XA_RGB_GRAY_MAP:
1246 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1248 case XA_RGB_RED_MAP:
1249 *red_max = vinfo->colormap_size - 1;
1250 *green_max = *blue_max = 0;
1252 case XA_RGB_GREEN_MAP:
1253 *green_max = vinfo->colormap_size - 1;
1254 *red_max = *blue_max = 0;
1256 case XA_RGB_BLUE_MAP:
1257 *blue_max = vinfo->colormap_size - 1;
1258 *red_max = *green_max = 0;
1266 /****************************************************************************/
1267 /* Determine the appropriate color allocations of a gray scale.
1269 * Keith Packard, MIT X Consortium
1273 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1274 unsigned long *blue_max)
1276 *red_max = (n * 30) / 100;
1277 *green_max = (n * 59) / 100;
1278 *blue_max = (n * 11) / 100;
1279 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1282 /****************************************************************************/
1283 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1284 * If a map has less than a minimum number of definable entries, we do not
1285 * produce an allocation for an RGB_DEFAULT_MAP.
1287 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1288 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1289 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1290 * Maximum green and maximum blue values are identical to maximum red.
1291 * This leaves at least 125 cells which clients can allocate.
1293 * Return 0 if an allocation has been determined, non-zero otherwise.
1297 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1298 unsigned long *green, unsigned long *blue)
1300 int ngrays; /* number of gray cells */
1302 switch (vinfo->c_class)
1306 if (vinfo->colormap_size > 65000)
1307 /* intended for displays with 16 planes */
1308 *red = *green = *blue = (unsigned long) 27;
1309 else if (vinfo->colormap_size > 4000)
1310 /* intended for displays with 12 planes */
1311 *red = *green = *blue = (unsigned long) 12;
1312 else if (vinfo->colormap_size < 250)
1315 /* intended for displays with 8 planes */
1316 *red = *green = *blue = (unsigned long)
1317 (icbrt(vinfo->colormap_size - 125) - 1);
1322 if (vinfo->colormap_size < 10)
1324 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1329 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1330 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1331 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1336 if (vinfo->colormap_size > 65000)
1338 else if (vinfo->colormap_size > 4000)
1340 else if (vinfo->colormap_size < 250)
1344 gray_allocation(ngrays, red, green, blue);
1353 /****************************************************************************/
1354 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1356 * For a DirectColor or TrueColor visual, the allocation is determined
1357 * by the red_mask, green_mask, and blue_mask members of the visual info.
1359 * Otherwise, if the colormap size is an integral power of 2, determine
1360 * the allocation according to the number of bits given to each color,
1361 * with green getting more than red, and red more than blue, if there
1362 * are to be inequities in the distribution. If the colormap size is
1363 * not an integral power of 2, let n = the number of colormap entries.
1364 * Then maximum red value = floor(cube_root(n)) - 1;
1365 * maximum blue value = floor(cube_root(n)) - 1;
1366 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1367 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1368 * defineable colormap entries.
1372 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1373 unsigned long *blue)
1376 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1378 *red = vinfo->red_mask;
1379 while ((*red & 01) == 0)
1381 *green = vinfo->green_mask;
1382 while ((*green & 01) == 0)
1384 *blue = vinfo->blue_mask;
1385 while ((*blue & 01) == 0)
1390 register int bits, n;
1392 /* Determine n such that n is the least integral power of 2 which is
1393 * greater than or equal to the number of entries in the colormap.
1397 while (vinfo->colormap_size > n)
1403 /* If the number of entries in the colormap is a power of 2, determine
1404 * the allocation by "dealing" the bits, first to green, then red, then
1405 * blue. If not, find the maximum integral red, green, and blue values
1406 * which, when multiplied together, do not exceed the number of
1410 if (n == vinfo->colormap_size)
1412 register int r, g, b;
1414 g = b + ((bits % 3) ? 1 : 0);
1415 r = b + (((bits % 3) == 2) ? 1 : 0);
1422 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1424 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1434 * integer cube roots by Newton's method
1436 * Stephen Gildea, MIT X Consortium, July 1991
1442 register int bits = 0;
1443 register unsigned n = a;
1450 return icbrt_with_bits(a, bits);
1455 icbrt_with_bits(int a, int bits)
1456 /* bits - log 2 of a */
1458 return icbrt_with_guess(a, a>>2*bits/3);
1461 #ifdef _X_ROOT_STATS
1462 int icbrt_loopcount;
1465 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1467 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1470 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1471 * Only works for positive integers (since that's all we need).
1472 * We actually return floor(cbrt(a)) because that's what we need here, too.
1476 icbrt_with_guess(int a, int guess)
1480 #ifdef _X_ROOT_STATS
1481 icbrt_loopcount = 0;
1489 #ifdef _X_ROOT_STATS
1492 delta = (guess - a/(guess*guess))/3;
1494 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1497 } while (delta != 0);
1499 if (guess*guess*guess > a)
1506 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1510 Copyright 1989, 1998 The Open Group
1512 Permission to use, copy, modify, distribute, and sell this software and its
1513 documentation for any purpose is hereby granted without fee, provided that
1514 the above copyright notice appear in all copies and that both that
1515 copyright notice and this permission notice appear in supporting
1518 The above copyright notice and this permission notice shall be included in
1519 all copies or substantial portions of the Software.
1521 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1522 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1523 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1524 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1525 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1526 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1528 Except as contained in this notice, the name of The Open Group shall not be
1529 used in advertising or otherwise to promote the sale, use or other dealings
1530 in this Software without prior written authorization from The Open Group.
1533 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1536 * Author: Donna Converse, MIT X Consortium
1540 #include <X11/Xlib.h>
1541 #include <X11/Xatom.h>
1542 #include <X11/Xutil.h>
1543 #include <X11/Xmu/StdCmap.h>
1545 #define lowbit(x) ((x) & (~(x) + 1))
1550 /* argument restrictions */
1551 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1552 unsigned long, Atom);
1555 * To create any one standard colormap, use XmuStandardColormap().
1557 * Create a standard colormap for the given screen, visualid, and visual
1558 * depth, with the given red, green, and blue maximum values, with the
1559 * given standard property name. Return a pointer to an XStandardColormap
1560 * structure which describes the newly created colormap, upon success.
1561 * Upon failure, return NULL.
1563 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1565 * Resources created by this function are not made permanent; that is the
1566 * caller's responsibility.
1570 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1571 unsigned int depth, Atom property, Colormap cmap,
1572 unsigned long red_max, unsigned long green_max,
1573 unsigned long blue_max)
1575 * dpy - specifies X server connection
1576 * screen - specifies display screen
1577 * visualid - identifies the visual type
1578 * depth - identifies the visual type
1579 * property - a standard colormap property
1580 * cmap - specifies colormap ID or None
1581 * red_max, green_max, blue_max - allocations
1584 XStandardColormap *stdcmap;
1586 XVisualInfo vinfo_template, *vinfo;
1590 /* Match the required visual information to an actual visual */
1591 vinfo_template.visualid = visualid;
1592 vinfo_template.screen = screen;
1593 vinfo_template.depth = depth;
1594 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1595 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1598 /* Check the validity of the combination of visual characteristics,
1599 * allocation, and colormap property. Create an XStandardColormap
1603 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1604 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1605 XFree((char *) vinfo);
1609 /* Fill in the XStandardColormap structure */
1611 if (cmap == DefaultColormap(dpy, screen)) {
1612 /* Allocating out of the default map, cannot use XFreeColormap() */
1613 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1614 0, 0, InputOnly, vinfo->visual,
1616 (XSetWindowAttributes *)NULL);
1617 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1618 XDestroyWindow(dpy, win);
1619 stdcmap->colormap = cmap;
1621 stdcmap->killid = ReleaseByFreeingColormap;
1622 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1623 vinfo->visual, AllocNone);
1625 stdcmap->red_max = red_max;
1626 stdcmap->green_max = green_max;
1627 stdcmap->blue_max = blue_max;
1628 if (property == XA_RGB_GRAY_MAP)
1629 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1630 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1631 stdcmap->red_mult = lowbit(vinfo->red_mask);
1632 stdcmap->green_mult = lowbit(vinfo->green_mask);
1633 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1635 stdcmap->red_mult = (red_max > 0)
1636 ? (green_max + 1) * (blue_max + 1) : 0;
1637 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1638 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1640 stdcmap->base_pixel = 0; /* base pixel may change */
1641 stdcmap->visualid = vinfo->visualid;
1643 /* Make the colormap */
1645 status = XmuCreateColormap(dpy, stdcmap);
1649 XFree((char *) vinfo);
1652 /* Free the colormap or the pixmap, if we created one */
1653 if (stdcmap->killid == ReleaseByFreeingColormap)
1654 XFreeColormap(dpy, stdcmap->colormap);
1655 else if (stdcmap->killid != None)
1656 XFreePixmap(dpy, stdcmap->killid);
1658 XFree((char *) stdcmap);
1659 return (XStandardColormap *) NULL;
1664 /****************************************************************************/
1666 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1667 unsigned long blue_max, Atom property)
1669 * vinfo - specifies visual
1670 * red_max, green_max, blue_max - specifies alloc
1671 * property - specifies property name
1674 unsigned long ncolors; /* number of colors requested */
1676 /* Determine that the number of colors requested is <= map size */
1678 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1681 mask = vinfo->red_mask;
1686 mask = vinfo->green_mask;
1689 if (green_max > mask)
1691 mask = vinfo->blue_mask;
1694 if (blue_max > mask)
1696 } else if (property == XA_RGB_GRAY_MAP) {
1697 ncolors = red_max + green_max + blue_max + 1;
1698 if (ncolors > vinfo->colormap_size)
1701 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1702 if (ncolors > vinfo->colormap_size)
1706 /* Determine that the allocation and visual make sense for the property */
1710 case XA_RGB_DEFAULT_MAP:
1711 if (red_max == 0 || green_max == 0 || blue_max == 0)
1714 case XA_RGB_RED_MAP:
1718 case XA_RGB_GREEN_MAP:
1722 case XA_RGB_BLUE_MAP:
1726 case XA_RGB_BEST_MAP:
1727 if (red_max == 0 || green_max == 0 || blue_max == 0)
1730 case XA_RGB_GRAY_MAP:
1731 if (red_max == 0 || blue_max == 0 || green_max == 0)
1741 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1745 Copyright 1989, 1998 The Open Group
1747 Permission to use, copy, modify, distribute, and sell this software and its
1748 documentation for any purpose is hereby granted without fee, provided that
1749 the above copyright notice appear in all copies and that both that
1750 copyright notice and this permission notice appear in supporting
1753 The above copyright notice and this permission notice shall be included in
1754 all copies or substantial portions of the Software.
1756 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1757 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1758 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1759 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1760 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1761 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1763 Except as contained in this notice, the name of The Open Group shall not be
1764 used in advertising or otherwise to promote the sale, use or other dealings
1765 in this Software without prior written authorization from The Open Group.
1768 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1771 * Author: Donna Converse, MIT X Consortium
1775 * CreateCmap.c - given a standard colormap description, make the map.
1780 #include <X11/Xlib.h>
1781 #include <X11/Xutil.h>
1782 #include <X11/Xmu/StdCmap.h>
1787 /* allocate entire map Read Only */
1788 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1790 /* allocate a cell, prefer Read Only */
1791 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1792 XColor*, unsigned long);
1794 /* allocate a cell Read Write */
1795 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1798 static int compare(_Xconst void*, _Xconst void*);
1800 /* find contiguous sequence of cells */
1801 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1803 /* frees resources before quitting */
1804 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1806 /* create a map in a RO visual type */
1807 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1809 /* create a map in a RW visual type */
1810 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1812 #define lowbit(x) ((x) & (~(x) + 1))
1813 #define TRUEMATCH(mult,max,mask) \
1814 (colormap->max * colormap->mult <= vinfo->mask && \
1815 lowbit(vinfo->mask) == colormap->mult)
1818 * To create any one colormap which is described by an XStandardColormap
1819 * structure, use XmuCreateColormap().
1821 * Return 0 on failure, non-zero on success.
1822 * Resources created by this function are not made permanent.
1823 * No argument error checking is provided. Use at your own risk.
1825 * All colormaps are created with read only allocations, with the exception
1826 * of read only allocations of colors in the default map or otherwise
1827 * which fail to return the expected pixel value, and these are individually
1828 * defined as read/write allocations. This is done so that all the cells
1829 * defined in the default map are contiguous, for use in image processing.
1830 * This typically happens with White and Black in the default map.
1832 * Colormaps of static visuals are considered to be successfully created if
1833 * the map of the static visual matches the definition given in the
1834 * standard colormap structure.
1838 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1839 /* dpy - specifies the connection under which the map is created
1840 * colormap - specifies the map to be created, and returns, particularly
1841 * if the map is created as a subset of the default colormap
1842 * of the screen, the base_pixel of the map.
1845 XVisualInfo vinfo_template; /* template visual information */
1846 XVisualInfo *vinfo; /* matching visual information */
1847 XVisualInfo *vpointer; /* for freeing the entire list */
1848 long vinfo_mask; /* specifies the visual mask value */
1849 int n; /* number of matching visuals */
1852 vinfo_template.visualid = colormap->visualid;
1853 vinfo_mask = VisualIDMask;
1854 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1857 /* A visual id may be valid on multiple screens. Also, there may
1858 * be multiple visuals with identical visual ids at different depths.
1859 * If the colormap is the Default Colormap, use the Default Visual.
1860 * Otherwise, arbitrarily, use the deepest visual.
1866 register int screen_number;
1870 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1871 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1877 for (i=0; i < n; i++, vinfo++) {
1878 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1883 XVisualInfo *v = NULL;
1885 for (i=0; i < n; i++, vinfo++)
1886 if (vinfo->depth > maxdepth) {
1887 maxdepth = vinfo->depth;
1894 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1895 vinfo->c_class == GrayScale)
1896 status = readwrite_map(dpy, vinfo, colormap);
1897 else if (vinfo->c_class == TrueColor)
1898 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1899 TRUEMATCH(green_mult, green_max, green_mask) &&
1900 TRUEMATCH(blue_mult, blue_max, blue_mask);
1902 status = readonly_map(dpy, vinfo, colormap);
1904 XFree((char *) vpointer);
1908 /****************************************************************************/
1910 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1912 register unsigned long i, n; /* index counters */
1913 unsigned long ncolors; /* number of colors to be defined */
1914 int npixels; /* number of pixels allocated R/W */
1915 int first_index; /* first index of pixels to use */
1916 int remainder; /* first index of remainder */
1917 XColor color; /* the definition of a color */
1918 unsigned long *pixels; /* array of colormap pixels */
1919 unsigned long delta;
1922 /* Determine ncolors, the number of colors to be defined.
1923 * Insure that 1 < ncolors <= the colormap size.
1925 if (vinfo->c_class == DirectColor) {
1926 ncolors = colormap->red_max;
1927 if (colormap->green_max > ncolors)
1928 ncolors = colormap->green_max;
1929 if (colormap->blue_max > ncolors)
1930 ncolors = colormap->blue_max;
1932 delta = lowbit(vinfo->red_mask) +
1933 lowbit(vinfo->green_mask) +
1934 lowbit(vinfo->blue_mask);
1936 ncolors = colormap->red_max * colormap->red_mult +
1937 colormap->green_max * colormap->green_mult +
1938 colormap->blue_max * colormap->blue_mult + 1;
1941 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1943 /* Allocate Read/Write as much of the colormap as we can possibly get.
1944 * Then insure that the pixels we were allocated are given in
1945 * monotonically increasing order, using a quicksort. Next, insure
1946 * that our allocation includes a subset of contiguous pixels at least
1947 * as long as the number of colors to be defined. Now we know that
1948 * these conditions are met:
1949 * 1) There are no free cells in the colormap.
1950 * 2) We have a contiguous sequence of pixels, monotonically
1951 * increasing, of length >= the number of colors requested.
1953 * One cell at a time, we will free, compute the next color value,
1954 * then allocate read only. This takes a long time.
1955 * This is done to insure that cells are allocated read only in the
1956 * contiguous order which we prefer. If the server has a choice of
1957 * cells to grant to an allocation request, the server may give us any
1958 * cell, so that is why we do these slow gymnastics.
1961 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1962 sizeof(unsigned long))) == NULL)
1965 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1966 vinfo->colormap_size, ncolors)) == 0) {
1967 free((char *) pixels);
1971 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1973 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1975 /* can't find enough contiguous cells, give up */
1976 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1978 free((char *) pixels);
1981 colormap->base_pixel = pixels[first_index];
1983 /* construct a gray map */
1984 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1985 colormap->blue_mult == 1)
1986 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1989 color.blue = color.green = color.red =
1990 (unsigned short) ((i * 65535) / (colormap->red_max +
1991 colormap->green_max +
1992 colormap->blue_max));
1994 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1999 /* construct a red ramp map */
2000 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2001 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2004 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2005 color.green = color.blue = 0;
2007 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2012 /* construct a green ramp map */
2013 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2014 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2017 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2018 color.red = color.blue = 0;
2020 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2025 /* construct a blue ramp map */
2026 else if (colormap->red_max == 0 && colormap->green_max == 0)
2027 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2030 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2031 color.red = color.green = 0;
2033 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2038 /* construct a standard red green blue cube map */
2041 #define calc(max,mult) (((n / colormap->mult) % \
2042 (colormap->max + 1)) * 65535) / colormap->max
2044 for (n=0, i=0; i < ncolors; i++, n += delta)
2046 color.pixel = n + colormap->base_pixel;
2047 color.red = calc(red_max, red_mult);
2048 color.green = calc(green_max, green_mult);
2049 color.blue = calc(blue_max, blue_mult);
2050 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2056 /* We have a read-only map defined. Now free unused cells,
2057 * first those occuring before the contiguous sequence begins,
2058 * then any following the contiguous sequence.
2062 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2065 XFreeColors(dpy, colormap->colormap,
2066 &(pixels[first_index + ncolors]), remainder,
2069 free((char *) pixels);
2074 /****************************************************************************/
2076 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2078 * dpy - the X server connection
2079 * cmap - specifies colormap ID
2080 * pixels - returns pixel allocations
2081 * m - specifies colormap size
2082 * n - specifies number of colors
2087 /* first try to allocate the entire colormap */
2088 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2089 (unsigned) 0, pixels, (unsigned) m))
2092 /* Allocate all available cells in the colormap, using a binary
2093 * algorithm to discover how many cells we can allocate in the colormap.
2097 p = n + ((m - n + 1) / 2);
2098 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2099 (unsigned) 0, pixels, (unsigned) p)) {
2103 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2114 /****************************************************************************/
2116 contiguous(unsigned long pixels[], int npixels, int ncolors,
2117 unsigned long delta, int *first, int *rem)
2118 /* pixels - specifies allocated pixels
2119 * npixels - specifies count of alloc'd pixels
2120 * ncolors - specifies needed sequence length
2121 * delta - between pixels
2122 * first - returns first index of sequence
2123 * rem - returns first index after sequence, or 0, if none follow
2126 register int i = 1; /* walking index into the pixel array */
2127 register int count = 1; /* length of sequence discovered so far */
2130 if (npixels == ncolors) {
2135 while (count < ncolors && ncolors - count <= *rem)
2137 if (pixels[i-1] + delta == pixels[i])
2146 if (count != ncolors)
2152 /****************************************************************************/
2154 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2155 int npixels, XColor *color, unsigned long p)
2157 unsigned long pixel;
2160 /* Free the read/write allocation of one cell in the colormap.
2161 * Request a read only allocation of one cell in the colormap.
2162 * If the read only allocation cannot be granted, give up, because
2163 * there must be no free cells in the colormap.
2164 * If the read only allocation is granted, but gives us a cell which
2165 * is not the one that we just freed, it is probably the case that
2166 * we are trying allocate White or Black or some other color which
2167 * already has a read-only allocation in the map. So we try to
2168 * allocate the previously freed cell with a read/write allocation,
2169 * because we want contiguous cells for image processing algorithms.
2172 pixel = color->pixel;
2173 request.red = color->red;
2174 request.green = color->green;
2175 request.blue = color->blue;
2177 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2178 if (! XAllocColor(dpy, cmap, color)
2179 || (color->pixel != pixel &&
2180 (!RWcell(dpy, cmap, color, &request, &pixel))))
2182 free_cells(dpy, cmap, pixels, npixels, (int)p);
2189 /****************************************************************************/
2191 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2194 * pixels - to be freed
2195 * npixels - original number allocated
2198 /* One of the npixels allocated has already been freed.
2199 * p is the index of the freed pixel.
2200 * First free the pixels preceeding p, and there are p of them;
2201 * then free the pixels following p, there are npixels - p - 1 of them.
2203 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2204 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2205 free((char *) pixels);
2209 /****************************************************************************/
2211 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2212 unsigned long *pixel)
2214 unsigned long n = *pixel;
2216 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2217 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2218 (unsigned) 0, pixel, (unsigned) 1))
2222 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2225 color->pixel = *pixel;
2226 color->flags = DoRed | DoGreen | DoBlue;
2227 color->red = request->red;
2228 color->green = request->green;
2229 color->blue = request->blue;
2230 XStoreColors(dpy, cmap, color, 1);
2235 /****************************************************************************/
2237 compare(_Xconst void *e1, _Xconst void *e2)
2239 return ((int)(*(long *)e1 - *(long *)e2));
2243 /****************************************************************************/
2245 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2250 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2251 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2253 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2255 color.pixel = (unsigned long) i;
2256 color.red = (unsigned short)
2257 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2259 if (vinfo->c_class == StaticColor) {
2260 color.green = (unsigned short)
2261 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2262 65535) / colormap->green_max);
2263 color.blue = (unsigned short)
2264 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2266 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2267 color.green = color.blue = color.red;
2269 XAllocColor(dpy, colormap->colormap, &color);
2270 if (color.pixel != (unsigned long) i)
2277 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2281 Copyright 1989, 1998 The Open Group
2283 Permission to use, copy, modify, distribute, and sell this software and its
2284 documentation for any purpose is hereby granted without fee, provided that
2285 the above copyright notice appear in all copies and that both that
2286 copyright notice and this permission notice appear in supporting
2289 The above copyright notice and this permission notice shall be included in
2290 all copies or substantial portions of the Software.
2292 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2293 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2294 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2295 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2296 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2297 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2299 Except as contained in this notice, the name of The Open Group shall not be
2300 used in advertising or otherwise to promote the sale, use or other dealings
2301 in this Software without prior written authorization from The Open Group.
2304 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2307 * Author: Donna Converse, MIT X Consortium
2310 #include <X11/Xlib.h>
2311 #include <X11/Xutil.h>
2312 #include <X11/Xmu/StdCmap.h>
2314 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2316 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2317 * XmuDeleteStandardColormap() will remove the specified property from the
2318 * specified screen, releasing any resources used by the colormap(s) of the
2319 * property if possible.
2323 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2324 /* dpy; - specifies the X server to connect to
2325 * screen - specifies the screen of the display
2326 * property - specifies the standard colormap property
2329 XStandardColormap *stdcmaps, *s;
2332 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2335 for (s=stdcmaps; count > 0; count--, s++) {
2336 if ((s->killid == ReleaseByFreeingColormap) &&
2337 (s->colormap != None) &&
2338 (s->colormap != DefaultColormap(dpy, screen))) {
2340 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2341 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2343 XFreeColormap(dpy, s->colormap);
2345 XSetErrorHandler(oldHandler);
2348 } else if (s->killid != None) {
2349 XKillClient(dpy, s->killid);
2352 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2353 XFree((char *) stdcmaps);