I'm working on a JavaFX project and would like to switch from Oracle JDK 1.8 to OpenJDK 11. So far the transition has been pretty seamless, but there is still one main problem related to touch/mouse input that's causing some trouble.
The JavaFX UI is supposed to run on a touch-enabled device, which used to work straight out of the box with Oracle JDK 1.8. When I touch the screen, the following sequence of mouse events is fired as expected:
MOUSE_PRESSED
MOUSE_RELEASED
MOUSE_CLICKED
After building the same application with OpenJDK11 (using OpenJFX 11 as an external library as JavaFX is no longer part of the JDK by default) I get the follwing sequence of events:
MOUSE_ENTERED_TARGET
MOUSE_ENTERED_TARGET
MOUSE_EXITED_TARGET
MOUSE_EXITED_TARGET
This explains why I can't click any buttons (or controls in general). So far so good. The question is, how do I get my MOUSE_{PRESSED,RELEASED,CLICKED} events back?
SSCE:
package com.example.jfxtouchtest;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TouchEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class JFXTouchTest {
public static void main(String[] args) {
Application.launch(JFXApp.class, args);
}
public static class JFXApp extends Application {
#Override
public void start(Stage primaryStage) {
primaryStage.addEventFilter(TouchEvent.ANY, e -> System.out.println("touch event: " + e.getEventType()));
primaryStage.addEventFilter(MouseEvent.ANY, e -> System.out.println("mouse event: " + e.getEventType()));
primaryStage.setScene(new Scene(new Pane()));
primaryStage.setWidth(800);
primaryStage.setHeight(600);
primaryStage.show();
}
}
}
I think it's worth noting that all fired events are MouseEvents (not TouchEvents), regardless of whether I'm using the touchscreen or not. That in itself is sort of strange in my opinion, but at least I'm getting the desired behaviour with JDK 8...
Some background information:
OS: Ubuntu 18.04.01 LTS
Kernel: 4.15.0-42-generic
Oracle JDK 1.8.0_191
OpenJDK 11.0.1
Touchscreen (as reported by xinput): Atmel maXTouch Digitizer
The touchscreen works just fine with other applications, click events seem to be handled as expected.
The somehwat related VM-arguments
-Dcom.sun.javafx.isEmbedded=true and
-Dcom.sun.javafx.touch=true
both seem to have no effect on the issue
There seems to be a slight difference in the xev output I'm getting depending on whether I'm using the mouse or the touchscreen:
Mouse (state is 0x0 for ButtonPress, 0x100 for ButtonRelease):
ButtonPress event, serial 34, synthetic NO, window 0x3400001,
root 0x193, subw 0x0, time 16982696, (93,90), root:(964,612),
state 0x0, button 1, same_screen YES
ButtonRelease event, serial 34, synthetic NO, window 0x3400001,
root 0x193, subw 0x0, time 16983364, (93,90), root:(964,612),
state 0x100, button 1, same_screen YES
Touchscreen (state is 0x100 in both cases):
ButtonPress event, serial 34, synthetic NO, window 0x3400001,
root 0x193, subw 0x0, time 17599475, (93,145), root:(964,667),
state 0x100, button 1, same_screen YES
ButtonRelease event, serial 34, synthetic NO, window 0x3400001,
root 0x193, subw 0x0, time 17599537, (93,145), root:(964,667),
state 0x100, button 1, same_screen YES
I'm not exactly sure what this means, though.
Any help would be greatly appreciated, even if it's just a confirmation that the issue is reproducible on another machine with another type of touchscreen! Many thanks in advance!
UPDATE: I have managed to get my hands on a different touchscreen in the meantime, and it seems to work fine with that one. What's interesting is that, just like with regular mouse events, xev reports two different states for ButtonPress and ButtonRelease, so maybe the state field being the same for both event types on the other touchscreen has something to do with this after all?
I had the same problem with my touch screen and JFX. My code works fine with Open JDK 1.8 and its corresponding JFX, it fails with OpenJDK 11 and its corresponding JFX. It works fine with the JDK and JFX from Liberica https://bell-sw.com/pages/java-11.0.7-for-Embedded/
So for me my workaround was to change to the Liberica JDK 11 and JFX distribution.
Other options may be JDK, JFX distributions from Azul or Corretto.
Force JavaFX to use gtk-2 by using the java parameter -Djdk.gtk.version=2. The touchscreen works with that setting although this causes other problems with our application (possibly related to 3rd party libraries).
Related
I have a reproducible problem with the Mint Cinnamon desktop locking up when hitting a breakpoint debugging with Eclipse. When I say it's locking up, I mean mouse clicks are completely inoperable (even on the Mint panel), but the mouse cursor still moves. Keyboard is unresponsive, except for some OS-level shortcuts like Alt-Tab. Alt-Tab looks like it's working, but selecting another window doesn't actually focus or activate the window (only the Alt-Tab selector popup works). I can only recover using Ctrl-Alt-ESC to restart Cinnamon. Everything proceeds fine after that.
Debugging and breakpoints work fine everywhere else as far as I can tell except when the breakpoint is inside an anon inner class or lambda.
Public git repo with a fairly simple example project causing this:
https://bitbucket.org/jfxexamples/eclipseminttest
Linux Mint 17.3 AND a totally new install of Mint 18 on a different PC - both behave the same
Eclipse Neon 4.6.0
Java 8 (1.8.0_92) - Oracle JDK (Using JavaFX)
Code below (you'll have to grab the project files to run it though):
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Sample.fxml"));
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
package application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
public class SampleController {
#FXML
private TabPane tabPane;
public void createTab() {
Tab tab = new Tab("New tab");//Breakpoint here does NOT freeze desktop
// tab.setOnCloseRequest(e -> {
// System.out.println("bleh");//Breakpoint here, freezes desktop
// });
tab.setOnCloseRequest(new EventHandler<Event>(){
#Override public void handle(Event e){
System.out.println("bleh");//Breakpoint here, also freezes desktop
}
});
tabPane.getTabs().add(tab);//Breakpoint here does NOT freeze desktop
int index = tabPane.getTabs().size() - 1;
tabPane.getSelectionModel().select(index);
}
}
Using Win10/IntellijCE/JDK1.8.0_92 there is no problem. Try using IntellijCE on Mint. If it works the problem is most likely with Cinnamon.
Cinnamon is on Github, so use their Issue Tracker there to report the bug.
Browsing the issues, there is even something maybe related to your issue: Check out https://github.com/linuxmint/Cinnamon/issues/1084.
I have had exactly the same problem in Linux Mint 17.3 Mate, with JDK 1.8.0_101, Eclipse Neon and a JavaFX application.
When debugging the application, the system freezes completely and I have to kill the process manually.
It seems a problem related with the X display. It should work if you set, in the VM arguments of your application, the flag:
-Dsun.awt.disablegrab=true
At least that worked for me...
This is a known problem on Linux. It is related to the XGrabPointer and XGrabKeyboard API calls (see X Pointer Grabbing). This API can be used by screensavers, so it is intended to make the keyboard and mouse unusable (apart from moving the mouse cursor).
During debugging, it is a problem. In the past, a workaround was to configure AllowDeactivateGrabsin xorg. That allowed to break the "grap" by a keyboard shortcut, by default CTRL+ALT+/. Since it was possible to bypass screensavers, it was disabled around 2012 because of its security implications.
On a modern Linux system, you can enable enable grab break actions:
setxkbmap -option grab:break_actions
Now, you can trigger a grab break by executing:
xdotool key XF86Ungrab
Once your keyboard is frozen, you might be not able to run it, so during debugging, I am calling it every two seconds:
while :; do sleep 2 ; xdotool key XF86Ungrab ; done
Notes:
setxkbmap is part of xorg-setxkbmap
xdotool is part of xdotool
While testing the setup, it is useful to have a ssh connection from another machine. Thus, if mouse and keyboard freeze up, you can always kill the process that grabbed the mouse and keyboard.
I am writing a Java application for image analysis which at one point opens ImageJ with
ImageJ ij = new ImageJ();
and also opens a Windows containing an ImagePlus.
Now, whenever one closes ImageJ first, the ImagePlus will not close when pushing the close button. The other way around works, however in both cases an exception is thrown after closing ImageJ:
java.lang.reflect.InvocationTargetException
at java.awt.EventQueue.invokeAndWait(EventQueue.java:1288)
at java.awt.Window.doDispose(Window.java:1209)
at java.awt.Window.dispose(Window.java:1147)
at ij.ImageJ.run(ImageJ.java:784)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: null source
at java.util.EventObject.<init>(EventObject.java:56)
at java.awt.AWTEvent.<init>(AWTEvent.java:337)
at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:285)
at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:174)
at sun.awt.X11.XBaseMenuWindow.dispose(XBaseMenuWindow.java:907)
...
I don't know whether it is related as it happens in both cases.
Any suggestions on how to force ImageJ to close all its windows?
The exception
This happens when using OpenJDK 7 on Linux. The exception is fixed in Java 8.
Also: note that that exception is not the actual cause of the quitting issue you are seeing.
The disposal problem
ImageJ 1.x's application disposal is a convoluted mess. (See this news post for some technical discussion.) It was really intended primarily to run as a standalone application, and is mostly tested with the exitWhenQuitting flag set to true such that the JVM shuts down upon closure of the main window. So it is not surprising that using ImageJ in a different fashion results in hanging image windows.
I have tested various workarounds—e.g.:
ij.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(final WindowEvent e) {
// dispose all image windows
for (final int id : WindowManager.getIDList()) {
final ImagePlus imp = WindowManager.getImage(id);
if (imp == null) continue;
final ImageWindow win = imp.getWindow();
if (win != null) win.dispose();
}
// dispose all other ImageJ windows
for (final Window w : WindowManager.getAllNonImageWindows()) {
w.dispose();
}
}
});
But none of them work as one might hope. It cost me weeks of development and experimentation to make quitting work as we wanted in ImageJ2, according to the news posted linked above.
Here is some code using ImageJ2 that almost behaves the way you want:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
import net.imagej.ImageJ;
public class IJDispose {
public static void main(final String... args) {
final ImageJ ij = new ImageJ();
ij.ui().showUI();
final JFrame frame = new JFrame("Hello");
final JButton b = new JButton("Close ImageJ");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
ij.getContext().dispose();
}
});
frame.getContentPane().add(b);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
After launching it, press Shift+B to open the Blobs sample image. Then click the "Close ImageJ" button from the non-ImageJ frame. You'll see that the ImageJ main window and the image window dispose as desired (using this code from ImageJ Legacy).
However, there are (at least) three problems:
This example does not hook up the ij.getContext().dispose() call to the actual ImageJ1 UI window closing event. And doing that would not be trivial (I say without having dug deeply in this code recently).
After disposing ImageJ, as well as the extra JFrame, the JVM is supposed to shut down. We put a lot of effort into making it do so, actually. But it actually doesn't with the current version of ImageJ, presumably due to some undisposed resource(s) somewhere. This is a bug.
Clicking the X on the main ImageJ window shuts down the entire JVM, because ImageJ1's exitWhenQuitting flag gets set to true. You could toggle it back to false yourself, but this is actually tricky due to class loading issues relating to the fact that ImageJ2 patches ImageJ1 at runtime using Javassist.
The next question is: How badly do you really need this to work?
This bug is known for years, yet is is still present in Java 1.7.0_25 version which I'm using on Windows 8. The following result are same regardless of wether i have numlock turned on or not:
Robot bot = new Robot();
bot.keyPress(KeyEvent.VK_UP); //this in documentation is non-numpad up arrow key
bot.keyRelease(KeyEvent.VK_UP); //pressed the numpad up arrow key
//folowing line is line #43
bot.keyPress(KeyEvent.VK_KP_UP); //this in documentation is numpad up arrow key
bot.keyRelease(KeyEvent.VK_KP_UP); //causes folowing exception:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid key code
at sun.awt.windows.WRobotPeer.keyPress(Native Method)
at java.awt.Robot.keyPress(Robot.java:358)
at test.RobotArrow.main(RobotArrow.java:43)
I know this question was already asked here but over a year ago, so is there any progress? I cant google anything, there is even an ofiicial bug report
So, is there finnaly a solution or not?
//PRESS WINDOWS + ARROW LEFT
Robot divideWindow = new Robot();
divideWindow.keyPress(KeyEvent.VK_WINDOWS);
divideWindow.delay(100);
divideWindow.keyPress(KeyEvent.VK_LEFT);
divideWindow.delay(100);
divideWindow.keyRelease(KeyEvent.VK_LEFT);
divideWindow.delay(100);
divideWindow.keyRelease(KeyEvent.VK_WINDOWS);
Works fine for me :)
A possible workaround is to disable numlock. See this jdk bug comment
I have a simple java application that uses JOGL. When I run it from eclipse, and then close the application window, javaw.exe remains running. Here is the the relevant code:
public class App {
private Display mDisplay;
private Shell mShell;
private GL4 mGl;
private int mProgramId;
private int mVsId;
private int mFsId;
// ...
public void start() {
if (!initialize()) {
return;
}
while (!mShell.isDisposed()) {
if (!mDisplay.readAndDispatch()) {
mDisplay.sleep();
}
}
destroy();
}
private void initialize() {
mDisplay = new Display();
mShell = new Shell(mDisplay);
// some SWT and opengl initialization code, which is irrelevant for this issue
// (at least I think so)
// getting GLProfile, GLContext, GL4 etc.
final String vsText = ResourceManager.getShaderText(vsPath);
final String fsText = ResourceManager.getShaderText(fsPath);
mVsId = mGl.glCreateShader(GL4.GL_VERTEX_SHADER);
mFsId = mGl.glCreateShader(GL4.GL_FRAGMENT_SHADER);
mGl.glShaderSource(mVsId, 1, new String[] { vsText }, null, 0);
mGl.glCompileShader(mVsId);
mGl.glShaderSource(mFsId, 1, new String[] { fsText }, null, 0);
mGl.glCompileShader(mFsId);
mProgramId = mGl.glCreateProgram();
mGl.glAttachShader(mProgramId, mFsId);
mGl.glAttachShader(mProgramId, mVsId);
// bind a constant attribute location for positions of vertices
mGl.glBindAttribLocation(mProgramId, 0, "in_Position");
// bind another constant attribute location, this time for color
mGl.glBindAttribLocation(mProgramId, 1, "in_Color");
mGl.glLinkProgram(mProgramId);
// here error code is 0x0 (no error)
int error = mGl.glGetError();
mShell.open();
return true;
}
private void destroy() {
// here error code is 0x502 (GL_INVALID_OPERATION)
int error = mGl.glGetError();
mGl.glDetachShader(mProgramId, mFsId);
mGl.glDetachShader(mProgramId, mVsId);
mGl.glDeleteShader(mFsId);
mGl.glDeleteShader(mVsId);
mGl.glDeleteProgram(mProgramId);
mDisplay.dispose();
}
}
I commented out all rendering code and most other opengl/JOGL related calls (besides getting GLProfile, GLContext, GL4 and everything listed in this sample) and this problem persists.
Generally, the application works fine, shaders compile and link without problem (I used validation which I didn't display in this sample) and it displays what it needs to. The only problem is that javaw.exe remains running after I close the application window (by pressing the x in the corner of the window).
This issue is removed only if I comment out mGl.glCompileShader(mVsId); and subsequent lines. If I leave this line, javaw.exe will remain running, so I guess the problem is related to shader initialization/destruction code.
Also, glGetError() returns 0 (no error) at the end of initialize() and 0x502 (GL_INVALID_OPERATION) at the beginning of destroy(). There is only the main loop in between and no opengl calls that I know of, since, for testing, I commented out all rendering code.
Any ideas?
Edit 2012-10-03:
I still don't know what the problem is, but since I updated my graphic card drivers, 'javaw.exe' terminates as it should after application is closed. I have AMD Radeon HD 6870. My current driver version is 8.982 from 2012-07-27, and I can't remember what the last version was, but I believe it was from january 2011 or so.
However, glGetError() still returns 0x502 at the beginning of destroy, so I guess there is still something wrong.
Assuming you use JOGL from jogamp.org, pls use either our SWT GLCanvas
or our NEWTCanvasSWT.
The latter is preferred due to custom GLCapabilities, pls check API doc.
This given plus you are doing everything SWT related on the SWT thread (read
linked unit tests), IMHO it should work - at least our unit tests.
Since you mentioned after an update (GPU/driver) your troubles ceased to exist,
it might have been a driver problem.
Now to your GL error. Trace GL errors can be simply done by setting the system property 'jogl.debug.DebugGL', i.e. on the commandline "-Djogl.debug.DebugGL".
This will install the debug pipeline for your GL object automatically and checks for GL error, which will throw an GLException if appear.
You can also trace via the property 'jogl.debug.TraceGL'.
I don't know if this is relevant or not, but may help someone I guess so I'm gonna share it here. Keep in mind I'm just a hobbyist getting started in Java SWT.
I made a simple application in Eclipse IDE using the Java SWT library. I made a ''Quit'' button in my main Window shell that when pushed calls this :
quitBtn.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
shell.getDisplay().dispose();
System.exit(0);
}
});
After exporting the .jar file to Desktop, I converted it to a .exe file with LaunchJ4 wrapper and check the "Allow only a single instance of the application" in the Single instance tab using the singleR3XPlayer mutex.
When I would close the .exe file with the "Quit" button, everything was fine and the javaw.exe would terminates. But when I closed the shell with the X button on the top-right window, javaw.exe would remains running. I figured that out when I tried to delete the .exe file (Windows "Used file, still open in Java(TM) Platform SE binary, close the file and retry" type of error pop-up) and as I couldn't open another instance of the file after closing it with the X button (because of the Single instance mutex). Also, multiple instances of javaw.exe would remains running if I would execute a few of the .jar file (even after closing them, but only with the X and not the "Quit" button).
I figured out closing the window with the X button would only dispose of the shell and not exit the program. But pressing the "Quit" button would because it called System.exit(0). So I did this :
// SWT Event Loop
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
// To make sure javaw.exe terminates when Window is closed
if (shell.isDisposed()) {
System.exit(0);
}
Hence, after my SWT Event loop is done (shell.isDisposed() == true), I made sure System.exit(0) would be called. This way, javaw.exe is terminated either way.
I don't know how SWT works and I don't know if that's the proper way to do it but it ensures javaw.exe is terminated once the application closes.
Hope that helps.
I have an applet, and it consist of an CLOSE button which closes the applet and redirects user to the home page. Home page consists 3 frames (Top, Left and Right). Once user clicks on the CLOSE button, the home page is appearing in the right frames, due to this now user has inconsistent view (multiple frames) of the page.
Code written in CLOSE button of the applet.
protected void cancelActionPerformed()
{
try
{
String type = "3";
AppletContext context = getAppletContext();
context.showDocument(new URL("javascript:goBack(\"" + type + "\")"));
destroy();
}
catch(MalformedURLException ex)
{
// System.out.println(ex.getMessage());
}
}
This is working perfectly in the JRE version 1.6 UPDATES 07 installed in the browser but higher updates of JRE creating this problem.
Kindly suggest if any thing wrong or any suggestion to overcome this situation.
Thank you
Regards
By default the JRE does not support java.net.URLs with the javascript protocol. So unless a handler has been installed (even though you never use it - horrible API) you will get a java.net.MalformedURLException.
Probably the easiest solution is to use the LiveConnect API to call the JavaScript.