[FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7

Started by terryhau, October 06, 2011, 14:59:18

Previous topic - Next topic

belzebub

I'm sorry this works only for restoring the focus, it won't help to get input keys when a game canvas is running. Still looking for a fix myself atm.

Glyder

Oh well, excuse me but I got to bring back this thread.
I happen to have the exactly same problem as the op.
Really looking forward to a solution.

basil

Hello! Been a while. I just grabbed the latest release and it is still the same much awesome lib to go with openGL!  ;D

Ran into exactly the same problem too. Display.setParent is making more swing components on the same window pretty much useless when it comes to mousewheel and keystrokes actually.

I tried to work around it hard and failed many times so far. One thing that works tho' is to put all swing components into a 2nd window. That resurrects the AWT events when switching focus. Also works when you minimise/maximise the canvas-window. It's alright in a early stage but still a show stopper later on since the canvas-window is not much more then a swing-window around the lwjgl frame, not more.

I found this : http://stackoverflow.com/questions/6187472/awt-canvas-cannot-gain-focus-in-the-presence-of-another-focusable-component

.. then this : http://www.java-gaming.org/index.php/topic,24650.0

and finally this thread.

It might be related to the GWLP_USERDATA issue :

https://github.com/LWJGL/lwjgl/blob/master/src/native/windows/org_lwjgl_opengl_Display.c

Quotedisplay_class_global = (jclass)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (display_class_global == NULL) {
display_class = (*env)->FindClass(env, "org/lwjgl/opengl/WindowsDisplay");
if (display_class != NULL) {
display_class_global = (*env)->NewGlobalRef(env, display_class);
if (display_class_global != NULL)
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)display_class_global);
}
}

affects only windows natives. I am not too good on the native-code, not sure if there is another way to handle it.

what do you think Matzon ?

cheers
bas


Matzon

not sure, haven't seen this code before :)
just not sure why we're not using a static variable instead to capture the global ref ...

basil

I'm trying to motivate my netbeans to compile the native sources but it denies to be easy yet. Do I need to use eclipse ?

spasi

I made some changes in an attempt to fix focus-related issues with Display.setParent. Please download and test the next build (#17) when it's up. I don't believe the GWLP_USERDATA thing was related to the problem, but it has been removed anyway.

basil

Ah, very nice!

just tested real quick and the AWT events work just fine now. that's for 64 and 32 bit version.

What behaves differently now are display-overlapping comboboxes/dropdowns, which are cut off and not rendered over the canvas. JComboBox.setLightWeightPopupEnabled neither true nor false does a change.

I will dig into the code later :)

thanks alot for the quick fix!

spasi

Tried setLightWeightPopupEnabled(false) and it seems to work for me, the popup appears above the OpenGL display. I'm on Windows 8, JDK 1.7.0_12.

edit: MenuBar works too, but not JMenuBar.

Glyder

Hello. I tried build #17 and got an error when setting DisplayMode:

Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\...\archive\libs\windows\lwjgl.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary1(Unknown Source)
	at java.lang.ClassLoader.loadLibrary0(Unknown Source)
	at java.lang.ClassLoader.loadLibrary(Unknown Source)
	at java.lang.Runtime.loadLibrary0(Unknown Source)
	at java.lang.System.loadLibrary(Unknown Source)
	at org.lwjgl.Sys$1.run(Sys.java:73)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.lwjgl.Sys.doLoadLibrary(Sys.java:66)
	at org.lwjgl.Sys.loadLibrary(Sys.java:95)
	at org.lwjgl.Sys.<clinit>(Sys.java:112)
	at org.lwjgl.opengl.Display.<clinit>(Display.java:139)
	..........

At
Display.setDisplayMode(new DisplayMode(800, 600));


Tried build #18 and got the same thing :(

spasi


basil

Yes, you have to find the proper .dll.

My previous test was on windows 7 with JDK 1.7.0_5. Updated to 1.7.0_11 and the popup issue went away :) (both 32 and 64 bit versions).

I also see you guys fixed the Display.setResizable(true) with Display.setParent issue too.

