Skip to content

Instantly share code, notes, and snippets.

@riccardobl
Last active June 23, 2020 09:31
Show Gist options
  • Save riccardobl/18603f9de508b1ab6c9e to your computer and use it in GitHub Desktop.
Save riccardobl/18603f9de508b1ab6c9e to your computer and use it in GitHub Desktop.
JavaFX Transparent WebView PATCH
/**
* @author Riccardo Balbo
* @description This patch aims to make the WebView capable to correctly render transparent pages.
* @license
* Copyright (c) 2015 Riccardo Balbo < riccardo @ forkforge . net >
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must
* not claim that you wrote the original software. If you use this
* software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must
* not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.lang.instrument.Instrumentation;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class TransparentWebViewPatch implements ClassFileTransformer{
private final ClassPool _CLASS_POOL=ClassPool.getDefault();
public static void premain(String agentArguments,Instrumentation instrumentation){
instrumentation.addTransformer(new TransparentWebViewPatch());
}
// This patch aims to make the WebView capable to correctly render
// transparent pages.
@Override
public byte[] transform(ClassLoader loader, String class_name, Class<?> class_being_redefined, ProtectionDomain protection_domain, byte[] byte_code) throws IllegalClassFormatException {
if(class_name.equals("com/sun/webkit/WebPage")){
System.out.println("> Patching "+class_name+" ...");
try{
CtClass ct_class=_CLASS_POOL.makeClass(new ByteArrayInputStream(byte_code));
// First thing to do is edit the fireLoadEvent in order to force
// the page to set its own
// background to transparent black (0x00000000 argb) each time
// it changes
CtMethod fireLoadEvent_method=ct_class.getDeclaredMethod("fireLoadEvent");
fireLoadEvent_method.insertBefore("{\n"+" "
+ "setBackgroundColor(0);\n"
+"}");
// DEPRECATED CODE: NOT WORKING FROM JAVA 1.8.0_66
// Then, we edit the the paint2GC method in order to call
// clearRect every time right before it
// start to draw a clip (clips are parts of the rendered frame).
// We need this because when the webpage is rendered with the
// backbuffer enabled,
// every clip is just drawn over the old rendered frame without
// care about the alpha channel.
// NOTE: there is a system property
// com.sun.webkit.pagebackbuffer that could do the trick without
// this entire patch, but i didn't succeed in getting anything
// useful out of it...
// CtMethod
// paint2GC_method=ct_class.getDeclaredMethod("paint2GC");
// paint2GC_method.insertAt(696,
// "{\n" +
// " com.sun.webkit.graphics.WCRectangle clip=$1.getClip(); \n"
// +
// "
// $1.clearRect(clip.getX(),clip.getY(),clip.getWidth(),clip.getHeight());\n"
// +
// "}"
// );
// END OF DEPRECATED CODE
// Then we replace the scroll method body in order to force the
// repaint of the entire frame
// when the page is scrolled
CtMethod scroll_method=ct_class.getDeclaredMethod("scroll");
scroll_method.setBody(
"{\n"+" "
+ "addDirtyRect(new com.sun.webkit.graphics.WCRectangle(0f,0f,(float)width,(float)height));\n"
+"}"
);
byte_code=ct_class.toBytecode();
ct_class.detach();
}catch(Exception e){
System.out.println("/!\\ "+class_name+" patching failed :(");
e.printStackTrace();
return byte_code;
}
System.out.println("> "+class_name+" patching succeeded!");
}else if(class_name.equals("com/sun/javafx/webkit/prism/WCGraphicsPrismContext")){
System.out.println("> Patching "+class_name+" ...");
try{
CtClass ct_class=_CLASS_POOL.makeClass(new ByteArrayInputStream(byte_code));
// Then, we edit the the WCGraphicsPrismContext.setClip method
// in order to call clearRect over the area of the clip.
CtClass signature[]=new CtClass[]{_CLASS_POOL.get("com.sun.webkit.graphics.WCRectangle")};
CtMethod setClip_method=ct_class.getDeclaredMethod("setClip",signature);
setClip_method.insertBefore(
"{"+" "
+ " $0.clearRect($1.getX(),$1.getY(),$1.getWidth(),$1.getHeight());"
+"}");
byte_code=ct_class.toBytecode();
ct_class.detach();
}catch(Exception e){
System.out.println("/!\\ "+class_name+" patching failed :(");
e.printStackTrace();
return byte_code;
}
System.out.println("> "+class_name+" patching succeeded!");
}
return byte_code;
}
}
origin_dir=$PWD
rm -R build
mkdir build
rm -R /tmp/buildTransparentWebViewPatch
mkdir /tmp/buildTransparentWebViewPatch
cp TransparentWebViewPatch.java /tmp/buildTransparentWebViewPatch
cd /tmp/buildTransparentWebViewPatch
echo "Downloading jboss javassist..."
wget https://github.com/jboss-javassist/javassist/releases/download/rel_3_20_0_ga/javassist.jar > /dev/null 2>&1
echo "Compiling..."
javac -cp javassist.jar TransparentWebViewPatch.java
echo "Building jar..."
sed -n '/\/\*\*/,/\*\//p' TransparentWebViewPatch.java > INFO.txt
echo "Premain-Class: TransparentWebViewPatch" > manifest.txt
jar -cvfm TransparentWebViewPatch.jar manifest.txt INFO.txt TransparentWebViewPatch.class TransparentWebViewPatch.java
cp TransparentWebViewPatch.jar $origin_dir/build/
cp javassist.jar $origin_dir/build/
rm -R /tmp/buildTransparentWebViewPatch
echo "Done!"
@1-alex98
Copy link

1-alex98 commented May 2, 2020

Well I removed patching the "scroll" method now it runs and works as well. No idea what I did but seems working :D

@1-alex98
Copy link

1-alex98 commented May 3, 2020

Ok in the end that was not the solution instead:

scroll_method.insertBefore(
            "{\n" + "   "
                + "addDirtyRect(new com.sun.webkit.graphics.WCRectangle(0f,0f,(float)width,(float)height));\n"
                + "return;"
                + "}"
        );

works, setBody(...) somehow does not work.

@tbphong
Copy link

tbphong commented Jun 22, 2020

I have problem with javafx 14.
javassist.CannotCompileException: [source error] no such class: com.sun.webkit.graphics.WCRectangle
javassist.NotFoundException: com.sun.webkit.graphics.WCRectangle

Can you give me some advice? Thanks you.

@tbphong
Copy link

tbphong commented Jun 22, 2020

I have fixed above problem
Console show msg

Patching com/sun/webkit/WebPage ...
com/sun/webkit/WebPage patching succeeded!
Patching com/sun/javafx/webkit/prism/WCGraphicsPrismContext ...
com/sun/javafx/webkit/prism/WCGraphicsPrismContext patching succeeded!

But the webview background still not transparent

@1-alex98
Copy link

@tbphong
Copy link

tbphong commented Jun 23, 2020

Hi axel1200.
I have used your version.
Console show msg.

Patching com/sun/webkit/WebPage ...
com/sun/webkit/WebPage patching succeeded!
Patching com/sun/javafx/webkit/prism/WCGraphicsPrismContext ...
com/sun/javafx/webkit/prism/WCGraphicsPrismContext patching succeeded!

But the webview background still not transparent
I use JDK 14, javaassist 3.27.0-GA, and Java Fx 14.
Can you tell me what u are using? Thank a lot.

@1-alex98
Copy link

I used jdk 11 :D not sure if that creates an issue. As javafx 14 says it needs jdk 11+. Not sure about the rest but you should find it in the repo

@1-alex98
Copy link

javassist.version=3.23.1-GA

@1-alex98
Copy link

And these vm parameters of which many should not be related -DnativeDir=build/resources/native -Dprism.dirtyopts=false -Xms128m -Xmx712m -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=33 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseStringDeduplication -javaagent:webview-patch/build/libs/webview-patch.jar -Djava.net.preferIPv4Stack=true -XX:TieredStopAtLevel=1 -noverify

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment