Leaflet does not work in WebEngine after JavaFX 17 - java

I have an application made with JavaFX 16 which contains a WebView used to show an interactive map using the Leaflet JS library.
I have a problem when I try to transition to JavaFX 17, the interactive map does not work anymore (it cannot be moved nor clicked, but it can be scrolled). I reproduced the bug on a minimal example with the OpenStreetMap website that uses Leaflet :
package test;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage stage) {
WebView webView = new WebView();
webView.getEngine().load("https://www.openstreetmap.org/");
Scene scene = new Scene(new StackPane(webView), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
The interactive map on the OpenStreetMap website is rendered correctly and can be zoomed in but it cannot be moved.
I am using Gradle to download JavaFX, this is my build.gradle :
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.10'
}
repositories {
mavenCentral()
}
javafx {
version = "17"
modules = [ 'javafx.controls', 'javafx.web']
}
application {
mainClass = 'test.App'
}
I reproduced the bug with versions :
18-ea+5
17.0.1
17
17-ea+2
but the map worked with versions :
16
15
So it seems that version 17 brings the issue.
Also I reproduced the bug on macOS 12 (M1 using x86 JavaFX with Rosetta) and on Ubuntu 20. So it does not seem to be an issue with JavaFX on macOS.
Other interactive maps such as Google map, Apple map and Bing map, worked with the same code as above, and MapBoxGL does not work because WebGL is not supported. So it seems that the issue is related to Leaflet.
So I wonder if it is a known issue, if anyone else has the same issue, or if it is an issue on my side ?

I have entered this into the JDK bug database because there seems to be a more general issue here. See: https://bugs.openjdk.java.net/browse/JDK-8276859 This is also not the only report about such an issue. See also: After Java update to the version 1.8.0_301 JavaFX WebView with Leaflet.Draw.Circle, Leaflet.Edit.Circle does not work as well as OSM is not draggable

It's nice to see that there are more of us looking into this.
I did some deeper investigation and was able to pinpoint the problem which consequently lead me to a workaround/hack which makes dragging of Leaflet map to work fine in WebKit (Java FX 17).
Findings:
This is definitely regression as dragging of Leaflet map works fine with JavaFX releases prior to 17. So as #José pointed out it's most probably related to WebKit 610.2 upgrade (JDK-8259635).
It seems to be related to PointerEvent which seems to not be properly generated in the case of Java FX 17. Following example outputs 1 when dragging with the mouse button down. But it outputs 0 in the case of WebView/WebKit inside Java FX 17. Note that e.buttons value is properly set to 1 in JavaFX WebView/WebKit versions prior to Java FX 17.
<!doctype html>
<body style="height: 200px">
<p>Click and drag & observe the console output</p>
<script>
var onMove = function (e) {
console.log("e.buttons: " + e.buttons);
}
var body = document.getElementsByTagName('body')[0];
document.addEventListener("pointermove", onMove, false);
</script>
</body>
Based on the finding no. 2 I was able to identify the JS code which prevent the Leaflet map from moving (while being dragged). In Leaflet 1.7.1. it's actually this if expression which consequently causes map to not be moved (because PointerEvent.buttons is wrongfully set to 0 by Java FX 17):
https://github.com/Leaflet/Leaflet/blob/bd88f73e8ddb90eb945a28bc1de9eb07f7386118/src/dom/DomEvent.Pointer.js#L104
I've already reported this through the Oracle bug report system (JDK-8278150). The issue was "mistakenly" closed - I've already provided them with the info explained in this answer so they will hopefully re-open it or tackle it under JDK-8276859.
Workaround (Leaflet 1.7.1):
Workaround/hack to make Leaflet map work again:
Comment out the if expressions at:
https://github.com/Leaflet/Leaflet/blob/bd88f73e8ddb90eb945a28bc1de9eb07f7386118/src/dom/DomEvent.Pointer.js#L104
This makes the Leaftlet map to move properly while being dragged in the Java FX 17 WebView - but please consider this more like a hack to make it work again as this was not tested out thoroughly...
Update 1
This issue seems to be gone with the latest master branch of Leaflet despite regression in JavaFX WebView/WebKit remains (can anyone please confirm this?).
Update 2
As stated by #mipa, the underlying issue was fixed in 8u291 and openjfx17. More info available at:
http://bugs.openjdk.java.net/browse/JDK-8278759

Related

Eclipse plugin development editor font

I am using Eclipse 3.7.0 for plugin development and I am using Xtext 2.9.2. My editor preferences isn't working correctly.
On windows 7, 8, 10 this happens:
.
On 64 bit builds, I am not able to change editor font. Hitting the change button does nothing but change the mouse to the busy/sandclock for a second and then back again to normal.
The same 64 bit builds were tested on windows XP and everything works as it should.
On 32 bit builds, everything works as expected and the windows font picker dialog appears.
This is how I create the preference page:
#Override
protected void createFieldEditors() {
// Add show font preference
fontField = new FontFieldEditor(JFaceResources.TEXT_FONT, EDIT_EDITOR_FONT_LABEL, getFieldEditorParent());
addField(fontField);
fontField.setPreferenceStore(getPreferenceStore());
// initialize the font preference with the default resources font if not initialized
String defaultFont = getPreferenceStore().getDefaultString(JFaceResources.TEXT_FONT);
if(defaultFont.isEmpty()) {
font= JFaceResources.getTextFont();
if (font != null) {
FontData[] data= font.getFontData();
if (data != null && data.length > 0) {
PreferenceConverter.setDefault(getPreferenceStore(), JFaceResources.TEXT_FONT, data[0]);
}
}
}
}
The .log file is empty and has nothing that is beneficial.
While debugging, I went to org.eclipse.swt.widgets.FontDialog.java and found that this line always returns false without the dialog appearing. From what I understand this call should be blocking and will only return when the dialog is closed either by X, OK or Cancel buttons but it returns immediately with false.
/* Open the dialog */
boolean success = OS.ChooseFont (lpcf)
I also tried something as minimal as this example and same thing happens.
Months passed and I figured out what was causing the issue.
Basically we have a JNI layer which loads some dll that requires MSVCR90.dll. This requires embedding MSVCR90.dll manifest into eclipse.exe used for our RCP, this is done using mt.exe provided by Microsoft Visual Studio.
While building I accidentally didn't embed the MSVCR90.dll manifest, this resulted into the error during loading the dll which says that MSVCR90.dll is missing. I however noticed that the treeview styling looked correct.
This was also the answer to my other question Eclipse RCP Jface/SWT TreeViewer on Windows 10. The manifest also affected the UI look and feel treeviews and progressbars didn't look like the ones provided by the OS.

Android Studio 2.2.0.12 designer automatically ads "#+id" prefix before view id and it causes this unusual error

When I type in this id for a GroupBox (the view is irrelevant, as this happens with all Views)
This is what I wrote in the id attribute :
Then after I press ENTER, Android Studio adds a "#+id prefix" :
This, after I compile, gives the following error in R.java:
error: type annotations are not supported in -source 1.7 (use -source
8 or higher to enable type annotations)
It comes from the line that has "#+id" as a prefix.
public static final class id {
public static final int #+id/groupBox=0x7f0c0055; // Error comes from this line
public static final int action0=0x7f0c006e; // ok
public static final int action_bar=0x7f0c0041; // ok
public static final int action_bar_activity_content=0x7f0c0000; // ok
public static final int action_bar_container=0x7f0c0040; // ok
// rest of lines ok
// ...
The project had been started in a previous version of Android Studio, hence the rest of the view names remain unaffected.
I tried manually erasing the prefix but it didn't work, I tried looking in Settings without luck, and tried searching online for a solution until I came to realize this is a new problem and the only hope is Stack Overflow.
========================================================================
I solved the problem this way : The update to Android Studio v2.2.0.12 happened right before the problem with the “#+id” prefix appeared. I simply uninstalled Android Studio from my computer, restarted my computer (important!) then reinstalled Android Studio. I chose the no import from previous version whatsoever option.
Notice: I still had the old Android Studio installer left, but allowed it to update to the latest version. After the update was done, the problem disappeared.
I am not 100% certain the solution will work for everybody, but I had quite a bit of experience with installing/uninstalling software on Windows (am using 8.1), and the software behaving abnormally if used before a restart. I hope this helps whomever is stuck with the same issue.

Offline tile caching using MapBox Android SDK

I have a working iOS prototype using the iOS tile-caching technique as shown below (Objective-C code):
RMTileCache * tileCache = [[RMTileCache alloc] initWithExpiryPeriod:0];
[tileCache setBackgroundCacheDelegate:self];
RMMapboxSource * tileSource = [[RMMapboxSource alloc] initWithMapID:mapID];
[tileCache beginBackgroundCacheForTileSource:tileSource southWest:southWest northEast:northEasth minZoom:minZoom maxZoom:maxZoom];
What this basically does is download the map, cache the tiles permanently and make it possible for the app to run offline in the future. Since we're going through the official payed API, this is of course not violating any of the legal restrictions.
Now I'd like to achieve the same on Android. I have the SDK running in Android Studio and a working project with a remote map using the Map ID, basically this (Android Eclipse layout XML):
<com.mapbox.mapboxsdk.views.MapView
android:id="#+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
mapid=“my_map_id" />
This works fine, but the solution has to be completely offline once the caching is done. My question is: is there a Java equivalent of the iOS source code above in the MapBox SDK? I attempted to look in the API, but could not find a solid reference to the tile caching system. And after some painful time trying to get it running based on the method names and code documentation, I gave up.
I'm running the latest GitHub distribution of MapBox along with the latest Android Studio, everything's up and running fine, but can't find the code to accomplish this. I don’t necessarily need an API reference, a few lines of code showing how it’s done would be enough.
Offline Tile Caching support is now available in the Mapbox Android SDK as of version 0.5.1. It was released on 20-December-2014. Here's a basic example of how to get started:
OfflineMapDownloader offlineMapDownloader = OfflineMapDownloader.getOfflineMapDownloader(getActivity());
BoundingBox boundingBox = mapView.getBoundingBox();
CoordinateSpan span = new CoordinateSpan(boundingBox.getLatitudeSpan(), boundingBox.getLongitudeSpan());
CoordinateRegion coordinateRegion = new CoordinateRegion(mapView.getCenter(), span);
offlineMapDownloader.beginDownloadingMapID("MapboxMapID", coordinateRegion, (int) mapView.getZoomLevel(), (int) mapView.getZoomLevel());
To load a previously saved map:
ArrayList<OfflineMapDatabase> offlineMapDatabases = offlineMapDownloader.getMutableOfflineMapDatabases();
OfflineMapDatabase db = offlineMapDatabases.get(0);
OfflineMapTileProvider tp = new OfflineMapTileProvider(getActivity(), db);
offlineMapOverlay = new TilesOverlay(tp);
mapView.addOverlay(offlineMapOverlay);
I asked this question to the support team, here's the answer:
"We don't currently have a release date for the Android SDK or for this feature, because both are in very early stages of development.
--
Tom MacWright
support#mapbox.com"
It's a very good product, I hope we can use it soon in Android.
In your layout file there must be:
<com.mapbox.mapboxsdk.views.MapView
android:id="#+id/yourMapViewId"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
In code where you want to initialize MapView:
File file = new File("your full path to tiles db");
MBTilesLayer mbTilesLayer = new MBTilesLayer(file);
MapView mapView = (MapView) findViewById(R.id.yourMapViewId);
mapView.setTileSource(mbTilesLayer);

How to ensure execution of latest version of class file?

OK so I started with this:
import java.awt.*;
import java.applet.*;
public class Oval extends Applet {
public void paint (Graphics g)
{
g.setColor(Color.red);
g.fillOval(50,50,70,70);
}
}
Saved it as Oval.java. Then I ran javac Oval and it spits out the class file. Linked the class file to my HTML and all was good. Then I tried to change the color of the oval to say Color.blue and everything was not so good. I just changed the code in the Oval.java file, then re-ran the javac Oval and the result was a "new" class file... but it's the output is the exact same.
Do I have to "reset" the memory space or something? I have tried for some time to get the answer but I simply lack the vocabulary to accurately ask the question.
Sounds like the browser is caching the class file. I would try
Running the applet using the Applet Viewer
If that works, then it's a browser caching issue (clear your browser's cache)
But if it doesn't look different, or like you want in the Applet Viewer, then it must be something in your local environment (either it's not building the source file you want, or the class is going somewhere unexpected)
It could be that your browser is caching the previous version of your applet. Try clearing / disabling your cache.
Maybe the old version is in your browser-cache? Try hitting the follwing keys on your page:
Windows: ctrl + F5
Mac/Apple: Apple + R or command + R
Linux: F5
You don't have to reset the java environment, ever.
You might have a browser window open, and your browser is attempting to be "smart" avoiding reload of a page which is already "fetched". Depending on the browser, you will need to learn how to clear the browser cache.

