Results 1 to 15 of 15

Thread: X11 server: multiple key_up signals before user releases button

  1. #1
    Serf
    Join Date
    Dec 2010
    Posts
    3

    Default X11 server: multiple key_up signals before user releases button

    Hi,I try to use clanlib (v2.2.4) in my project (on linux) and found strange behaviour of keyboard input - my code always receives key_up signal after key_down even if user has not released button. But I expect to receive multiple key_down signals and only one key_up signal.
    After some investigation I found, that it is default behaviour of X11 server, and if I want to receive only one KeyReleased event I should use something like XkbSetDetectableAutorepeat to specifiy behaviour manualy.
    So questions:
    - Is current behaviour of keyboard input in clanlib correct?
    - Is there are correct way to detect long key presses with current clanlib functionality?
    I know that I always can get current keyboard state, but I think that it is less beautiful solution than a correct sequence of events.

    P.S. sorry for my English.

  2. #2
    Serf
    Join Date
    Dec 2010
    Posts
    4

    Default

    Just thought I'd add that I'm experiencing the same issue. XkbSetDetectableAutorepeat does appear to be a solution but I'm clueless as to how to implement it in my program.

    Any suggestions would be greatly appreciated.
    Last edited by flusteredpie; 12-06-2010 at 12:45 AM.

  3. #3
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Quote Originally Posted by Tiendil View Post
    my code always receives key_up signal after key_down even if user has not released button. But I expect to receive multiple key_down signals and only one key_up signal.
    It sounds like you have connected to the wrong signal. Double check the connection code. (you may have something like CL_Slot key_up = ... keyboard_sig_down() )

    The keyboard code has not changed for a couple of years. I would be very surprised if it has stopped working

    ... But with the ever changing linux world, who knows!

    Have a look at the Examples/Input/Input example.

    Press the spacebar key and observer the line "Keyboard : System Keyboard : SPACE is released"


  4. #4
    Serf
    Join Date
    Dec 2010
    Posts
    4

    Default

    Interestingly that program doesn't seem to use sig_key_up anywhere. In that example, the release state is being checked for with this line;

    keyboard.get_keycode(CL_KEY_SPACE) ? "Pressed" : "Released"));

    The problem with using that for what I'm doing is that I only want a section of code to be triggered once - just as the key is released. Implementing it the way it's done in that example would result in the release code being triggered repeatedly until the associated key is pressed.

    I suppose I could store the previous key press, check if its still in a down state and if it's not run the release code once. It's not the most elegant of solutions but if it's the ONLY solution then I'll settle.

  5. #5
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    It works here.

    Try this code in the basic2d example:

    Code:
    #include "precomp.h"
    #include "basic2d.h"
    
    // The start of the Application
    int Basic2D::start(const std::vector<CL_String> &args)
    {
    	quit = false;
    	cow = 0;
    
    	// Set the window
    	CL_DisplayWindowDescription desc;
    	desc.set_title("ClanLib Basic2D Example");
    	desc.set_size(CL_Size(640, 480), true);
    	desc.set_allow_resize(true);
    
    	CL_DisplayWindow window(desc);
    
    	// Connect the Window close event
    	CL_Slot slot_quit = window.sig_window_close().connect(this, &Basic2D::on_window_close);
    
    	// Connect a keyboard handler to on_key_up()
    	CL_Slot slot_input_up = (window.get_ic().get_keyboard()).sig_key_up().connect(this, &Basic2D::on_input_up);
    	CL_Slot slot_input_down = (window.get_ic().get_keyboard()).sig_key_down().connect(this, &Basic2D::on_input_down);
    
    	// Get the graphic context
    	CL_GraphicContext gc = window.get_gc();
    
    	// Run until someone presses escape
    	while (!quit)
    	{
    		switch (cow)
    		{
    			case 0:
    				gc.clear(CL_Colorf(0.0f,0.0f,0.2f));
    				break;
    			case 1:
    				gc.clear(CL_Colorf(0.0f,1.0f,0.2f));
    				break;
    			default:
    				gc.clear(CL_Colorf(1.0f,0.0f,0.2f));
    		}
    
    		window.flip(1);
    		CL_KeepAlive::process(0);
    	}
    
    	return 0;
    }
    
    // A key was pressed
    void Basic2D::on_input_up(const CL_InputEvent &key, const CL_InputState &state)
    {
    	if(key.id == CL_KEY_ESCAPE)
    	{
    		quit = true;
    	}
    	if(key.id == CL_KEY_A)
    	{
    		cow--;
    	}
    }
    
    void Basic2D::on_input_down(const CL_InputEvent &key, const CL_InputState &state)
    {
    	if(key.id == CL_KEY_A)
    	{
    		cow++;
    	}
    }
    
    // The window was closed
    void Basic2D::on_window_close()
    {
    	quit = true;
    }
    Add to basic2d.h:
    Code:
    	void on_input_down(const CL_InputEvent &key, const CL_InputState &state);
    	int cow;
    Hold down 'A', and the screen goes green. Release, it goes blue. It never goes red

    This is on Ubuntu running gnome (ClanLib 2.2.5)
    Last edited by rombust; 12-06-2010 at 03:42 PM. Reason: clanlib version

  6. #6
    Serf
    Join Date
    Dec 2010
    Posts
    4

    Default

    Ah thanks, thats cleared it all up for me. My problem was down to the messy way I was dealing with input signals.

    That said, while your example works, xorg is still sending repeated up and down signals when you hold the key down. I appreciate this isn't a clanlib issue - it's just the rather unusual default behavior that xorg exhibits. I would have expected a lengthy key press to result in multiple key down signals, and one key up on release. My messy way of doing it would have worked had this been the case.

  7. #7
    Serf
    Join Date
    Dec 2010
    Posts
    3

    Default

    I discovered tool named `xev` it prints content of X11 events. With it's help I found, that:
    - on my Fedora 13 and Ubuntu 10 X11 really send more than one KeyReleased event, but events go in pairs <KeyReleased, KeyPressed> (in one frame) KeyPressed event always go after KeyReleased (except the last event).
    - if, for example, I press S button then press D button, I cease to receive events from the S even if I does not hold down D anymore (except the last KeyReleased event)

    Such behavior confuses me, but I probably did not write windowed programms for a long time :-)

    As a result, I decided to use CL_InputDevice::get_keycode instead of keyboard's signals.
    Thanks for help.

  8. #8
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    It may be because of keyboard ghosting.

    A very good explanation:
    http://www.microsoft.com/appliedscie...Explained.mspx

    A not so good explanation:
    http://en.wikipedia.org/wiki/Rollover_(key)

    So, if you hold down multiple keys, you may not get the release of a certain key.
    It is possible X tries to fix this internally, to predict if ghosting will occur. I do not know.

  9. #9
    Serf
    Join Date
    Dec 2010
    Posts
    3

    Default

    Thank, first paper is excellent.

  10. #10
    Lesser Knight
    Join Date
    Jan 2010
    Posts
    52

    Default

    I'm getting this problem and I'm not sure how to solve it.... I haven't tried Rombust's test app yet (I'm at work, will try when I get home), but, I have implemented it essentially the same way, using signals, so I would expect it to work the same. When I get home, I'll try it, and update this thread to let you know if I get the same behavior.

    Basically I have a guy that walks using the arrow keys. When you hold down the arrow key, he is meant to travel in that direction, and when you let go (key up), it needs to set his animation to his "standing still" animation. However, I find that as he walks, he gets set to "standing still" quite often as he is walking. In other words, the key_up signal is firing.
    Last edited by Nightwind0; 01-06-2011 at 06:29 PM.

  11. #11
    Lesser Knight
    Join Date
    Jan 2010
    Posts
    52

    Default

    Guys, look at this:
    http://stackoverflow.com/questions/2...1-applications

    It seems like perhaps the "key ups" I am seeing are just auto-repeats, and not actual keypresses, and there is a code example showing how to look for true key-ups. Perhaps we could get something like this in ClanLib ?

    Alternatively, like was mentioned earlier in this thread, if we could somehow enable "XkbSetDetectableAutorepeat" via clanlib??? I believe that would give me the behavior I need.

  12. #12
    Lesser Knight
    Join Date
    Jan 2010
    Posts
    52

    Default

    Quote Originally Posted by rombust View Post
    It works here.

    Try this code in the basic2d example:

    Code:
    #include "precomp.h"
    #include "basic2d.h"
    
    // The start of the Application
    int Basic2D::start(const std::vector<CL_String> &args)
    {
    	quit = false;
    	cow = 0;
    
    	// Set the window
    	CL_DisplayWindowDescription desc;
    	desc.set_title("ClanLib Basic2D Example");
    	desc.set_size(CL_Size(640, 480), true);
    	desc.set_allow_resize(true);
    
    	CL_DisplayWindow window(desc);
    
    	// Connect the Window close event
    	CL_Slot slot_quit = window.sig_window_close().connect(this, &Basic2D::on_window_close);
    
    	// Connect a keyboard handler to on_key_up()
    	CL_Slot slot_input_up = (window.get_ic().get_keyboard()).sig_key_up().connect(this, &Basic2D::on_input_up);
    	CL_Slot slot_input_down = (window.get_ic().get_keyboard()).sig_key_down().connect(this, &Basic2D::on_input_down);
    
    	// Get the graphic context
    	CL_GraphicContext gc = window.get_gc();
    
    	// Run until someone presses escape
    	while (!quit)
    	{
    		switch (cow)
    		{
    			case 0:
    				gc.clear(CL_Colorf(0.0f,0.0f,0.2f));
    				break;
    			case 1:
    				gc.clear(CL_Colorf(0.0f,1.0f,0.2f));
    				break;
    			default:
    				gc.clear(CL_Colorf(1.0f,0.0f,0.2f));
    		}
    
    		window.flip(1);
    		CL_KeepAlive::process(0);
    	}
    
    	return 0;
    }
    
    // A key was pressed
    void Basic2D::on_input_up(const CL_InputEvent &key, const CL_InputState &state)
    {
    	if(key.id == CL_KEY_ESCAPE)
    	{
    		quit = true;
    	}
    	if(key.id == CL_KEY_A)
    	{
    		cow--;
    	}
    }
    
    void Basic2D::on_input_down(const CL_InputEvent &key, const CL_InputState &state)
    {
    	if(key.id == CL_KEY_A)
    	{
    		cow++;
    	}
    }
    
    // The window was closed
    void Basic2D::on_window_close()
    {
    	quit = true;
    }
    Add to basic2d.h:
    Code:
    	void on_input_down(const CL_InputEvent &key, const CL_InputState &state);
    	int cow;
    Hold down 'A', and the screen goes green. Release, it goes blue. It never goes red

    This is on Ubuntu running gnome (ClanLib 2.2.5)
    Rombust, I tried this and you're right BUT the only reason it works is because you get matching keydowns for every keyup (as the auto-repeat happens). Both are happening at once, so, thats why you never see it go red.

    If you put a simple print of a single character (and cout.flush()) in the on_input_up, you will see that actually you are getting up/down pairs over and over again as you hold it down.

    I'd like to try for a patch that fixes this, but I am worried that if I turn off the auto-repeat, some current apps that depend on it will break.... Ideally, there would be a flag or something so I could turn it on explicitly, what do you think?

  13. #13
    Lesser Knight
    Join Date
    Jan 2010
    Posts
    52

    Default

    I've posted a patch for this in the developer forum. I think the other people who posted in this thread would like it.

  14. #14
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Note, this has now been fixed thanks to Nightwind0
    It will be in 2.2.6 release (or now, in SVN)

  15. #15
    Serf
    Join Date
    Dec 2010
    Posts
    4

    Default

    That's excellent news. I'm really impressed with how quickly this has been turned around. Thanks to all involved.

Similar Threads

  1. Questions from new user
    By Ogga in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 11-30-2009, 07:52 AM
  2. Multiple "keydown" signals on a single keystroke
    By zag in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 10-19-2008, 11:04 PM
  3. proble with signals and slots
    By piotrek in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 06-27-2008, 12:00 PM
  4. signals & threads
    By wamma in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 04-18-2008, 10:34 PM
  5. Connect to signals
    By void_kill in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 04-11-2007, 02:23 PM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •