Here you have a patch sent to the ML of ClanLib.
---
Hi,

Old SDL Keyboard behaviour was very strange : when a key was hit and
then release, it looked like it couldn't be released. It was true ! I
saw that ClanLib stored a "last_keycode", and get_keycode(id) just check
if id==last_keycode :-/ I think that it was a joke from Lawouach :

<<  Lawouach : well basically this method ensure that we are consistent
as kepp_alive() uses SDL_PollEvent() which get only one event at a time.
This means that between two calls at keep_alive, we can't change this
value but we don't manage any event either. >>

So, I choosed to use a std::map<int, bool> to store keyboard state (only
store keys when are in state "down"). The state is updated at each
CL_InputDevice_SDLKeyboard::handle_keyboard_event. std::list<int> could
be a better solution, because generally only few keys are down in the
same time. What do you think about this ?

See attached patch. I used unified diff, and is in the right way (not my
last patch :-P).

Bye, Haypo
--- cl_cvs2/Sources/SDL/input_device_sdlkeyboard.h	2004-08-24 01:36:59.000000000 +0200
+++ cl_cvs/Sources/SDL/input_device_sdlkeyboard.h	2004-09-20 01:03:54.000000000 +0200
@@ -30,6 +30,7 @@
 #include "API/signals.h"
 
 #include <SDL/SDL.h>
+#include <map>
 
 class CL_DisplayWindow_SDL;
 
@@ -70,7 +71,10 @@
 private:
 	CL_DisplayWindow_SDL *owner;
 	CL_Slot slot_sdlevent;
-	int last_keycode;
+	typedef std::map<int, bool>::iterator state_iterator;
+	typedef std::map<int, bool>::const_iterator state_const_iterator;
+	typedef std::map<int, bool>::value_type state_pair;
+	std::map<int, bool> state;
 };
 
 #endif
--- cl_cvs2/Sources/SDL/input_device_sdlkeyboard.cpp	2004-08-24 01:36:59.000000000 +0200
+++ cl_cvs/Sources/SDL/input_device_sdlkeyboard.cpp	2004-09-20 01:03:57.000000000 +0200
@@ -37,7 +37,6 @@
 {
 	type = CL_InputDevice::keyboard;
 	slot_sdlevent = owner->sig_sdl_keyboard_event.connect(this, &CL_InputDevice_SDLKeyboard::handle_keyboard_event);
-	last_keycode = 0;
 }
 
 CL_InputDevice_SDLKeyboard::~CL_InputDevice_SDLKeyboard()
@@ -428,9 +427,8 @@
 	if(!owner->has_focus())
 		return false;
 
-	// Lawouach : well basically this method ensure that we are consistent as kepp_alive() uses SDL_PollEvent() which get only one event at a time
-	// This means that between two calls at keep_alive, we can't change this value but we don't manage any event either
-	return (keysym == last_keycode);
+	state_const_iterator pos = state.find (keysym);
+	return (pos != state.end());
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -921,11 +919,18 @@
 	if (event.key.type == SDL_KEYDOWN) 
 	{
 		cl_event.type = CL_InputEvent::pressed;
-		last_keycode = cl_event.id;
+
+		state_iterator pos = state.find (cl_event.id);
+		if (pos == state.end()) {
+		  state_pair key(cl_event.id, true);
+		  state.insert (key);
+		}
 	}
 	else if (event.key.type == SDL_KEYUP) 
 	{
 		cl_event.type = CL_InputEvent::released;
+		state_iterator pos = state.find (cl_event.id);
+		if (pos != state.end()) state.erase(pos);
 	}
 	cl_event.device = owner->keyboard;
 	cl_event.mouse_pos = CL_Point(owner->mouse.get_x(), owner->mouse.get_y());

Répondre à