Linux: Fixed Display.setIcon memory leak.
This commit is contained in:
parent
9e1280d281
commit
48cf79e55f
|
@ -692,6 +692,27 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void convertIcon(ByteBuffer icon, int width, int height) {
|
||||||
|
int x = 0;
|
||||||
|
int y = 5;
|
||||||
|
byte r,g,b,a;
|
||||||
|
|
||||||
|
int depth = 4;
|
||||||
|
|
||||||
|
for (y = 0; y < height; y++) {
|
||||||
|
for (x = 0; x < width; x++) {
|
||||||
|
r = icon.get((x*4)+(y*width*4));
|
||||||
|
g = icon.get((x*4)+(y*width*4)+1);
|
||||||
|
b = icon.get((x*4)+(y*width*4)+2);
|
||||||
|
a = icon.get((x*4)+(y*width*4)+3);
|
||||||
|
|
||||||
|
icon.put((x*depth)+(y*width*depth), b); // blue
|
||||||
|
icon.put((x*depth)+(y*width*depth)+1, g); // green
|
||||||
|
icon.put((x*depth)+(y*width*depth)+2, r);
|
||||||
|
icon.put((x*depth)+(y*width*depth)+3, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets one or more icons for the Display.
|
* Sets one or more icons for the Display.
|
||||||
|
@ -700,23 +721,36 @@ final class LinuxDisplay implements DisplayImplementation {
|
||||||
* <li>Linux (and similar platforms) expect one 32x32 icon.</li>
|
* <li>Linux (and similar platforms) expect one 32x32 icon.</li>
|
||||||
* <li>Mac OS X should be supplied one 128x128 icon</li>
|
* <li>Mac OS X should be supplied one 128x128 icon</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions nescesarry for the specific platform.
|
* The implementation will use the supplied ByteBuffers with image data in RGBA and perform any conversions necessary for the specific platform.
|
||||||
*
|
*
|
||||||
* @param icons Array of icons in RGBA mode
|
* @param icons Array of icons in RGBA mode
|
||||||
* @return number of icons used.
|
* @return number of icons used.
|
||||||
*/
|
*/
|
||||||
public int setIcon(ByteBuffer[] icons) {
|
public int setIcon(ByteBuffer[] icons) {
|
||||||
|
lockAWT();
|
||||||
|
try {
|
||||||
|
incDisplay();
|
||||||
|
try {
|
||||||
for (int i=0;i<icons.length;i++) {
|
for (int i=0;i<icons.length;i++) {
|
||||||
int size = icons[i].limit() / 4;
|
int size = icons[i].limit() / 4;
|
||||||
|
int dimension = (int)Math.sqrt(size);
|
||||||
if (((int) Math.sqrt(size)) == 32) {
|
if (dimension == 32) {
|
||||||
nSetWindowIcon(icons[i]);
|
convertIcon(icons[i], dimension, dimension);
|
||||||
|
nSetWindowIcon(icons[i], icons[i].capacity(), dimension, dimension);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
} finally {
|
||||||
|
decDisplay();
|
||||||
|
}
|
||||||
|
} catch (LWJGLException e) {
|
||||||
|
LWJGLUtil.log("Failed to set display icon: " + e);
|
||||||
|
return 0;
|
||||||
|
} finally {
|
||||||
|
unlockAWT();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native int nSetWindowIcon(ByteBuffer icon);
|
private static native void nSetWindowIcon(ByteBuffer icon, int icons_size, int width, int height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ static Atom delete_atom;
|
||||||
static Colormap cmap;
|
static Colormap cmap;
|
||||||
static Window current_win;
|
static Window current_win;
|
||||||
static int current_depth;
|
static int current_depth;
|
||||||
|
static Pixmap current_icon_pixmap;
|
||||||
|
|
||||||
static Visual *current_visual;
|
static Visual *current_visual;
|
||||||
|
|
||||||
|
@ -316,6 +317,13 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetTitle(JNIEnv * env
|
||||||
free(title);
|
free(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void freeIconPixmap() {
|
||||||
|
if (current_icon_pixmap != 0) {
|
||||||
|
XFreePixmap(getDisplay(), current_icon_pixmap);
|
||||||
|
current_icon_pixmap = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void destroyWindow(JNIEnv *env) {
|
static void destroyWindow(JNIEnv *env) {
|
||||||
if (glx_window != None) {
|
if (glx_window != None) {
|
||||||
lwjgl_glXDestroyWindow(getDisplay(), glx_window);
|
lwjgl_glXDestroyWindow(getDisplay(), glx_window);
|
||||||
|
@ -323,6 +331,7 @@ static void destroyWindow(JNIEnv *env) {
|
||||||
}
|
}
|
||||||
XDestroyWindow(getDisplay(), current_win);
|
XDestroyWindow(getDisplay(), current_win);
|
||||||
XFreeColormap(getDisplay(), cmap);
|
XFreeColormap(getDisplay(), cmap);
|
||||||
|
freeIconPixmap();
|
||||||
setRepeatMode(env, AutoRepeatModeDefault);
|
setRepeatMode(env, AutoRepeatModeDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,61 +522,53 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUnlockAWT(JNIEnv *env
|
||||||
jawt.Unlock(env);
|
jawt.Unlock(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setIcon(char *data,int width,int height) {
|
static void setIcon(JNIEnv *env, char *data, int icon_size, int width,int height) {
|
||||||
XWMHints* win_hints;
|
XWMHints* win_hints;
|
||||||
int x = 0;
|
freeIconPixmap();
|
||||||
int y = 5;
|
current_icon_pixmap = XCreatePixmap(getDisplay(), getCurrentWindow(), width, height, current_depth);
|
||||||
char r,g,b,a;
|
/* We need to copy the image data since XDestroyImage will also free its data buffer, which can't be allowed
|
||||||
|
* since the data buffer is managed by the jvm (it's the storage for the direct ByteBuffer)
|
||||||
|
*/
|
||||||
|
char *icon_copy = (char *)malloc(sizeof(*icon_copy)*icon_size);
|
||||||
|
|
||||||
int depth = 4;
|
if (icon_copy == NULL) {
|
||||||
|
throwException(env, "malloc failed");
|
||||||
for (y=0;y<height;y++) {
|
return;
|
||||||
for (x=0;x<width;x++) {
|
|
||||||
r = data[(x*4)+(y*width*4)];
|
|
||||||
g = data[(x*4)+(y*width*4)+1];
|
|
||||||
b = data[(x*4)+(y*width*4)+2];
|
|
||||||
a = data[(x*4)+(y*width*4)+3];
|
|
||||||
|
|
||||||
data[(x*depth)+(y*width*depth)] = b; // blue
|
|
||||||
data[(x*depth)+(y*width*depth)+1] = g; // green
|
|
||||||
data[(x*depth)+(y*width*depth)+2] = r;
|
|
||||||
data[(x*depth)+(y*width*depth)+3] = a;
|
|
||||||
}
|
}
|
||||||
|
memcpy(icon_copy, data, icon_size);
|
||||||
|
XImage *image = XCreateImage(getDisplay(), current_visual, current_depth, ZPixmap, 0, icon_copy, width, height, 32, 0);
|
||||||
|
if (image == NULL) {
|
||||||
|
freeIconPixmap();
|
||||||
|
free(icon_copy);
|
||||||
|
throwException(env, "XCreateImage failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pixmap icon_pixmap = XCreatePixmap(getDisplay(), getCurrentWindow(), width, height, current_depth);
|
GC gc = XCreateGC(getDisplay(), current_icon_pixmap, 0, NULL);
|
||||||
|
XPutImage(getDisplay(), current_icon_pixmap, gc, image, 0, 0, 0, 0, width, height);
|
||||||
XImage *image = XCreateImage(getDisplay(), current_visual, current_depth, ZPixmap, 0, data, width, height, 32, 0);
|
XFreeGC(getDisplay(), gc);
|
||||||
|
XDestroyImage(image);
|
||||||
GC gc = XCreateGC(getDisplay(), icon_pixmap, 0, NULL);
|
// We won't free icon_copy because it is freed by XDestroyImage
|
||||||
|
|
||||||
XPutImage(getDisplay(), icon_pixmap, gc, image, 0, 0, 0, 0, width, height);
|
|
||||||
|
|
||||||
win_hints = XAllocWMHints();
|
win_hints = XAllocWMHints();
|
||||||
if (!win_hints) {
|
if (win_hints == NULL) {
|
||||||
return -1;
|
throwException(env, "XAllocWMHints failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
win_hints->flags = IconPixmapHint;
|
win_hints->flags = IconPixmapHint;
|
||||||
win_hints->icon_pixmap = icon_pixmap;
|
win_hints->icon_pixmap = current_icon_pixmap;
|
||||||
|
|
||||||
XSetWMHints(getDisplay(), getCurrentWindow(), win_hints);
|
XSetWMHints(getDisplay(), getCurrentWindow(), win_hints);
|
||||||
XFree(win_hints);
|
XFree(win_hints);
|
||||||
XFlush(getDisplay());
|
XFlush(getDisplay());
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowIcon
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetWindowIcon
|
||||||
(JNIEnv *env, jclass clazz, jobject iconBuffer)
|
(JNIEnv *env, jclass clazz, jobject iconBuffer, jint icon_size, jint width, jint height)
|
||||||
{
|
{
|
||||||
char *imgData = (char *)(*env)->GetDirectBufferAddress(env, iconBuffer);
|
char *imgData = (char *)(*env)->GetDirectBufferAddress(env, iconBuffer);
|
||||||
|
|
||||||
if (setIcon(imgData,32,32) == 0)
|
setIcon(env, imgData, icon_size, width, height);
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue