LWJGL Forum

Archive => Resolved Bugs/RFE => Topic started by: terryhau on October 06, 2011, 14:59:18

Title: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: terryhau on October 06, 2011, 14:59:18
I have a working LWJGL canvas by using Display.setParent(canvas). After the canvas is focused the first time, it starts grabbing keyboard events, but never lets go. If I click on a text box after, I can not type into it. Actually, anything needing the keyboard will not work, for example, accelerators/hotkeys for menu items and command buttons.

Anyone know of a workaround? Or am I doing something wrong?

Edit: I have found that the problem only happens when running JRE7.


import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;

public class Window
{
   private JFrame frame;
   private Canvas glCanvas = new Canvas();
   private final JPanel panel1 = new JPanel();
   private final JPanel panel2 = new JPanel();
   private final JTextPane textPane = new JTextPane();

   /**
    * Launch the application.
    */
   public static void main(String[] args)
   {
       EventQueue.invokeLater(new Runnable()
       {
           public void run()
           {
               try
               {
                   Window window = new Window();
                   window.frame.setVisible(true);
                   Display.create();
               }
               catch (Exception e)
               {
                   e.printStackTrace();
               }
           }
       });
       
       EventQueue.invokeLater(new Runnable()
       {
           public void run()
           {
               GL11.glClearColor(1f, 0f, 0f, 1f);
               GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
               Display.update();
               
               EventQueue.invokeLater(this);
           }
       });
   }
   
   /**
    * Create the application.
    */
   public Window()
   {
       initialize();
   }
   
   /**
    * Initialize the contents of the frame.
    */
   private void initialize()
   {
       frame = new JFrame();
       frame.addWindowListener(new FrameWindowListener());
       frame.setBounds(100, 100, 450, 300);
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.getContentPane().setLayout(new GridLayout(0, 2, 0, 0));
       frame.getContentPane().add(panel1);
       panel1.setLayout(null);
       textPane.setBounds(10, 5, 124, 20);
       
       panel1.add(textPane);
       frame.getContentPane().add(panel2);
       panel2.setLayout(new BorderLayout(0, 0));
       
       glCanvas.setIgnoreRepaint(true);
       panel2.add(glCanvas);
       try { Display.setParent(glCanvas); }
       catch(LWJGLException e) { e.printStackTrace(); }
   }
   
   private class FrameWindowListener extends WindowAdapter
   {
       @Override
       public void windowClosing(WindowEvent e)
       {
           Display.destroy();
       }
   }
}
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: kappa on October 06, 2011, 15:31:15
Which OS are you on? and which version LWJGL are you using?
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: terryhau on October 06, 2011, 15:32:39
Sorry

LWJGL 2.7.1
Windows 7 64-bit.

