forked from dorkbox/SystemTray
Code polish/cleanup. Added tray icon size adjustments for linux/unix
This commit is contained in:
parent
2c2e835ab2
commit
69db7215b4
@ -16,6 +16,7 @@
|
|||||||
package dorkbox.systemTray.util;
|
package dorkbox.systemTray.util;
|
||||||
|
|
||||||
import static dorkbox.systemTray.SystemTray.logger;
|
import static dorkbox.systemTray.SystemTray.logger;
|
||||||
|
import static javassist.bytecode.Opcode.BIPUSH;
|
||||||
|
|
||||||
import java.awt.AWTException;
|
import java.awt.AWTException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -24,11 +25,18 @@ import dorkbox.systemTray.SystemTray;
|
|||||||
import dorkbox.util.BootStrapClassLoader;
|
import dorkbox.util.BootStrapClassLoader;
|
||||||
import dorkbox.util.OS;
|
import dorkbox.util.OS;
|
||||||
import javassist.ClassPool;
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtBehavior;
|
||||||
import javassist.CtClass;
|
import javassist.CtClass;
|
||||||
import javassist.CtField;
|
import javassist.CtField;
|
||||||
import javassist.CtMethod;
|
import javassist.CtMethod;
|
||||||
import javassist.CtNewMethod;
|
import javassist.CtNewMethod;
|
||||||
import javassist.Modifier;
|
import javassist.Modifier;
|
||||||
|
import javassist.bytecode.BadBytecode;
|
||||||
|
import javassist.bytecode.CodeIterator;
|
||||||
|
import javassist.bytecode.ConstPool;
|
||||||
|
import javassist.bytecode.InstructionPrinter;
|
||||||
|
import javassist.bytecode.MethodInfo;
|
||||||
|
import javassist.bytecode.Mnemonic;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -134,10 +142,13 @@ class SystemTrayFixes {
|
|||||||
// have to modify the SystemTray.getIconSize as well.
|
// have to modify the SystemTray.getIconSize as well.
|
||||||
trayClass.setModifiers(trayClass.getModifiers() & javassist.Modifier.PUBLIC);
|
trayClass.setModifiers(trayClass.getModifiers() & javassist.Modifier.PUBLIC);
|
||||||
trayClass.getConstructors()[0].setModifiers(trayClass.getConstructors()[0].getModifiers() & javassist.Modifier.PUBLIC);
|
trayClass.getConstructors()[0].setModifiers(trayClass.getConstructors()[0].getModifiers() & javassist.Modifier.PUBLIC);
|
||||||
CtMethod ctMethodGet = trayClass.getDeclaredMethod("getTrayIconSize");
|
|
||||||
ctMethodGet.setBody("{" +
|
|
||||||
"return new java.awt.Dimension(" + trayIconSize + ", " + trayIconSize + ");" +
|
CtBehavior methodInfos[] = new CtBehavior[]{
|
||||||
"}");
|
trayClass.getDeclaredMethod("getTrayIconSize")
|
||||||
|
};
|
||||||
|
|
||||||
|
fixTraySize(methodInfos, trayIconSize);
|
||||||
|
|
||||||
trayBytes = trayClass.toBytecode();
|
trayBytes = trayClass.toBytecode();
|
||||||
}
|
}
|
||||||
@ -159,17 +170,17 @@ class SystemTrayFixes {
|
|||||||
"int rasterImageWidth = rasterImage.getWidth();" +
|
"int rasterImageWidth = rasterImage.getWidth();" +
|
||||||
|
|
||||||
"for (int i = 0; i < numberOfPixels; i++) {" +
|
"for (int i = 0; i < numberOfPixels; i++) {" +
|
||||||
" int iByte = i / 8;" +
|
"int iByte = i / 8;" +
|
||||||
" int augmentMask = 1 << (7 - (i % 8));" +
|
"int augmentMask = 1 << (7 - (i % 8));" +
|
||||||
" if ((pixels[i] & 0xFF000000) == 0) {" +
|
"if ((pixels[i] & 0xFF000000) == 0) {" +
|
||||||
" if (iByte < mask.length) {" +
|
"if (iByte < mask.length) {" +
|
||||||
" mask[iByte] |= augmentMask;" +
|
"mask[iByte] |= augmentMask;" +
|
||||||
" }" +
|
"}" +
|
||||||
" }" +
|
"}" +
|
||||||
"}" +
|
"}" +
|
||||||
|
|
||||||
"if (rasterImage instanceof sun.awt.image.IntegerComponentRaster) {" +
|
"if (rasterImage instanceof sun.awt.image.IntegerComponentRaster) {" +
|
||||||
" rasterImageWidth = ((sun.awt.image.IntegerComponentRaster)rasterImage).getScanlineStride();" +
|
"rasterImageWidth = ((sun.awt.image.IntegerComponentRaster)rasterImage).getScanlineStride();" +
|
||||||
"}" +
|
"}" +
|
||||||
|
|
||||||
"setNativeIcon(((java.awt.image.DataBufferInt)bufferedImage.getRaster().getDataBuffer()).getData(), " +
|
"setNativeIcon(((java.awt.image.DataBufferInt)bufferedImage.getRaster().getDataBuffer()).getData(), " +
|
||||||
@ -180,7 +191,7 @@ class SystemTrayFixes {
|
|||||||
"java.awt.Image image = $1;" +
|
"java.awt.Image image = $1;" +
|
||||||
|
|
||||||
"if (isDisposed()) {" +
|
"if (isDisposed()) {" +
|
||||||
" return;" +
|
"return;" +
|
||||||
"}" +
|
"}" +
|
||||||
|
|
||||||
"int imageWidth = image.getWidth(observer);" +
|
"int imageWidth = image.getWidth(observer);" +
|
||||||
@ -190,21 +201,21 @@ class SystemTrayFixes {
|
|||||||
"java.awt.Graphics2D g = trayIcon.createGraphics();" +
|
"java.awt.Graphics2D g = trayIcon.createGraphics();" +
|
||||||
|
|
||||||
"if (g != null) {" +
|
"if (g != null) {" +
|
||||||
" try {" +
|
"try {" +
|
||||||
// this will render the image "nicely"
|
// this will render the image "nicely"
|
||||||
" g.addRenderingHints(new java.awt.RenderingHints(java.awt.RenderingHints.KEY_RENDERING," +
|
"g.addRenderingHints(new java.awt.RenderingHints(java.awt.RenderingHints.KEY_RENDERING," +
|
||||||
"java.awt.RenderingHints.VALUE_RENDER_QUALITY));" +
|
"java.awt.RenderingHints.VALUE_RENDER_QUALITY));" +
|
||||||
" g.drawImage(image, 0, 0, imageWidth, imageHeight, observer);" +
|
"g.drawImage(image, 0, 0, imageWidth, imageHeight, observer);" +
|
||||||
|
|
||||||
" createNativeImage(trayIcon);" +
|
"createNativeImage(trayIcon);" +
|
||||||
|
|
||||||
" updateNativeIcon(!firstUpdate);" +
|
"updateNativeIcon(!firstUpdate);" +
|
||||||
" if (firstUpdate) {" +
|
"if (firstUpdate) {" +
|
||||||
" firstUpdate = false;" +
|
"firstUpdate = false;" +
|
||||||
" }" +
|
"}" +
|
||||||
" } finally {" +
|
"} finally {" +
|
||||||
" g.dispose();" +
|
"g.dispose();" +
|
||||||
" }" +
|
"}" +
|
||||||
"}" +
|
"}" +
|
||||||
"}");
|
"}");
|
||||||
|
|
||||||
@ -406,7 +417,7 @@ class SystemTrayFixes {
|
|||||||
* Spectacularly enough, because this uses X11, it works on any X backend -- regardless of GtkStatusIcon or AppIndicator support. This
|
* Spectacularly enough, because this uses X11, it works on any X backend -- regardless of GtkStatusIcon or AppIndicator support. This
|
||||||
* actually provides **more** support than GtkStatusIcons or AppIndicators, since this will ALWAYS work.
|
* actually provides **more** support than GtkStatusIcons or AppIndicators, since this will ALWAYS work.
|
||||||
*
|
*
|
||||||
* Additionally, the size of the tray is hard-coded to be 24 -- so we want to fix that as well.
|
* Additionally, the size of the tray is hard-coded to be 24.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* The down side, is that there is a "grey" box -- so hack around this issue by getting the color of a pixel in the notification area 1
|
* The down side, is that there is a "grey" box -- so hack around this issue by getting the color of a pixel in the notification area 1
|
||||||
@ -422,11 +433,8 @@ class SystemTrayFixes {
|
|||||||
* http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/tip/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java
|
* http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/tip/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java
|
||||||
*/
|
*/
|
||||||
public static
|
public static
|
||||||
void fixLinux() {
|
void fixLinux(int trayIconSize) {
|
||||||
// linux/mac doesn't have transparent backgrounds for "swing" system tray icons
|
// linux/mac doesn't have transparent backgrounds for "swing" system tray icons
|
||||||
// TODO Fix the tray icon size to something other than (hardcoded) 24. This will be a lot of work, since this value is in the
|
|
||||||
// constructor, and there is a significant amount of code and anonymous classes there - and javassist does not support non-staic
|
|
||||||
// anonymous classes.
|
|
||||||
|
|
||||||
if (isOracleVM()) {
|
if (isOracleVM()) {
|
||||||
// not fixing things that are not broken.
|
// not fixing things that are not broken.
|
||||||
@ -445,22 +453,13 @@ class SystemTrayFixes {
|
|||||||
String className = "sun.awt.X11.XTrayIconPeer";
|
String className = "sun.awt.X11.XTrayIconPeer";
|
||||||
byte[] eFrameBytes;
|
byte[] eFrameBytes;
|
||||||
byte[] trayIconBytes;
|
byte[] trayIconBytes;
|
||||||
|
byte[] trayPeerBytes;
|
||||||
|
|
||||||
{
|
{
|
||||||
CtClass trayIconClass = pool.get(className);
|
CtClass trayIconClass = pool.get(className);
|
||||||
|
|
||||||
ctField = new CtField(pool.get("java.awt.Robot"), "robot", trayIconClass);
|
|
||||||
ctField.setModifiers(Modifier.STATIC);
|
|
||||||
trayIconClass.addField(ctField);
|
|
||||||
|
|
||||||
ctField = new CtField(pool.get("java.awt.Color"), "color", trayIconClass);
|
|
||||||
ctField.setModifiers(Modifier.STATIC);
|
|
||||||
trayIconClass.addField(ctField);
|
|
||||||
|
|
||||||
trayIconBytes = trayIconClass.toBytecode();
|
|
||||||
|
|
||||||
|
|
||||||
CtClass eFrameClass = null;
|
CtClass eFrameClass = null;
|
||||||
|
CtClass trayPeerClass;
|
||||||
|
|
||||||
CtClass[] nestedClasses = trayIconClass.getNestedClasses();
|
CtClass[] nestedClasses = trayIconClass.getNestedClasses();
|
||||||
for (CtClass nestedClass : nestedClasses) {
|
for (CtClass nestedClass : nestedClasses) {
|
||||||
String name = nestedClass.getName();
|
String name = nestedClass.getName();
|
||||||
@ -474,12 +473,41 @@ class SystemTrayFixes {
|
|||||||
throw new RuntimeException("Unable to find required classes to fix. Unable to continue initialization.");
|
throw new RuntimeException("Unable to find required classes to fix. Unable to continue initialization.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ctField = new CtField(pool.get("java.awt.Robot"), "robot", trayIconClass);
|
||||||
|
ctField.setModifiers(Modifier.STATIC);
|
||||||
|
trayIconClass.addField(ctField);
|
||||||
|
|
||||||
|
ctField = new CtField(pool.get("java.awt.Color"), "color", trayIconClass);
|
||||||
|
ctField.setModifiers(Modifier.STATIC);
|
||||||
|
trayIconClass.addField(ctField);
|
||||||
|
|
||||||
|
|
||||||
|
// fix other classes for icon size.
|
||||||
|
trayPeerClass = pool.get("sun.awt.X11.XSystemTrayPeer");
|
||||||
|
|
||||||
|
// now we have to replace ALL instances (in the constructor and other methods), where the icon size is set (default is 24).
|
||||||
|
// Since, looking at the source code, there is NO other case where the number 24 is used (except for size), we just
|
||||||
|
// bytecode replace 24 with our specified size.
|
||||||
|
|
||||||
|
CtBehavior methodInfos[] = new CtBehavior[]{
|
||||||
|
trayIconClass.getDeclaredConstructors()[0], // only 1 constructor
|
||||||
|
trayIconClass.getDeclaredMethod("getBounds"),
|
||||||
|
trayPeerClass.getDeclaredMethod("getTrayIconSize")
|
||||||
|
};
|
||||||
|
|
||||||
|
fixTraySize(methodInfos, trayIconSize);
|
||||||
|
|
||||||
|
trayIconBytes = trayIconClass.toBytecode();
|
||||||
|
trayPeerBytes = trayPeerClass.toBytecode();
|
||||||
|
|
||||||
|
|
||||||
// gets the pixel color just to the side of the icon. The CRITICAL thing to notice, is that this happens before the
|
// gets the pixel color just to the side of the icon. The CRITICAL thing to notice, is that this happens before the
|
||||||
// AWT window is positioned, so there can be a different system tray icon at this position (at this exact point in
|
// AWT window is positioned, so there can be a different system tray icon at this position (at this exact point in
|
||||||
// time. This means we cannot take a screen shot, because before the window is placed, another icon is in this spot,
|
// time). This means we cannot take a screen shot because before the window is placed, another icon is in this
|
||||||
// and when the window is placed, it's too late to take a screenshot. The second best option is to take a sample of
|
// spot; and when the window is placed, it's too late to take a screenshot. The second best option is to take a sample of
|
||||||
// the pixel color, so at least we can fake transparency. This only works if the notification area is a solid color,
|
// the pixel color, so at least we can fake transparency (this is what we do). This only works if the notification area
|
||||||
// and not an image or gradient.
|
// is a solid color, and not an image or gradient.
|
||||||
CtMethod methodVisible = CtNewMethod.make(
|
CtMethod methodVisible = CtNewMethod.make(
|
||||||
"public void setVisible(boolean b) " +
|
"public void setVisible(boolean b) " +
|
||||||
"{ " +
|
"{ " +
|
||||||
@ -490,198 +518,19 @@ class SystemTrayFixes {
|
|||||||
|
|
||||||
"java.awt.Point loc = getPeer().getLocationOnScreen();" +
|
"java.awt.Point loc = getPeer().getLocationOnScreen();" +
|
||||||
className + ".color = " + className + ".robot.getPixelColor(loc.x-1, loc.y-1);" +
|
className + ".color = " + className + ".robot.getPixelColor(loc.x-1, loc.y-1);" +
|
||||||
// this sets the background of the native component, NOT THE ICON (otherwise weird "grey" flashes occur
|
// this sets the background of the native component, NOT THE ICON (otherwise weird "grey" flashes occur)
|
||||||
"setBackground(" + className + ".color);" +
|
"setBackground(" + className + ".color);" +
|
||||||
"}" +
|
"}" +
|
||||||
|
|
||||||
"super.setVisible(b);" +
|
"super.setVisible(b);" +
|
||||||
" }",
|
" }", eFrameClass);
|
||||||
eFrameClass);
|
|
||||||
eFrameClass.addMethod(methodVisible);
|
eFrameClass.addMethod(methodVisible);
|
||||||
|
|
||||||
eFrameBytes = eFrameClass.toBytecode();
|
eFrameBytes = eFrameClass.toBytecode();
|
||||||
|
|
||||||
|
|
||||||
// CtMethod ctMethodRepaintImage = iconCanvasClass.getDeclaredMethod("repaintImage");
|
|
||||||
|
|
||||||
|
|
||||||
// MethodInfo methodInfo = ctMethodRepaintImage.getMethodInfo();
|
|
||||||
// ConstPool pool2 = methodInfo.getConstPool();
|
|
||||||
// CodeIterator ci = methodInfo.getCodeAttribute().iterator();
|
|
||||||
// int lineNumber = -1;
|
|
||||||
//
|
|
||||||
// while (ci.hasNext()) {
|
|
||||||
// int index = ci.next();
|
|
||||||
// lineNumber = methodInfo.getLineNumber(index);
|
|
||||||
// int opcode = ci.byteAt(index);
|
|
||||||
//
|
|
||||||
// String op = Mnemonic.OPCODE[opcode];
|
|
||||||
// switch (opcode) {
|
|
||||||
// case INVOKEVIRTUAL: {
|
|
||||||
// int i = ci.u16bitAt(index + 1);
|
|
||||||
//
|
|
||||||
// // specifically inject the pixel grabbing code JUST before update happens.
|
|
||||||
// if (pool2.getMethodrefClassName(i)
|
|
||||||
// .equals("sun.awt.X11.XTrayIconPeer$IconCanvas") &&
|
|
||||||
//
|
|
||||||
// pool2.getMethodrefName(i)
|
|
||||||
// .equals("update") &&
|
|
||||||
//
|
|
||||||
// pool2.getMethodrefType(i)
|
|
||||||
// .equals("(Ljava/awt/Graphics;)V")) {
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//// " if (robot == null) {" +
|
|
||||||
//// " robot = new java.awt.Robot();" +
|
|
||||||
//// " }" +
|
|
||||||
//// " if (doClear) {" +
|
|
||||||
|
|
||||||
//// " java.awt.Point loc = getLocationOnScreen();" +
|
|
||||||
//// " color = robot.getPixelColor(loc.x-1, loc.y-1);" +
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// System.out.println(op + " " + "#" + i + " = Method " + pool2.getMethodrefClassName(i) + "." +
|
|
||||||
// pool2.getMethodrefName(i) + "(" + pool2.getMethodrefType(i) + ")");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//// System.out.println(lineNumber + " * " + Mnemonic.OPCODE[op] + " ");
|
|
||||||
// System.out.println(lineNumber + " * " + InstructionPrinter.instructionString(ci, index, pool2));
|
|
||||||
// }
|
|
||||||
|
|
||||||
//new Canvas().update();
|
|
||||||
|
|
||||||
// CtMethod methodUpdate = iconCanvasClass.getMethod("update", "(Ljava/awt/Graphics;)V");
|
|
||||||
|
|
||||||
|
|
||||||
// for(CtMethod method:iconCanvasClass.getDeclaredMethods()){
|
|
||||||
// System.err.println("MEthod: " + method.getName());
|
|
||||||
// method.insertBefore("System.out.println(\"Before every method call....\");");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (CtMethod method : iconCanvasClass.getMethods()) {
|
|
||||||
//// System.err.println("Method: " + method.getName());
|
|
||||||
// if (method.getName()
|
|
||||||
// .equals("getBackground")) {
|
|
||||||
//
|
|
||||||
// System.err.println("found " + method.getName());
|
|
||||||
//// method.insertBefore("System.err.println(\"Before every method call....\");");
|
|
||||||
// method.setBody("return color;");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// StringBuilder collector = new StringBuilder();
|
|
||||||
// int lastLine = -1;
|
|
||||||
//
|
|
||||||
// while (ci.hasNext()) {
|
|
||||||
// int index = ci.next();
|
|
||||||
// lineNumber = methodInfo.getLineNumber(index);
|
|
||||||
// int op = ci.byteAt(index);
|
|
||||||
//
|
|
||||||
// if (lastLine == -1) {
|
|
||||||
// lastLine = lineNumber;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (lineNumber != lastLine) {
|
|
||||||
// if (collector.length() > 0) {
|
|
||||||
// System.out.println(lastLine + " : " + collector);
|
|
||||||
// }
|
|
||||||
// lastLine = lineNumber;
|
|
||||||
// collector.delete(0, collector.length());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// collector.append(Mnemonic.OPCODE[op])
|
|
||||||
// .append(" ");
|
|
||||||
//
|
|
||||||
//// System.out.println(lineNumber + " * " + Mnemonic.OPCODE[op] + " ");
|
|
||||||
// System.out.println(lineNumber + " * " + InstructionPrinter.instructionString(ci, index, pool2));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (collector.length() > 0) {
|
|
||||||
// System.out.println(lineNumber + " : " + collector);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// String body = "{" +
|
|
||||||
// "boolean doClear = $1;" +
|
|
||||||
//
|
|
||||||
// "java.lang.System.err.println(\"update image: \" + doClear);" +
|
|
||||||
//
|
|
||||||
// "java.awt.Graphics g = getGraphics();" +
|
|
||||||
// "if (g != null) {" +
|
|
||||||
// " try {" +
|
|
||||||
// " if (isVisible()) {" +
|
|
||||||
// " if (robot == null) {" +
|
|
||||||
// " robot = new java.awt.Robot();" +
|
|
||||||
// " }" +
|
|
||||||
// " if (doClear) {" +
|
|
||||||
// // gets the pixel color just to the side of the icon. The CRITICAL thing to notice, is that this happens before the
|
|
||||||
// // AWT window is positioned, so there can be a different system tray icon at this position (at this exact point in
|
|
||||||
// // time. This means we cannot take a screen shot, because before the window is placed, another icon is in this spot,
|
|
||||||
// // and when the window is placed, it's too late to take a screenshot. The second best option is to take a sample of
|
|
||||||
// // the pixel color, so at least we can fake transparency. This only works if the notification area is a solid color,
|
|
||||||
// // and not an image or gradient.
|
|
||||||
// " java.awt.Point loc = getLocationOnScreen();" +
|
|
||||||
// " color = robot.getPixelColor(loc.x-1, loc.y-1);" +
|
|
||||||
// " update(g);" +
|
|
||||||
// " } else {" +
|
|
||||||
// " paint(g);" +
|
|
||||||
// " }" +
|
|
||||||
// " }" +
|
|
||||||
// " } finally {" +
|
|
||||||
// " g.dispose();" +
|
|
||||||
// " }" +
|
|
||||||
// "}" +
|
|
||||||
// "}";
|
|
||||||
// ctMethodRepaintImage.setBody(body);
|
|
||||||
|
|
||||||
//
|
|
||||||
// CtMethod ctMethodPaint = iconCanvasClass.getDeclaredMethod("paint");
|
|
||||||
// body = "{" +
|
|
||||||
// "java.awt.Graphics g = $1;" +
|
|
||||||
//
|
|
||||||
// "if (g != null && curW > 0 && curH > 0) {" +
|
|
||||||
// " java.awt.image.BufferedImage bufImage = new java.awt.image.BufferedImage(curW, curH, java.awt.image.BufferedImage.TYPE_INT_ARGB);" +
|
|
||||||
// " java.awt.Graphics2D gr = bufImage.createGraphics();" +
|
|
||||||
// " if (gr != null) {" +
|
|
||||||
// " try {" +
|
|
||||||
//
|
|
||||||
// // this will render the image "nicely"
|
|
||||||
// " gr.addRenderingHints(new java.awt.RenderingHints(java.awt.RenderingHints.KEY_RENDERING," +
|
|
||||||
// " java.awt.RenderingHints.VALUE_RENDER_QUALITY));" +
|
|
||||||
//
|
|
||||||
// // Have to replace the color with the correct pixel color to simulate transparency
|
|
||||||
// " gr.setColor(color);" +
|
|
||||||
// " gr.fillRect(0, 0, curW, curH);" +
|
|
||||||
// " gr.drawImage(image, 0, 0, curW, curH, observer);" +
|
|
||||||
// " gr.dispose();" +
|
|
||||||
// " g.drawImage(bufImage, 0, 0, curW, curH, null);" +
|
|
||||||
// " } finally {" +
|
|
||||||
// " g.dispose();" +
|
|
||||||
// " }" +
|
|
||||||
// " }" +
|
|
||||||
// "}" +
|
|
||||||
// "}";
|
|
||||||
// ctMethodPaint.setBody(body);
|
|
||||||
|
|
||||||
|
|
||||||
// iconCanvasClass.writeFile("/tmp/modifiedClassesFolder");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// whoosh, past the classloader and directly into memory.
|
// whoosh, past the classloader and directly into memory.
|
||||||
BootStrapClassLoader.defineClass(trayIconBytes);
|
BootStrapClassLoader.defineClass(trayIconBytes);
|
||||||
|
BootStrapClassLoader.defineClass(trayPeerBytes);
|
||||||
BootStrapClassLoader.defineClass(eFrameBytes);
|
BootStrapClassLoader.defineClass(eFrameBytes);
|
||||||
|
|
||||||
if (SystemTray.DEBUG) {
|
if (SystemTray.DEBUG) {
|
||||||
@ -691,4 +540,70 @@ class SystemTrayFixes {
|
|||||||
logger.error("Error setting tray icon background color", e);
|
logger.error("Error setting tray icon background color", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static
|
||||||
|
void fixTraySize(final CtBehavior[] behaviors, final int traySize) {
|
||||||
|
for (CtBehavior behavior : behaviors) {
|
||||||
|
CodeIterator methodIterator = behavior.getMethodInfo().getCodeAttribute().iterator();
|
||||||
|
|
||||||
|
while (methodIterator.hasNext()) {
|
||||||
|
int index;
|
||||||
|
try {
|
||||||
|
index = methodIterator.next();
|
||||||
|
int opcode = methodIterator.byteAt(index);
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
case BIPUSH: {
|
||||||
|
int i = methodIterator.byteAt(index + 1);
|
||||||
|
|
||||||
|
if (i == 24) {
|
||||||
|
// re-write this to be our custom size.
|
||||||
|
methodIterator.writeByte((byte) traySize, index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (BadBytecode badBytecode) {
|
||||||
|
badBytecode.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static
|
||||||
|
void showMethodBytecode(final CtBehavior constructorOrMethod) throws BadBytecode {
|
||||||
|
MethodInfo methodInfo = constructorOrMethod.getMethodInfo(); // only 1 constructor
|
||||||
|
ConstPool pool2 = methodInfo.getConstPool();
|
||||||
|
CodeIterator ci = methodInfo.getCodeAttribute().iterator();
|
||||||
|
int lineNumber = -1;
|
||||||
|
StringBuilder collector = new StringBuilder();
|
||||||
|
int lastLine = -1;
|
||||||
|
|
||||||
|
while (ci.hasNext()) {
|
||||||
|
int index = ci.next();
|
||||||
|
lineNumber = methodInfo.getLineNumber(index);
|
||||||
|
int op = ci.byteAt(index);
|
||||||
|
|
||||||
|
if (lastLine == -1) {
|
||||||
|
lastLine = lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineNumber != lastLine) {
|
||||||
|
if (collector.length() > 0) {
|
||||||
|
System.err.println(lastLine + " : " + collector);
|
||||||
|
}
|
||||||
|
lastLine = lineNumber;
|
||||||
|
collector.delete(0, collector.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
collector.append(Mnemonic.OPCODE[op])
|
||||||
|
.append(" ");
|
||||||
|
|
||||||
|
System.out.println(lineNumber + " * " + Mnemonic.OPCODE[op] + " ");
|
||||||
|
System.out.println(lineNumber + " * " + InstructionPrinter.instructionString(ci, index, pool2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collector.length() > 0) {
|
||||||
|
System.err.println(lineNumber + " : " + collector);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user