From: megacz Date: Fri, 30 Jan 2004 06:47:48 +0000 (+0000) Subject: 2002/06/04 04:46:52 X-Git-Tag: RC3~1708 X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=80b1c566e72f8c30cf29da35f2ae918d7cee93d7 2002/06/04 04:46:52 darcs-hash:20040130064748-2ba56-c927cb81cccae3aa7de57aeda25d84b082ec655f.gz --- diff --git a/CHANGES b/CHANGES index b78b203..c15cc96 100644 --- a/CHANGES +++ b/CHANGES @@ -178,3 +178,5 @@ 01-Jun megacz Main.java: custom splash screen support +01-Jun megacz POSIX.cc, POSIX.java: finally completed POSIX support + diff --git a/src/org/xwt/plat/POSIX.cc b/src/org/xwt/plat/POSIX.cc index b5d4662..c07ec1c 100644 --- a/src/org/xwt/plat/POSIX.cc +++ b/src/org/xwt/plat/POSIX.cc @@ -1,3 +1,6 @@ +// Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL] +// see below for copyright information on the second portion of this file + #include #include #include @@ -13,6 +16,7 @@ #include #include #include +#include #include #include @@ -38,131 +42,91 @@ static XStandardColormap* colormap_info; static XShmSegmentInfo shm_info; static Window selectionWindow; static int shm_supported; +static int shm_pixmaps_supported; static int screen_num; static int colorDepth = 0; static Display* display; +static int shm_size = 0; -#define min(a, b) (a < b ? a : b) +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) < (b) ? (b) : (a)) // X11DoubleBuffer ////////////////////////////////////////////////////////////////////// -void org::xwt::plat::POSIX$X11DoubleBuffer::drawPicture(org::xwt::Picture* s, - jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) { - - if (pm == NULL) return; +// ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size +static void ensureShmSize(int size) { + if (size > shm_size) { + if (shm_size > 0) { + XShmDetach(display, &shm_info); + shmdt(shm_info.shmaddr); + shmctl(shm_info.shmid, IPC_RMID, 0); + } + shm_size = 3 * size / 2; + shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL); + shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0); + shm_info.readOnly = False; + XSync(display, False); + shmctl(shm_info.shmid, IPC_RMID, 0); + XShmAttach(display, &shm_info); + XSync(display, False); + } +} + +void org::xwt::plat::POSIX$X11DoubleBuffer::fastDrawPicture(org::xwt::Picture* s, + jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) { org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s; - - int scaling = dx2 - dx1 != sx2 - sx1 || dy2 - dy1 != sy2 - sy1; - - // FIXME: this needs to be moved into the fastpath-only to prevent image wriggling + + // it's safe to clip manually since we no that no scaling will be done if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; } if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; } if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; } if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; } if (dx1 > clipx + clipw) return; if (dy1 > clipy + cliph) return; - if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return; - - // fastpath: if the X11Picture has a pixmap, and no scaling, and all-or-nothing alpha - if (!scaling && source->doublebuf != NULL) { - if (source->doublebuf->stipple != NULL) { - XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple)); - XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1); - } else { - XSetClipMask(display, (*((GC*)clipped_gc)), None); - } - XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1); - return; + + if (source->doublebuf->stipple != NULL) { + XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple)); + XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1); + } else { + XSetClipMask(display, (*((GC*)clipped_gc)), None); } + XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1); +} - // slowpath: true alpha or scaling - - // the following optimizations were abandoned because they don't - // improve performance in the presence of XSHM extensions, and - // therefore aren't worth the code-bloat: - // - scaling clipmask bitmaps (and caching them) - // - caching pre-scaled XImages - - // ximage from our destination -- if true_alpha is false, we can use malloc() instead of XGetImage +void org::xwt::plat::POSIX$X11DoubleBuffer::slowDrawPicture(org::xwt::Picture* s, + jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) { + + org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s; XImage* xi; - - if (force_slowpath && shm_supported) { - - // if the shared memory area is unsuitable, destroy it - - if (((XImage*)shm_ximage) != NULL && (dx2 - dx1 != ((XImage*)shm_ximage)->width || dy2 - dy1 != ((XImage*)shm_ximage)->height)) { - XShmDetach(display, &shm_info); - XDestroyImage(((XImage*)shm_ximage)); - } - - // FIXME: replace 4 with something sensible - if (((XImage*)shm_ximage) != NULL && (dx2 - dx1) * (dy2 - dy1) * 4 < old_shmsize) { - shmdt(shm_info.shmaddr); - shmctl(shm_info.shmid, IPC_RMID, 0); - memset(&shm_info, 0, sizeof(XShmSegmentInfo)); - shm_info.shmaddr = NULL; - } - - // if we need to recreate the shared memory area - if (shm_info.shmaddr == NULL) { - old_shmsize = xi->bytes_per_line * xi->height; - memset(&shm_info, 0, sizeof(XShmSegmentInfo)); - shm_info.shmid = shmget(IPC_PRIVATE, xi->bytes_per_line * xi->height, IPC_CREAT | 0777 | IPC_EXCL); - shm_info.shmaddr = xi->data = (char*)shmat(shm_info.shmid, 0, 0); - shm_info.readOnly = False; - - XSync(display, False); - shmctl(shm_info.shmid, IPC_RMID, 0); - XShmAttach(display, &shm_info); - XSync(display, False); - } - - xi = ((XImage*)shm_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, shm_info.shmaddr, &shm_info, dx2 - dx1, dy2 - dy1); - - } else if (shared_pixmap && shm_supported) { - xi = ((XImage*)mxi); + + // FASTEST: shared pixmap; twiddle bits in video ram directly + if (shared_pixmap) { + XSync(display, False); // ensure that all pending operations have rendered + xi = (XImage*)fake_ximage; + + // MEDIUM: write to a shared ximage, then ask the server to do the blit + } else if (shm_supported) { + xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1); + ensureShmSize(xi->bytes_per_line * xi->height); + xi->data = shm_info.shmaddr; + XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes); + // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit } else { xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap); - } - // FIXME: xoffset? - // FIXME: optimize pixels that have 0xFF or 0x00 alpha - // endian issues - - - // further assumption: the only time source->data will be null is - // if we're drawing from a bordercache -- but those don't get - // stretched. - if (source->data == NULL || elements(source->data) == NULL) { - printf("AIEEEEE %i %i %i %i\n", dx2 - dx1, dy2 - dy1, sx2 - sx1, sy2 - sy1); - return; - } int* sourcedata = (int*)elements(source->data); - - for(int y=dy1; y= clipy + cliph) continue; + char* current_pixel = (xi->data + y * xi->bytes_per_line) + + (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line); - char* bitstart; - if (shared_pixmap && shm_supported) { - // FIXME: not sure if bitmap_unit is the right thing - bitstart = xi->data + y * xi->bytes_per_line + dx1 * (xi->bits_per_pixel / 8); - } else { - bitstart = xi->data + (y - dy1) * xi->bytes_per_line; - } - - for(int x=dx1; xbits_per_pixel / 8) { - - if (x < clipx || x >= clipx + clipw) continue; - + for(int x=max(dx1, clipx); xbits_per_pixel / 8) { int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1; int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1; - // note that we can assume that source->data exists here, since writeable PixelGrids (ie - // doublebuffers) never have true_alpha, and are never scaled. int sourcepixel = sourcedata[source_x + source_y * source->getWidth()]; int alpha = (sourcepixel & 0xFF000000) >> 24; int source_red = (sourcepixel & 0x00FF0000) >> 16; @@ -170,13 +134,14 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::drawPicture(org::xwt::Picture* s, int source_blue = (sourcepixel & 0x000000FF); int red = 0, blue = 0, green = 0; + if (alpha == 0x00) continue; if (alpha != 0xFF) { int targetpixel; switch (xi->bits_per_pixel) { - case 8: targetpixel = (int)(*bitstart); break; - case 16: targetpixel = (int)(*((u_int16_t*)bitstart)); break; - case 24: targetpixel = (((int)*bitstart) << 16) | (((int)*(bitstart + 1)) << 8) | (((int)*(bitstart + 2))); break; - case 32: targetpixel = *((int*)bitstart); break; + case 8: targetpixel = (int)(*current_pixel); break; + case 16: targetpixel = (int)(*((u_int16_t*)current_pixel)); break; + case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break; + case 32: targetpixel = *((int*)current_pixel); break; default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!")); } @@ -197,27 +162,32 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::drawPicture(org::xwt::Picture* s, red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF); green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF); blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF); - - int destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult + + u_int32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult + blue * colormap_info->blue_mult + colormap_info->base_pixel; - + switch (xi->bits_per_pixel) { - case 8: *bitstart = (char)(destpixel & 0xFF); break; - case 16: *((u_int16_t*)bitstart) = (u_int16_t)destpixel; break; - case 24: break; // FIXME, unimplemented - case 32: *((int*)bitstart) = destpixel; break; + case 8: *current_pixel = (char)(destpixel & 0xFF); break; + case 16: *((u_int16_t*)current_pixel) = (u_int16_t)destpixel; break; + case 24: { + int offset = (int)current_pixel & 0x3; + u_int64_t dest = ((u_int64_t)destpixel) << (8 * offset); + u_int64_t mask = ((u_int64_t)0xffffff) << (8 * offset); + u_int64_t* base = (u_int64_t*)(current_pixel - offset); + *base = (*base & ~mask) | dest; + break; + } + case 32: *((u_int32_t*)current_pixel) = destpixel; break; default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!")); } - } } - if (force_slowpath && shm_supported) { - // watch for concurrency issues if we're going to keep the shm region around - XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False); + if (shared_pixmap) { + // do nothing, we wrote directly to video memory - } if (shared_pixmap && shm_supported) { - // do nothing, it's all taken care of + } else if (shm_supported) { + XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False); + XDestroyImage(xi); } else { XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1); @@ -225,37 +195,46 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::drawPicture(org::xwt::Picture* s, } } +void org::xwt::plat::POSIX$X11DoubleBuffer::finalize() { + if (shared_pixmap) { + XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment; + XShmDetach(display, sinfo); + shmdt(sinfo->shmaddr); + shmctl(sinfo->shmid, IPC_RMID, 0); + XDestroyImage((XImage*)fake_ximage); + free(sinfo); + } + if (stipple) { + XFreePixmap(display, *((Pixmap*)stipple)); + free(stipple); + } + XFreePixmap(display, *((Pixmap*)pm)); + XFreeGC(display, *((GC*)gc)); + XFreeGC(display, *((GC*)clipped_gc)); +} + void org::xwt::plat::POSIX$X11DoubleBuffer::natInit() { if (width == 0 || height == 0) return; - + shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap)); - if (shared_pixmap && shm_supported) { - - // FIXME: check if server pixmaps are XYPixmaps - printf("CREATING SHARED (*((Pixmap*)pm)) %i %i\n", width, height); - + if (!shared_pixmap) + (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth); + else { XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo)); - ((XImage*)mxi) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height); - - memset(sinfo, 0, sizeof(XShmSegmentInfo)); - - sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)mxi)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL); - ((XImage*)mxi)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0); + shm_segment = (gnu::gcj::RawData*)sinfo; + ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height); + sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL); + ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0); sinfo->readOnly = False; XShmAttach(display, sinfo); - XSync(display, False); shmctl(sinfo->shmid, IPC_RMID, 0); - - (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, 0), sinfo->shmaddr, sinfo, width, height, colorDepth); + (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth); XSync(display, False); - - } else { - (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, 0), width, height, colorDepth); - } + gc = (gnu::gcj::RawData*)malloc(sizeof(GC)); clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC)); (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0); @@ -270,7 +249,7 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::natInit() { void org::xwt::plat::POSIX$X11DoubleBuffer::createStipple(org::xwt::plat::POSIX$X11Picture* xpi) { stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap)); - (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, 0), width, height, 1); + (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1); XImage xi; xi.data = (char*)malloc((width + 1) * height); @@ -295,7 +274,7 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::createStipple(org::xwt::plat::POSIX$ XGCValues vm; vm.graphics_exposures = 0; - XChangeGC(display, (*((GC*)stipple_gc)), GCGraphicsExposures, &vm); + XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm); XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height); } @@ -315,7 +294,7 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, j if (y < clipy) { h -= (clipy - y); y = clipy; } if (x + w > clipx + clipw) w = (clipx + clipw - x); if (y + h > clipy + cliph) h = (cliph + clipy - y); - + XSetForeground(display, (*((GC*)gc)), ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult + ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult + @@ -324,7 +303,6 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, j ); XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h); - } void org::xwt::plat::POSIX$X11DoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) { @@ -341,14 +319,15 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::drawString(::java::lang::String* fon ); // Grab the string - char buf[text->length() + 1]; - JvGetStringUTFRegion(text, 0, text->length(), buf); - buf[text->length()] = '\0'; + int len = min(1024, JvGetStringUTFLength(text)); + char buf[len + 1]; + JvGetStringUTFRegion(text, 0, len, buf); + buf[len] = '\0'; // Build the XTextItem structure XTextItem textitem; textitem.chars = buf; - textitem.nchars = text->length(); + textitem.nchars = len; textitem.delta = 0; textitem.font = ((XFontStruct*)org::xwt::plat::POSIX::fontToXFont(font))->fid; @@ -359,6 +338,19 @@ void org::xwt::plat::POSIX$X11DoubleBuffer::drawString(::java::lang::String* fon // X11Surface ////////////////////////////////////////////////////////////////////// +void org::xwt::plat::POSIX$X11Surface::setIcon(org::xwt::Picture* pic) { + org::xwt::plat::POSIX$X11Picture* p = ((org::xwt::plat::POSIX$X11Picture*)pic); + org::xwt::plat::POSIX$X11DoubleBuffer* old_dbuf = p->doublebuf; + p->buildDoubleBuffer(1); + XWMHints xwmh; + memset(&xwmh, 0, sizeof(XWMHints)); + xwmh.flags |= IconPixmapHint | IconMaskHint; + xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm); + xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple); + XSetWMHints(display, (*((Window*)window)), &xwmh); + p->doublebuf = old_dbuf; +} + void org::xwt::plat::POSIX$X11Surface::setTitleBarText(java::lang::String* s) { int len = min(JvGetStringUTFLength(s), 1024); char buf[len + 1]; @@ -395,9 +387,16 @@ void org::xwt::plat::POSIX$X11Surface::setLocation (jint x, jint y) { XMoveWindo void org::xwt::plat::POSIX$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); } void org::xwt::plat::POSIX$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); } +void org::xwt::plat::POSIX$X11Surface::setInvisible(jboolean i) { + if (i) XUnmapWindow(display, (*((Window*)window))); + else XMapRaised(display, (*((Window*)window))); + XFlush(display); +} + void org::xwt::plat::POSIX$X11Surface::_setMinimized(jboolean b) { if (b) XIconifyWindow(display, (*((Window*)window)), screen_num); else XMapRaised(display, (*((Window*)window))); + XFlush(display); } void org::xwt::plat::POSIX$X11Surface::natInit() { @@ -409,12 +408,12 @@ void org::xwt::plat::POSIX$X11Surface::natInit() { KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask; - *((Window*)window) = XCreateWindow(display, DefaultRootWindow(display), 10, 10, 500, 300, 0, + *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 500, 300, 0, colorDepth, InputOutput, CopyFromParent, CWColormap | CWBitGravity | CWEventMask, &xswa); if (!framed) { - // FIXME: figure out why this works and make it elegant + // I don't know why this works.... int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 }; XChangeProperty(display, (*((Window*)window)), XInternAtom(display, "_MOTIF_WM_HINTS", False), @@ -615,7 +614,7 @@ void org::xwt::plat::POSIX$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) { Window child; int x_out, y_out; XConfigureEvent* xce = (XConfigureEvent*)(e); - XTranslateCoordinates(display, (*((Window*)window)), DefaultRootWindow(display), 0, 0, &x_out, &y_out, &child); + XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child); if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height); if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out); @@ -656,6 +655,29 @@ void org::xwt::plat::POSIX$X11Surface::syncCursor() { jint org::xwt::plat::POSIX::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); } jint org::xwt::plat::POSIX::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); } +jstring org::xwt::plat::POSIX::getBrowserEnvString() { + char* envstr = getenv("BROWSER"); + return envstr == NULL ? NULL : JvNewStringLatin1(envstr); +} + +void org::xwt::plat::POSIX::spawnChildProcess(JArray* cmd) { + jstring* cmdstrings = elements(cmd); + char* cmd2[cmd->length + 1]; + cmd2[cmd->length] = NULL; + for(int i=0; ilength; i++) { + cmd2[i] = (char*)malloc(JvGetStringUTFLength(cmdstrings[i])); + JvGetStringUTFRegion(cmdstrings[i], 0, JvGetStringUTFLength(cmdstrings[i]), cmd2[i]); + } + + if (!fork()) { + signal(SIGHUP, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + execvp(cmd2[0], cmd2); + } +} + void org::xwt::plat::POSIX::eventThread() { XEvent e; while(true) { @@ -682,6 +704,14 @@ void org::xwt::plat::POSIX::_setClipBoard(jstring s) { XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime); } +typedef int (X11ErrorHandler)(Display*, XErrorEvent*); +int errorHandler(Display* d, XErrorEvent* e) { + // this error handler is only installed during the initial + // test to see if shm is present + java::lang::System::out->println(JvNewStringLatin1("here")); + shm_supported = 0; +} + void org::xwt::plat::POSIX::natInit() { if (!XInitThreads()) @@ -691,8 +721,21 @@ void org::xwt::plat::POSIX::natInit() { screen_num = XDefaultScreen(display); colorDepth = (jint)(DefaultDepth(((Display*)display), 0)); shm_info.shmaddr = NULL; + shm_supported = (XShmQueryExtension(display) == True); - //shm_supported = 0; + if (shm_supported) { + X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler); + XShmSegmentInfo sinfo; + sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL); + sinfo.readOnly = False; + // if the server is remote, this will trigger the error handler + XShmAttach(display, &sinfo); + XSync(display, False); + XSetErrorHandler(oldHandler); + } + + if (shm_supported) + shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap); crosshair = JvNewStringLatin1("crosshair"); east = JvNewStringLatin1("east"); @@ -722,7 +765,7 @@ void org::xwt::plat::POSIX::natInit() { wait_cursor = XCreateFontCursor(display, XC_watch); default_cursor = XCreateFontCursor(display, XC_left_ptr); - selectionWindow = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL); + selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL); visual = DefaultVisual(display, screen_num); char buf[255]; sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled"); @@ -786,6 +829,18 @@ jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lan ////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +// // +// Everything below this point was taken, cut-and-paste, from the // +// source for libXmu. It implements the official 'standard colormap // +// creation algorithm. // +// // +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */ diff --git a/src/org/xwt/plat/POSIX.java b/src/org/xwt/plat/POSIX.java index f331f9a..0be6ced 100644 --- a/src/org/xwt/plat/POSIX.java +++ b/src/org/xwt/plat/POSIX.java @@ -1,15 +1,6 @@ // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL] package org.xwt.plat; -// FIXME: protected void _newBrowserWindow(String url) -// FIXME: When should I use RootWindow versus DefaultRootWindow? -// FIXME: Solaris: xwt.altKeyName -> "Meta" -// FIXME: minimize/taskbar icon -// FIXME: 15bpp? can't assume depth/8 == bytespp -// FIXME: check for x resource / memory leaks -// FIXME: WM_HINTS flags: icon pixmap, icon window [[ have to wait until we have gnome/kde wm's installed ]] -// FIXME: code-review POSIX.cc - import java.awt.*; import java.awt.image.*; import gnu.gcj.RawData; @@ -43,6 +34,7 @@ public class POSIX extends GCJ { // General Methods /////////////////////////////////////////////////////// + protected String _getAltKeyName() { return System.getProperty("os.name", "").indexOf("SunOS") != -1 ? "Meta" : "Alt"; } protected String[] _listFonts() { return fontList; } protected String getDescriptiveName() { return "GCJ Linux Binary"; } protected Picture _createPicture(int[] data, int w, int h) { return new POSIX.X11Picture(data, w, h); } @@ -60,6 +52,34 @@ public class POSIX extends GCJ { protected native void eventThread(); private native void natInit(); + /** returns the $BROWSER environment variable, since System.getenv() is useless */ + private static native String getBrowserEnvString(); + + /** spawns a process which is immune to SIGHUP */ + private static native void spawnChildProcess(String[] command); + + protected void _newBrowserWindow(String url) { + String browserString = getBrowserEnvString(); + if (browserString == null) { + browserString = "netscape " + url; + } else if (browserString.indexOf("%s") != -1) { + browserString = + browserString.substring(0, browserString.indexOf("%s")) + + url + browserString.substring(browserString.indexOf("%s") + 2); + } else { + browserString += " " + url; + } + + StringTokenizer st = new StringTokenizer(browserString, " "); + String[] cmd = new String[st.countTokens()]; + for(int i=0; st.hasMoreTokens(); i++) { + cmd[i] = st.nextToken(); + System.out.println(i + ":" + cmd[i]); + } + + spawnChildProcess(cmd); + } + public POSIX() { } public void init() { natInit(); @@ -77,9 +97,9 @@ public class POSIX extends GCJ { boolean framed = false; Semaphore waitForCreation = new Semaphore(); - public void setIcon(Picture p) { /* FIXME */ } - public void setInvisible(boolean i) { /* FIXME */ } + public native void setInvisible(boolean i); public void _setMaximized(boolean m) { if (Log.on) Log.log(this, "POSIX/X11 can't maximize windows"); } + public native void setIcon(Picture p); public native void _setMinimized(boolean b); public native void setTitleBarText(String s); public native void setSize(int w, int h); @@ -104,9 +124,13 @@ public class POSIX extends GCJ { // Our Subclass of Picture /////////////////////////////////////////////// - // FIXME: what if display server runs out of pixmap space? Think resource conservation... - - /** Implements a Picture as an X11 Pixmap */ + /** + * Implements a Picture. No special X11 structure is created + * unless the image has no alpha (in which case a + * non-shared-pixmap DoubleBuffer is created), or all-or-nothing + * alpha (in which case a non-shared-pixmap DoubleBuffer with a + * stipple bitmap is created). + */ public static class X11Picture implements Picture { int width; @@ -121,21 +145,36 @@ public class POSIX extends GCJ { this.data = data; this.width = w; this.height = h; + boolean needsStipple = false; // if we have any non-0x00, non-0xFF alphas, we can't double buffer ourselves for(int i=0; i