I have tried someone else's LWJGL canvas based app, and it has the same problem.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: kappa on October 06, 2011, 16:02:55
Are you able to reproduce the problem when running this (http://lwjgl.org/applet/)? I've tried it on Windows XP and it seems to work fine without capturing keyboard input when clicking elsewhere.

There was a similar issue like the above when running on Linux (which is fixed for the 2.8 release) but not seen or heard about it happening on Windows, maybe an issue with Windows 7?
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: terryhau on October 06, 2011, 16:26:51
I'm not sure how I can test the problem in that applet, since the whole applet is just one canvas, and there's no other components to click on to 'unfocus' the opengl canvas.
The browser still responds to key presses if that's what you mean.

My program is not an applet. Basically what i have is a Swing window, with a canvas (Display.parent set to the canvas) and a textbox. After clicking in the canvas, I can't type in the textbox, or use the keyboard for anything other than lwjgl input.

Also I'm running JRE 7 64-bit.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: Matzon on October 06, 2011, 17:52:48
does this also reproduce the error for you?

1min hackjob - works on my win7 64-bit, 32bit vm

/*
* Copyright (c) 2011 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
*   notice, this list of conditions and the following disclaimer in the
*   documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
*   its contributors may be used to endorse or promote products derived
*   from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.test.input;

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;

/**
* <p>
* </p>
* @author Brian Matzon <brian@matzon.dk>
*/
public class SwingInputTest {
    private JFrame frame;
    private final JPanel panel1 = new JPanel();
    private final JPanel panel2 = new JPanel();
    private final JTextPane textPane = new JTextPane();
   
/** The Canvas where the LWJGL Display is added */
Canvas display_parent;

/** Thread which runs the main game loop */
Thread gameThread;

/** is the game loop running */
boolean running;
   
   
public SwingInputTest() {
}

/**
* Once the Canvas is created its add notify method will call this method to
* start the LWJGL Display and game loop in another thread.
*/
public void startLWJGL() {
gameThread = new Thread() {
public void run() {
running = true;
try {
Display.setParent(display_parent);
//Display.setVSyncEnabled(true);
Display.create();
initGL();
} catch (LWJGLException e) {
e.printStackTrace();
}
gameLoop();
}
};
gameThread.start();
}


protected void gameLoop() {
while(running) {
System.out.println("--GAMELOOP--");


Display.update();

if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
glClearColor(1f, 0, 0, 0);
System.out.println("Pigs in space!");
} else {
glClearColor(1f, 1f, 1f, 0f);
}
glClear(GL_COLOR_BUFFER_BIT);

Display.sync(10);
}
Display.destroy();
}

protected void initGL() {
}

/**
* Tell game loop to stop running, after which the LWJGL Display will be destoryed.
* The main thread will wait for the Display.destroy() to complete
*/
private void stopLWJGL() {
running = false;
try {
gameThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}


private void execute() {
frame.setVisible(true);
}

private void initialize() {
frame = new JFrame();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
frame.remove(display_parent);
frame.dispose();
}
});
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new GridLayout(0, 2, 0, 0));
        frame.getContentPane().add(panel1);
        panel1.setLayout(null);
        textPane.setBounds(10, 5, 124, 20);
       
        panel1.add(textPane);
        frame.getContentPane().add(panel2);
        panel2.setLayout(new BorderLayout(0, 0));

        display_parent = new Canvas() {
public void addNotify() {
super.addNotify();
startLWJGL();
}
public void removeNotify() {
stopLWJGL();
super.removeNotify();
}
};
display_parent.setFocusable(true);
display_parent.requestFocus();
display_parent.setIgnoreRepaint(true);
        panel2.add(display_parent);
}

public static void main(String[] args) {
SwingInputTest sit = new SwingInputTest();
sit.initialize();
sit.execute();
}
}

Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: terryhau on October 06, 2011, 17:55:31
Yes, your test reproduces the error for me.
Once I click on the opengl canvas, I can't type in the textbox.

Did you try with JRE6 or JRE7?
I'll try 32-bit VM to see if that's the cause.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: Matzon on October 06, 2011, 19:37:14
well, you have to click back in the text box before you can type in it again ?  ::)
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: terryhau on October 06, 2011, 23:07:04
Yes of course I am doing that. You have to click on the canvas once initially for lwjgl to start capturing keyboard input. Then you click in the textbox. I even get the typing cursor appear showing the text box is focused, but still can't type.

Did you try with JRE6 or JRE7?

I just tested this on a 32bit machine running JRE7 32-bit. The problem still exists.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: terryhau on October 06, 2011, 23:34:04
I just tested this on JRE6 (64-bit) and it works fine, So the problem is with JRE7.

After seeing it work properly on JRE6, I noticed some other problems with it on JRE7.
In JRE7, When you click on on the canvas, it doesn't actually get focus because the cursor continues to blink on the textbox (however lwjgl still begins to capture keyboard input).
If I add a focus listener to the canvas, the focusGained and focusLost are never fired. I think it's because the canvas doesn't recognize that it's gaining/losing focus, lwjgl doesn't release the keyboard.

Problem still exists in 2.8.0 nightly.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused
Post by: jediTofu on October 07, 2011, 02:52:22
I read that in JRE7 they edited awt/swing (heavyweight/leightweight components) to work more seamlessly together, so that's probably causing something weird now with LWJGL.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: Matzon on October 07, 2011, 08:47:12
\o/ - link?

