I have a SWT app that opens a OpenGL window (using the LWJGL library) after a button is pressed. It is supposed to close it's main SWT window and open a new one with an OpenGL context. Works fine on Windows. On Mac, I get this error:
2010-03-05 02:28:25.315 java[1315:a07] [Java CocoaComponent compatibility mode]: Enabled
2010-03-05 02:28:25.316 java[1315:a07] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
2010-03-05 02:28:25.317 java[1315:a07] Apple AWT Startup Exception : _createMenuRef called with existing principal MenuRef already associated with menu
2010-03-05 02:28:25.318 java[1315:a07] Apple AWT Restarting Native Event Thread
The SWT window closes and then the app hangs, with no windows open.
It looks like the SWT app doesn't shut down cleanly and leaves it's menu entries associated with it, which prevents the LWJGL window from opening. Mac OS X only wants one application menu. SWT doesn't free it's own menu and LWJGL wants to add another.
Facts:
A button in the SWT dialog is supposed to close the dialog and open a LWJGL window (org.lwjgl.opengl.Display).
The button sets a static variable in the app to tell it what to do next after the SWT window is closed, so the LWJGL window is NOT being opened from a SWT callback directly.
The button then closes the SWT window. I don't know the correct way of doing this but tried various combinations of shell.close, shell.dispose, display.close and display.dispose, none of them worked. They all close the window but the error occurs every time.
Does anyone know what could be done to make this work?
UPDATE: This simply does not work and it seems that Apple will not fix it, ever. The only way around it is to launch a new app instance and pass it a parameter that tells it to open the second window.
UPDATE 2: In this particular case, I solved the problem by using the SWT dialog for the Windows version of the app and for the Mac version, I wrote a native Cocoa dialog which invokes the JVM and runs the LWJGL app when needed. That works pretty well.
It would appear to me that the problem is not SWT creating a new window or LWJGL actually doing so. I believe the problem lies in the fact that under Mac, the application menu must be registered to the process, and for some reason or another, there is a conflict of interest between the two.
You might have some better luck juggling things around a little:
What happens when you create a LWJGL window first, then create a SWT shell?
What happens when you initialize LWJGL statically before creating a SWT shell, then proceed to create the shell and create an LWJGL window?
Incidentally, to close a SWT window, all you need to do is dispose of the Shell:
shell.dispose();
Related
In Java 7 and 8 there is a bug in Swing menus that causes it to be slow when running an application remotely over X11 while other X11 applications are running. This issue was introduced in Java 7 and has never been fixed. Does anyone have any suggestions on a workaround. Using nxclient addresses this Swing menu issue, but introduces its own unwelcome issues.
The steps to reproduce the Swing menu issue are:
- run any X11 application locally with some activity
- log into a remote server using ssh -Y someserver
- execute any Java GUI application (e.g. jvisualvm) running Java 7 or 8
- select a menu and observe a several second delay in response
Just spent an entire day trying to solve the same issue. There's barely any info out there.
Local machines:
Linux FedoraCore 20, KDE desktop, NVIDIA GeForce 7300 LE
Linux FedoraCore 20, KDE desktop, NVIDIA GeForce GT 720
Running remote Java GUI over ssh, swing popups are extremely slow for PC2. Desktop freezes until popup appears. On the other hand, PC1 runs very fast/smooth, with no problems at all.
Turns out, in my case, the problem is that PC2 has 2 monitors. The closest bug report I could find is: JDK-8004103 : sun.awt.X11.XToolkit.getScreenInsets() may be very slow and it appears to be still open.
Temporary Workarounds:
In KDE, Disable second monitor, Launch Application, Enable second monitor
Work in Gnome Desktop (My Gnome environment not affected by this issue)
Launch remote Java app using Java 6 (Issue not present in Java6)
None of these are ideal workarounds, but considering that my Desktop freezes for 3-4 seconds every time I click on a menu item, they'll do for the time being.
I finally found much better workaround for this problem. When opening the SSH connection to the remote computer, set ForwardX11Trusted option to "no".
ssh -o ForwardX11Trusted=no -X user#host.domain
For me, opening a ComboBox reduced from ~14s to instantly. Unfortunately, I currently don't have any Java applications with Swing Menu installed on the server, but I think this should work for Menus too.
If you don't want to type that option every time, add the following line to ssh config file (/etc/ssh/ssh_config)
ForwardX11Trusted no
Well, there still doesn't seem to be much information out there on how to work around this problem and running an application via remote X11/xinerama makes it practically unusable. In particular, menu navigation takes an eternity. The work-around that we employed has 2 parts to it.
At the startup of your application call:
JPopupMenu.setDefaultLightWeightPopuEnable(false);
This will force the popups to use heavy weight popups. Lightweight popups make multiple calls to the X windows across the network to determine what is visible, obscurred, etc. When operating over remote X11 this becomes a very expensive call. Lightweight popups make these calls everytime the popup becomes visible. Heavyweight popups make this call when they are 1st invoked, but every successive popup action reuses the heavyweight component that I'm guessing is managed by the window manager so the menus thereafter are very responsive.
Create a new XineramaJMenu class that extends JMenu. This class must override the method:
protected Point getPopupMenuOrigin()
{...}
copy the code for this method from JMenu, but replace the line:
Insets screenInsets = toolkit.getScreenInsets(gc);
with
Insets screenInsets = new Insets(0,0,0,0);
This eliminates the getScreenInsets(...) call, which makes multiple calls to the remote X server to determine the max inset values of the child windows. We eliminate this expensive call across the network and accept a default 0 inset.
Unfortunately, this will require you to replace all instances of JMenu with XineramaJMenu, but it at least results in usable menus when running your application over remote X11.
I was able to solve this problem on a RHEL 7 system with NVidia graphics board and NVidia driver 340.96 running KDE 4.14.8 by adding this option to the Screen section of the X server config file.
Option "nvidiaXineramaInfo" "Off"
The NVidia driver manual has this to say about this option:
The NVIDIA X driver normally provides a Xinerama extension that X
clients (such as window managers) can use to discover the current
layout of display devices within an X screen. Some window mangers get
confused by this information, so this option is provided to disable
this behavior.
Perhaps KDE is one of the window managers that gets confused?
On the Mac where I do my programming, I have an app installed called BetterTouchTool that allows me to bind keyboard shortcuts to 'gestures' on my trackpad. I have bound a gesture (that doesn't have an Apple default) to the shortcut command+Q, which quits the active program. I have found this very convenient for quickly quitting programs that I am testing, so that I can get back to writing code.
However for the graphical game that I am programming, this action makes it so that I can't use a three finger swipe to switch between windows (several other gestures are also disabled). This will also happen if I go up to the menu and click quit or if I click the red x close button. The fix is to either restart my computer or (and this is really weird) to click the in-game close button which calls System.exit(0);. I know that most players will be using this but I still want to figure out why this is happening. In addition games like Minecraft on my computer don't do this.
I am using a JFrame with setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); in the code. In an attempt to fix the issue I have tried registering a com.apple.eawt.QuitHandler that calls System.exit(0); in the handler.
I have no idea what would be considered relevant code here, so whatever you would like to see, just let me know.
I figured it out. There was one rouge Thread.sleep() call in my JFrame that was somehow effecting my system.
We have an SWT application which does a time consuming calculation when pressing a button and after that opens a new window. The calculation is done in the UI thread (which is not very nice, but it is a legacy application), so during operation the window is frozen. Usually on completion of the job the new window is repainted correctly. But if the application is run on Windows 7 an I connect to that computer using Windows remote desktop, after finishing the operation the new window sometimes is not painted correctly. This happens when I do the following:
Press the calculation button
Switch to another window which overlaps my application
Switch back to my application (which is still not responding)
Wait for the calculation to be finished.
The new window opens, but the content is not painted correctly.
After minimizing and restoring the window, the repaint is done correctly.
One solution would be to set maximum details in the remote desktop settings. But this takes too much bandwidth.
I tested with SWT versions 3.4.1, 3.6.1, and 4.2.1 and remote connection from XP->Windows 7 as well as Windows 7->Windows 7.
Try using paintListener,layout or redraw and also you have to know that is a good practise to put the redrawing in the graphical thread (I mean the main loop for the SWT application).
I found out what solves my issue:
Right afer opening the new window with shell.open() I added a shell.redraw(). Could have thought about that earlier ;-)
bla
Thank you!
EDIT:
Unfortunately this did not the trick in all situations. It works only if I switch back to my application before the title bar shows the text "(Not responding)". Switching back when "(Not responding)" is already indicated in the title bar, the behaviour is as before.
I have developed a java program that runs fine in Mac OS X (10.6.7).
But if I click on another window such as Finder or another application, my program freezes, or the graphics are not updated anymore. If I click on my program again the graphics are updated again and runs well.
Does anyone know what that can be?
I coded it with the LWJGL and slick libraries.
Thanks!
Taken from here:
By default slick will not render anything if it does not have focus,
so good practice for applets is to set
container.setAlwaysRender(true);
so that it always renders even when it doesn't have focus.
This seems to refer to GameContainer.setAlwaysRender. Although the forum post talks about applet, both AppGameContainer (standalone-application) and AppletGameContainer.Container extend from it.
I have an application in java swing which runs in the system tray most of the time. The user can use the Tray Menu to perform several actions. One of those actions is to show the app window. The problem I have is with usability on OS X.
In windows, if the user brings up the app window and later switches to another app, they can switch back to my application using the taskbar. But in OS X, the app runs in a mode in which the app does not have a menu and also will not appear in the Command + Tab list.
__LSUIElement is set to true in the info.plist file
So my problem is that if the user opens the app window, later switches to another app, they cannot switch back unless they click on the window itself (which could be behind many other windows). The simplest way is for the user to open the window again using the tray icon, but since the window is already open I am unable to bring it to the front.
So, How to I take focus away from other applications and bring my window to the front?
EDIT:
My issue is not with getting the 'Application running as agent'. I already have that working. The issue I have is to get my program window to the top when its created. I am unable to do this in java.
You can call activateIgnoringOtherApps: with a true parameter when the user clicks on the icon in the menu bar (or however you open the window). You'll have to hook into Cocoa from Java, though.
The code provided in the answer to the question below did the trick
How to bring a window to the front?
After much effort trying to do the same thing, I found that the following was the simplest solution for me:
try {
String[] cmd = new String[2];
cmd[0] = "open";
cmd[1] = "/Applications/MyApp.app";
Runtime.getRuntime().exec(cmd);
}
catch(Exception ex) {
//ignore since there's nothing else that can be done
}
Essentially, I chose to execute another process through the JVM which uses the "open" command on Mac OS X to open the app that wraps the java program that created the tray icon. Telling it to open itself again causes the window to be brought to the front since it is already running.