HTML no longer working in JLabel (and other components)

I have a java applet that I've written and have been running it for quite a while. In the applet I have a bunch of JLabels that use HTML in their text content (which is allowed, and has been working for years). The main reason I use HTML is to allow line breaks in JLabels.
The issue: fairly recently the JLabels that have HTML in them (some don't) stopped displaying their text. I think it might have something to do with the recent java update (Java SE 6 Update 22, on 2010-Oct-12) not 100 percent sure, but the problems did seem to start around then. Maybe a bug has been introduced? or feature removed?
I tried with a JEditorPane and seemed to have the same issues when the content was HTML.
Also something important to note is that the first time you load the applet (first time your java runtime starts) it works FINE, but if you refresh the webpage then it has the issues as described.
Does anyone have similar issues? anyone have any insights? or am I just doing something dumb?
I made a very simple test applet and I can reproduce the issues with 100% regularity (remembering that the first time the runtime loads it will work fine, only successive refreshes will cause the issues):
[HelloWorldApplet.java]
import javax.swing.*;
public class HelloWorldApplet extends JApplet
{
public void init()
{
this.add(new JLabel("Hello Everybody (Text)"), java.awt.BorderLayout.NORTH);
this.add(new JLabel("<html><body>Hello Everybody (HTML)</body></html>"), java.awt.BorderLayout.SOUTH);
}
}
[HellowWorldApplet.html]
<html>
<title>A Test</title>
<body>
<applet code="HelloWorldApplet.class" width="320" height="120">
You need Java
</applet>
</body>
</html>
PS. I've been mainly testing using Chrome but I did breifly try in IE 8 also.
Also I (obviously) have the latest Java SE 6 update 22 installed as my run time, and have the matching update for my JDK. I compile the above test applet using simply: "javac HelloWorldApplet.java"
Wasted an afternoon looking for the cause of this, see the following bug report http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6993691
The workaround in the bug report is:
import javax.swing.*;
import javax.swing.text.html.parser.ParserDelegator;
public class HelloWorldApplet extends JApplet {
public void init() {
ParserDelegator workaround = new ParserDelegator();
applet.add(new JLabel("Hello Everybody (Text)"), java.awt.BorderLayout.NORTH);
applet.add(new JLabel("<html>Hello Everybody (HTML)</html>"), java.awt.BorderLayout.SOUTH);
}
}
Sounds from the description like a threading issue.
Unfortunately applets are not constructed or have their lifecycle methods called on the AWT Event Dispatch Thread (EDT).
Technically your constructor and init code should be executed inside java.awt.EventQueue.invokeAndWait.

Categories

Resources