related? : https://bugs.eclipse.org/bugs/show_bug.cgi?id=353683
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: terryhau on October 07, 2011, 09:12:47
Yes that looks like the same issue.
So I take it, it's up to the Java people to fix it?
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: belzebub on September 18, 2012, 15:12:15
Is there any update on this one? Anybody that found a workaround yet?
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: belzebub on September 18, 2012, 20:14:29
This is my current very ugly workaround: adding a global AWT event listener to grab focus events (as the normal textfield events are eaten by awt), then just disabling and enabling everything from toplevel (my container and swing are at the toplevel). To prevent a loop (focus->hide->show->new focus->hide->show->new focus) I kept a boolean to see if you are in "restoring" state.

mainFrame.addWindowFocusListener(new WindowFocusListener() {

         @Override
         public void windowGainedFocus(WindowEvent arg0) {
            log.info("window gained focus");
            SwingUtilities.invokeLater( new Runnable() {
               public void run() {                   
                  if(!inRestoringState){
                     inRestoringState = true;
                     mainFrame.setVisible(false);
                     mainFrame.setVisible(true);
                  } else {
                     inRestoringState = false;
                  }
                 }
               } );
            log.info("refreshed");
         }

         @Override
         public void windowLostFocus(WindowEvent arg0) {
         }
            
         });
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: belzebub on September 25, 2012, 06:57:33
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.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: Glyder on January 10, 2013, 03:42:49
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.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: basil on January 28, 2013, 11:57:43
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 (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 (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 (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

Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: Matzon on January 28, 2013, 21:34:38
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 ...
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: basil on January 29, 2013, 13:33:25
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 ?
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: spasi on January 29, 2013, 21:11:26
I made some changes in an attempt to fix focus-related issues with Display.setParent. Please download and test the next build (http://www.newdawnsoftware.com/jenkins/view/LWJGL-git/job/LWJGL-git/label=winxp642/) (#17) when it's up. I don't believe the GWLP_USERDATA thing was related to the problem, but it has been removed anyway.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: basil on January 30, 2013, 00:52:04
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!
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: spasi on January 30, 2013, 13:15:52
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.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: Glyder on January 30, 2013, 18:06:11
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 :(
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: spasi on January 30, 2013, 18:29:30
You can download the x64 dll from here (http://www.newdawnsoftware.com/jenkins/view/LWJGL-git/job/LWJGL-git/label=apollo/).
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: basil on January 30, 2013, 18:53:57
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/ (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
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: spasi on January 30, 2013, 19:06:16
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.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: basil on January 30, 2013, 19:55:00
makes sense. totally fine with me :)
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: tvdberg on March 07, 2013, 15:09:01
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?

Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: tvdberg on March 15, 2013, 07:00:15
Any ideas?

The keyboard focus problem is resolved since build #17 but the solution has caused another focus related problem
(see previous post).
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: spasi on March 15, 2013, 11:41:49
Could you please create an issue on github (https://github.com/LWJGL/lwjgl/issues?state=open) and attach a code sample that reproduces the problem?
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: basil on March 15, 2013, 12:30:52
I'll check your code when I get on my IDE.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: tvdberg on March 15, 2013, 15:46:06
I've created the issue with attached source on github:

https://github.com/LWJGL/lwjgl/issues/20 (https://github.com/LWJGL/lwjgl/issues/20)

I never worked before with github so i'm hoping everything is fine.
Title: Re: [BUG] LWJGL in a canvas - Captures keyboard input even when unfocused (on JRE7)
Post by: spasi on April 17, 2013, 19:39:03
Please try the next nightly build (http://ci.newdawnsoftware.com/job/LWJGL-git-dist/).
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 18, 2013, 12:09:06
We're still seeing the later focus issue, even with the latest nightly build.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 18, 2013, 14:06:35
I think I might have a working fix for AWT's focus behavior change in JDK 7. Please try the next build (#54).
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 18, 2013, 14:23:34
That's great news. Any ETA on the build? I'm looking forward to it,
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 18, 2013, 15:41:21
The build is ready.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: tvdberg on April 18, 2013, 20:13:39
I've just tested build #54 and it looks very promising. There are no focus related issues any more for as far as I can see.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 23, 2013, 13:57:35
The build solves all issues when you're using the default Look and Feels. I've found strange behavior still occurs when using the Substance Look and Feel. This only occurs when running the applet in the browser and not when running from an AppletViewer context.

Here's a test case to reproduce:

1. Load the applet
2. Select 'Focus' button in the debug internal frame
3. Select the game frame by clicking on the title bar (NOT the canvas)
4. Attempt to open the File menu.
5. Observe how the File menu stays collapsed.


package test;

import java.awt.Canvas;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.metal.MetalLookAndFeel;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel;

public class CanvasFocusTest extends JApplet {

    /**
     *
     */
    private static final long serialVersionUID = 2853176700479564421L;
    private JMenuBar menuBar;
    private Canvas canvas;
    private Thread gameThread;

    private boolean running;

    private JInternalFrame createDebugFrame() {

        JInternalFrame internalFrame = new JInternalFrame("Debug Frame");
        internalFrame.setLayout(new FlowLayout(FlowLayout.CENTER));
        internalFrame.setSize(400, 100);
        internalFrame.setVisible(true);

        JButton focus = new JButton("Focus");
        focus.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.setFocusable(true);
            }
        });
        internalFrame.add(focus);

        JButton unfocus = new JButton("Unfocus");
        unfocus.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.setFocusable(false);
            }
        });

        internalFrame.add(unfocus);

        JButton metal = new JButton("Metal");
        metal.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                switchMetal();
            }
        });

        internalFrame.add(metal);

        JButton substance = new JButton("Substance");
        substance.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                switchSubstance();
            }
        });

        internalFrame.add(substance);
        return internalFrame;
    }

    private JInternalFrame createGameFrame() {
        JInternalFrame canvasFrame = new JInternalFrame("Game Frame");
        canvasFrame.setSize(800, 600);
        canvasFrame.setLocation(80, 80);
        canvasFrame.setVisible(true);

        canvas = new Canvas() {
            @Override
            public final void addNotify() {
                super.addNotify();
                startLWJGL();
            }

            @Override
            public final void removeNotify() {
                stopLWJGL();
                super.removeNotify();
            }
        };

        canvasFrame.add(canvas);
        canvas.setSize(canvasFrame.getContentPane().getSize());
        canvas.setFocusable(true);
        canvas.requestFocus();
        canvas.setIgnoreRepaint(true);

        Thread thread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    while (!Mouse.isCreated()) {
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    while (Mouse.next()) {
                        int wheelD = Mouse.getDWheel();
                        if (wheelD != 0) {
                            System.out.println("" + wheelD);
                        }
                    }
                }
            }
        };
        thread.start();

        return canvasFrame;
    }

    protected void gameLoop() {
        while (running) {
            Display.sync(60);
            Display.update();
        }

        Display.destroy();
    }

    @Override
    public void init() {

    }

    protected void initGL() {
    }

    private void loadSwing() {

        switchSubstance();

        menuBar = new JMenuBar();
        JMenu file = new JMenu("File");
        file.add(new JMenuItem("Item 1"));
        file.add(new JMenuItem("Item 2"));
        file.add(new JMenuItem("Item 3"));
        menuBar.add(file);

        setJMenuBar(menuBar);

        JDesktopPane desktop = new JDesktopPane();
        this.add(desktop);

        JInternalFrame canvasFrame = createGameFrame();
        desktop.add(canvasFrame);

        JInternalFrame debugFrame = createDebugFrame();
        desktop.add(debugFrame);

        this.setSize(1024, 768);

    }

    @Override
    public void start() {

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                loadSwing();
            }
        });

    }

    public void startLWJGL() {
        gameThread = new Thread() {

            @Override
            public void run() {
                running = true;
                try {
                    Display.setParent(canvas);
                    Display.create();
                    initGL();
                } catch (LWJGLException e) {
                    e.printStackTrace();
                    return;
                }
                gameLoop();
            }
        };
        gameThread.start();
    }

    private void stopLWJGL() {
        Display.destroy();
    }

    protected void switchMetal() {
        try {
            UIManager.setLookAndFeel(new MetalLookAndFeel());
            UIManager.getLookAndFeelDefaults().put("ClassLoader", getClass().getClassLoader());
            SwingUtilities.updateComponentTreeUI(this);
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }

    protected void switchSubstance() {
        try {
            UIManager.setLookAndFeel(new SubstanceBusinessBlackSteelLookAndFeel());
            UIManager.getLookAndFeelDefaults().put("ClassLoader", getClass().getClassLoader());
            SwingUtilities.updateComponentTreeUI(this);
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }

}



The Substance L&F jars can be found here: http://grepcode.com/snapshot/repo1.maven.org/maven2/com.github.insubstantial/substance/7.2.1/
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 23, 2013, 23:06:17
You need to make sure you're satisfying AWT's requirements for heavyweight-lightweight component mixing. Details here (http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html).

I wasn't able to test exactly what you described, but I managed to reproduced the issue using your code in a JFrame instead of an applet (without Substance too). AWT's mixing doesn't seem to work well when the JInternalFrame z-indices change. The fix was to add a ComponentListener and an InternalFrameListener to the game frame and do this on each event:

SwingUtilities.getWindowAncestor(canvasFrame).validate();

Another issue I noticed is that clicking on the game canvas does not active the JInternalFrame, or bring it to the front. This happens only on Windows, on Linux it behaves correctly. I'll try to implement a fix for that and let you know.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 24, 2013, 00:26:17
The internal frame activation should be fixed now, please try the next nightly build.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 24, 2013, 10:07:37
It only partially fixed the issue. I've created a video that shows the issue and also deployed an applet where the issue can be reproduced:

Video: http://www.tygron.com/bug/lwjgl_video.html (http://www.tygron.com/bug/lwjgl_video.html)
Applet: http://www.tygron.com/bug/index.html (http://www.tygron.com/bug/index.html)
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 24, 2013, 11:36:30
I decompiled the applet and I don't see the validate() calls I suggested you should use. I'm afraid that's the only way to make it work properly. Also, please update to the latest nightly (http://ci.newdawnsoftware.com/job/LWJGL-git-dist/) (#63), it has another fix that may affect your test case.

I also don't see the point of the Focus/Unfocus buttons, what are you trying to achieve exactly?
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 24, 2013, 11:47:44
I thought I was using the right build. I'll check to be sure and implement the fix you're suggesting. The focus/unfocus are show that the menu behaves differently is the canvas is set focusable or not.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 24, 2013, 11:58:31
You need to keep in mind though that making the Canvas unfocusable doesn't do anything for the LWJGL Display on top of it. LWJGL doesn't support unfocusable Displays.

Sorry about the build, I pushed the latest change late last night.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 24, 2013, 12:08:24
It does affect the ability to open the menu though. When it's set to unfocusable the menu works, but the mousewheel does not register in LWJGL. If it's set to focusable the mousewheel works, but the menu does not work.

I've added your code suggestions (rather roughly) and made sure to use the dll's and jars from the daily build. This doesn't seem to solve the issue though. The results can be seen here (newly deployed at time of this post): http://www.tygron.com/bug/index.html

Try opening the File menu as soon as the applet loads.

Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 24, 2013, 12:12:32
Works fine for me. What JRE and browser are you testing on?
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 24, 2013, 12:21:43
Chrome 26.0.1410.64
Java Plug-in 10.21.2.11
Using JRE version 1.7.0_21-b11 Java HotSpot(TM) Client VM

Firefox 20.0.1
Java Plug-in 10.21.2.11
Using JRE version 1.7.0_21-b11 Java HotSpot(TM) Client VM

Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: spasi on April 25, 2013, 15:51:16
I've been able to reproduce the problem. Basically AWT behaves very differently in applets than it does in normal applications. I've been trying all evening yesterday to make the LWJGL display behave "naturally" with focus (like any other AWT component), but it seems impossible. I did find a solution for standalone execution, but then it would be problematic in applets. I have currently pushed some code that fixes most of the issues in both applets and standalone apps, but acts weirdly in some corner-cases; e.g. if the LWJGL display has focus and you open a menu and close it immediately, normally you'd expect that the last focused component would be refocused. This doesn't happen.

Please try the next build and let me know how it goes.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 25, 2013, 19:06:34
This seems to fix the issue in the test case. I'm going to test in our main application now.
Title: Re: [FIXED] LWJGL in a canvas - Captures keyboard input even when unfocused on JRE7
Post by: JeroenWarmerdam on April 25, 2013, 19:41:45
The latest update fixed the issues. Thanks. If anything pops up in production I'll let you know.