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, jint rgb, jboolean alphaOnly) {
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;
127 // FEATURE: be smarter here; can we do something better for the alphaonly case?
128 if (alphaOnly) sourcepixel = rgb;
129 int source_red = (sourcepixel & 0x00FF0000) >> 16;
130 int source_green = (sourcepixel & 0x0000FF00) >> 8;
131 int source_blue = (sourcepixel & 0x000000FF);
132 int red = 0, blue = 0, green = 0;
134 if (alpha == 0x00) continue;
137 switch (xi->bits_per_pixel) {
138 case 8: targetpixel = (int)(*current_pixel); break;
139 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
140 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
141 case 32: targetpixel = *((int*)current_pixel); break;
142 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
145 targetpixel -= colormap_info->base_pixel;
147 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
148 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
149 red = targetpixel / colormap_info->red_mult;
150 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
151 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
153 blue = targetpixel / colormap_info->blue_mult;
154 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
155 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
159 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
160 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
161 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
162 uint32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
163 blue * colormap_info->blue_mult + colormap_info->base_pixel;
165 switch (xi->bits_per_pixel) {
166 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
167 case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
169 int offset = (int)current_pixel & 0x3;
170 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
171 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
172 uint64_t* base = (uint64_t*)(current_pixel - offset);
173 *base = (*base & ~mask) | dest;
176 case 32: *((uint32_t*)current_pixel) = destpixel; break;
177 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
183 // do nothing, we wrote directly to video memory
185 } else if (shm_supported) {
186 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
190 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
195 void org::xwt::plat::X11$X11PixelBuffer::finalize() {
197 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
198 XShmDetach(display, sinfo);
199 shmdt(sinfo->shmaddr);
200 shmctl(sinfo->shmid, IPC_RMID, 0);
201 XDestroyImage((XImage*)fake_ximage);
205 XFreePixmap(display, *((Pixmap*)stipple));
208 XFreePixmap(display, *((Pixmap*)pm));
209 XFreeGC(display, *((GC*)gc));
210 XFreeGC(display, *((GC*)clipped_gc));
213 void org::xwt::plat::X11$X11PixelBuffer::natInit() {
215 if (width == 0 || height == 0) return;
216 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
217 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
220 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
222 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
223 shm_segment = (gnu::gcj::RawData*)sinfo;
224 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
225 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
226 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
227 sinfo->readOnly = False;
228 XShmAttach(display, sinfo);
229 XSync(display, False);
230 shmctl(sinfo->shmid, IPC_RMID, 0);
231 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
232 XSync(display, False);
235 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
236 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
237 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
238 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
241 vm.graphics_exposures = 0;
242 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
243 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
246 void org::xwt::plat::X11$X11PixelBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
248 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
249 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
252 xi.data = (char*)malloc((width + 1) * height);
259 xi.byte_order = LSBFirst;
261 xi.bytes_per_line = (width / 8) + 1;
262 xi.bits_per_pixel = 1;
264 jint* d = (jint*)elements(xpi->data);
265 memset(xi.data, 0xFF, (width + 1) * height);
266 for(int x=0; x<width; x++)
267 for (int y=0; y<height; y++)
268 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
270 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
273 vm.graphics_exposures = 0;
274 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
276 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
279 void org::xwt::plat::X11$X11Surface::blit(org::xwt::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
280 org::xwt::plat::X11$X11PixelBuffer *xdb = (org::xwt::plat::X11$X11PixelBuffer*)db;
281 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
285 void org::xwt::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
290 if (x < clipx) { w -= (clipx - x); x = clipx; }
291 if (y < clipy) { h -= (clipy - y); y = clipy; }
292 if (x + w > clipx + clipw) w = (clipx + clipw - x);
293 if (y + h > clipy + cliph) h = (cliph + clipy - y);
295 XSetForeground(display, (*((GC*)gc)),
296 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
297 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
298 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
299 colormap_info->base_pixel
302 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
306 // X11Surface //////////////////////////////////////////////////////////////////////
308 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
309 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
310 org::xwt::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
311 p->buildPixelBuffer(1);
313 memset(&xwmh, 0, sizeof(XWMHints));
314 xwmh.flags |= IconPixmapHint | IconMaskHint;
315 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
316 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
317 XSetWMHints(display, (*((Window*)window)), &xwmh);
318 p->doublebuf = old_dbuf;
321 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
322 int len = min(JvGetStringUTFLength(s), 1024);
324 JvGetStringUTFRegion(s, 0, len, buf);
328 tp.value = (unsigned char*)buf;
330 tp.encoding = XA_STRING;
332 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
333 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
336 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
338 hints.min_width = minw;
339 hints.min_height = minh;
340 hints.max_width = maxw;
341 hints.max_height = maxh;
342 hints.flags = PMinSize | PMaxSize;
343 XSetWMNormalHints(display, (*((Window*)window)), &hints);
346 void org::xwt::plat::X11$X11Surface::setSize (jint width, jint height) {
347 if (width <= 0 || height <= 0) return;
348 XResizeWindow(display, (*((Window*)window)), width, height);
352 void org::xwt::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
353 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
354 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
356 void org::xwt::plat::X11$X11Surface::_dispose() {
357 // without this we get phantom messages after the window is gone
358 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
359 XDestroyWindow(display, (*((Window*)window)));
362 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
363 if (i) XUnmapWindow(display, (*((Window*)window)));
364 else XMapRaised(display, (*((Window*)window)));
368 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
369 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
370 else XMapRaised(display, (*((Window*)window)));
374 void org::xwt::plat::X11$X11Surface::natInit() {
375 XSetWindowAttributes xswa;
376 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
377 xswa.bit_gravity = NorthWestGravity;
378 xswa.colormap = s_colormap;
379 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
380 KeyPressMask | KeyReleaseMask | ButtonPressMask |
381 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
382 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
383 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
384 colorDepth, InputOutput, CopyFromParent,
385 CWColormap | CWBitGravity | CWEventMask, &xswa);
388 // I don't know why this works....
389 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
390 XChangeProperty(display, (*((Window*)window)),
391 XInternAtom(display, "_MOTIF_WM_HINTS", False),
392 XInternAtom(display, "_MOTIF_WM_HINTS", False),
400 tp.value = (unsigned char*)"XWT";
402 tp.encoding = XA_STRING;
404 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
406 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
407 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
409 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
410 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
413 XMapRaised(display, (*((Window*)window)));
416 waitForCreation->block();
417 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
420 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
421 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
424 vm.graphics_exposures = 0;
425 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
429 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
431 XEvent* e = (XEvent*)ev;
432 if (e->type == Expose) {
433 XExposeEvent *expose = (XExposeEvent*)(e);
434 Dirty(expose->x, expose->y, expose->width, expose->height);
436 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
437 } else if (e->type == UnmapNotify) { Minimized(1);
438 } else if (e->type == FocusIn) { Focused(1);
439 } else if (e->type == FocusOut) { Focused(0);
440 } else if (e->type == ClientMessage) {
441 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
443 } else if (e->type == KeyPress || e->type == KeyRelease) {
444 XKeyEvent *xbe = (XKeyEvent*)(e);
446 // drop faked KeyRelease events generated by the X server's autorepeat
447 if (e->type == KeyRelease) {
449 XQueryKeymap(display, depressed);
450 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
456 unsigned int savestate = xbe->state;
457 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
458 XLookupString(xbe, s, 20, NULL, NULL);
459 xbe->state = savestate;
461 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
465 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
467 case XK_BackSpace: s = "back_space"; break;
468 case XK_Tab: s = "tab"; break;
469 case XK_Linefeed: s = "enter"; break;
470 case XK_Return: s = "enter"; break;
471 case XK_Scroll_Lock: s = "scroll_lock"; break;
472 case XK_Escape: s = "escape"; break;
473 case XK_Insert: s = "insert"; break;
474 case XK_Delete: s = "delete"; break;
475 case XK_Home: s = "home"; break;
476 case XK_Left: s = "left"; break;
477 case XK_Up: s = "up"; break;
478 case XK_Right: s = "right"; break;
479 case XK_Down: s = "down"; break;
480 case XK_Page_Up: s = "page_up"; break;
481 case XK_Page_Down: s = "page_down"; break;
482 case XK_End: s = "end"; break;
483 case XK_Num_Lock: s = "num_lock"; break;
484 case XK_KP_Tab: s = "tab"; break;
485 case XK_KP_Enter: s = "enter"; break;
486 case XK_KP_F1: s = "f1"; break;
487 case XK_KP_F2: s = "f2"; break;
488 case XK_KP_F3: s = "f3"; break;
489 case XK_KP_F4: s = "f4"; break;
490 case XK_KP_Home: s = "home"; break;
491 case XK_KP_Left: s = "left"; break;
492 case XK_KP_Up: s = "up"; break;
493 case XK_KP_Right: s = "right"; break;
494 case XK_KP_Down: s = "down"; break;
495 case XK_KP_Page_Up: s = "page_up"; break;
496 case XK_KP_Page_Down: s = "page_down"; break;
497 case XK_KP_End: s = "end"; break;
498 case XK_KP_Insert: s = "insert"; break;
499 case XK_KP_Delete: s = "delete"; break;
500 case XK_F1: s = "f1"; break;
501 case XK_F2: s = "f2"; break;
502 case XK_F3: s = "f3"; break;
503 case XK_F4: s = "f4"; break;
504 case XK_F5: s = "f5"; break;
505 case XK_F6: s = "f6"; break;
506 case XK_F7: s = "f7"; break;
507 case XK_F8: s = "f8"; break;
508 case XK_F9: s = "f9"; break;
509 case XK_F10: s = "f10"; break;
510 case XK_F11: s = "f11"; break;
511 case XK_F12: s = "f12"; break;
512 case XK_Shift_L: s = "shift"; break;
513 case XK_Shift_R: s = "shift"; break;
514 case XK_Control_L: s = "control"; break;
515 case XK_Control_R: s = "control"; break;
516 case XK_Meta_L: s = "alt"; break;
517 case XK_Meta_R: s = "alt"; break;
518 case XK_Alt_L: s = "alt"; break;
519 case XK_Alt_R: s = "alt"; break;
524 jstring s2 = JvNewStringLatin1(s);
525 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
526 if (e->type == KeyRelease) KeyReleased(s2);
528 } else if (e->type == ButtonPress) {
529 XButtonEvent* xbe = (XButtonEvent*)(e);
530 if (xbe->button == 2) xbe->button = 3;
531 else if (xbe->button == 3) xbe->button = 2;
534 } else if (e->type == ButtonRelease) {
535 XButtonEvent* xbe = (XButtonEvent*)(e);
536 if (xbe->button == 2) xbe->button = 3;
537 else if (xbe->button == 3) xbe->button = 2;
538 Release(xbe->button);
540 } else if (e->type == MotionNotify) {
541 XMotionEvent* xme = (XMotionEvent*)(e);
542 Move(xme->x, xme->y);
544 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
545 XCrossingEvent* xce = (XCrossingEvent*)(e);
546 Move(xce->x, xce->y);
548 } else if (e->type == ConfigureNotify) {
551 XConfigureEvent* xce = (XConfigureEvent*)(e);
552 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
553 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
554 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
559 static jstring crosshair, east, hand, move, north, northeast, northwest,
560 south, southeast, southwest, text, west, wait_string;
561 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
562 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
563 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
565 void org::xwt::plat::X11$X11Surface::syncCursor() {
568 if (cursor->equals(crosshair)) curs = crosshair_cursor;
569 else if (cursor->equals(east)) curs = east_cursor;
570 else if (cursor->equals(hand)) curs = hand_cursor;
571 else if (cursor->equals(move)) curs = move_cursor;
572 else if (cursor->equals(north)) curs = north_cursor;
573 else if (cursor->equals(northeast)) curs = northeast_cursor;
574 else if (cursor->equals(northwest)) curs = northwest_cursor;
575 else if (cursor->equals(south)) curs = south_cursor;
576 else if (cursor->equals(southeast)) curs = southeast_cursor;
577 else if (cursor->equals(southwest)) curs = southwest_cursor;
578 else if (cursor->equals(text)) curs = text_cursor;
579 else if (cursor->equals(west)) curs = west_cursor;
580 else if (cursor->equals(wait_string)) curs = wait_cursor;
581 else curs = default_cursor;
583 XDefineCursor(display, (*((Window*)window)), curs);
588 // X11 ///////////////////////////////////////////////////////////////////
590 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
591 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
593 static void dispatchSelectionEvent(XEvent* e) {
594 if (e->type == SelectionNotify) {
595 XSelectionEvent* xsn = (XSelectionEvent*)(e);
596 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
600 unsigned long numitems;
602 unsigned long bytes_after;
603 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
604 True, AnyPropertyType, &returntype, &returnformat,
605 &numitems, &bytes_after, &ret);
606 org::xwt::plat::X11::clipboard =
607 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
609 org::xwt::plat::X11::waiting_for_selection_event->release();
611 } else if (e->type == SelectionRequest) {
612 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
614 xsn.type = SelectionNotify;
615 xsn.serial = xsr->serial;
616 xsn.send_event = True;
617 xsn.display = display;
618 xsn.requestor = xsr->requestor;
619 xsn.selection = xsr->selection;
620 xsn.target = xsr->target;
621 xsn.property = xsr->property;
622 xsn.time = xsr->time;
624 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
626 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
629 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
630 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
634 void org::xwt::plat::X11::eventThread() {
637 XNextEvent(display, &e);
638 if (e.type == SelectionNotify || e.type == SelectionRequest) {
639 dispatchSelectionEvent(&e);
641 org::xwt::plat::X11$X11Surface* surface =
642 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
643 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
648 jstring org::xwt::plat::X11::_getClipBoard() {
649 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
651 org::xwt::plat::X11::waiting_for_selection_event->block();
655 void org::xwt::plat::X11::_setClipBoard(jstring s) {
657 int len = JvGetStringUTFLength(clipboard);
659 JvGetStringUTFRegion(clipboard, 0, len, buf);
661 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
664 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
665 int errorHandler(Display* d, XErrorEvent* e) {
666 // this error handler is only installed during the initial
667 // test to see if shm is present
671 void org::xwt::plat::X11::natInit() {
674 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
676 char* DISPLAY = getenv("DISPLAY");
677 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
678 display = XOpenDisplay(DISPLAY);
681 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
683 screen_num = XDefaultScreen(display);
684 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
685 shm_info.shmaddr = NULL;
687 // FIXME: SHM doesn't work on Darwin
688 //shm_supported = (XShmQueryExtension(display) == True);
690 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
691 XShmSegmentInfo sinfo;
692 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
693 sinfo.readOnly = False;
694 // if the server is remote, this will trigger the error handler
695 XShmAttach(display, &sinfo);
696 XSync(display, False);
697 XSetErrorHandler(oldHandler);
701 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
703 crosshair = JvNewStringLatin1("crosshair");
704 east = JvNewStringLatin1("east");
705 hand = JvNewStringLatin1("hand");
706 move = JvNewStringLatin1("move");
707 north = JvNewStringLatin1("north");
708 northeast = JvNewStringLatin1("northeast");
709 northwest = JvNewStringLatin1("northwest");
710 south = JvNewStringLatin1("south");
711 southeast = JvNewStringLatin1("southeast");
712 southwest = JvNewStringLatin1("southwest");
713 text = JvNewStringLatin1("text");
714 west = JvNewStringLatin1("west");
715 wait_string = JvNewStringLatin1("wait");
716 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
717 east_cursor = XCreateFontCursor(display, XC_right_side);
718 hand_cursor = XCreateFontCursor(display, XC_hand2);
719 move_cursor = XCreateFontCursor(display, XC_fleur);
720 north_cursor = XCreateFontCursor(display, XC_top_side);
721 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
722 northwest_cursor = XCreateFontCursor(display, XC_left_side);
723 south_cursor = XCreateFontCursor(display, XC_bottom_side);
724 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
725 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
726 text_cursor = XCreateFontCursor(display, XC_xterm);
727 west_cursor = XCreateFontCursor(display, XC_right_side);
728 wait_cursor = XCreateFontCursor(display, XC_watch);
729 default_cursor = XCreateFontCursor(display, XC_left_ptr);
731 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
732 visual = DefaultVisual(display, screen_num);
734 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
735 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
736 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
737 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
738 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
739 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
740 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
742 // FIXME: don't know why (True, False) is the best solution...
743 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
744 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
746 XStandardColormap* best_map_info = NULL;
748 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
749 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
750 if (!best_map_info->colormap)
751 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
752 if (best_map_info->red_max == 0)
753 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
754 s_colormap = best_map_info->colormap;
755 colormap_info = best_map_info;
757 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
758 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
759 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
760 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
761 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
762 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
763 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
764 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
769 //////////////////////////////////////////////////////////////////////////////
770 //////////////////////////////////////////////////////////////////////////////
771 //////////////////////////////////////////////////////////////////////////////
772 //////////////////////////////////////////////////////////////////////////////
774 // Everything below this point was taken, cut-and-paste, from the //
775 // source for libXmu. It implements the official 'standard colormap //
776 // creation algorithm. I made some small changes to //
777 // XmuDeleteStandardColormap //
779 //////////////////////////////////////////////////////////////////////////////
780 //////////////////////////////////////////////////////////////////////////////
781 //////////////////////////////////////////////////////////////////////////////
782 //////////////////////////////////////////////////////////////////////////////
784 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
788 Copyright 1989, 1998 The Open Group
790 Permission to use, copy, modify, distribute, and sell this software and its
791 documentation for any purpose is hereby granted without fee, provided that
792 the above copyright notice appear in all copies and that both that
793 copyright notice and this permission notice appear in supporting
796 The above copyright notice and this permission notice shall be included in
797 all copies or substantial portions of the Software.
799 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
800 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
801 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
802 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
803 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
804 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
806 Except as contained in this notice, the name of The Open Group shall not be
807 used in advertising or otherwise to promote the sale, use or other dealings
808 in this Software without prior written authorization from The Open Group.
811 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
814 * Author: Donna Converse, MIT X Consortium
818 #include <X11/Xlib.h>
819 #include <X11/Xatom.h>
820 #include <X11/Xutil.h>
821 #include <X11/Xmu/StdCmap.h>
827 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
830 * To create a standard colormap if one does not currently exist, or
831 * replace the currently existing standard colormap, use
832 * XmuLookupStandardColormap().
834 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
835 * will determine the best allocation for the property under the specified
836 * visual, and determine the whether to create a new colormap or to use
837 * the default colormap of the screen. It will call XmuStandardColormap()
838 * to create the standard colormap.
840 * If replace is true, any previous definition of the property will be
841 * replaced. If retain is true, the property and the colormap will be
842 * made permanent for the duration of the server session. However,
843 * pre-existing property definitions which are not replaced cannot be made
844 * permanent by a call to XmuLookupStandardColormap(); a request to retain
845 * resources pertains to newly created resources.
847 * Returns 0 on failure, non-zero on success. A request to create a
848 * standard colormap upon a visual which cannot support such a map is
849 * considered a failure. An example of this would be requesting any
850 * standard colormap property on a monochrome visual, or, requesting an
851 * RGB_BEST_MAP on a display whose colormap size is 16.
855 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
856 unsigned int depth, Atom property,
857 Bool replace, Bool retain)
859 * dpy - specifies X server connection
860 * screen - specifies screen of display
861 * visualid - specifies the visual type
862 * depth - specifies the visual type
863 * property - a standard colormap property
864 * replace - specifies whether to replace
865 * retain - specifies whether to retain
868 Display *odpy; /* original display connection */
869 XStandardColormap *colormap;
870 XVisualInfo vinfo_template, *vinfo; /* visual */
872 unsigned long r_max, g_max, b_max; /* allocation */
874 Colormap cmap; /* colormap ID */
878 /* Match the requested visual */
880 vinfo_template.visualid = visualid;
881 vinfo_template.screen = screen;
882 vinfo_template.depth = depth;
883 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
884 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
888 /* Monochrome visuals have no standard maps */
890 if (vinfo->colormap_size <= 2) {
891 XFree((char *) vinfo);
895 /* If the requested property already exists on this screen, and,
896 * if the replace flag has not been set to true, return success.
897 * lookup() will remove a pre-existing map if replace is true.
900 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
901 replace) && !replace) {
902 XFree((char *) vinfo);
906 /* Determine the best allocation for this property under the requested
907 * visualid and depth, and determine whether or not to use the default
908 * colormap of the screen.
911 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
912 XFree((char *) vinfo);
916 cmap = (property == XA_RGB_DEFAULT_MAP &&
917 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
918 ? DefaultColormap(dpy, screen) : None;
920 /* If retaining resources, open a new connection to the same server */
924 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
925 XFree((char *) vinfo);
930 /* Create the standard colormap */
932 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
933 cmap, r_max, g_max, b_max);
935 /* Set the standard colormap property */
940 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
942 /* Someone has defined the property since we last looked.
943 * Since we will not replace it, release our own resources.
944 * If this is the default map, our allocations will be freed
945 * when this connection closes.
947 if (colormap->killid == ReleaseByFreeingColormap)
948 XFreeColormap(dpy, colormap->colormap);
950 XSetCloseDownMode(dpy, RetainPermanent);
953 XFree((char *) colormap);
959 XFree((char *) vinfo);
963 /***************************************************************************/
965 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
966 * the visualid is used to determine whether the indicated standard colormap
967 * exists. If the map exists and replace is true, delete the resources used
968 * by the map and remove the property. Return true if the map exists,
969 * or did exist and was deleted; return false if the map was not found.
971 * Note that this is not the way that a Status return is normally used.
973 * If new is not NULL, new points to an XStandardColormap structure which
974 * describes a standard colormap of the specified property. It will be made
975 * a standard colormap of the screen if none already exists, or if replace
980 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
981 XStandardColormap *cnew, Bool replace)
983 * dpy - specifies display connection
984 * screen - specifies screen number
985 * visualid - specifies visualid for std map
986 * property - specifies colormap property name
987 * cnew - specifies a standard colormap
988 * replace - specifies whether to replace
993 XStandardColormap *stdcmaps, *s;
994 Window win = RootWindow(dpy, screen);
996 /* The property does not already exist */
998 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1000 XSetRGBColormaps(dpy, win, cnew, 1, property);
1004 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1006 if (property != XA_RGB_DEFAULT_MAP) {
1008 XmuDeleteStandardColormap(dpy, screen, property);
1010 XSetRGBColormaps(dpy, win, cnew, 1, property);
1012 XFree((char *)stdcmaps);
1016 /* The property exists and is RGB_DEFAULT_MAP */
1018 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1021 /* No RGB_DEFAULT_MAP property matches the given visualid */
1025 XStandardColormap *m, *maps;
1027 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1028 (XStandardColormap)));
1030 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1031 m->colormap = maps->colormap;
1032 m->red_max = maps->red_max;
1033 m->red_mult = maps->red_mult;
1034 m->green_max = maps->green_max;
1035 m->green_mult = maps->green_mult;
1036 m->blue_max = maps->blue_max;
1037 m->blue_mult = maps->blue_mult;
1038 m->base_pixel = maps->base_pixel;
1039 m->visualid = maps->visualid;
1040 m->killid = maps->killid;
1042 m->colormap = cnew->colormap;
1043 m->red_max = cnew->red_max;
1044 m->red_mult = cnew->red_mult;
1045 m->green_max = cnew->green_max;
1046 m->green_mult = cnew->green_mult;
1047 m->blue_max = cnew->blue_max;
1048 m->blue_mult = cnew->blue_mult;
1049 m->base_pixel = cnew->base_pixel;
1050 m->visualid = cnew->visualid;
1051 m->killid = cnew->killid;
1053 XSetRGBColormaps(dpy, win, s, ++count, property);
1056 XFree((char *) stdcmaps);
1060 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1063 /* Free old resources first - we may need them, particularly in
1064 * the default colormap of the screen. However, because of this,
1065 * it is possible that we will destroy the old resource and fail
1066 * to create a new one if XmuStandardColormap() fails.
1070 XmuDeleteStandardColormap(dpy, screen, property);
1072 XSetRGBColormaps(dpy, win, cnew, 1, property);
1075 XStandardColormap *map;
1077 /* s still points to the matching standard colormap */
1079 if (s->killid == ReleaseByFreeingColormap) {
1080 if ((s->colormap != None) &&
1081 (s->colormap != DefaultColormap(dpy, screen)))
1082 XFreeColormap(dpy, s->colormap);
1084 else if (s->killid != None)
1085 XKillClient(dpy, s->killid);
1087 map = (cnew) ? cnew : stdcmaps + --count;
1089 s->colormap = map->colormap;
1090 s->red_max = map->red_max;
1091 s->red_mult = map->red_mult;
1092 s->green_max = map->green_max;
1093 s->green_mult = map->green_mult;
1094 s->blue_max = map->blue_max;
1095 s->blue_mult = map->blue_mult;
1096 s->visualid = map->visualid;
1097 s->killid = map->killid;
1099 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1102 XFree((char *) stdcmaps);
1106 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1110 Copyright 1989, 1994, 1998 The Open Group
1112 Permission to use, copy, modify, distribute, and sell this software and its
1113 documentation for any purpose is hereby granted without fee, provided that
1114 the above copyright notice appear in all copies and that both that
1115 copyright notice and this permission notice appear in supporting
1118 The above copyright notice and this permission notice shall be included in
1119 all copies or substantial portions of the Software.
1121 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1122 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1123 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1124 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1125 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1126 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1128 Except as contained in this notice, the name of The Open Group shall not be
1129 used in advertising or otherwise to promote the sale, use or other dealings
1130 in this Software without prior written authorization from The Open Group.
1133 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1136 * Author: Donna Converse, MIT X Consortium
1139 #include <X11/Xlib.h>
1140 #include <X11/Xatom.h>
1141 #include <X11/Xutil.h>
1142 #include <X11/Xmu/StdCmap.h>
1145 #define lowbit(x) ((x) & (~(x) + 1))
1150 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1152 static int default_allocation(XVisualInfo*, unsigned long*,
1153 unsigned long*, unsigned long*);
1154 static void gray_allocation(int, unsigned long*, unsigned long*,
1156 static int icbrt(int);
1157 static int icbrt_with_bits(int, int);
1158 static int icbrt_with_guess(int, int);
1160 /* To determine the best allocation of reds, greens, and blues in a
1161 * standard colormap, use XmuGetColormapAllocation.
1162 * vinfo specifies visual information for a chosen visual
1163 * property specifies one of the standard colormap property names
1164 * red_max returns maximum red value
1165 * green_max returns maximum green value
1166 * blue_max returns maximum blue value
1168 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1169 * It is assumed that the visual is appropriate for the colormap property.
1173 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1174 unsigned long *red_max,
1175 unsigned long *green_max,
1176 unsigned long *blue_max)
1180 if (vinfo->colormap_size <= 2)
1185 case XA_RGB_DEFAULT_MAP:
1186 status = default_allocation(vinfo, red_max, green_max, blue_max);
1188 case XA_RGB_BEST_MAP:
1189 best_allocation(vinfo, red_max, green_max, blue_max);
1191 case XA_RGB_GRAY_MAP:
1192 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1194 case XA_RGB_RED_MAP:
1195 *red_max = vinfo->colormap_size - 1;
1196 *green_max = *blue_max = 0;
1198 case XA_RGB_GREEN_MAP:
1199 *green_max = vinfo->colormap_size - 1;
1200 *red_max = *blue_max = 0;
1202 case XA_RGB_BLUE_MAP:
1203 *blue_max = vinfo->colormap_size - 1;
1204 *red_max = *green_max = 0;
1212 /****************************************************************************/
1213 /* Determine the appropriate color allocations of a gray scale.
1215 * Keith Packard, MIT X Consortium
1219 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1220 unsigned long *blue_max)
1222 *red_max = (n * 30) / 100;
1223 *green_max = (n * 59) / 100;
1224 *blue_max = (n * 11) / 100;
1225 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1228 /****************************************************************************/
1229 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1230 * If a map has less than a minimum number of definable entries, we do not
1231 * produce an allocation for an RGB_DEFAULT_MAP.
1233 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1234 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1235 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1236 * Maximum green and maximum blue values are identical to maximum red.
1237 * This leaves at least 125 cells which clients can allocate.
1239 * Return 0 if an allocation has been determined, non-zero otherwise.
1243 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1244 unsigned long *green, unsigned long *blue)
1246 int ngrays; /* number of gray cells */
1248 switch (vinfo->c_class)
1252 if (vinfo->colormap_size > 65000)
1253 /* intended for displays with 16 planes */
1254 *red = *green = *blue = (unsigned long) 27;
1255 else if (vinfo->colormap_size > 4000)
1256 /* intended for displays with 12 planes */
1257 *red = *green = *blue = (unsigned long) 12;
1258 else if (vinfo->colormap_size < 250)
1261 /* intended for displays with 8 planes */
1262 *red = *green = *blue = (unsigned long)
1263 (icbrt(vinfo->colormap_size - 125) - 1);
1268 if (vinfo->colormap_size < 10)
1270 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1275 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1276 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1277 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1282 if (vinfo->colormap_size > 65000)
1284 else if (vinfo->colormap_size > 4000)
1286 else if (vinfo->colormap_size < 250)
1290 gray_allocation(ngrays, red, green, blue);
1299 /****************************************************************************/
1300 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1302 * For a DirectColor or TrueColor visual, the allocation is determined
1303 * by the red_mask, green_mask, and blue_mask members of the visual info.
1305 * Otherwise, if the colormap size is an integral power of 2, determine
1306 * the allocation according to the number of bits given to each color,
1307 * with green getting more than red, and red more than blue, if there
1308 * are to be inequities in the distribution. If the colormap size is
1309 * not an integral power of 2, let n = the number of colormap entries.
1310 * Then maximum red value = floor(cube_root(n)) - 1;
1311 * maximum blue value = floor(cube_root(n)) - 1;
1312 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1313 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1314 * defineable colormap entries.
1318 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1319 unsigned long *blue)
1322 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1324 *red = vinfo->red_mask;
1325 while ((*red & 01) == 0)
1327 *green = vinfo->green_mask;
1328 while ((*green & 01) == 0)
1330 *blue = vinfo->blue_mask;
1331 while ((*blue & 01) == 0)
1336 register int bits, n;
1338 /* Determine n such that n is the least integral power of 2 which is
1339 * greater than or equal to the number of entries in the colormap.
1343 while (vinfo->colormap_size > n)
1349 /* If the number of entries in the colormap is a power of 2, determine
1350 * the allocation by "dealing" the bits, first to green, then red, then
1351 * blue. If not, find the maximum integral red, green, and blue values
1352 * which, when multiplied together, do not exceed the number of
1356 if (n == vinfo->colormap_size)
1358 register int r, g, b;
1360 g = b + ((bits % 3) ? 1 : 0);
1361 r = b + (((bits % 3) == 2) ? 1 : 0);
1368 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1370 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1380 * integer cube roots by Newton's method
1382 * Stephen Gildea, MIT X Consortium, July 1991
1388 register int bits = 0;
1389 register unsigned n = a;
1396 return icbrt_with_bits(a, bits);
1401 icbrt_with_bits(int a, int bits)
1402 /* bits - log 2 of a */
1404 return icbrt_with_guess(a, a>>2*bits/3);
1407 #ifdef _X_ROOT_STATS
1408 int icbrt_loopcount;
1411 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1413 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1416 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1417 * Only works for positive integers (since that's all we need).
1418 * We actually return floor(cbrt(a)) because that's what we need here, too.
1422 icbrt_with_guess(int a, int guess)
1426 #ifdef _X_ROOT_STATS
1427 icbrt_loopcount = 0;
1435 #ifdef _X_ROOT_STATS
1438 delta = (guess - a/(guess*guess))/3;
1440 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1443 } while (delta != 0);
1445 if (guess*guess*guess > a)
1452 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1456 Copyright 1989, 1998 The Open Group
1458 Permission to use, copy, modify, distribute, and sell this software and its
1459 documentation for any purpose is hereby granted without fee, provided that
1460 the above copyright notice appear in all copies and that both that
1461 copyright notice and this permission notice appear in supporting
1464 The above copyright notice and this permission notice shall be included in
1465 all copies or substantial portions of the Software.
1467 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1468 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1469 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1470 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1471 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1472 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1474 Except as contained in this notice, the name of The Open Group shall not be
1475 used in advertising or otherwise to promote the sale, use or other dealings
1476 in this Software without prior written authorization from The Open Group.
1479 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1482 * Author: Donna Converse, MIT X Consortium
1486 #include <X11/Xlib.h>
1487 #include <X11/Xatom.h>
1488 #include <X11/Xutil.h>
1489 #include <X11/Xmu/StdCmap.h>
1491 #define lowbit(x) ((x) & (~(x) + 1))
1496 /* argument restrictions */
1497 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1498 unsigned long, Atom);
1501 * To create any one standard colormap, use XmuStandardColormap().
1503 * Create a standard colormap for the given screen, visualid, and visual
1504 * depth, with the given red, green, and blue maximum values, with the
1505 * given standard property name. Return a pointer to an XStandardColormap
1506 * structure which describes the newly created colormap, upon success.
1507 * Upon failure, return NULL.
1509 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1511 * Resources created by this function are not made permanent; that is the
1512 * caller's responsibility.
1516 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1517 unsigned int depth, Atom property, Colormap cmap,
1518 unsigned long red_max, unsigned long green_max,
1519 unsigned long blue_max)
1521 * dpy - specifies X server connection
1522 * screen - specifies display screen
1523 * visualid - identifies the visual type
1524 * depth - identifies the visual type
1525 * property - a standard colormap property
1526 * cmap - specifies colormap ID or None
1527 * red_max, green_max, blue_max - allocations
1530 XStandardColormap *stdcmap;
1532 XVisualInfo vinfo_template, *vinfo;
1536 /* Match the required visual information to an actual visual */
1537 vinfo_template.visualid = visualid;
1538 vinfo_template.screen = screen;
1539 vinfo_template.depth = depth;
1540 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1541 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1544 /* Check the validity of the combination of visual characteristics,
1545 * allocation, and colormap property. Create an XStandardColormap
1549 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1550 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1551 XFree((char *) vinfo);
1555 /* Fill in the XStandardColormap structure */
1557 if (cmap == DefaultColormap(dpy, screen)) {
1558 /* Allocating out of the default map, cannot use XFreeColormap() */
1559 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1560 0, 0, InputOnly, vinfo->visual,
1562 (XSetWindowAttributes *)NULL);
1563 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1564 XDestroyWindow(dpy, win);
1565 stdcmap->colormap = cmap;
1567 stdcmap->killid = ReleaseByFreeingColormap;
1568 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1569 vinfo->visual, AllocNone);
1571 stdcmap->red_max = red_max;
1572 stdcmap->green_max = green_max;
1573 stdcmap->blue_max = blue_max;
1574 if (property == XA_RGB_GRAY_MAP)
1575 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1576 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1577 stdcmap->red_mult = lowbit(vinfo->red_mask);
1578 stdcmap->green_mult = lowbit(vinfo->green_mask);
1579 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1581 stdcmap->red_mult = (red_max > 0)
1582 ? (green_max + 1) * (blue_max + 1) : 0;
1583 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1584 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1586 stdcmap->base_pixel = 0; /* base pixel may change */
1587 stdcmap->visualid = vinfo->visualid;
1589 /* Make the colormap */
1591 status = XmuCreateColormap(dpy, stdcmap);
1595 XFree((char *) vinfo);
1598 /* Free the colormap or the pixmap, if we created one */
1599 if (stdcmap->killid == ReleaseByFreeingColormap)
1600 XFreeColormap(dpy, stdcmap->colormap);
1601 else if (stdcmap->killid != None)
1602 XFreePixmap(dpy, stdcmap->killid);
1604 XFree((char *) stdcmap);
1605 return (XStandardColormap *) NULL;
1610 /****************************************************************************/
1612 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1613 unsigned long blue_max, Atom property)
1615 * vinfo - specifies visual
1616 * red_max, green_max, blue_max - specifies alloc
1617 * property - specifies property name
1620 unsigned long ncolors; /* number of colors requested */
1622 /* Determine that the number of colors requested is <= map size */
1624 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1627 mask = vinfo->red_mask;
1632 mask = vinfo->green_mask;
1635 if (green_max > mask)
1637 mask = vinfo->blue_mask;
1640 if (blue_max > mask)
1642 } else if (property == XA_RGB_GRAY_MAP) {
1643 ncolors = red_max + green_max + blue_max + 1;
1644 if (ncolors > vinfo->colormap_size)
1647 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1648 if (ncolors > vinfo->colormap_size)
1652 /* Determine that the allocation and visual make sense for the property */
1656 case XA_RGB_DEFAULT_MAP:
1657 if (red_max == 0 || green_max == 0 || blue_max == 0)
1660 case XA_RGB_RED_MAP:
1664 case XA_RGB_GREEN_MAP:
1668 case XA_RGB_BLUE_MAP:
1672 case XA_RGB_BEST_MAP:
1673 if (red_max == 0 || green_max == 0 || blue_max == 0)
1676 case XA_RGB_GRAY_MAP:
1677 if (red_max == 0 || blue_max == 0 || green_max == 0)
1687 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1691 Copyright 1989, 1998 The Open Group
1693 Permission to use, copy, modify, distribute, and sell this software and its
1694 documentation for any purpose is hereby granted without fee, provided that
1695 the above copyright notice appear in all copies and that both that
1696 copyright notice and this permission notice appear in supporting
1699 The above copyright notice and this permission notice shall be included in
1700 all copies or substantial portions of the Software.
1702 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1703 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1704 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1705 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1706 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1707 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1709 Except as contained in this notice, the name of The Open Group shall not be
1710 used in advertising or otherwise to promote the sale, use or other dealings
1711 in this Software without prior written authorization from The Open Group.
1714 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1717 * Author: Donna Converse, MIT X Consortium
1721 * CreateCmap.c - given a standard colormap description, make the map.
1726 #include <X11/Xlib.h>
1727 #include <X11/Xutil.h>
1728 #include <X11/Xmu/StdCmap.h>
1733 /* allocate entire map Read Only */
1734 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1736 /* allocate a cell, prefer Read Only */
1737 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1738 XColor*, unsigned long);
1740 /* allocate a cell Read Write */
1741 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1744 static int compare(_Xconst void*, _Xconst void*);
1746 /* find contiguous sequence of cells */
1747 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1749 /* frees resources before quitting */
1750 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1752 /* create a map in a RO visual type */
1753 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1755 /* create a map in a RW visual type */
1756 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1758 #define lowbit(x) ((x) & (~(x) + 1))
1759 #define TRUEMATCH(mult,max,mask) \
1760 (colormap->max * colormap->mult <= vinfo->mask && \
1761 lowbit(vinfo->mask) == colormap->mult)
1764 * To create any one colormap which is described by an XStandardColormap
1765 * structure, use XmuCreateColormap().
1767 * Return 0 on failure, non-zero on success.
1768 * Resources created by this function are not made permanent.
1769 * No argument error checking is provided. Use at your own risk.
1771 * All colormaps are created with read only allocations, with the exception
1772 * of read only allocations of colors in the default map or otherwise
1773 * which fail to return the expected pixel value, and these are individually
1774 * defined as read/write allocations. This is done so that all the cells
1775 * defined in the default map are contiguous, for use in image processing.
1776 * This typically happens with White and Black in the default map.
1778 * Colormaps of static visuals are considered to be successfully created if
1779 * the map of the static visual matches the definition given in the
1780 * standard colormap structure.
1784 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1785 /* dpy - specifies the connection under which the map is created
1786 * colormap - specifies the map to be created, and returns, particularly
1787 * if the map is created as a subset of the default colormap
1788 * of the screen, the base_pixel of the map.
1791 XVisualInfo vinfo_template; /* template visual information */
1792 XVisualInfo *vinfo; /* matching visual information */
1793 XVisualInfo *vpointer; /* for freeing the entire list */
1794 long vinfo_mask; /* specifies the visual mask value */
1795 int n; /* number of matching visuals */
1798 vinfo_template.visualid = colormap->visualid;
1799 vinfo_mask = VisualIDMask;
1800 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1803 /* A visual id may be valid on multiple screens. Also, there may
1804 * be multiple visuals with identical visual ids at different depths.
1805 * If the colormap is the Default Colormap, use the Default Visual.
1806 * Otherwise, arbitrarily, use the deepest visual.
1812 register int screen_number;
1816 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1817 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1823 for (i=0; i < n; i++, vinfo++) {
1824 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1829 XVisualInfo *v = NULL;
1831 for (i=0; i < n; i++, vinfo++)
1832 if (vinfo->depth > maxdepth) {
1833 maxdepth = vinfo->depth;
1840 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1841 vinfo->c_class == GrayScale)
1842 status = readwrite_map(dpy, vinfo, colormap);
1843 else if (vinfo->c_class == TrueColor)
1844 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1845 TRUEMATCH(green_mult, green_max, green_mask) &&
1846 TRUEMATCH(blue_mult, blue_max, blue_mask);
1848 status = readonly_map(dpy, vinfo, colormap);
1850 XFree((char *) vpointer);
1854 /****************************************************************************/
1856 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1858 register unsigned long i, n; /* index counters */
1859 unsigned long ncolors; /* number of colors to be defined */
1860 int npixels; /* number of pixels allocated R/W */
1861 int first_index; /* first index of pixels to use */
1862 int remainder; /* first index of remainder */
1863 XColor color; /* the definition of a color */
1864 unsigned long *pixels; /* array of colormap pixels */
1865 unsigned long delta;
1868 /* Determine ncolors, the number of colors to be defined.
1869 * Insure that 1 < ncolors <= the colormap size.
1871 if (vinfo->c_class == DirectColor) {
1872 ncolors = colormap->red_max;
1873 if (colormap->green_max > ncolors)
1874 ncolors = colormap->green_max;
1875 if (colormap->blue_max > ncolors)
1876 ncolors = colormap->blue_max;
1878 delta = lowbit(vinfo->red_mask) +
1879 lowbit(vinfo->green_mask) +
1880 lowbit(vinfo->blue_mask);
1882 ncolors = colormap->red_max * colormap->red_mult +
1883 colormap->green_max * colormap->green_mult +
1884 colormap->blue_max * colormap->blue_mult + 1;
1887 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1889 /* Allocate Read/Write as much of the colormap as we can possibly get.
1890 * Then insure that the pixels we were allocated are given in
1891 * monotonically increasing order, using a quicksort. Next, insure
1892 * that our allocation includes a subset of contiguous pixels at least
1893 * as long as the number of colors to be defined. Now we know that
1894 * these conditions are met:
1895 * 1) There are no free cells in the colormap.
1896 * 2) We have a contiguous sequence of pixels, monotonically
1897 * increasing, of length >= the number of colors requested.
1899 * One cell at a time, we will free, compute the next color value,
1900 * then allocate read only. This takes a long time.
1901 * This is done to insure that cells are allocated read only in the
1902 * contiguous order which we prefer. If the server has a choice of
1903 * cells to grant to an allocation request, the server may give us any
1904 * cell, so that is why we do these slow gymnastics.
1907 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1908 sizeof(unsigned long))) == NULL)
1911 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1912 vinfo->colormap_size, ncolors)) == 0) {
1913 free((char *) pixels);
1917 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1919 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1921 /* can't find enough contiguous cells, give up */
1922 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1924 free((char *) pixels);
1927 colormap->base_pixel = pixels[first_index];
1929 /* construct a gray map */
1930 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1931 colormap->blue_mult == 1)
1932 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1935 color.blue = color.green = color.red =
1936 (unsigned short) ((i * 65535) / (colormap->red_max +
1937 colormap->green_max +
1938 colormap->blue_max));
1940 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1945 /* construct a red ramp map */
1946 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1947 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1950 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1951 color.green = color.blue = 0;
1953 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1958 /* construct a green ramp map */
1959 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1960 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1963 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1964 color.red = color.blue = 0;
1966 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1971 /* construct a blue ramp map */
1972 else if (colormap->red_max == 0 && colormap->green_max == 0)
1973 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1976 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1977 color.red = color.green = 0;
1979 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1984 /* construct a standard red green blue cube map */
1987 #define calc(max,mult) (((n / colormap->mult) % \
1988 (colormap->max + 1)) * 65535) / colormap->max
1990 for (n=0, i=0; i < ncolors; i++, n += delta)
1992 color.pixel = n + colormap->base_pixel;
1993 color.red = calc(red_max, red_mult);
1994 color.green = calc(green_max, green_mult);
1995 color.blue = calc(blue_max, blue_mult);
1996 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2002 /* We have a read-only map defined. Now free unused cells,
2003 * first those occuring before the contiguous sequence begins,
2004 * then any following the contiguous sequence.
2008 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2011 XFreeColors(dpy, colormap->colormap,
2012 &(pixels[first_index + ncolors]), remainder,
2015 free((char *) pixels);
2020 /****************************************************************************/
2022 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2024 * dpy - the X server connection
2025 * cmap - specifies colormap ID
2026 * pixels - returns pixel allocations
2027 * m - specifies colormap size
2028 * n - specifies number of colors
2033 /* first try to allocate the entire colormap */
2034 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2035 (unsigned) 0, pixels, (unsigned) m))
2038 /* Allocate all available cells in the colormap, using a binary
2039 * algorithm to discover how many cells we can allocate in the colormap.
2043 p = n + ((m - n + 1) / 2);
2044 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2045 (unsigned) 0, pixels, (unsigned) p)) {
2049 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2060 /****************************************************************************/
2062 contiguous(unsigned long pixels[], int npixels, int ncolors,
2063 unsigned long delta, int *first, int *rem)
2064 /* pixels - specifies allocated pixels
2065 * npixels - specifies count of alloc'd pixels
2066 * ncolors - specifies needed sequence length
2067 * delta - between pixels
2068 * first - returns first index of sequence
2069 * rem - returns first index after sequence, or 0, if none follow
2072 register int i = 1; /* walking index into the pixel array */
2073 register int count = 1; /* length of sequence discovered so far */
2076 if (npixels == ncolors) {
2081 while (count < ncolors && ncolors - count <= *rem)
2083 if (pixels[i-1] + delta == pixels[i])
2092 if (count != ncolors)
2098 /****************************************************************************/
2100 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2101 int npixels, XColor *color, unsigned long p)
2103 unsigned long pixel;
2106 /* Free the read/write allocation of one cell in the colormap.
2107 * Request a read only allocation of one cell in the colormap.
2108 * If the read only allocation cannot be granted, give up, because
2109 * there must be no free cells in the colormap.
2110 * If the read only allocation is granted, but gives us a cell which
2111 * is not the one that we just freed, it is probably the case that
2112 * we are trying allocate White or Black or some other color which
2113 * already has a read-only allocation in the map. So we try to
2114 * allocate the previously freed cell with a read/write allocation,
2115 * because we want contiguous cells for image processing algorithms.
2118 pixel = color->pixel;
2119 request.red = color->red;
2120 request.green = color->green;
2121 request.blue = color->blue;
2123 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2124 if (! XAllocColor(dpy, cmap, color)
2125 || (color->pixel != pixel &&
2126 (!RWcell(dpy, cmap, color, &request, &pixel))))
2128 free_cells(dpy, cmap, pixels, npixels, (int)p);
2135 /****************************************************************************/
2137 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2140 * pixels - to be freed
2141 * npixels - original number allocated
2144 /* One of the npixels allocated has already been freed.
2145 * p is the index of the freed pixel.
2146 * First free the pixels preceeding p, and there are p of them;
2147 * then free the pixels following p, there are npixels - p - 1 of them.
2149 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2150 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2151 free((char *) pixels);
2155 /****************************************************************************/
2157 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2158 unsigned long *pixel)
2160 unsigned long n = *pixel;
2162 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2163 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2164 (unsigned) 0, pixel, (unsigned) 1))
2168 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2171 color->pixel = *pixel;
2172 color->flags = DoRed | DoGreen | DoBlue;
2173 color->red = request->red;
2174 color->green = request->green;
2175 color->blue = request->blue;
2176 XStoreColors(dpy, cmap, color, 1);
2181 /****************************************************************************/
2183 compare(_Xconst void *e1, _Xconst void *e2)
2185 return ((int)(*(long *)e1 - *(long *)e2));
2189 /****************************************************************************/
2191 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2196 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2197 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2199 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2201 color.pixel = (unsigned long) i;
2202 color.red = (unsigned short)
2203 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2205 if (vinfo->c_class == StaticColor) {
2206 color.green = (unsigned short)
2207 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2208 65535) / colormap->green_max);
2209 color.blue = (unsigned short)
2210 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2212 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2213 color.green = color.blue = color.red;
2215 XAllocColor(dpy, colormap->colormap, &color);
2216 if (color.pixel != (unsigned long) i)
2223 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2227 Copyright 1989, 1998 The Open Group
2229 Permission to use, copy, modify, distribute, and sell this software and its
2230 documentation for any purpose is hereby granted without fee, provided that
2231 the above copyright notice appear in all copies and that both that
2232 copyright notice and this permission notice appear in supporting
2235 The above copyright notice and this permission notice shall be included in
2236 all copies or substantial portions of the Software.
2238 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2239 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2240 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2241 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2242 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2243 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2245 Except as contained in this notice, the name of The Open Group shall not be
2246 used in advertising or otherwise to promote the sale, use or other dealings
2247 in this Software without prior written authorization from The Open Group.
2250 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2253 * Author: Donna Converse, MIT X Consortium
2256 #include <X11/Xlib.h>
2257 #include <X11/Xutil.h>
2258 #include <X11/Xmu/StdCmap.h>
2260 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2262 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2263 * XmuDeleteStandardColormap() will remove the specified property from the
2264 * specified screen, releasing any resources used by the colormap(s) of the
2265 * property if possible.
2269 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2270 /* dpy; - specifies the X server to connect to
2271 * screen - specifies the screen of the display
2272 * property - specifies the standard colormap property
2275 XStandardColormap *stdcmaps, *s;
2278 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2281 for (s=stdcmaps; count > 0; count--, s++) {
2282 if ((s->killid == ReleaseByFreeingColormap) &&
2283 (s->colormap != None) &&
2284 (s->colormap != DefaultColormap(dpy, screen))) {
2286 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2287 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2289 XFreeColormap(dpy, s->colormap);
2291 XSetErrorHandler(oldHandler);
2294 } else if (s->killid != None) {
2295 XKillClient(dpy, s->killid);
2298 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2299 XFree((char *) stdcmaps);