Mouse.isButtonDown() is always up/down

Started by EgonOlsen, February 25, 2008, 18:01:35

Previous topic - Next topic

EgonOlsen

Hi,

in some code, i had a busy wait for releasing the mouse button after it has been pressed before. This worked in 1.1 and prior, but it fails in 1.1.4. Please have a look at this code:

import org.lwjgl.input.*;
import org.lwjgl.opengl.*;

public class MouseTest {

	public static void main(String[] args) throws Exception {
		Display.create();
		Mouse.create();
		while (!Mouse.isButtonDown(0)) {
			Mouse.poll();
			Thread.sleep(100);
			System.out.println(" Not down!");
		}
		while (Mouse.isButtonDown(0)) {
			Mouse.poll();
			Thread.sleep(100);
			System.out.println("Down!");
		}
		Display.destroy();
	}
}


In 1.1, it waits for a click and afterwards, it waits for a release...all fine. In 1.1.4, the enters the first loop and never registers that the button has been pressed. Or, if you leave the first loop out and enter the second loop with a pressed button, it never gets released. Am i doing something wrong, am i missing something or is this a bug?

Edit: This is under Windows. I haven't tried another OS.

Matzon

Does adding a Display.update(); into the loops change the behavior ?
Generally it is assumed that update is _always_ called in a loop. Failure to do so may result in window behavior issues - and input problems.

EgonOlsen

With Display.update() it works, but there is nothing to update. I don't want to swap buffers in that situation, just wait for the button to be released. In fact, calling update in that loop cause the screen to flicker because it constantly swaps buffers...that looks just wrong. This worked fine in 1.1 and prior, so i hope that update() isn't really needed here. Shouldn't Mouse.poll() be sufficient to poll this input device?

Matzon

I am not entirely sure of the specifics of this, but it has to do with some internal changes in how we get input. Nowadays input/keys are delivered to the window thread and these are processed in the processMessages() method (which you may call instead). Note however, due to how windows structures its message boxes, the events are ONLY delivered to the thread that created the window initially.

from http://msdn2.microsoft.com/en-us/library/ms644927(VS.85).aspx:
QuoteThe system maintains a single system message queue and one thread-specific message queue for each graphical user interface (GUI) thread. To avoid the overhead of creating a message queue for nonâ€"GUI threads, all threads are created initially without a message queue. The system creates a thread-specific message queue only when the thread makes its first call to one of the User or Windows Graphics Device Interface (GDI) functions.

Whenever the user moves the mouse, clicks the mouse buttons, or types on the keyboard, the device driver for the mouse or keyboard converts the input into messages and places them in the system message queue. The system removes the messages, one at a time, from the system message queue, examines them to determine the destination window, and then posts them to the message queue of the thread that created the destination window. A thread's message queue receives all mouse and keyboard messages for the windows created by the thread. The thread removes messages from its queue and directs the system to send them to the appropriate window procedure for processing.

we had a related discussion here: http://echelog.matzon.dk/logs/browse/lwjgl/1200092400 - at about 20:00

EgonOlsen

Its all in the same thread, so this isn't a problem. It works with a call to Display.processMessages(). However, i think that this should be changed. It not intuitive that i have to do something with the Display to use Mouse properly. If this is needed, Mouse should encapsulate this IMHO. Can't the Mouse.poll() do the Display.processMessages()-call instead?

EgonOlsen

*bump*

Can anyone comment an this? Am i really supposed to make Display process its messages to poll the keyboard successfully in this case or are there any plans to fix this?

kappa

Not sure why you are doing a Mouse.create(), since Display.create() includes both Mouse.create() and Keyboard.create().

also remember that Display.update() includes both Mouse.poll() and Keyboard.poll().

Besides can't you use Mouse.getEvent*() methods to solve this problem?

EgonOlsen

Quote from: javalwjgl on March 02, 2008, 13:41:47
Not sure why you are doing a Mouse.create(), since Display.create() includes both Mouse.create() and Keyboard.create().

also remember that Display.update() includes both Mouse.poll() and Keyboard.poll().

Besides can't you use Mouse.getEvent*() methods to solve this problem?
I'm doing a Mouse.create() because the Javadocs don't say anything about Display.create() already doing this (or i'm blind...). I know that it does, but i wanted to be sure in case that this may change sometimes.
The problem is not that Display.update() wouldn't poll the Mouse, the problem is that i can't poll() the Mouse myself without doing a Display.update() (which is bogus in this situation because there is nothing to update) or at least a Display.processMessages(). My point is, that this is implicit wisdom. Nobody can tell this from looking at the documentation and it hasn't been this way until i upgraded to 1.1.4. I think that either the docs should tell it or (and much better) that the Mouse should handle this internally and i'm asking if there is a chance that this may happen in the future, so that the code works again as it is.

elias

It probably won't be fixed in the future. Your particular problem is a side effect from dropping DirectInput and using regular Windows messages instead, making the windows version behave much like the linux version (have you tried your test with lwjgl 1.1 on linux?). The requirement that new updates to the input devices can only come from Display.processMessages should be documented, since we discovered that processMessage can be expensive (linux again) and only allow it to be called once in LWJGL itself (Display.update()).

- elias