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);
303 // X11Surface //////////////////////////////////////////////////////////////////////
305 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
306 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
307 org::xwt::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
308 p->buildPixelBuffer(1);
310 memset(&xwmh, 0, sizeof(XWMHints));
311 xwmh.flags |= IconPixmapHint | IconMaskHint;
312 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
313 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
314 XSetWMHints(display, (*((Window*)window)), &xwmh);
315 p->doublebuf = old_dbuf;
318 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
319 int len = min(JvGetStringUTFLength(s), 1024);
321 JvGetStringUTFRegion(s, 0, len, buf);
325 tp.value = (unsigned char*)buf;
327 tp.encoding = XA_STRING;
329 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
330 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
333 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
335 hints.min_width = minw;
336 hints.min_height = minh;
337 hints.max_width = maxw;
338 hints.max_height = maxh;
339 hints.flags = PMinSize | PMaxSize;
340 XSetWMNormalHints(display, (*((Window*)window)), &hints);
343 void org::xwt::plat::X11$X11Surface::setSize (jint width, jint height) {
344 if (width <= 0 || height <= 0) return;
345 XResizeWindow(display, (*((Window*)window)), width, height);
349 void org::xwt::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
350 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
351 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
353 void org::xwt::plat::X11$X11Surface::_dispose() {
354 // without this we get phantom messages after the window is gone
355 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
356 XDestroyWindow(display, (*((Window*)window)));
359 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
360 if (i) XUnmapWindow(display, (*((Window*)window)));
361 else XMapRaised(display, (*((Window*)window)));
365 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
366 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
367 else XMapRaised(display, (*((Window*)window)));
371 void org::xwt::plat::X11$X11Surface::natInit() {
372 XSetWindowAttributes xswa;
373 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
374 xswa.bit_gravity = NorthWestGravity;
375 xswa.colormap = s_colormap;
376 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
377 KeyPressMask | KeyReleaseMask | ButtonPressMask |
378 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
379 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
380 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
381 colorDepth, InputOutput, CopyFromParent,
382 CWColormap | CWBitGravity | CWEventMask, &xswa);
385 // I don't know why this works....
386 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
387 XChangeProperty(display, (*((Window*)window)),
388 XInternAtom(display, "_MOTIF_WM_HINTS", False),
389 XInternAtom(display, "_MOTIF_WM_HINTS", False),
397 tp.value = (unsigned char*)"XWT";
399 tp.encoding = XA_STRING;
401 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
403 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
404 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
406 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
407 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
410 XMapRaised(display, (*((Window*)window)));
413 waitForCreation->block();
414 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
417 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
418 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
421 vm.graphics_exposures = 0;
422 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
426 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
428 XEvent* e = (XEvent*)ev;
429 if (e->type == Expose) {
430 XExposeEvent *expose = (XExposeEvent*)(e);
431 Dirty(expose->x, expose->y, expose->width, expose->height);
433 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
434 } else if (e->type == UnmapNotify) { Minimized(1);
435 } else if (e->type == FocusIn) { Focused(1);
436 } else if (e->type == FocusOut) { Focused(0);
437 } else if (e->type == ClientMessage) {
438 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
440 } else if (e->type == KeyPress || e->type == KeyRelease) {
441 XKeyEvent *xbe = (XKeyEvent*)(e);
443 // drop faked KeyRelease events generated by the X server's autorepeat
444 if (e->type == KeyRelease) {
446 XQueryKeymap(display, depressed);
447 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
453 unsigned int savestate = xbe->state;
454 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
455 XLookupString(xbe, s, 20, NULL, NULL);
456 xbe->state = savestate;
458 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
462 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
464 case XK_BackSpace: s = "back_space"; break;
465 case XK_Tab: s = "tab"; break;
466 case XK_Linefeed: s = "enter"; break;
467 case XK_Return: s = "enter"; break;
468 case XK_Scroll_Lock: s = "scroll_lock"; break;
469 case XK_Escape: s = "escape"; break;
470 case XK_Insert: s = "insert"; break;
471 case XK_Delete: s = "delete"; break;
472 case XK_Home: s = "home"; break;
473 case XK_Left: s = "left"; break;
474 case XK_Up: s = "up"; break;
475 case XK_Right: s = "right"; break;
476 case XK_Down: s = "down"; break;
477 case XK_Page_Up: s = "page_up"; break;
478 case XK_Page_Down: s = "page_down"; break;
479 case XK_End: s = "end"; break;
480 case XK_Num_Lock: s = "num_lock"; break;
481 case XK_KP_Tab: s = "tab"; break;
482 case XK_KP_Enter: s = "enter"; break;
483 case XK_KP_F1: s = "f1"; break;
484 case XK_KP_F2: s = "f2"; break;
485 case XK_KP_F3: s = "f3"; break;
486 case XK_KP_F4: s = "f4"; break;
487 case XK_KP_Home: s = "home"; break;
488 case XK_KP_Left: s = "left"; break;
489 case XK_KP_Up: s = "up"; break;
490 case XK_KP_Right: s = "right"; break;
491 case XK_KP_Down: s = "down"; break;
492 case XK_KP_Page_Up: s = "page_up"; break;
493 case XK_KP_Page_Down: s = "page_down"; break;
494 case XK_KP_End: s = "end"; break;
495 case XK_KP_Insert: s = "insert"; break;
496 case XK_KP_Delete: s = "delete"; break;
497 case XK_F1: s = "f1"; break;
498 case XK_F2: s = "f2"; break;
499 case XK_F3: s = "f3"; break;
500 case XK_F4: s = "f4"; break;
501 case XK_F5: s = "f5"; break;
502 case XK_F6: s = "f6"; break;
503 case XK_F7: s = "f7"; break;
504 case XK_F8: s = "f8"; break;
505 case XK_F9: s = "f9"; break;
506 case XK_F10: s = "f10"; break;
507 case XK_F11: s = "f11"; break;
508 case XK_F12: s = "f12"; break;
509 case XK_Shift_L: s = "shift"; break;
510 case XK_Shift_R: s = "shift"; break;
511 case XK_Control_L: s = "control"; break;
512 case XK_Control_R: s = "control"; break;
513 case XK_Meta_L: s = "alt"; break;
514 case XK_Meta_R: s = "alt"; break;
515 case XK_Alt_L: s = "alt"; break;
516 case XK_Alt_R: s = "alt"; break;
521 jstring s2 = JvNewStringLatin1(s);
522 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
523 if (e->type == KeyRelease) KeyReleased(s2);
525 } else if (e->type == ButtonPress) {
526 XButtonEvent* xbe = (XButtonEvent*)(e);
527 if (xbe->button == 2) xbe->button = 3;
528 else if (xbe->button == 3) xbe->button = 2;
531 } else if (e->type == ButtonRelease) {
532 XButtonEvent* xbe = (XButtonEvent*)(e);
533 if (xbe->button == 2) xbe->button = 3;
534 else if (xbe->button == 3) xbe->button = 2;
535 Release(xbe->button);
537 } else if (e->type == MotionNotify) {
538 XMotionEvent* xme = (XMotionEvent*)(e);
539 Move(xme->x, xme->y);
541 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
542 XCrossingEvent* xce = (XCrossingEvent*)(e);
543 Move(xce->x, xce->y);
545 } else if (e->type == ConfigureNotify) {
548 XConfigureEvent* xce = (XConfigureEvent*)(e);
549 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
550 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
551 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
556 static jstring crosshair, east, hand, move, north, northeast, northwest,
557 south, southeast, southwest, text, west, wait_string;
558 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
559 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
560 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
562 void org::xwt::plat::X11$X11Surface::syncCursor() {
565 if (cursor->equals(crosshair)) curs = crosshair_cursor;
566 else if (cursor->equals(east)) curs = east_cursor;
567 else if (cursor->equals(hand)) curs = hand_cursor;
568 else if (cursor->equals(move)) curs = move_cursor;
569 else if (cursor->equals(north)) curs = north_cursor;
570 else if (cursor->equals(northeast)) curs = northeast_cursor;
571 else if (cursor->equals(northwest)) curs = northwest_cursor;
572 else if (cursor->equals(south)) curs = south_cursor;
573 else if (cursor->equals(southeast)) curs = southeast_cursor;
574 else if (cursor->equals(southwest)) curs = southwest_cursor;
575 else if (cursor->equals(text)) curs = text_cursor;
576 else if (cursor->equals(west)) curs = west_cursor;
577 else if (cursor->equals(wait_string)) curs = wait_cursor;
578 else curs = default_cursor;
580 XDefineCursor(display, (*((Window*)window)), curs);
585 // X11 ///////////////////////////////////////////////////////////////////
587 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
588 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
590 static void dispatchSelectionEvent(XEvent* e) {
591 if (e->type == SelectionNotify) {
592 XSelectionEvent* xsn = (XSelectionEvent*)(e);
593 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
597 unsigned long numitems;
599 unsigned long bytes_after;
600 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
601 True, AnyPropertyType, &returntype, &returnformat,
602 &numitems, &bytes_after, &ret);
603 org::xwt::plat::X11::clipboard =
604 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
606 org::xwt::plat::X11::waiting_for_selection_event->release();
608 } else if (e->type == SelectionRequest) {
609 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
611 xsn.type = SelectionNotify;
612 xsn.serial = xsr->serial;
613 xsn.send_event = True;
614 xsn.display = display;
615 xsn.requestor = xsr->requestor;
616 xsn.selection = xsr->selection;
617 xsn.target = xsr->target;
618 xsn.property = xsr->property;
619 xsn.time = xsr->time;
621 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
623 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
626 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
627 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
631 void org::xwt::plat::X11::eventThread() {
634 XNextEvent(display, &e);
635 if (e.type == SelectionNotify || e.type == SelectionRequest) {
636 dispatchSelectionEvent(&e);
638 org::xwt::plat::X11$X11Surface* surface =
639 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
640 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
645 jstring org::xwt::plat::X11::_getClipBoard() {
646 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
648 org::xwt::plat::X11::waiting_for_selection_event->block();
652 void org::xwt::plat::X11::_setClipBoard(jstring s) {
654 int len = JvGetStringUTFLength(clipboard);
656 JvGetStringUTFRegion(clipboard, 0, len, buf);
658 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
661 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
662 int errorHandler(Display* d, XErrorEvent* e) {
663 // this error handler is only installed during the initial
664 // test to see if shm is present
668 void org::xwt::plat::X11::natInit() {
671 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
673 char* DISPLAY = getenv("DISPLAY");
674 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
675 display = XOpenDisplay(DISPLAY);
678 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
680 screen_num = XDefaultScreen(display);
681 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
682 shm_info.shmaddr = NULL;
684 // FIXME: SHM doesn't work on Darwin
685 //shm_supported = (XShmQueryExtension(display) == True);
687 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
688 XShmSegmentInfo sinfo;
689 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
690 sinfo.readOnly = False;
691 // if the server is remote, this will trigger the error handler
692 XShmAttach(display, &sinfo);
693 XSync(display, False);
694 XSetErrorHandler(oldHandler);
698 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
700 crosshair = JvNewStringLatin1("crosshair");
701 east = JvNewStringLatin1("east");
702 hand = JvNewStringLatin1("hand");
703 move = JvNewStringLatin1("move");
704 north = JvNewStringLatin1("north");
705 northeast = JvNewStringLatin1("northeast");
706 northwest = JvNewStringLatin1("northwest");
707 south = JvNewStringLatin1("south");
708 southeast = JvNewStringLatin1("southeast");
709 southwest = JvNewStringLatin1("southwest");
710 text = JvNewStringLatin1("text");
711 west = JvNewStringLatin1("west");
712 wait_string = JvNewStringLatin1("wait");
713 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
714 east_cursor = XCreateFontCursor(display, XC_right_side);
715 hand_cursor = XCreateFontCursor(display, XC_hand2);
716 move_cursor = XCreateFontCursor(display, XC_fleur);
717 north_cursor = XCreateFontCursor(display, XC_top_side);
718 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
719 northwest_cursor = XCreateFontCursor(display, XC_left_side);
720 south_cursor = XCreateFontCursor(display, XC_bottom_side);
721 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
722 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
723 text_cursor = XCreateFontCursor(display, XC_xterm);
724 west_cursor = XCreateFontCursor(display, XC_right_side);
725 wait_cursor = XCreateFontCursor(display, XC_watch);
726 default_cursor = XCreateFontCursor(display, XC_left_ptr);
728 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
729 visual = DefaultVisual(display, screen_num);
731 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
732 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
733 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
734 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
735 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
736 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
737 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
739 // FIXME: don't know why (True, False) is the best solution...
740 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
741 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
743 XStandardColormap* best_map_info = NULL;
745 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
746 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
747 if (!best_map_info->colormap)
748 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
749 if (best_map_info->red_max == 0)
750 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
751 s_colormap = best_map_info->colormap;
752 colormap_info = best_map_info;
754 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
755 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
756 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
757 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
758 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
759 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
760 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
761 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
766 //////////////////////////////////////////////////////////////////////////////
767 //////////////////////////////////////////////////////////////////////////////
768 //////////////////////////////////////////////////////////////////////////////
769 //////////////////////////////////////////////////////////////////////////////
771 // Everything below this point was taken, cut-and-paste, from the //
772 // source for libXmu. It implements the official 'standard colormap //
773 // creation algorithm. I made some small changes to //
774 // XmuDeleteStandardColormap //
776 //////////////////////////////////////////////////////////////////////////////
777 //////////////////////////////////////////////////////////////////////////////
778 //////////////////////////////////////////////////////////////////////////////
779 //////////////////////////////////////////////////////////////////////////////
781 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
785 Copyright 1989, 1998 The Open Group
787 Permission to use, copy, modify, distribute, and sell this software and its
788 documentation for any purpose is hereby granted without fee, provided that
789 the above copyright notice appear in all copies and that both that
790 copyright notice and this permission notice appear in supporting
793 The above copyright notice and this permission notice shall be included in
794 all copies or substantial portions of the Software.
796 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
797 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
798 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
799 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
800 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
801 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
803 Except as contained in this notice, the name of The Open Group shall not be
804 used in advertising or otherwise to promote the sale, use or other dealings
805 in this Software without prior written authorization from The Open Group.
808 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
811 * Author: Donna Converse, MIT X Consortium
815 #include <X11/Xlib.h>
816 #include <X11/Xatom.h>
817 #include <X11/Xutil.h>
818 #include <X11/Xmu/StdCmap.h>
824 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
827 * To create a standard colormap if one does not currently exist, or
828 * replace the currently existing standard colormap, use
829 * XmuLookupStandardColormap().
831 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
832 * will determine the best allocation for the property under the specified
833 * visual, and determine the whether to create a new colormap or to use
834 * the default colormap of the screen. It will call XmuStandardColormap()
835 * to create the standard colormap.
837 * If replace is true, any previous definition of the property will be
838 * replaced. If retain is true, the property and the colormap will be
839 * made permanent for the duration of the server session. However,
840 * pre-existing property definitions which are not replaced cannot be made
841 * permanent by a call to XmuLookupStandardColormap(); a request to retain
842 * resources pertains to newly created resources.
844 * Returns 0 on failure, non-zero on success. A request to create a
845 * standard colormap upon a visual which cannot support such a map is
846 * considered a failure. An example of this would be requesting any
847 * standard colormap property on a monochrome visual, or, requesting an
848 * RGB_BEST_MAP on a display whose colormap size is 16.
852 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
853 unsigned int depth, Atom property,
854 Bool replace, Bool retain)
856 * dpy - specifies X server connection
857 * screen - specifies screen of display
858 * visualid - specifies the visual type
859 * depth - specifies the visual type
860 * property - a standard colormap property
861 * replace - specifies whether to replace
862 * retain - specifies whether to retain
865 Display *odpy; /* original display connection */
866 XStandardColormap *colormap;
867 XVisualInfo vinfo_template, *vinfo; /* visual */
869 unsigned long r_max, g_max, b_max; /* allocation */
871 Colormap cmap; /* colormap ID */
875 /* Match the requested visual */
877 vinfo_template.visualid = visualid;
878 vinfo_template.screen = screen;
879 vinfo_template.depth = depth;
880 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
881 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
885 /* Monochrome visuals have no standard maps */
887 if (vinfo->colormap_size <= 2) {
888 XFree((char *) vinfo);
892 /* If the requested property already exists on this screen, and,
893 * if the replace flag has not been set to true, return success.
894 * lookup() will remove a pre-existing map if replace is true.
897 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
898 replace) && !replace) {
899 XFree((char *) vinfo);
903 /* Determine the best allocation for this property under the requested
904 * visualid and depth, and determine whether or not to use the default
905 * colormap of the screen.
908 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
909 XFree((char *) vinfo);
913 cmap = (property == XA_RGB_DEFAULT_MAP &&
914 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
915 ? DefaultColormap(dpy, screen) : None;
917 /* If retaining resources, open a new connection to the same server */
921 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
922 XFree((char *) vinfo);
927 /* Create the standard colormap */
929 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
930 cmap, r_max, g_max, b_max);
932 /* Set the standard colormap property */
937 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
939 /* Someone has defined the property since we last looked.
940 * Since we will not replace it, release our own resources.
941 * If this is the default map, our allocations will be freed
942 * when this connection closes.
944 if (colormap->killid == ReleaseByFreeingColormap)
945 XFreeColormap(dpy, colormap->colormap);
947 XSetCloseDownMode(dpy, RetainPermanent);
950 XFree((char *) colormap);
956 XFree((char *) vinfo);
960 /***************************************************************************/
962 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
963 * the visualid is used to determine whether the indicated standard colormap
964 * exists. If the map exists and replace is true, delete the resources used
965 * by the map and remove the property. Return true if the map exists,
966 * or did exist and was deleted; return false if the map was not found.
968 * Note that this is not the way that a Status return is normally used.
970 * If new is not NULL, new points to an XStandardColormap structure which
971 * describes a standard colormap of the specified property. It will be made
972 * a standard colormap of the screen if none already exists, or if replace
977 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
978 XStandardColormap *cnew, Bool replace)
980 * dpy - specifies display connection
981 * screen - specifies screen number
982 * visualid - specifies visualid for std map
983 * property - specifies colormap property name
984 * cnew - specifies a standard colormap
985 * replace - specifies whether to replace
990 XStandardColormap *stdcmaps, *s;
991 Window win = RootWindow(dpy, screen);
993 /* The property does not already exist */
995 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
997 XSetRGBColormaps(dpy, win, cnew, 1, property);
1001 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1003 if (property != XA_RGB_DEFAULT_MAP) {
1005 XmuDeleteStandardColormap(dpy, screen, property);
1007 XSetRGBColormaps(dpy, win, cnew, 1, property);
1009 XFree((char *)stdcmaps);
1013 /* The property exists and is RGB_DEFAULT_MAP */
1015 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1018 /* No RGB_DEFAULT_MAP property matches the given visualid */
1022 XStandardColormap *m, *maps;
1024 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1025 (XStandardColormap)));
1027 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1028 m->colormap = maps->colormap;
1029 m->red_max = maps->red_max;
1030 m->red_mult = maps->red_mult;
1031 m->green_max = maps->green_max;
1032 m->green_mult = maps->green_mult;
1033 m->blue_max = maps->blue_max;
1034 m->blue_mult = maps->blue_mult;
1035 m->base_pixel = maps->base_pixel;
1036 m->visualid = maps->visualid;
1037 m->killid = maps->killid;
1039 m->colormap = cnew->colormap;
1040 m->red_max = cnew->red_max;
1041 m->red_mult = cnew->red_mult;
1042 m->green_max = cnew->green_max;
1043 m->green_mult = cnew->green_mult;
1044 m->blue_max = cnew->blue_max;
1045 m->blue_mult = cnew->blue_mult;
1046 m->base_pixel = cnew->base_pixel;
1047 m->visualid = cnew->visualid;
1048 m->killid = cnew->killid;
1050 XSetRGBColormaps(dpy, win, s, ++count, property);
1053 XFree((char *) stdcmaps);
1057 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1060 /* Free old resources first - we may need them, particularly in
1061 * the default colormap of the screen. However, because of this,
1062 * it is possible that we will destroy the old resource and fail
1063 * to create a new one if XmuStandardColormap() fails.
1067 XmuDeleteStandardColormap(dpy, screen, property);
1069 XSetRGBColormaps(dpy, win, cnew, 1, property);
1072 XStandardColormap *map;
1074 /* s still points to the matching standard colormap */
1076 if (s->killid == ReleaseByFreeingColormap) {
1077 if ((s->colormap != None) &&
1078 (s->colormap != DefaultColormap(dpy, screen)))
1079 XFreeColormap(dpy, s->colormap);
1081 else if (s->killid != None)
1082 XKillClient(dpy, s->killid);
1084 map = (cnew) ? cnew : stdcmaps + --count;
1086 s->colormap = map->colormap;
1087 s->red_max = map->red_max;
1088 s->red_mult = map->red_mult;
1089 s->green_max = map->green_max;
1090 s->green_mult = map->green_mult;
1091 s->blue_max = map->blue_max;
1092 s->blue_mult = map->blue_mult;
1093 s->visualid = map->visualid;
1094 s->killid = map->killid;
1096 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1099 XFree((char *) stdcmaps);
1103 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1107 Copyright 1989, 1994, 1998 The Open Group
1109 Permission to use, copy, modify, distribute, and sell this software and its
1110 documentation for any purpose is hereby granted without fee, provided that
1111 the above copyright notice appear in all copies and that both that
1112 copyright notice and this permission notice appear in supporting
1115 The above copyright notice and this permission notice shall be included in
1116 all copies or substantial portions of the Software.
1118 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1119 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1120 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1121 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1122 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1123 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1125 Except as contained in this notice, the name of The Open Group shall not be
1126 used in advertising or otherwise to promote the sale, use or other dealings
1127 in this Software without prior written authorization from The Open Group.
1130 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1133 * Author: Donna Converse, MIT X Consortium
1136 #include <X11/Xlib.h>
1137 #include <X11/Xatom.h>
1138 #include <X11/Xutil.h>
1139 #include <X11/Xmu/StdCmap.h>
1142 #define lowbit(x) ((x) & (~(x) + 1))
1147 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1149 static int default_allocation(XVisualInfo*, unsigned long*,
1150 unsigned long*, unsigned long*);
1151 static void gray_allocation(int, unsigned long*, unsigned long*,
1153 static int icbrt(int);
1154 static int icbrt_with_bits(int, int);
1155 static int icbrt_with_guess(int, int);
1157 /* To determine the best allocation of reds, greens, and blues in a
1158 * standard colormap, use XmuGetColormapAllocation.
1159 * vinfo specifies visual information for a chosen visual
1160 * property specifies one of the standard colormap property names
1161 * red_max returns maximum red value
1162 * green_max returns maximum green value
1163 * blue_max returns maximum blue value
1165 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1166 * It is assumed that the visual is appropriate for the colormap property.
1170 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1171 unsigned long *red_max,
1172 unsigned long *green_max,
1173 unsigned long *blue_max)
1177 if (vinfo->colormap_size <= 2)
1182 case XA_RGB_DEFAULT_MAP:
1183 status = default_allocation(vinfo, red_max, green_max, blue_max);
1185 case XA_RGB_BEST_MAP:
1186 best_allocation(vinfo, red_max, green_max, blue_max);
1188 case XA_RGB_GRAY_MAP:
1189 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1191 case XA_RGB_RED_MAP:
1192 *red_max = vinfo->colormap_size - 1;
1193 *green_max = *blue_max = 0;
1195 case XA_RGB_GREEN_MAP:
1196 *green_max = vinfo->colormap_size - 1;
1197 *red_max = *blue_max = 0;
1199 case XA_RGB_BLUE_MAP:
1200 *blue_max = vinfo->colormap_size - 1;
1201 *red_max = *green_max = 0;
1209 /****************************************************************************/
1210 /* Determine the appropriate color allocations of a gray scale.
1212 * Keith Packard, MIT X Consortium
1216 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1217 unsigned long *blue_max)
1219 *red_max = (n * 30) / 100;
1220 *green_max = (n * 59) / 100;
1221 *blue_max = (n * 11) / 100;
1222 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1225 /****************************************************************************/
1226 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1227 * If a map has less than a minimum number of definable entries, we do not
1228 * produce an allocation for an RGB_DEFAULT_MAP.
1230 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1231 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1232 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1233 * Maximum green and maximum blue values are identical to maximum red.
1234 * This leaves at least 125 cells which clients can allocate.
1236 * Return 0 if an allocation has been determined, non-zero otherwise.
1240 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1241 unsigned long *green, unsigned long *blue)
1243 int ngrays; /* number of gray cells */
1245 switch (vinfo->c_class)
1249 if (vinfo->colormap_size > 65000)
1250 /* intended for displays with 16 planes */
1251 *red = *green = *blue = (unsigned long) 27;
1252 else if (vinfo->colormap_size > 4000)
1253 /* intended for displays with 12 planes */
1254 *red = *green = *blue = (unsigned long) 12;
1255 else if (vinfo->colormap_size < 250)
1258 /* intended for displays with 8 planes */
1259 *red = *green = *blue = (unsigned long)
1260 (icbrt(vinfo->colormap_size - 125) - 1);
1265 if (vinfo->colormap_size < 10)
1267 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1272 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1273 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1274 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1279 if (vinfo->colormap_size > 65000)
1281 else if (vinfo->colormap_size > 4000)
1283 else if (vinfo->colormap_size < 250)
1287 gray_allocation(ngrays, red, green, blue);
1296 /****************************************************************************/
1297 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1299 * For a DirectColor or TrueColor visual, the allocation is determined
1300 * by the red_mask, green_mask, and blue_mask members of the visual info.
1302 * Otherwise, if the colormap size is an integral power of 2, determine
1303 * the allocation according to the number of bits given to each color,
1304 * with green getting more than red, and red more than blue, if there
1305 * are to be inequities in the distribution. If the colormap size is
1306 * not an integral power of 2, let n = the number of colormap entries.
1307 * Then maximum red value = floor(cube_root(n)) - 1;
1308 * maximum blue value = floor(cube_root(n)) - 1;
1309 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1310 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1311 * defineable colormap entries.
1315 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1316 unsigned long *blue)
1319 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1321 *red = vinfo->red_mask;
1322 while ((*red & 01) == 0)
1324 *green = vinfo->green_mask;
1325 while ((*green & 01) == 0)
1327 *blue = vinfo->blue_mask;
1328 while ((*blue & 01) == 0)
1333 register int bits, n;
1335 /* Determine n such that n is the least integral power of 2 which is
1336 * greater than or equal to the number of entries in the colormap.
1340 while (vinfo->colormap_size > n)
1346 /* If the number of entries in the colormap is a power of 2, determine
1347 * the allocation by "dealing" the bits, first to green, then red, then
1348 * blue. If not, find the maximum integral red, green, and blue values
1349 * which, when multiplied together, do not exceed the number of
1353 if (n == vinfo->colormap_size)
1355 register int r, g, b;
1357 g = b + ((bits % 3) ? 1 : 0);
1358 r = b + (((bits % 3) == 2) ? 1 : 0);
1365 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1367 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1377 * integer cube roots by Newton's method
1379 * Stephen Gildea, MIT X Consortium, July 1991
1385 register int bits = 0;
1386 register unsigned n = a;
1393 return icbrt_with_bits(a, bits);
1398 icbrt_with_bits(int a, int bits)
1399 /* bits - log 2 of a */
1401 return icbrt_with_guess(a, a>>2*bits/3);
1404 #ifdef _X_ROOT_STATS
1405 int icbrt_loopcount;
1408 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1410 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1413 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1414 * Only works for positive integers (since that's all we need).
1415 * We actually return floor(cbrt(a)) because that's what we need here, too.
1419 icbrt_with_guess(int a, int guess)
1423 #ifdef _X_ROOT_STATS
1424 icbrt_loopcount = 0;
1432 #ifdef _X_ROOT_STATS
1435 delta = (guess - a/(guess*guess))/3;
1437 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1440 } while (delta != 0);
1442 if (guess*guess*guess > a)
1449 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1453 Copyright 1989, 1998 The Open Group
1455 Permission to use, copy, modify, distribute, and sell this software and its
1456 documentation for any purpose is hereby granted without fee, provided that
1457 the above copyright notice appear in all copies and that both that
1458 copyright notice and this permission notice appear in supporting
1461 The above copyright notice and this permission notice shall be included in
1462 all copies or substantial portions of the Software.
1464 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1465 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1466 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1467 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1468 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1469 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1471 Except as contained in this notice, the name of The Open Group shall not be
1472 used in advertising or otherwise to promote the sale, use or other dealings
1473 in this Software without prior written authorization from The Open Group.
1476 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1479 * Author: Donna Converse, MIT X Consortium
1483 #include <X11/Xlib.h>
1484 #include <X11/Xatom.h>
1485 #include <X11/Xutil.h>
1486 #include <X11/Xmu/StdCmap.h>
1488 #define lowbit(x) ((x) & (~(x) + 1))
1493 /* argument restrictions */
1494 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1495 unsigned long, Atom);
1498 * To create any one standard colormap, use XmuStandardColormap().
1500 * Create a standard colormap for the given screen, visualid, and visual
1501 * depth, with the given red, green, and blue maximum values, with the
1502 * given standard property name. Return a pointer to an XStandardColormap
1503 * structure which describes the newly created colormap, upon success.
1504 * Upon failure, return NULL.
1506 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1508 * Resources created by this function are not made permanent; that is the
1509 * caller's responsibility.
1513 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1514 unsigned int depth, Atom property, Colormap cmap,
1515 unsigned long red_max, unsigned long green_max,
1516 unsigned long blue_max)
1518 * dpy - specifies X server connection
1519 * screen - specifies display screen
1520 * visualid - identifies the visual type
1521 * depth - identifies the visual type
1522 * property - a standard colormap property
1523 * cmap - specifies colormap ID or None
1524 * red_max, green_max, blue_max - allocations
1527 XStandardColormap *stdcmap;
1529 XVisualInfo vinfo_template, *vinfo;
1533 /* Match the required visual information to an actual visual */
1534 vinfo_template.visualid = visualid;
1535 vinfo_template.screen = screen;
1536 vinfo_template.depth = depth;
1537 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1538 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1541 /* Check the validity of the combination of visual characteristics,
1542 * allocation, and colormap property. Create an XStandardColormap
1546 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1547 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1548 XFree((char *) vinfo);
1552 /* Fill in the XStandardColormap structure */
1554 if (cmap == DefaultColormap(dpy, screen)) {
1555 /* Allocating out of the default map, cannot use XFreeColormap() */
1556 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1557 0, 0, InputOnly, vinfo->visual,
1559 (XSetWindowAttributes *)NULL);
1560 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1561 XDestroyWindow(dpy, win);
1562 stdcmap->colormap = cmap;
1564 stdcmap->killid = ReleaseByFreeingColormap;
1565 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1566 vinfo->visual, AllocNone);
1568 stdcmap->red_max = red_max;
1569 stdcmap->green_max = green_max;
1570 stdcmap->blue_max = blue_max;
1571 if (property == XA_RGB_GRAY_MAP)
1572 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1573 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1574 stdcmap->red_mult = lowbit(vinfo->red_mask);
1575 stdcmap->green_mult = lowbit(vinfo->green_mask);
1576 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1578 stdcmap->red_mult = (red_max > 0)
1579 ? (green_max + 1) * (blue_max + 1) : 0;
1580 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1581 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1583 stdcmap->base_pixel = 0; /* base pixel may change */
1584 stdcmap->visualid = vinfo->visualid;
1586 /* Make the colormap */
1588 status = XmuCreateColormap(dpy, stdcmap);
1592 XFree((char *) vinfo);
1595 /* Free the colormap or the pixmap, if we created one */
1596 if (stdcmap->killid == ReleaseByFreeingColormap)
1597 XFreeColormap(dpy, stdcmap->colormap);
1598 else if (stdcmap->killid != None)
1599 XFreePixmap(dpy, stdcmap->killid);
1601 XFree((char *) stdcmap);
1602 return (XStandardColormap *) NULL;
1607 /****************************************************************************/
1609 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1610 unsigned long blue_max, Atom property)
1612 * vinfo - specifies visual
1613 * red_max, green_max, blue_max - specifies alloc
1614 * property - specifies property name
1617 unsigned long ncolors; /* number of colors requested */
1619 /* Determine that the number of colors requested is <= map size */
1621 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1624 mask = vinfo->red_mask;
1629 mask = vinfo->green_mask;
1632 if (green_max > mask)
1634 mask = vinfo->blue_mask;
1637 if (blue_max > mask)
1639 } else if (property == XA_RGB_GRAY_MAP) {
1640 ncolors = red_max + green_max + blue_max + 1;
1641 if (ncolors > vinfo->colormap_size)
1644 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1645 if (ncolors > vinfo->colormap_size)
1649 /* Determine that the allocation and visual make sense for the property */
1653 case XA_RGB_DEFAULT_MAP:
1654 if (red_max == 0 || green_max == 0 || blue_max == 0)
1657 case XA_RGB_RED_MAP:
1661 case XA_RGB_GREEN_MAP:
1665 case XA_RGB_BLUE_MAP:
1669 case XA_RGB_BEST_MAP:
1670 if (red_max == 0 || green_max == 0 || blue_max == 0)
1673 case XA_RGB_GRAY_MAP:
1674 if (red_max == 0 || blue_max == 0 || green_max == 0)
1684 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1688 Copyright 1989, 1998 The Open Group
1690 Permission to use, copy, modify, distribute, and sell this software and its
1691 documentation for any purpose is hereby granted without fee, provided that
1692 the above copyright notice appear in all copies and that both that
1693 copyright notice and this permission notice appear in supporting
1696 The above copyright notice and this permission notice shall be included in
1697 all copies or substantial portions of the Software.
1699 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1700 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1702 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1703 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1704 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1706 Except as contained in this notice, the name of The Open Group shall not be
1707 used in advertising or otherwise to promote the sale, use or other dealings
1708 in this Software without prior written authorization from The Open Group.
1711 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1714 * Author: Donna Converse, MIT X Consortium
1718 * CreateCmap.c - given a standard colormap description, make the map.
1723 #include <X11/Xlib.h>
1724 #include <X11/Xutil.h>
1725 #include <X11/Xmu/StdCmap.h>
1730 /* allocate entire map Read Only */
1731 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1733 /* allocate a cell, prefer Read Only */
1734 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1735 XColor*, unsigned long);
1737 /* allocate a cell Read Write */
1738 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1741 static int compare(_Xconst void*, _Xconst void*);
1743 /* find contiguous sequence of cells */
1744 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1746 /* frees resources before quitting */
1747 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1749 /* create a map in a RO visual type */
1750 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1752 /* create a map in a RW visual type */
1753 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1755 #define lowbit(x) ((x) & (~(x) + 1))
1756 #define TRUEMATCH(mult,max,mask) \
1757 (colormap->max * colormap->mult <= vinfo->mask && \
1758 lowbit(vinfo->mask) == colormap->mult)
1761 * To create any one colormap which is described by an XStandardColormap
1762 * structure, use XmuCreateColormap().
1764 * Return 0 on failure, non-zero on success.
1765 * Resources created by this function are not made permanent.
1766 * No argument error checking is provided. Use at your own risk.
1768 * All colormaps are created with read only allocations, with the exception
1769 * of read only allocations of colors in the default map or otherwise
1770 * which fail to return the expected pixel value, and these are individually
1771 * defined as read/write allocations. This is done so that all the cells
1772 * defined in the default map are contiguous, for use in image processing.
1773 * This typically happens with White and Black in the default map.
1775 * Colormaps of static visuals are considered to be successfully created if
1776 * the map of the static visual matches the definition given in the
1777 * standard colormap structure.
1781 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1782 /* dpy - specifies the connection under which the map is created
1783 * colormap - specifies the map to be created, and returns, particularly
1784 * if the map is created as a subset of the default colormap
1785 * of the screen, the base_pixel of the map.
1788 XVisualInfo vinfo_template; /* template visual information */
1789 XVisualInfo *vinfo; /* matching visual information */
1790 XVisualInfo *vpointer; /* for freeing the entire list */
1791 long vinfo_mask; /* specifies the visual mask value */
1792 int n; /* number of matching visuals */
1795 vinfo_template.visualid = colormap->visualid;
1796 vinfo_mask = VisualIDMask;
1797 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1800 /* A visual id may be valid on multiple screens. Also, there may
1801 * be multiple visuals with identical visual ids at different depths.
1802 * If the colormap is the Default Colormap, use the Default Visual.
1803 * Otherwise, arbitrarily, use the deepest visual.
1809 register int screen_number;
1813 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1814 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1820 for (i=0; i < n; i++, vinfo++) {
1821 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1826 XVisualInfo *v = NULL;
1828 for (i=0; i < n; i++, vinfo++)
1829 if (vinfo->depth > maxdepth) {
1830 maxdepth = vinfo->depth;
1837 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1838 vinfo->c_class == GrayScale)
1839 status = readwrite_map(dpy, vinfo, colormap);
1840 else if (vinfo->c_class == TrueColor)
1841 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1842 TRUEMATCH(green_mult, green_max, green_mask) &&
1843 TRUEMATCH(blue_mult, blue_max, blue_mask);
1845 status = readonly_map(dpy, vinfo, colormap);
1847 XFree((char *) vpointer);
1851 /****************************************************************************/
1853 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1855 register unsigned long i, n; /* index counters */
1856 unsigned long ncolors; /* number of colors to be defined */
1857 int npixels; /* number of pixels allocated R/W */
1858 int first_index; /* first index of pixels to use */
1859 int remainder; /* first index of remainder */
1860 XColor color; /* the definition of a color */
1861 unsigned long *pixels; /* array of colormap pixels */
1862 unsigned long delta;
1865 /* Determine ncolors, the number of colors to be defined.
1866 * Insure that 1 < ncolors <= the colormap size.
1868 if (vinfo->c_class == DirectColor) {
1869 ncolors = colormap->red_max;
1870 if (colormap->green_max > ncolors)
1871 ncolors = colormap->green_max;
1872 if (colormap->blue_max > ncolors)
1873 ncolors = colormap->blue_max;
1875 delta = lowbit(vinfo->red_mask) +
1876 lowbit(vinfo->green_mask) +
1877 lowbit(vinfo->blue_mask);
1879 ncolors = colormap->red_max * colormap->red_mult +
1880 colormap->green_max * colormap->green_mult +
1881 colormap->blue_max * colormap->blue_mult + 1;
1884 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1886 /* Allocate Read/Write as much of the colormap as we can possibly get.
1887 * Then insure that the pixels we were allocated are given in
1888 * monotonically increasing order, using a quicksort. Next, insure
1889 * that our allocation includes a subset of contiguous pixels at least
1890 * as long as the number of colors to be defined. Now we know that
1891 * these conditions are met:
1892 * 1) There are no free cells in the colormap.
1893 * 2) We have a contiguous sequence of pixels, monotonically
1894 * increasing, of length >= the number of colors requested.
1896 * One cell at a time, we will free, compute the next color value,
1897 * then allocate read only. This takes a long time.
1898 * This is done to insure that cells are allocated read only in the
1899 * contiguous order which we prefer. If the server has a choice of
1900 * cells to grant to an allocation request, the server may give us any
1901 * cell, so that is why we do these slow gymnastics.
1904 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1905 sizeof(unsigned long))) == NULL)
1908 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1909 vinfo->colormap_size, ncolors)) == 0) {
1910 free((char *) pixels);
1914 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1916 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1918 /* can't find enough contiguous cells, give up */
1919 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1921 free((char *) pixels);
1924 colormap->base_pixel = pixels[first_index];
1926 /* construct a gray map */
1927 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1928 colormap->blue_mult == 1)
1929 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1932 color.blue = color.green = color.red =
1933 (unsigned short) ((i * 65535) / (colormap->red_max +
1934 colormap->green_max +
1935 colormap->blue_max));
1937 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1942 /* construct a red ramp map */
1943 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1944 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1947 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1948 color.green = color.blue = 0;
1950 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1955 /* construct a green ramp map */
1956 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1957 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1960 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1961 color.red = color.blue = 0;
1963 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1968 /* construct a blue ramp map */
1969 else if (colormap->red_max == 0 && colormap->green_max == 0)
1970 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1973 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1974 color.red = color.green = 0;
1976 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1981 /* construct a standard red green blue cube map */
1984 #define calc(max,mult) (((n / colormap->mult) % \
1985 (colormap->max + 1)) * 65535) / colormap->max
1987 for (n=0, i=0; i < ncolors; i++, n += delta)
1989 color.pixel = n + colormap->base_pixel;
1990 color.red = calc(red_max, red_mult);
1991 color.green = calc(green_max, green_mult);
1992 color.blue = calc(blue_max, blue_mult);
1993 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1999 /* We have a read-only map defined. Now free unused cells,
2000 * first those occuring before the contiguous sequence begins,
2001 * then any following the contiguous sequence.
2005 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2008 XFreeColors(dpy, colormap->colormap,
2009 &(pixels[first_index + ncolors]), remainder,
2012 free((char *) pixels);
2017 /****************************************************************************/
2019 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2021 * dpy - the X server connection
2022 * cmap - specifies colormap ID
2023 * pixels - returns pixel allocations
2024 * m - specifies colormap size
2025 * n - specifies number of colors
2030 /* first try to allocate the entire colormap */
2031 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2032 (unsigned) 0, pixels, (unsigned) m))
2035 /* Allocate all available cells in the colormap, using a binary
2036 * algorithm to discover how many cells we can allocate in the colormap.
2040 p = n + ((m - n + 1) / 2);
2041 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2042 (unsigned) 0, pixels, (unsigned) p)) {
2046 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2057 /****************************************************************************/
2059 contiguous(unsigned long pixels[], int npixels, int ncolors,
2060 unsigned long delta, int *first, int *rem)
2061 /* pixels - specifies allocated pixels
2062 * npixels - specifies count of alloc'd pixels
2063 * ncolors - specifies needed sequence length
2064 * delta - between pixels
2065 * first - returns first index of sequence
2066 * rem - returns first index after sequence, or 0, if none follow
2069 register int i = 1; /* walking index into the pixel array */
2070 register int count = 1; /* length of sequence discovered so far */
2073 if (npixels == ncolors) {
2078 while (count < ncolors && ncolors - count <= *rem)
2080 if (pixels[i-1] + delta == pixels[i])
2089 if (count != ncolors)
2095 /****************************************************************************/
2097 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2098 int npixels, XColor *color, unsigned long p)
2100 unsigned long pixel;
2103 /* Free the read/write allocation of one cell in the colormap.
2104 * Request a read only allocation of one cell in the colormap.
2105 * If the read only allocation cannot be granted, give up, because
2106 * there must be no free cells in the colormap.
2107 * If the read only allocation is granted, but gives us a cell which
2108 * is not the one that we just freed, it is probably the case that
2109 * we are trying allocate White or Black or some other color which
2110 * already has a read-only allocation in the map. So we try to
2111 * allocate the previously freed cell with a read/write allocation,
2112 * because we want contiguous cells for image processing algorithms.
2115 pixel = color->pixel;
2116 request.red = color->red;
2117 request.green = color->green;
2118 request.blue = color->blue;
2120 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2121 if (! XAllocColor(dpy, cmap, color)
2122 || (color->pixel != pixel &&
2123 (!RWcell(dpy, cmap, color, &request, &pixel))))
2125 free_cells(dpy, cmap, pixels, npixels, (int)p);
2132 /****************************************************************************/
2134 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2137 * pixels - to be freed
2138 * npixels - original number allocated
2141 /* One of the npixels allocated has already been freed.
2142 * p is the index of the freed pixel.
2143 * First free the pixels preceeding p, and there are p of them;
2144 * then free the pixels following p, there are npixels - p - 1 of them.
2146 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2147 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2148 free((char *) pixels);
2152 /****************************************************************************/
2154 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2155 unsigned long *pixel)
2157 unsigned long n = *pixel;
2159 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2160 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2161 (unsigned) 0, pixel, (unsigned) 1))
2165 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2168 color->pixel = *pixel;
2169 color->flags = DoRed | DoGreen | DoBlue;
2170 color->red = request->red;
2171 color->green = request->green;
2172 color->blue = request->blue;
2173 XStoreColors(dpy, cmap, color, 1);
2178 /****************************************************************************/
2180 compare(_Xconst void *e1, _Xconst void *e2)
2182 return ((int)(*(long *)e1 - *(long *)e2));
2186 /****************************************************************************/
2188 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2193 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2194 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2196 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2198 color.pixel = (unsigned long) i;
2199 color.red = (unsigned short)
2200 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2202 if (vinfo->c_class == StaticColor) {
2203 color.green = (unsigned short)
2204 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2205 65535) / colormap->green_max);
2206 color.blue = (unsigned short)
2207 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2209 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2210 color.green = color.blue = color.red;
2212 XAllocColor(dpy, colormap->colormap, &color);
2213 if (color.pixel != (unsigned long) i)
2220 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2224 Copyright 1989, 1998 The Open Group
2226 Permission to use, copy, modify, distribute, and sell this software and its
2227 documentation for any purpose is hereby granted without fee, provided that
2228 the above copyright notice appear in all copies and that both that
2229 copyright notice and this permission notice appear in supporting
2232 The above copyright notice and this permission notice shall be included in
2233 all copies or substantial portions of the Software.
2235 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2236 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2237 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2238 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2239 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2240 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2242 Except as contained in this notice, the name of The Open Group shall not be
2243 used in advertising or otherwise to promote the sale, use or other dealings
2244 in this Software without prior written authorization from The Open Group.
2247 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2250 * Author: Donna Converse, MIT X Consortium
2253 #include <X11/Xlib.h>
2254 #include <X11/Xutil.h>
2255 #include <X11/Xmu/StdCmap.h>
2257 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2259 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2260 * XmuDeleteStandardColormap() will remove the specified property from the
2261 * specified screen, releasing any resources used by the colormap(s) of the
2262 * property if possible.
2266 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2267 /* dpy; - specifies the X server to connect to
2268 * screen - specifies the screen of the display
2269 * property - specifies the standard colormap property
2272 XStandardColormap *stdcmaps, *s;
2275 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2278 for (s=stdcmaps; count > 0; count--, s++) {
2279 if ((s->killid == ReleaseByFreeingColormap) &&
2280 (s->colormap != None) &&
2281 (s->colormap != DefaultColormap(dpy, screen))) {
2283 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2284 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2286 XFreeColormap(dpy, s->colormap);
2288 XSetErrorHandler(oldHandler);
2291 } else if (s->killid != None) {
2292 XKillClient(dpy, s->killid);
2295 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2296 XFree((char *) stdcmaps);