AWTGLCanvas Input Bug

Started by kappa, September 19, 2007, 22:44:32

Previous topic - Next topic

kappa

This is a problem with AWTGLCanvas handling mouse and keyboard inputs.

Problem
----------
What happens is when you click a mouse button or a Keyboard key the input takes a long delay to for the key to register or is missed.
This is very annoying as it makes the app/applet unusable as the input keys don't work or are unresponsive.

Symptoms
------------
The problem only appears when the app has a bit of load on it, e.g. when used with a game, so does not appear in the OpenGL test where only a light load is put on, like drawing a single quad.

This problem does not happen on Windows only on Linux and possibly MacOS.

Observations
-----------------
if you remove the line setVSyncEnabled(true), then because the fps jumps very high the problem disappears but if the fps goes down the problem reappears. Have also noticed putting a thread sleep/yield in the game loop after keyboard and mouse is polled makes the problem go away, but this is more of a hack solution and seriously affects fps.

Theory
---------
i think it is that the input (LinuxAWTInput) is not getting enough time to read in the inputs hence the keys getting missed or delayed in being read.

Would be very nice if a fix can be found for this as it would allow vsync'ed applets to work properly on all platforms.


I have been able to reproduce the symptoms in the applet test called OpenGL by adding a for loop around the quad to draw it multiple times, notice how the problem disappears, if you comment out the line setVSyncEnabled(true).


public void paintGL() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);

		GL11.glPushMatrix();
		GL11.glTranslatef(x, y, 0.0f);
		GL11.glRotatef(angle, 0, 0, 1.0f);
		
		for (int i = 0; i < 100; i++) {
			GL11.glBegin(GL11.GL_QUADS);
			GL11.glVertex2i(-50, -50);
			GL11.glVertex2i(50, -50);
			GL11.glVertex2i(50, 50);
			GL11.glVertex2i(-50, 50);
			GL11.glEnd();
		}
		
		GL11.glPopMatrix();

		angle += 1;

		if (Mouse.isCreated()) {
			Mouse.poll();
			while (Mouse.next()) {
				x += Mouse.getEventDX();
				y += Mouse.getEventDY();
			}
		}
		if (Keyboard.isCreated()) {
			Keyboard.poll();
		}
		while (Keyboard.isCreated() && Keyboard.next()) {
			if (Keyboard.getEventKey() != Keyboard.KEY_NONE) {
				String key_name = Keyboard.getKeyName(Keyboard.getEventKey());
				if (Keyboard.getEventKeyState()) {
					switch (Keyboard.getEventKey()) {
						case Keyboard.KEY_H:
							AWTInputAdapter.destroy();
							break;
						case Keyboard.KEY_G:
							Mouse.setGrabbed(!Mouse.isGrabbed());
							break;
						default:
							break;
					}
					System.out.println("Pressed: " + key_name);
				} else
					System.out.println("Released: " + key_name);
			}
			if (Keyboard.getEventCharacter() != Keyboard.CHAR_NONE)
				System.out.println("Typed: " + Keyboard.getEventCharacter());
		}
		if (Keyboard.isCreated()) {
			if (Keyboard.isKeyDown(Keyboard.KEY_UP))
				y += 5;
			else if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
				y -= 5;
			if (Keyboard.isKeyDown(Keyboard.KEY_LEFT))
				x -= 5;
			else if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
				x += 5;
		}
		try {
			swapBuffers();
			if (isVisible())
				repaint();
		} catch (Exception e) {/*OK*/
		}
	}

Matzon

this isn't caused by checking input in the paint method ??

kappa

that could possibly be the problem, AWTGLCanvas does check the inputs in the paint(g) method which then draws paintGL(g), maybe moving it to another method/or thread will help?

Evil-Devil

Iam still for the way of providing two implementations of the AWTCanvas. One like the first we had were the programmer have to take care of input and all the thinks himself and another subclass where those stuff is handled like now or in a improved way.

How do you ppl think about this? My ModelLoader uses the first attempt and is currently not functional with the latest version of lwjgl as i haven't had the time to reuse the code or to create my own AWTCanvas class. Especially when workin with more than one Canvas at time it becomes frustrating :(

kappa

you can still do it the old way with the current AWTGLCanvas, just don't create a AWTInputAdapter.

Evil-Devil

There is much more stuff i don't like in the current AWTGLCanvas class, like the check for current context, vsync and so on. I have to overwrite the stuff each time i use the class... Ok i overwrite it one time and can reuse the class but then the stuff i overwrite could be done in another subclass by the framework too and give us a small and a full compliant version of the canvas.

My 2 cent.