Maybe it is interesting for you, I found another different behaviour compared to 2.8.5. While it is not and was not possible to resize the canvas or display you can force it now. I use a tiny windows-tool that mimics gnome's way to move and resize windows : http://sourceforge.net/projects/winxmove/. Maybe it's not a big issue, you'll be surprised how many "non-resizeable" windows frames you can resize with it anyway ;)

With 2.8.5 winxmove grabbed the JFrame, now it allows me to drag the display outside the canvas and resize it without getting Display.wasResized() to fire (obviously).

thanks again for the support!

cheers
bas

spasi

That's because in 2.8.5 the Display was a child window inside the JFrame. Technically, this means it was like a sub-area of the AWT window, not a real window. With the recent changes, the Display becomes a popup, which is an independent window you can drag around. This was the only way to fix the focus issue. You'll now notice that when you click inside the Display the JFrame loses focus completely (see the window title). This matches the behavior on Linux.


tvdberg

Hello,

After the focus bugfix I tried build #21 today. I think that i've found another problem.

I have a JFrame with a JTabbedPane with three tabs, on two tabs I've added a JPanel and on the third tab a canvas with lwjgl. See the code below for the canvas lwjgl implementation:

public class CanvasPanel extends JPanel {

	private Canvas display_parent;

	private Thread drawThread;
	private boolean running = false;

	public CanvasPanel() {

		InitializeComponents();
	}

	private void InitializeComponents() {

		this.setLayout(new BorderLayout());

		try {
			display_parent = new Canvas() {

				public final void addNotify() {

					super.addNotify();
					startLWJGL();
				}

				public final void removeNotify() {

					stopLWJGL();
					super.removeNotify();
				}
			};

			display_parent.setSize(getWidth(), getHeight());

			display_parent.setFocusable(true);
			display_parent.requestFocus();
			display_parent.setIgnoreRepaint(true);
			setVisible(true);
			
			this.add(display_parent);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Start lwjgl op.
	 */
	private void startLWJGL() {

		drawThread = new Thread("3D_RenderThread") {

			public void run() {

				running = true;

				try {

					Display.setParent(display_parent);
					
					// Probeer een Display te creëeren met een pixelformat(AntiAliasing). Indien dit lukt maak dan een display zonder pixelformat.
					try {

						PixelFormat pf = new PixelFormat().withDepthBits(24).withSamples(2);
						Display.create(pf);
					}
					catch (Exception e) {

						System.out.println("Pixel format not suporrted");
						Display.create();
					}

					// initialiseer openGl.
					InitGL();
				}
				catch (LWJGLException e) {

					e.printStackTrace();
					return;
				}

				DrawLoop();
			}
		};

		drawThread.start();
	}

	/**
	 * Laat opengl stoppen met tekenen en beëindigd de thread.
	 */
	private void stopLWJGL() {

		running = false;

		try {

			drawThread.join();
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Initialiseer de instellingen voor opengl.
	 */
	protected void InitGL() {

		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glOrtho(0, 800, 0, 600, 1, -1);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
	}

	/**
	 * Teken alles op het canvas.
	 */
	public void DrawLoop() {

		while (running) {

			Update();
			Draw();

			// Update en synchroniseer het display altijd omdat anders de de besturing niet meer wordt vrijgegegeven.
			Display.sync(60);
			Display.update();
		}

		Display.destroy();
	}

	public void Update() {

		GL11.glViewport(0, 0, display_parent.getWidth(), display_parent.getHeight());
	}

	public void Draw() {

		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

		GL11.glColor3f(0.5f, 0.5f, 1.0f);

		GL11.glBegin(GL11.GL_QUADS);
		GL11.glVertex2f(100, 100);
		GL11.glVertex2f(100 + 200, 100);
		GL11.glVertex2f(100 + 200, 100 + 200);
		GL11.glVertex2f(100, 100 + 200);
		GL11.glEnd();

		GL11.glFlush();
	}


The problem is that the Canvas with lwjgl is always visible, it doesn't matter which tab is selected. In lwjgl 2.8.5 is everything working fine. I tried both Java jre 1.6 and 1.7u17.

Am I missing something or is this another focus related bug?


tvdberg

Any ideas?

The keyboard focus problem is resolved since build #17 but the solution has caused another focus related problem
(see previous post).