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