1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // see below for copyright information on the second portion of this file
7 #include <X11/extensions/XShm.h>
8 #include <X11/keysymdef.h>
9 #include <X11/keysym.h>
10 #include <X11/cursorfont.h>
11 #include <X11/Xutil.h>
12 #include <X11/Xatom.h>
13 #include <X11/Xmu/StdCmap.h>
15 #include <java/lang/String.h>
16 #include <org/xwt/Surface.h>
17 #include <org/xwt/Picture.h>
18 #include <org/xwt/Box.h>
19 #include <org/xwt/plat/X11.h>
20 #include <org/xwt/plat/X11$X11Surface.h>
21 #include <org/xwt/plat/X11$X11Picture.h>
22 #include <org/xwt/plat/X11$X11PixelBuffer.h>
23 #include <org/xwt/util/Semaphore.h>
24 #include <org/xwt/Platform.h>
25 #include <java/lang/Long.h>
26 #include <java/util/Hashtable.h>
27 #include <org/xwt/util/Log.h>
29 #include <java/lang/System.h>
30 #include <java/io/PrintStream.h>
32 // static (per-xserver) data
33 static Visual* visual;
34 static Colormap s_colormap;
35 static XStandardColormap* colormap_info;
36 static XShmSegmentInfo shm_info;
37 static Window selectionWindow;
38 static int shm_supported = 0;
39 static int shm_pixmaps_supported;
40 static int screen_num;
41 static int colorDepth = 0;
42 static Display* display;
43 static int shm_size = 0;
45 #define min(a, b) ((a) < (b) ? (a) : (b))
46 #define max(a, b) ((a) < (b) ? (b) : (a))
48 // X11PixelBuffer //////////////////////////////////////////////////////////////////////
50 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
51 static void ensureShmSize(int size) {
52 if (size > shm_size) {
54 XShmDetach(display, &shm_info);
55 shmdt(shm_info.shmaddr);
56 shmctl(shm_info.shmid, IPC_RMID, 0);
58 shm_size = 3 * size / 2;
59 shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
60 shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
61 shm_info.readOnly = False;
62 XSync(display, False);
63 shmctl(shm_info.shmid, IPC_RMID, 0);
64 XShmAttach(display, &shm_info);
65 XSync(display, False);
69 void org::xwt::plat::X11$X11PixelBuffer::fastDrawPicture(org::xwt::Picture* s,
70 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
71 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
73 // it's safe to clip manually since we no that no scaling will be done
74 if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
75 if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
76 if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
77 if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
78 if (dx1 > clipx + clipw) return;
79 if (dy1 > clipy + cliph) return;
80 if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
82 if (source->doublebuf->stipple != NULL) {
83 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
84 XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
86 XSetClipMask(display, (*((GC*)clipped_gc)), None);
88 XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
91 void org::xwt::plat::X11$X11PixelBuffer::slowDrawPicture(org::xwt::Picture* s,
92 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
94 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
97 // FASTEST: shared pixmap; twiddle bits in video ram directly
99 XSync(display, False); // ensure that all pending operations have rendered
100 xi = (XImage*)fake_ximage;
102 // MEDIUM: write to a shared ximage, then ask the server to do the blit
103 } else if (shm_supported) {
104 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1);
105 ensureShmSize(xi->bytes_per_line * xi->height);
106 xi->data = shm_info.shmaddr;
107 XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes);
109 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
111 xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
114 int* sourcedata = (int*)elements(source->data);
115 for(int y=max(dy1, clipy); y<min(dy2, clipy + cliph); y++) {
117 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
118 (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line);
120 for(int x=max(dx1, clipx); x<min(dx2, clipx + clipw); x++, current_pixel += xi->bits_per_pixel / 8) {
121 int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
122 int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
124 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
125 int alpha = (sourcepixel & 0xFF000000) >> 24;
126 int source_red = (sourcepixel & 0x00FF0000) >> 16;
127 int source_green = (sourcepixel & 0x0000FF00) >> 8;
128 int source_blue = (sourcepixel & 0x000000FF);
129 int red = 0, blue = 0, green = 0;
131 if (alpha == 0x00) continue;
134 switch (xi->bits_per_pixel) {
135 case 8: targetpixel = (int)(*current_pixel); break;
136 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
137 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
138 case 32: targetpixel = *((int*)current_pixel); break;
139 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
142 targetpixel -= colormap_info->base_pixel;
144 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
145 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
146 red = targetpixel / colormap_info->red_mult;
147 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
148 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
150 blue = targetpixel / colormap_info->blue_mult;
151 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
152 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
156 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
157 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
158 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
159 uint32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
160 blue * colormap_info->blue_mult + colormap_info->base_pixel;
162 switch (xi->bits_per_pixel) {
163 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
164 case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
166 int offset = (int)current_pixel & 0x3;
167 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
168 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
169 uint64_t* base = (uint64_t*)(current_pixel - offset);
170 *base = (*base & ~mask) | dest;
173 case 32: *((uint32_t*)current_pixel) = destpixel; break;
174 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
180 // do nothing, we wrote directly to video memory
182 } else if (shm_supported) {
183 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
187 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
192 void org::xwt::plat::X11$X11PixelBuffer::finalize() {
194 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
195 XShmDetach(display, sinfo);
196 shmdt(sinfo->shmaddr);
197 shmctl(sinfo->shmid, IPC_RMID, 0);
198 XDestroyImage((XImage*)fake_ximage);
202 XFreePixmap(display, *((Pixmap*)stipple));
205 XFreePixmap(display, *((Pixmap*)pm));
206 XFreeGC(display, *((GC*)gc));
207 XFreeGC(display, *((GC*)clipped_gc));
210 void org::xwt::plat::X11$X11PixelBuffer::natInit() {
212 if (width == 0 || height == 0) return;
213 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
214 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
217 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
219 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
220 shm_segment = (gnu::gcj::RawData*)sinfo;
221 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
222 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
223 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
224 sinfo->readOnly = False;
225 XShmAttach(display, sinfo);
226 XSync(display, False);
227 shmctl(sinfo->shmid, IPC_RMID, 0);
228 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
229 XSync(display, False);
232 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
233 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
234 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
235 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
238 vm.graphics_exposures = 0;
239 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
240 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
243 void org::xwt::plat::X11$X11PixelBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
245 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
246 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
249 xi.data = (char*)malloc((width + 1) * height);
256 xi.byte_order = LSBFirst;
258 xi.bytes_per_line = (width / 8) + 1;
259 xi.bits_per_pixel = 1;
261 jint* d = (jint*)elements(xpi->data);
262 memset(xi.data, 0xFF, (width + 1) * height);
263 for(int x=0; x<width; x++)
264 for (int y=0; y<height; y++)
265 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
267 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
270 vm.graphics_exposures = 0;
271 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
273 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
276 void org::xwt::plat::X11$X11Surface::blit(org::xwt::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
277 org::xwt::plat::X11$X11PixelBuffer *xdb = (org::xwt::plat::X11$X11PixelBuffer*)db;
278 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
282 void org::xwt::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
287 if (x < clipx) { w -= (clipx - x); x = clipx; }
288 if (y < clipy) { h -= (clipy - y); y = clipy; }
289 if (x + w > clipx + clipw) w = (clipx + clipw - x);
290 if (y + h > clipy + cliph) h = (cliph + clipy - y);
292 XSetForeground(display, (*((GC*)gc)),
293 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
294 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
295 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
296 colormap_info->base_pixel
299 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
302 void org::xwt::plat::X11$X11PixelBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
305 rect.x = clipx, rect.y = clipy; rect.width = clipw; rect.height = cliph;
306 XSetClipMask(display, (*((GC*)clipped_gc)), None);
307 XSetClipRectangles(display, (*((GC*)clipped_gc)), 0, 0, &rect, 1, YSorted);
308 XSetForeground(display, (*((GC*)clipped_gc)),
309 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
310 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
311 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
312 colormap_info->base_pixel
316 int len = min(1024, JvGetStringUTFLength(text));
318 JvGetStringUTFRegion(text, 0, len, buf);
321 // Build the XTextItem structure
323 textitem.chars = buf;
324 textitem.nchars = len;
326 textitem.font = ((XFontStruct*)org::xwt::plat::X11::fontToXFont(font))->fid;
329 XDrawText(display, (*((Pixmap*)pm)), (*((GC*)clipped_gc)), x, y, &textitem, 1);
333 // X11Surface //////////////////////////////////////////////////////////////////////
335 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
336 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
337 org::xwt::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
338 p->buildPixelBuffer(1);
340 memset(&xwmh, 0, sizeof(XWMHints));
341 xwmh.flags |= IconPixmapHint | IconMaskHint;
342 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
343 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
344 XSetWMHints(display, (*((Window*)window)), &xwmh);
345 p->doublebuf = old_dbuf;
348 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
349 int len = min(JvGetStringUTFLength(s), 1024);
351 JvGetStringUTFRegion(s, 0, len, buf);
355 tp.value = (unsigned char*)buf;
357 tp.encoding = XA_STRING;
359 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
360 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
363 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
365 hints.min_width = minw;
366 hints.min_height = minh;
367 hints.max_width = maxw;
368 hints.max_height = maxh;
369 hints.flags = PMinSize | PMaxSize;
370 XSetWMNormalHints(display, (*((Window*)window)), &hints);
373 void org::xwt::plat::X11$X11Surface::setSize (jint width, jint height) {
374 if (width <= 0 || height <= 0) return;
375 XResizeWindow(display, (*((Window*)window)), width, height);
379 void org::xwt::plat::X11$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
380 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
381 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
383 void org::xwt::plat::X11$X11Surface::_dispose() {
384 // without this we get phantom messages after the window is gone
385 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
386 XDestroyWindow(display, (*((Window*)window)));
389 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
390 if (i) XUnmapWindow(display, (*((Window*)window)));
391 else XMapRaised(display, (*((Window*)window)));
395 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
396 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
397 else XMapRaised(display, (*((Window*)window)));
401 void org::xwt::plat::X11$X11Surface::natInit() {
402 XSetWindowAttributes xswa;
403 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
404 xswa.bit_gravity = NorthWestGravity;
405 xswa.colormap = s_colormap;
406 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
407 KeyPressMask | KeyReleaseMask | ButtonPressMask |
408 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
409 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
410 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
411 colorDepth, InputOutput, CopyFromParent,
412 CWColormap | CWBitGravity | CWEventMask, &xswa);
415 // I don't know why this works....
416 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
417 XChangeProperty(display, (*((Window*)window)),
418 XInternAtom(display, "_MOTIF_WM_HINTS", False),
419 XInternAtom(display, "_MOTIF_WM_HINTS", False),
427 tp.value = (unsigned char*)"XWT";
429 tp.encoding = XA_STRING;
431 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
433 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
434 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
436 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
437 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
440 XMapRaised(display, (*((Window*)window)));
443 waitForCreation->block();
444 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
447 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
448 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
451 vm.graphics_exposures = 0;
452 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
456 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
458 XEvent* e = (XEvent*)ev;
459 if (e->type == Expose) {
460 XExposeEvent *expose = (XExposeEvent*)(e);
461 Dirty(expose->x, expose->y, expose->width, expose->height);
463 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
464 } else if (e->type == UnmapNotify) { Minimized(1);
465 } else if (e->type == FocusIn) { Focused(1);
466 } else if (e->type == FocusOut) { Focused(0);
467 } else if (e->type == ClientMessage) {
468 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
470 } else if (e->type == KeyPress || e->type == KeyRelease) {
471 XKeyEvent *xbe = (XKeyEvent*)(e);
473 // drop faked KeyRelease events generated by the X server's autorepeat
474 if (e->type == KeyRelease) {
476 XQueryKeymap(display, depressed);
477 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
483 unsigned int savestate = xbe->state;
484 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
485 XLookupString(xbe, s, 20, NULL, NULL);
486 xbe->state = savestate;
488 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
492 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
494 case XK_BackSpace: s = "back_space"; break;
495 case XK_Tab: s = "tab"; break;
496 case XK_Linefeed: s = "enter"; break;
497 case XK_Return: s = "enter"; break;
498 case XK_Scroll_Lock: s = "scroll_lock"; break;
499 case XK_Escape: s = "escape"; break;
500 case XK_Insert: s = "insert"; break;
501 case XK_Delete: s = "delete"; break;
502 case XK_Home: s = "home"; break;
503 case XK_Left: s = "left"; break;
504 case XK_Up: s = "up"; break;
505 case XK_Right: s = "right"; break;
506 case XK_Down: s = "down"; break;
507 case XK_Page_Up: s = "page_up"; break;
508 case XK_Page_Down: s = "page_down"; break;
509 case XK_End: s = "end"; break;
510 case XK_Num_Lock: s = "num_lock"; break;
511 case XK_KP_Tab: s = "tab"; break;
512 case XK_KP_Enter: s = "enter"; break;
513 case XK_KP_F1: s = "f1"; break;
514 case XK_KP_F2: s = "f2"; break;
515 case XK_KP_F3: s = "f3"; break;
516 case XK_KP_F4: s = "f4"; break;
517 case XK_KP_Home: s = "home"; break;
518 case XK_KP_Left: s = "left"; break;
519 case XK_KP_Up: s = "up"; break;
520 case XK_KP_Right: s = "right"; break;
521 case XK_KP_Down: s = "down"; break;
522 case XK_KP_Page_Up: s = "page_up"; break;
523 case XK_KP_Page_Down: s = "page_down"; break;
524 case XK_KP_End: s = "end"; break;
525 case XK_KP_Insert: s = "insert"; break;
526 case XK_KP_Delete: s = "delete"; break;
527 case XK_F1: s = "f1"; break;
528 case XK_F2: s = "f2"; break;
529 case XK_F3: s = "f3"; break;
530 case XK_F4: s = "f4"; break;
531 case XK_F5: s = "f5"; break;
532 case XK_F6: s = "f6"; break;
533 case XK_F7: s = "f7"; break;
534 case XK_F8: s = "f8"; break;
535 case XK_F9: s = "f9"; break;
536 case XK_F10: s = "f10"; break;
537 case XK_F11: s = "f11"; break;
538 case XK_F12: s = "f12"; break;
539 case XK_Shift_L: s = "shift"; break;
540 case XK_Shift_R: s = "shift"; break;
541 case XK_Control_L: s = "control"; break;
542 case XK_Control_R: s = "control"; break;
543 case XK_Meta_L: s = "alt"; break;
544 case XK_Meta_R: s = "alt"; break;
545 case XK_Alt_L: s = "alt"; break;
546 case XK_Alt_R: s = "alt"; break;
551 jstring s2 = JvNewStringLatin1(s);
552 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
553 if (e->type == KeyRelease) KeyReleased(s2);
555 } else if (e->type == ButtonPress) {
556 XButtonEvent* xbe = (XButtonEvent*)(e);
557 if (xbe->button == 2) xbe->button = 3;
558 else if (xbe->button == 3) xbe->button = 2;
561 } else if (e->type == ButtonRelease) {
562 XButtonEvent* xbe = (XButtonEvent*)(e);
563 if (xbe->button == 2) xbe->button = 3;
564 else if (xbe->button == 3) xbe->button = 2;
565 Release(xbe->button);
567 } else if (e->type == MotionNotify) {
568 XMotionEvent* xme = (XMotionEvent*)(e);
569 Move(xme->x, xme->y);
571 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
572 XCrossingEvent* xce = (XCrossingEvent*)(e);
573 Move(xce->x, xce->y);
575 } else if (e->type == ConfigureNotify) {
578 XConfigureEvent* xce = (XConfigureEvent*)(e);
579 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
580 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
581 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
586 static jstring crosshair, east, hand, move, north, northeast, northwest,
587 south, southeast, southwest, text, west, wait_string;
588 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
589 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
590 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
592 void org::xwt::plat::X11$X11Surface::syncCursor() {
595 if (cursor->equals(crosshair)) curs = crosshair_cursor;
596 else if (cursor->equals(east)) curs = east_cursor;
597 else if (cursor->equals(hand)) curs = hand_cursor;
598 else if (cursor->equals(move)) curs = move_cursor;
599 else if (cursor->equals(north)) curs = north_cursor;
600 else if (cursor->equals(northeast)) curs = northeast_cursor;
601 else if (cursor->equals(northwest)) curs = northwest_cursor;
602 else if (cursor->equals(south)) curs = south_cursor;
603 else if (cursor->equals(southeast)) curs = southeast_cursor;
604 else if (cursor->equals(southwest)) curs = southwest_cursor;
605 else if (cursor->equals(text)) curs = text_cursor;
606 else if (cursor->equals(west)) curs = west_cursor;
607 else if (cursor->equals(wait_string)) curs = wait_cursor;
608 else curs = default_cursor;
610 XDefineCursor(display, (*((Window*)window)), curs);
615 // X11 ///////////////////////////////////////////////////////////////////
617 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
618 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
620 static void dispatchSelectionEvent(XEvent* e) {
621 if (e->type == SelectionNotify) {
622 XSelectionEvent* xsn = (XSelectionEvent*)(e);
623 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
627 unsigned long numitems;
629 unsigned long bytes_after;
630 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
631 True, AnyPropertyType, &returntype, &returnformat,
632 &numitems, &bytes_after, &ret);
633 org::xwt::plat::X11::clipboard =
634 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
636 org::xwt::plat::X11::waiting_for_selection_event->release();
638 } else if (e->type == SelectionRequest) {
639 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
641 xsn.type = SelectionNotify;
642 xsn.serial = xsr->serial;
643 xsn.send_event = True;
644 xsn.display = display;
645 xsn.requestor = xsr->requestor;
646 xsn.selection = xsr->selection;
647 xsn.target = xsr->target;
648 xsn.property = xsr->property;
649 xsn.time = xsr->time;
651 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
653 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
656 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
657 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
661 void org::xwt::plat::X11::eventThread() {
664 XNextEvent(display, &e);
665 if (e.type == SelectionNotify || e.type == SelectionRequest) {
666 dispatchSelectionEvent(&e);
668 org::xwt::plat::X11$X11Surface* surface =
669 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
670 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
675 jstring org::xwt::plat::X11::_getClipBoard() {
676 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
678 org::xwt::plat::X11::waiting_for_selection_event->block();
682 void org::xwt::plat::X11::_setClipBoard(jstring s) {
684 int len = JvGetStringUTFLength(clipboard);
686 JvGetStringUTFRegion(clipboard, 0, len, buf);
688 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
691 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
692 int errorHandler(Display* d, XErrorEvent* e) {
693 // this error handler is only installed during the initial
694 // test to see if shm is present
698 void org::xwt::plat::X11::natInit() {
701 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
703 char* DISPLAY = getenv("DISPLAY");
704 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
705 display = XOpenDisplay(DISPLAY);
708 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
710 screen_num = XDefaultScreen(display);
711 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
712 shm_info.shmaddr = NULL;
714 // FIXME: SHM doesn't work on Darwin
715 //shm_supported = (XShmQueryExtension(display) == True);
717 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
718 XShmSegmentInfo sinfo;
719 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
720 sinfo.readOnly = False;
721 // if the server is remote, this will trigger the error handler
722 XShmAttach(display, &sinfo);
723 XSync(display, False);
724 XSetErrorHandler(oldHandler);
728 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
730 crosshair = JvNewStringLatin1("crosshair");
731 east = JvNewStringLatin1("east");
732 hand = JvNewStringLatin1("hand");
733 move = JvNewStringLatin1("move");
734 north = JvNewStringLatin1("north");
735 northeast = JvNewStringLatin1("northeast");
736 northwest = JvNewStringLatin1("northwest");
737 south = JvNewStringLatin1("south");
738 southeast = JvNewStringLatin1("southeast");
739 southwest = JvNewStringLatin1("southwest");
740 text = JvNewStringLatin1("text");
741 west = JvNewStringLatin1("west");
742 wait_string = JvNewStringLatin1("wait");
743 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
744 east_cursor = XCreateFontCursor(display, XC_right_side);
745 hand_cursor = XCreateFontCursor(display, XC_hand2);
746 move_cursor = XCreateFontCursor(display, XC_fleur);
747 north_cursor = XCreateFontCursor(display, XC_top_side);
748 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
749 northwest_cursor = XCreateFontCursor(display, XC_left_side);
750 south_cursor = XCreateFontCursor(display, XC_bottom_side);
751 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
752 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
753 text_cursor = XCreateFontCursor(display, XC_xterm);
754 west_cursor = XCreateFontCursor(display, XC_right_side);
755 wait_cursor = XCreateFontCursor(display, XC_watch);
756 default_cursor = XCreateFontCursor(display, XC_left_ptr);
758 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
759 visual = DefaultVisual(display, screen_num);
761 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
762 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
763 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
764 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
765 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
766 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
767 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
769 // FIXME: don't know why (True, False) is the best solution...
770 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
771 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
773 XStandardColormap* best_map_info = NULL;
775 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
776 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
777 if (!best_map_info->colormap)
778 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
779 if (best_map_info->red_max == 0)
780 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
781 s_colormap = best_map_info->colormap;
782 colormap_info = best_map_info;
784 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
785 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
786 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
787 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
788 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
789 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
790 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
791 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
794 JArray<java::lang::String*>* org::xwt::plat::X11::listNativeFonts() {
796 char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
797 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
798 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
799 for(int i=0; i<numfonts; i++)
800 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
804 gnu::gcj::RawData* org::xwt::plat::X11::fontStringToStruct(jstring s) {
805 int len = min(1024, JvGetStringUTFLength(s));
807 JvGetStringUTFRegion(s, 0, len, buf);
809 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
812 jint org::xwt::plat::X11::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
813 jint org::xwt::plat::X11::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
814 jint org::xwt::plat::X11::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
815 if (text == NULL) return 0;
816 int len = JvGetStringUTFLength(text);
818 JvGetStringUTFRegion(text, 0, len, buf);
820 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
824 //////////////////////////////////////////////////////////////////////////////
825 //////////////////////////////////////////////////////////////////////////////
826 //////////////////////////////////////////////////////////////////////////////
827 //////////////////////////////////////////////////////////////////////////////
829 // Everything below this point was taken, cut-and-paste, from the //
830 // source for libXmu. It implements the official 'standard colormap //
831 // creation algorithm. I made some small changes to //
832 // XmuDeleteStandardColormap //
834 //////////////////////////////////////////////////////////////////////////////
835 //////////////////////////////////////////////////////////////////////////////
836 //////////////////////////////////////////////////////////////////////////////
837 //////////////////////////////////////////////////////////////////////////////
839 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
843 Copyright 1989, 1998 The Open Group
845 Permission to use, copy, modify, distribute, and sell this software and its
846 documentation for any purpose is hereby granted without fee, provided that
847 the above copyright notice appear in all copies and that both that
848 copyright notice and this permission notice appear in supporting
851 The above copyright notice and this permission notice shall be included in
852 all copies or substantial portions of the Software.
854 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
855 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
856 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
857 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
858 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
859 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
861 Except as contained in this notice, the name of The Open Group shall not be
862 used in advertising or otherwise to promote the sale, use or other dealings
863 in this Software without prior written authorization from The Open Group.
866 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
869 * Author: Donna Converse, MIT X Consortium
873 #include <X11/Xlib.h>
874 #include <X11/Xatom.h>
875 #include <X11/Xutil.h>
876 #include <X11/Xmu/StdCmap.h>
882 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
885 * To create a standard colormap if one does not currently exist, or
886 * replace the currently existing standard colormap, use
887 * XmuLookupStandardColormap().
889 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
890 * will determine the best allocation for the property under the specified
891 * visual, and determine the whether to create a new colormap or to use
892 * the default colormap of the screen. It will call XmuStandardColormap()
893 * to create the standard colormap.
895 * If replace is true, any previous definition of the property will be
896 * replaced. If retain is true, the property and the colormap will be
897 * made permanent for the duration of the server session. However,
898 * pre-existing property definitions which are not replaced cannot be made
899 * permanent by a call to XmuLookupStandardColormap(); a request to retain
900 * resources pertains to newly created resources.
902 * Returns 0 on failure, non-zero on success. A request to create a
903 * standard colormap upon a visual which cannot support such a map is
904 * considered a failure. An example of this would be requesting any
905 * standard colormap property on a monochrome visual, or, requesting an
906 * RGB_BEST_MAP on a display whose colormap size is 16.
910 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
911 unsigned int depth, Atom property,
912 Bool replace, Bool retain)
914 * dpy - specifies X server connection
915 * screen - specifies screen of display
916 * visualid - specifies the visual type
917 * depth - specifies the visual type
918 * property - a standard colormap property
919 * replace - specifies whether to replace
920 * retain - specifies whether to retain
923 Display *odpy; /* original display connection */
924 XStandardColormap *colormap;
925 XVisualInfo vinfo_template, *vinfo; /* visual */
927 unsigned long r_max, g_max, b_max; /* allocation */
929 Colormap cmap; /* colormap ID */
933 /* Match the requested visual */
935 vinfo_template.visualid = visualid;
936 vinfo_template.screen = screen;
937 vinfo_template.depth = depth;
938 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
939 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
943 /* Monochrome visuals have no standard maps */
945 if (vinfo->colormap_size <= 2) {
946 XFree((char *) vinfo);
950 /* If the requested property already exists on this screen, and,
951 * if the replace flag has not been set to true, return success.
952 * lookup() will remove a pre-existing map if replace is true.
955 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
956 replace) && !replace) {
957 XFree((char *) vinfo);
961 /* Determine the best allocation for this property under the requested
962 * visualid and depth, and determine whether or not to use the default
963 * colormap of the screen.
966 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
967 XFree((char *) vinfo);
971 cmap = (property == XA_RGB_DEFAULT_MAP &&
972 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
973 ? DefaultColormap(dpy, screen) : None;
975 /* If retaining resources, open a new connection to the same server */
979 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
980 XFree((char *) vinfo);
985 /* Create the standard colormap */
987 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
988 cmap, r_max, g_max, b_max);
990 /* Set the standard colormap property */
995 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
997 /* Someone has defined the property since we last looked.
998 * Since we will not replace it, release our own resources.
999 * If this is the default map, our allocations will be freed
1000 * when this connection closes.
1002 if (colormap->killid == ReleaseByFreeingColormap)
1003 XFreeColormap(dpy, colormap->colormap);
1004 } else if (retain) {
1005 XSetCloseDownMode(dpy, RetainPermanent);
1008 XFree((char *) colormap);
1014 XFree((char *) vinfo);
1018 /***************************************************************************/
1020 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1021 * the visualid is used to determine whether the indicated standard colormap
1022 * exists. If the map exists and replace is true, delete the resources used
1023 * by the map and remove the property. Return true if the map exists,
1024 * or did exist and was deleted; return false if the map was not found.
1026 * Note that this is not the way that a Status return is normally used.
1028 * If new is not NULL, new points to an XStandardColormap structure which
1029 * describes a standard colormap of the specified property. It will be made
1030 * a standard colormap of the screen if none already exists, or if replace
1035 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1036 XStandardColormap *cnew, Bool replace)
1038 * dpy - specifies display connection
1039 * screen - specifies screen number
1040 * visualid - specifies visualid for std map
1041 * property - specifies colormap property name
1042 * cnew - specifies a standard colormap
1043 * replace - specifies whether to replace
1048 XStandardColormap *stdcmaps, *s;
1049 Window win = RootWindow(dpy, screen);
1051 /* The property does not already exist */
1053 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1055 XSetRGBColormaps(dpy, win, cnew, 1, property);
1059 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1061 if (property != XA_RGB_DEFAULT_MAP) {
1063 XmuDeleteStandardColormap(dpy, screen, property);
1065 XSetRGBColormaps(dpy, win, cnew, 1, property);
1067 XFree((char *)stdcmaps);
1071 /* The property exists and is RGB_DEFAULT_MAP */
1073 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1076 /* No RGB_DEFAULT_MAP property matches the given visualid */
1080 XStandardColormap *m, *maps;
1082 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1083 (XStandardColormap)));
1085 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1086 m->colormap = maps->colormap;
1087 m->red_max = maps->red_max;
1088 m->red_mult = maps->red_mult;
1089 m->green_max = maps->green_max;
1090 m->green_mult = maps->green_mult;
1091 m->blue_max = maps->blue_max;
1092 m->blue_mult = maps->blue_mult;
1093 m->base_pixel = maps->base_pixel;
1094 m->visualid = maps->visualid;
1095 m->killid = maps->killid;
1097 m->colormap = cnew->colormap;
1098 m->red_max = cnew->red_max;
1099 m->red_mult = cnew->red_mult;
1100 m->green_max = cnew->green_max;
1101 m->green_mult = cnew->green_mult;
1102 m->blue_max = cnew->blue_max;
1103 m->blue_mult = cnew->blue_mult;
1104 m->base_pixel = cnew->base_pixel;
1105 m->visualid = cnew->visualid;
1106 m->killid = cnew->killid;
1108 XSetRGBColormaps(dpy, win, s, ++count, property);
1111 XFree((char *) stdcmaps);
1115 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1118 /* Free old resources first - we may need them, particularly in
1119 * the default colormap of the screen. However, because of this,
1120 * it is possible that we will destroy the old resource and fail
1121 * to create a new one if XmuStandardColormap() fails.
1125 XmuDeleteStandardColormap(dpy, screen, property);
1127 XSetRGBColormaps(dpy, win, cnew, 1, property);
1130 XStandardColormap *map;
1132 /* s still points to the matching standard colormap */
1134 if (s->killid == ReleaseByFreeingColormap) {
1135 if ((s->colormap != None) &&
1136 (s->colormap != DefaultColormap(dpy, screen)))
1137 XFreeColormap(dpy, s->colormap);
1139 else if (s->killid != None)
1140 XKillClient(dpy, s->killid);
1142 map = (cnew) ? cnew : stdcmaps + --count;
1144 s->colormap = map->colormap;
1145 s->red_max = map->red_max;
1146 s->red_mult = map->red_mult;
1147 s->green_max = map->green_max;
1148 s->green_mult = map->green_mult;
1149 s->blue_max = map->blue_max;
1150 s->blue_mult = map->blue_mult;
1151 s->visualid = map->visualid;
1152 s->killid = map->killid;
1154 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1157 XFree((char *) stdcmaps);
1161 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1165 Copyright 1989, 1994, 1998 The Open Group
1167 Permission to use, copy, modify, distribute, and sell this software and its
1168 documentation for any purpose is hereby granted without fee, provided that
1169 the above copyright notice appear in all copies and that both that
1170 copyright notice and this permission notice appear in supporting
1173 The above copyright notice and this permission notice shall be included in
1174 all copies or substantial portions of the Software.
1176 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1177 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1178 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1179 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1180 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1181 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1183 Except as contained in this notice, the name of The Open Group shall not be
1184 used in advertising or otherwise to promote the sale, use or other dealings
1185 in this Software without prior written authorization from The Open Group.
1188 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1191 * Author: Donna Converse, MIT X Consortium
1194 #include <X11/Xlib.h>
1195 #include <X11/Xatom.h>
1196 #include <X11/Xutil.h>
1197 #include <X11/Xmu/StdCmap.h>
1200 #define lowbit(x) ((x) & (~(x) + 1))
1205 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1207 static int default_allocation(XVisualInfo*, unsigned long*,
1208 unsigned long*, unsigned long*);
1209 static void gray_allocation(int, unsigned long*, unsigned long*,
1211 static int icbrt(int);
1212 static int icbrt_with_bits(int, int);
1213 static int icbrt_with_guess(int, int);
1215 /* To determine the best allocation of reds, greens, and blues in a
1216 * standard colormap, use XmuGetColormapAllocation.
1217 * vinfo specifies visual information for a chosen visual
1218 * property specifies one of the standard colormap property names
1219 * red_max returns maximum red value
1220 * green_max returns maximum green value
1221 * blue_max returns maximum blue value
1223 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1224 * It is assumed that the visual is appropriate for the colormap property.
1228 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1229 unsigned long *red_max,
1230 unsigned long *green_max,
1231 unsigned long *blue_max)
1235 if (vinfo->colormap_size <= 2)
1240 case XA_RGB_DEFAULT_MAP:
1241 status = default_allocation(vinfo, red_max, green_max, blue_max);
1243 case XA_RGB_BEST_MAP:
1244 best_allocation(vinfo, red_max, green_max, blue_max);
1246 case XA_RGB_GRAY_MAP:
1247 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1249 case XA_RGB_RED_MAP:
1250 *red_max = vinfo->colormap_size - 1;
1251 *green_max = *blue_max = 0;
1253 case XA_RGB_GREEN_MAP:
1254 *green_max = vinfo->colormap_size - 1;
1255 *red_max = *blue_max = 0;
1257 case XA_RGB_BLUE_MAP:
1258 *blue_max = vinfo->colormap_size - 1;
1259 *red_max = *green_max = 0;
1267 /****************************************************************************/
1268 /* Determine the appropriate color allocations of a gray scale.
1270 * Keith Packard, MIT X Consortium
1274 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1275 unsigned long *blue_max)
1277 *red_max = (n * 30) / 100;
1278 *green_max = (n * 59) / 100;
1279 *blue_max = (n * 11) / 100;
1280 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1283 /****************************************************************************/
1284 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1285 * If a map has less than a minimum number of definable entries, we do not
1286 * produce an allocation for an RGB_DEFAULT_MAP.
1288 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1289 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1290 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1291 * Maximum green and maximum blue values are identical to maximum red.
1292 * This leaves at least 125 cells which clients can allocate.
1294 * Return 0 if an allocation has been determined, non-zero otherwise.
1298 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1299 unsigned long *green, unsigned long *blue)
1301 int ngrays; /* number of gray cells */
1303 switch (vinfo->c_class)
1307 if (vinfo->colormap_size > 65000)
1308 /* intended for displays with 16 planes */
1309 *red = *green = *blue = (unsigned long) 27;
1310 else if (vinfo->colormap_size > 4000)
1311 /* intended for displays with 12 planes */
1312 *red = *green = *blue = (unsigned long) 12;
1313 else if (vinfo->colormap_size < 250)
1316 /* intended for displays with 8 planes */
1317 *red = *green = *blue = (unsigned long)
1318 (icbrt(vinfo->colormap_size - 125) - 1);
1323 if (vinfo->colormap_size < 10)
1325 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1330 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1331 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1332 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1337 if (vinfo->colormap_size > 65000)
1339 else if (vinfo->colormap_size > 4000)
1341 else if (vinfo->colormap_size < 250)
1345 gray_allocation(ngrays, red, green, blue);
1354 /****************************************************************************/
1355 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1357 * For a DirectColor or TrueColor visual, the allocation is determined
1358 * by the red_mask, green_mask, and blue_mask members of the visual info.
1360 * Otherwise, if the colormap size is an integral power of 2, determine
1361 * the allocation according to the number of bits given to each color,
1362 * with green getting more than red, and red more than blue, if there
1363 * are to be inequities in the distribution. If the colormap size is
1364 * not an integral power of 2, let n = the number of colormap entries.
1365 * Then maximum red value = floor(cube_root(n)) - 1;
1366 * maximum blue value = floor(cube_root(n)) - 1;
1367 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1368 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1369 * defineable colormap entries.
1373 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1374 unsigned long *blue)
1377 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1379 *red = vinfo->red_mask;
1380 while ((*red & 01) == 0)
1382 *green = vinfo->green_mask;
1383 while ((*green & 01) == 0)
1385 *blue = vinfo->blue_mask;
1386 while ((*blue & 01) == 0)
1391 register int bits, n;
1393 /* Determine n such that n is the least integral power of 2 which is
1394 * greater than or equal to the number of entries in the colormap.
1398 while (vinfo->colormap_size > n)
1404 /* If the number of entries in the colormap is a power of 2, determine
1405 * the allocation by "dealing" the bits, first to green, then red, then
1406 * blue. If not, find the maximum integral red, green, and blue values
1407 * which, when multiplied together, do not exceed the number of
1411 if (n == vinfo->colormap_size)
1413 register int r, g, b;
1415 g = b + ((bits % 3) ? 1 : 0);
1416 r = b + (((bits % 3) == 2) ? 1 : 0);
1423 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1425 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1435 * integer cube roots by Newton's method
1437 * Stephen Gildea, MIT X Consortium, July 1991
1443 register int bits = 0;
1444 register unsigned n = a;
1451 return icbrt_with_bits(a, bits);
1456 icbrt_with_bits(int a, int bits)
1457 /* bits - log 2 of a */
1459 return icbrt_with_guess(a, a>>2*bits/3);
1462 #ifdef _X_ROOT_STATS
1463 int icbrt_loopcount;
1466 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1468 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1471 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1472 * Only works for positive integers (since that's all we need).
1473 * We actually return floor(cbrt(a)) because that's what we need here, too.
1477 icbrt_with_guess(int a, int guess)
1481 #ifdef _X_ROOT_STATS
1482 icbrt_loopcount = 0;
1490 #ifdef _X_ROOT_STATS
1493 delta = (guess - a/(guess*guess))/3;
1495 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1498 } while (delta != 0);
1500 if (guess*guess*guess > a)
1507 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1511 Copyright 1989, 1998 The Open Group
1513 Permission to use, copy, modify, distribute, and sell this software and its
1514 documentation for any purpose is hereby granted without fee, provided that
1515 the above copyright notice appear in all copies and that both that
1516 copyright notice and this permission notice appear in supporting
1519 The above copyright notice and this permission notice shall be included in
1520 all copies or substantial portions of the Software.
1522 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1523 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1524 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1525 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1526 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1527 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1529 Except as contained in this notice, the name of The Open Group shall not be
1530 used in advertising or otherwise to promote the sale, use or other dealings
1531 in this Software without prior written authorization from The Open Group.
1534 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1537 * Author: Donna Converse, MIT X Consortium
1541 #include <X11/Xlib.h>
1542 #include <X11/Xatom.h>
1543 #include <X11/Xutil.h>
1544 #include <X11/Xmu/StdCmap.h>
1546 #define lowbit(x) ((x) & (~(x) + 1))
1551 /* argument restrictions */
1552 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1553 unsigned long, Atom);
1556 * To create any one standard colormap, use XmuStandardColormap().
1558 * Create a standard colormap for the given screen, visualid, and visual
1559 * depth, with the given red, green, and blue maximum values, with the
1560 * given standard property name. Return a pointer to an XStandardColormap
1561 * structure which describes the newly created colormap, upon success.
1562 * Upon failure, return NULL.
1564 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1566 * Resources created by this function are not made permanent; that is the
1567 * caller's responsibility.
1571 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1572 unsigned int depth, Atom property, Colormap cmap,
1573 unsigned long red_max, unsigned long green_max,
1574 unsigned long blue_max)
1576 * dpy - specifies X server connection
1577 * screen - specifies display screen
1578 * visualid - identifies the visual type
1579 * depth - identifies the visual type
1580 * property - a standard colormap property
1581 * cmap - specifies colormap ID or None
1582 * red_max, green_max, blue_max - allocations
1585 XStandardColormap *stdcmap;
1587 XVisualInfo vinfo_template, *vinfo;
1591 /* Match the required visual information to an actual visual */
1592 vinfo_template.visualid = visualid;
1593 vinfo_template.screen = screen;
1594 vinfo_template.depth = depth;
1595 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1596 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1599 /* Check the validity of the combination of visual characteristics,
1600 * allocation, and colormap property. Create an XStandardColormap
1604 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1605 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1606 XFree((char *) vinfo);
1610 /* Fill in the XStandardColormap structure */
1612 if (cmap == DefaultColormap(dpy, screen)) {
1613 /* Allocating out of the default map, cannot use XFreeColormap() */
1614 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1615 0, 0, InputOnly, vinfo->visual,
1617 (XSetWindowAttributes *)NULL);
1618 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1619 XDestroyWindow(dpy, win);
1620 stdcmap->colormap = cmap;
1622 stdcmap->killid = ReleaseByFreeingColormap;
1623 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1624 vinfo->visual, AllocNone);
1626 stdcmap->red_max = red_max;
1627 stdcmap->green_max = green_max;
1628 stdcmap->blue_max = blue_max;
1629 if (property == XA_RGB_GRAY_MAP)
1630 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1631 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1632 stdcmap->red_mult = lowbit(vinfo->red_mask);
1633 stdcmap->green_mult = lowbit(vinfo->green_mask);
1634 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1636 stdcmap->red_mult = (red_max > 0)
1637 ? (green_max + 1) * (blue_max + 1) : 0;
1638 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1639 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1641 stdcmap->base_pixel = 0; /* base pixel may change */
1642 stdcmap->visualid = vinfo->visualid;
1644 /* Make the colormap */
1646 status = XmuCreateColormap(dpy, stdcmap);
1650 XFree((char *) vinfo);
1653 /* Free the colormap or the pixmap, if we created one */
1654 if (stdcmap->killid == ReleaseByFreeingColormap)
1655 XFreeColormap(dpy, stdcmap->colormap);
1656 else if (stdcmap->killid != None)
1657 XFreePixmap(dpy, stdcmap->killid);
1659 XFree((char *) stdcmap);
1660 return (XStandardColormap *) NULL;
1665 /****************************************************************************/
1667 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1668 unsigned long blue_max, Atom property)
1670 * vinfo - specifies visual
1671 * red_max, green_max, blue_max - specifies alloc
1672 * property - specifies property name
1675 unsigned long ncolors; /* number of colors requested */
1677 /* Determine that the number of colors requested is <= map size */
1679 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1682 mask = vinfo->red_mask;
1687 mask = vinfo->green_mask;
1690 if (green_max > mask)
1692 mask = vinfo->blue_mask;
1695 if (blue_max > mask)
1697 } else if (property == XA_RGB_GRAY_MAP) {
1698 ncolors = red_max + green_max + blue_max + 1;
1699 if (ncolors > vinfo->colormap_size)
1702 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1703 if (ncolors > vinfo->colormap_size)
1707 /* Determine that the allocation and visual make sense for the property */
1711 case XA_RGB_DEFAULT_MAP:
1712 if (red_max == 0 || green_max == 0 || blue_max == 0)
1715 case XA_RGB_RED_MAP:
1719 case XA_RGB_GREEN_MAP:
1723 case XA_RGB_BLUE_MAP:
1727 case XA_RGB_BEST_MAP:
1728 if (red_max == 0 || green_max == 0 || blue_max == 0)
1731 case XA_RGB_GRAY_MAP:
1732 if (red_max == 0 || blue_max == 0 || green_max == 0)
1742 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1746 Copyright 1989, 1998 The Open Group
1748 Permission to use, copy, modify, distribute, and sell this software and its
1749 documentation for any purpose is hereby granted without fee, provided that
1750 the above copyright notice appear in all copies and that both that
1751 copyright notice and this permission notice appear in supporting
1754 The above copyright notice and this permission notice shall be included in
1755 all copies or substantial portions of the Software.
1757 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1758 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1759 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1760 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1761 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1762 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1764 Except as contained in this notice, the name of The Open Group shall not be
1765 used in advertising or otherwise to promote the sale, use or other dealings
1766 in this Software without prior written authorization from The Open Group.
1769 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1772 * Author: Donna Converse, MIT X Consortium
1776 * CreateCmap.c - given a standard colormap description, make the map.
1781 #include <X11/Xlib.h>
1782 #include <X11/Xutil.h>
1783 #include <X11/Xmu/StdCmap.h>
1788 /* allocate entire map Read Only */
1789 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1791 /* allocate a cell, prefer Read Only */
1792 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1793 XColor*, unsigned long);
1795 /* allocate a cell Read Write */
1796 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1799 static int compare(_Xconst void*, _Xconst void*);
1801 /* find contiguous sequence of cells */
1802 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1804 /* frees resources before quitting */
1805 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1807 /* create a map in a RO visual type */
1808 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1810 /* create a map in a RW visual type */
1811 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1813 #define lowbit(x) ((x) & (~(x) + 1))
1814 #define TRUEMATCH(mult,max,mask) \
1815 (colormap->max * colormap->mult <= vinfo->mask && \
1816 lowbit(vinfo->mask) == colormap->mult)
1819 * To create any one colormap which is described by an XStandardColormap
1820 * structure, use XmuCreateColormap().
1822 * Return 0 on failure, non-zero on success.
1823 * Resources created by this function are not made permanent.
1824 * No argument error checking is provided. Use at your own risk.
1826 * All colormaps are created with read only allocations, with the exception
1827 * of read only allocations of colors in the default map or otherwise
1828 * which fail to return the expected pixel value, and these are individually
1829 * defined as read/write allocations. This is done so that all the cells
1830 * defined in the default map are contiguous, for use in image processing.
1831 * This typically happens with White and Black in the default map.
1833 * Colormaps of static visuals are considered to be successfully created if
1834 * the map of the static visual matches the definition given in the
1835 * standard colormap structure.
1839 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1840 /* dpy - specifies the connection under which the map is created
1841 * colormap - specifies the map to be created, and returns, particularly
1842 * if the map is created as a subset of the default colormap
1843 * of the screen, the base_pixel of the map.
1846 XVisualInfo vinfo_template; /* template visual information */
1847 XVisualInfo *vinfo; /* matching visual information */
1848 XVisualInfo *vpointer; /* for freeing the entire list */
1849 long vinfo_mask; /* specifies the visual mask value */
1850 int n; /* number of matching visuals */
1853 vinfo_template.visualid = colormap->visualid;
1854 vinfo_mask = VisualIDMask;
1855 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1858 /* A visual id may be valid on multiple screens. Also, there may
1859 * be multiple visuals with identical visual ids at different depths.
1860 * If the colormap is the Default Colormap, use the Default Visual.
1861 * Otherwise, arbitrarily, use the deepest visual.
1867 register int screen_number;
1871 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1872 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1878 for (i=0; i < n; i++, vinfo++) {
1879 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1884 XVisualInfo *v = NULL;
1886 for (i=0; i < n; i++, vinfo++)
1887 if (vinfo->depth > maxdepth) {
1888 maxdepth = vinfo->depth;
1895 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1896 vinfo->c_class == GrayScale)
1897 status = readwrite_map(dpy, vinfo, colormap);
1898 else if (vinfo->c_class == TrueColor)
1899 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1900 TRUEMATCH(green_mult, green_max, green_mask) &&
1901 TRUEMATCH(blue_mult, blue_max, blue_mask);
1903 status = readonly_map(dpy, vinfo, colormap);
1905 XFree((char *) vpointer);
1909 /****************************************************************************/
1911 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1913 register unsigned long i, n; /* index counters */
1914 unsigned long ncolors; /* number of colors to be defined */
1915 int npixels; /* number of pixels allocated R/W */
1916 int first_index; /* first index of pixels to use */
1917 int remainder; /* first index of remainder */
1918 XColor color; /* the definition of a color */
1919 unsigned long *pixels; /* array of colormap pixels */
1920 unsigned long delta;
1923 /* Determine ncolors, the number of colors to be defined.
1924 * Insure that 1 < ncolors <= the colormap size.
1926 if (vinfo->c_class == DirectColor) {
1927 ncolors = colormap->red_max;
1928 if (colormap->green_max > ncolors)
1929 ncolors = colormap->green_max;
1930 if (colormap->blue_max > ncolors)
1931 ncolors = colormap->blue_max;
1933 delta = lowbit(vinfo->red_mask) +
1934 lowbit(vinfo->green_mask) +
1935 lowbit(vinfo->blue_mask);
1937 ncolors = colormap->red_max * colormap->red_mult +
1938 colormap->green_max * colormap->green_mult +
1939 colormap->blue_max * colormap->blue_mult + 1;
1942 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1944 /* Allocate Read/Write as much of the colormap as we can possibly get.
1945 * Then insure that the pixels we were allocated are given in
1946 * monotonically increasing order, using a quicksort. Next, insure
1947 * that our allocation includes a subset of contiguous pixels at least
1948 * as long as the number of colors to be defined. Now we know that
1949 * these conditions are met:
1950 * 1) There are no free cells in the colormap.
1951 * 2) We have a contiguous sequence of pixels, monotonically
1952 * increasing, of length >= the number of colors requested.
1954 * One cell at a time, we will free, compute the next color value,
1955 * then allocate read only. This takes a long time.
1956 * This is done to insure that cells are allocated read only in the
1957 * contiguous order which we prefer. If the server has a choice of
1958 * cells to grant to an allocation request, the server may give us any
1959 * cell, so that is why we do these slow gymnastics.
1962 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1963 sizeof(unsigned long))) == NULL)
1966 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1967 vinfo->colormap_size, ncolors)) == 0) {
1968 free((char *) pixels);
1972 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1974 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1976 /* can't find enough contiguous cells, give up */
1977 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1979 free((char *) pixels);
1982 colormap->base_pixel = pixels[first_index];
1984 /* construct a gray map */
1985 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1986 colormap->blue_mult == 1)
1987 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1990 color.blue = color.green = color.red =
1991 (unsigned short) ((i * 65535) / (colormap->red_max +
1992 colormap->green_max +
1993 colormap->blue_max));
1995 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2000 /* construct a red ramp map */
2001 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2002 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2005 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2006 color.green = color.blue = 0;
2008 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2013 /* construct a green ramp map */
2014 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2015 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2018 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2019 color.red = color.blue = 0;
2021 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2026 /* construct a blue ramp map */
2027 else if (colormap->red_max == 0 && colormap->green_max == 0)
2028 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2031 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2032 color.red = color.green = 0;
2034 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2039 /* construct a standard red green blue cube map */
2042 #define calc(max,mult) (((n / colormap->mult) % \
2043 (colormap->max + 1)) * 65535) / colormap->max
2045 for (n=0, i=0; i < ncolors; i++, n += delta)
2047 color.pixel = n + colormap->base_pixel;
2048 color.red = calc(red_max, red_mult);
2049 color.green = calc(green_max, green_mult);
2050 color.blue = calc(blue_max, blue_mult);
2051 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2057 /* We have a read-only map defined. Now free unused cells,
2058 * first those occuring before the contiguous sequence begins,
2059 * then any following the contiguous sequence.
2063 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2066 XFreeColors(dpy, colormap->colormap,
2067 &(pixels[first_index + ncolors]), remainder,
2070 free((char *) pixels);
2075 /****************************************************************************/
2077 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2079 * dpy - the X server connection
2080 * cmap - specifies colormap ID
2081 * pixels - returns pixel allocations
2082 * m - specifies colormap size
2083 * n - specifies number of colors
2088 /* first try to allocate the entire colormap */
2089 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2090 (unsigned) 0, pixels, (unsigned) m))
2093 /* Allocate all available cells in the colormap, using a binary
2094 * algorithm to discover how many cells we can allocate in the colormap.
2098 p = n + ((m - n + 1) / 2);
2099 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2100 (unsigned) 0, pixels, (unsigned) p)) {
2104 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2115 /****************************************************************************/
2117 contiguous(unsigned long pixels[], int npixels, int ncolors,
2118 unsigned long delta, int *first, int *rem)
2119 /* pixels - specifies allocated pixels
2120 * npixels - specifies count of alloc'd pixels
2121 * ncolors - specifies needed sequence length
2122 * delta - between pixels
2123 * first - returns first index of sequence
2124 * rem - returns first index after sequence, or 0, if none follow
2127 register int i = 1; /* walking index into the pixel array */
2128 register int count = 1; /* length of sequence discovered so far */
2131 if (npixels == ncolors) {
2136 while (count < ncolors && ncolors - count <= *rem)
2138 if (pixels[i-1] + delta == pixels[i])
2147 if (count != ncolors)
2153 /****************************************************************************/
2155 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2156 int npixels, XColor *color, unsigned long p)
2158 unsigned long pixel;
2161 /* Free the read/write allocation of one cell in the colormap.
2162 * Request a read only allocation of one cell in the colormap.
2163 * If the read only allocation cannot be granted, give up, because
2164 * there must be no free cells in the colormap.
2165 * If the read only allocation is granted, but gives us a cell which
2166 * is not the one that we just freed, it is probably the case that
2167 * we are trying allocate White or Black or some other color which
2168 * already has a read-only allocation in the map. So we try to
2169 * allocate the previously freed cell with a read/write allocation,
2170 * because we want contiguous cells for image processing algorithms.
2173 pixel = color->pixel;
2174 request.red = color->red;
2175 request.green = color->green;
2176 request.blue = color->blue;
2178 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2179 if (! XAllocColor(dpy, cmap, color)
2180 || (color->pixel != pixel &&
2181 (!RWcell(dpy, cmap, color, &request, &pixel))))
2183 free_cells(dpy, cmap, pixels, npixels, (int)p);
2190 /****************************************************************************/
2192 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2195 * pixels - to be freed
2196 * npixels - original number allocated
2199 /* One of the npixels allocated has already been freed.
2200 * p is the index of the freed pixel.
2201 * First free the pixels preceeding p, and there are p of them;
2202 * then free the pixels following p, there are npixels - p - 1 of them.
2204 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2205 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2206 free((char *) pixels);
2210 /****************************************************************************/
2212 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2213 unsigned long *pixel)
2215 unsigned long n = *pixel;
2217 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2218 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2219 (unsigned) 0, pixel, (unsigned) 1))
2223 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2226 color->pixel = *pixel;
2227 color->flags = DoRed | DoGreen | DoBlue;
2228 color->red = request->red;
2229 color->green = request->green;
2230 color->blue = request->blue;
2231 XStoreColors(dpy, cmap, color, 1);
2236 /****************************************************************************/
2238 compare(_Xconst void *e1, _Xconst void *e2)
2240 return ((int)(*(long *)e1 - *(long *)e2));
2244 /****************************************************************************/
2246 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2251 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2252 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2254 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2256 color.pixel = (unsigned long) i;
2257 color.red = (unsigned short)
2258 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2260 if (vinfo->c_class == StaticColor) {
2261 color.green = (unsigned short)
2262 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2263 65535) / colormap->green_max);
2264 color.blue = (unsigned short)
2265 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2267 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2268 color.green = color.blue = color.red;
2270 XAllocColor(dpy, colormap->colormap, &color);
2271 if (color.pixel != (unsigned long) i)
2278 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2282 Copyright 1989, 1998 The Open Group
2284 Permission to use, copy, modify, distribute, and sell this software and its
2285 documentation for any purpose is hereby granted without fee, provided that
2286 the above copyright notice appear in all copies and that both that
2287 copyright notice and this permission notice appear in supporting
2290 The above copyright notice and this permission notice shall be included in
2291 all copies or substantial portions of the Software.
2293 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2294 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2295 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2296 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2297 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2298 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2300 Except as contained in this notice, the name of The Open Group shall not be
2301 used in advertising or otherwise to promote the sale, use or other dealings
2302 in this Software without prior written authorization from The Open Group.
2305 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2308 * Author: Donna Converse, MIT X Consortium
2311 #include <X11/Xlib.h>
2312 #include <X11/Xutil.h>
2313 #include <X11/Xmu/StdCmap.h>
2315 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2317 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2318 * XmuDeleteStandardColormap() will remove the specified property from the
2319 * specified screen, releasing any resources used by the colormap(s) of the
2320 * property if possible.
2324 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2325 /* dpy; - specifies the X server to connect to
2326 * screen - specifies the screen of the display
2327 * property - specifies the standard colormap property
2330 XStandardColormap *stdcmaps, *s;
2333 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2336 for (s=stdcmaps; count > 0; count--, s++) {
2337 if ((s->killid == ReleaseByFreeingColormap) &&
2338 (s->colormap != None) &&
2339 (s->colormap != DefaultColormap(dpy, screen))) {
2341 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2342 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2344 XFreeColormap(dpy, s->colormap);
2346 XSetErrorHandler(oldHandler);
2349 } else if (s->killid != None) {
2350 XKillClient(dpy, s->killid);
2353 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2354 XFree((char *) stdcmaps);