[FIXED] hasFocus() method doesn't work

Started by Flekken, January 20, 2012, 18:05:18

Previous topic - Next topic

Flekken

Hi!

I downloaded the Slick game library and i was trying out the tests when i came across this problem. I tried out the CanvasContainerTest when i found this. When is use the lwjgl 2.8.2 and run this test its render() method not getting called, but when i use the lwjgl 2.8.1 it works. I debugged these and found out that this method is only called when the hasFocus() method returns true. So in the 2.8.2 version the lwjgl always false. This happens in the 2.8.3 also.

I do not really understand what going on in the source code, but i compared the 2.8.1 and 2.8.2 and find something missing in LinuxDisplay where the focused variable is located. What i can understand is in 2.8.1 Focus can be changed through processEvents() method by setFocus(), and checkInput(). In checkInput() there is a difference that i would like to point out. The checkInput() method change focus if xembedded is true and parent is focused and even if xembedded is false and parent is focused. Now from the 2.8.2 the "else" focus change is missing and i think this causes the problem. I write the missing focus change into the source code of lwjgl then build it, and it works again!

Workaround the problem until this is solved is to use in setAlwaysRender(true) method in Slick, but there is obviously wrong somewhere.

This is the same problem in the Slick forums:http://slick.javaunlimited.net/viewtopic.php?f=3&t=4395

So the conclusion. I don't know what the problem is. Lwjgl or Slick code. Help me out here.

If you want to run the CanvasContainerTest you need slick.jar and lwjgl.jar and the natives.

The codes:

LinuxDisplay 2.8.1 checkInput():
private void checkInput() {
        if (parent == null) return;

	if (xembedded) {
		long current_focus_window = 0;
		if (last_window_focus != current_focus_window || parent_focused != focused) {
			if (isParentWindowActive(current_focus_window)) {
				if (parent_focused) {
					nSetInputFocus(getDisplay(), current_window, CurrentTime);
					last_window_focus = current_window;
					focused = true;
				}
				else {
					// return focus to the parent proxy focus window
					nSetInputFocus(getDisplay(), parent_proxy_focus_window, CurrentTime);
					last_window_focus = parent_proxy_focus_window;
					focused = false;
				}
			}
			else {
				last_window_focus = current_focus_window;
				focused = false;
			}
		}
	}
	else {
		if (parent_focused != keyboard_grabbed) {
			if (parent_focused) {
				grabKeyboard();
				input_released = false;
				focused = true;
			}
			else {
				ungrabKeyboard();
				input_released = true;
				focused = false;
			}
		}
	}
}


lwjgl 2.8.2 checkInput():
private void checkInput() {
	if (parent == null) return;

	if (xembedded) {
		long current_focus_window = 0;
        	if (last_window_focus != current_focus_window || parent_focused != focused) {
			if (isParentWindowActive(current_focus_window)) {
				if (parent_focused) {
					nSetInputFocus(getDisplay(), current_window, CurrentTime);
					last_window_focus = current_window;
					focused = true;
				}
				else {
					// return focus to the parent proxy focus window
					nSetInputFocus(getDisplay(), parent_proxy_focus_window, CurrentTime);
					last_window_focus = parent_proxy_focus_window;
					focused = false;
				}
			}
			else {
				last_window_focus = current_focus_window;
				focused = false;
			}
		}
	}
	else {
		if (parent_focus_changed && parent_focused) {
			setInputFocusUnsafe(getWindow());
			parent_focus_changed = false;
		}
	}
}


Slick - CanvasContainerTest:
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import org.newdawn.slick.BasicGame;
import org.newdawn.slick.CanvasGameContainer;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

/**
 * A test for the AWT Canvas container
 *
 * @author kevin
 */
public class CanvasContainerTest extends BasicGame {
	/** The TGA image loaded */
	private Image tga;
	/** The TGA image loaded */
	private Image scaleMe;
	/** The TGA image loaded */
	private Image scaled;
	/** The GIF version of the image */
	private Image gif;
	/** The image we're currently displaying */
	private Image image;
	/** A sub part of the logo image */
	private Image subImage;
	/** The current rotation of our test image */
	private float rot;
	
	/**
	 * Create a new image rendering test
	 */
	public CanvasContainerTest() {
		super("Canvas Container Test");
		
	}
	
	/**
	 * @see org.newdawn.slick.BasicGame#init(org.newdawn.slick.GameContainer)
	 */
	public void init(GameContainer container) throws SlickException {
		image = tga = new Image("testdata/logo.tga");
		scaleMe = new Image("testdata/logo.tga", true, Image.FILTER_NEAREST);
		gif = new Image("testdata/logo.gif");
		scaled = gif.getScaledCopy(120, 120);
		subImage = image.getSubImage(200,0,70,260);
		rot = 0;
		//container.setAlwaysRender(true);
		
	}

	/**
	 * @see org.newdawn.slick.BasicGame#render(org.newdawn.slick.GameContainer, org.newdawn.slick.Graphics)
	 */
	public void render(GameContainer container, Graphics g) {
		image.draw(0,0);
		image.draw(500,0,200,100);
		scaleMe.draw(500,100,200,100);
		scaled.draw(400,500);
		Image flipped = scaled.getFlippedCopy(true, false);
		flipped.draw(520,500);
		Image flipped2 = flipped.getFlippedCopy(false, true);
		flipped2.draw(520,380);
		Image flipped3 = flipped2.getFlippedCopy(true, false);
		flipped3.draw(400,380);
		
		for (int i=0;i<3;i++) {
			subImage.draw(200+(i*30),300);
		}
		
		g.translate(500, 200);
		g.rotate(50, 50, rot);
		g.scale(0.3f,0.3f);
		image.draw();
		g.resetTransform();
	}

	/**
	 * @see org.newdawn.slick.BasicGame#update(org.newdawn.slick.GameContainer, int)
	 */
	public void update(GameContainer container, int delta) {
		rot += delta * 0.1f;
		if (rot > 360) {
			rot -= 360;
		}
	}

	/**
	 * Entry point to our test
	 * 
	 * @param argv The arguments to pass into the test
	 */
	public static void main(String[] argv) {
		try {
			CanvasGameContainer container = new CanvasGameContainer(new CanvasContainerTest());
			
			Frame frame = new Frame("Test");
			frame.setLayout(new GridLayout(1,2));
			frame.setSize(500,500);
			frame.add(container);
			
			frame.addWindowListener(new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					System.exit(0);
				}
			});
			
			frame.setVisible(true);
			container.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @see org.newdawn.slick.BasicGame#keyPressed(int, char)
	 */
	public void keyPressed(int key, char c) {
		if (key == Input.KEY_SPACE) {
			if (image == gif) {
				image = tga;
			} else {
				image = gif;
			}
		}
	}
}

princec


Flekken

Thank you for moving the topic. I wasn't sure it was belonged here so i posted there. Sorry for the plus work.

kappa

Yes its a known bug as reported here and here. Its something that can be fixed, however need to find some time (hopefully this weekend) to sit down and debug it properly.

Flekken

I only search the forums for hasFocus() and not isActive(). I hope my little research narrows down the problem and helps. Keep up the good work!

Matzon


Shazer2

The post at the slick forum was from me. I found a solution and it was because the GameContainer or AppGameContainer (slick) doesn't render without focus. If your problem is the same as mine, what you need to do is add this app.setAlwaysRender(true); (change app to your GameContainer variable name) to your code.

~Shazer2

kappa

Quote from: Matzon on January 21, 2012, 12:50:55
is this linux specific?

Yes, specific to Linux when using Display.setParent().

Flekken

Quote from: Shazer2 on January 21, 2012, 13:07:57
The post at the slick forum was from me. I found a solution and it was because the GameContainer or AppGameContainer (slick) doesn't render without focus. If your problem is the same as mine, what you need to do is add this app.setAlwaysRender(true); (change app to your GameContainer variable name) to your code.
~Shazer2

I know, but this is only a workaround. You can also use lwjgl 2.8.1.

Quote from: kappa on January 20, 2012, 20:12:22
Yes its a known bug as reported here and here. Its something that can be fixed, however need to find some time (hopefully this weekend) to sit down and debug it properly.

I  just realised when i read the minecraft topic the third time i happaned to came across this bug a few weeks ago when i played minecraft. I tried to changed from 2.8.1 to 2.8.2 to get rid of the sticky key problem but this bug happened, so I changed back.

Hope you fix soon so i can play minecraft without the sticky key problem  :).

kappa

This should be fixed now and part of the next nightly build (after build #1522).

Flekken

I will wait for the nightly build because i just build from the svn and it doesn't work. I think I may have did something wrong with build, compiling or something.

kappa

nightly build is up now, so do please test and confirm.

Flekken

Not working. Both CanvasContainerTest and Minecraft not responding to clicks inside the windows.

kappa

just applied a small tweak to the above patch, please do try with latest nightly (when its built or build it yourself).

CanvasContainerTest works for me now, however it does require a click to start since slick doesn't draw unless the canvas has focus and the canvas is not initially focused, this seems like expected behaviour.

Thanks for testing and reporting your results.

Flekken

Working! Both Minecraft and CanvasContainerTest.
Thanks for the patch and for your time. Good job!

The click is expected behaviour, don't mind that.