Index: trunk/src/gl/gl_window.cc
===================================================================
--- trunk/src/gl/gl_window.cc	(revision 44)
+++ trunk/src/gl/gl_window.cc	(revision 93)
@@ -10,4 +10,141 @@
 
 using namespace nv;
+
+static bool sdl_key_event_to_io_event( const SDL_KeyboardEvent& ke, io_event& kevent )
+{
+	kevent.type        = EV_KEY;
+	kevent.key.pressed = ( ke.state != SDL_RELEASED );
+	kevent.key.ascii   = 0;
+	kevent.key.code    = KEY_NONE;
+
+	// if result is a typable char place it into the structure
+	if (ke.keysym.unicode >= 32 && ke.keysym.unicode < 128 )
+	{
+		kevent.key.ascii = (char)ke.keysym.unicode;
+	}
+
+	// Get the Key value from the SDL Keyboard event
+	int result = ke.keysym.sym;
+
+	// Check the control and shift states
+	kevent.key.alt     = (ke.keysym.mod & KMOD_ALT ) != 0;
+	kevent.key.control = (ke.keysym.mod & KMOD_CTRL ) != 0;
+	kevent.key.shift   = (ke.keysym.mod & KMOD_SHIFT ) != 0;
+
+	// if result is a typable char from the directly transformable ranges
+	if ( ( result >= KEY_A && result <= KEY_Z ) || 
+		( result >= KEY_0 && result <= KEY_9 ) ||
+		result == ' ' )
+	{
+		kevent.key.code = static_cast<key_code>(result);
+	}
+
+	// if result is a typable char from the a..z range
+	if ( result >= KEY_A + 32 && result <= KEY_Z + 32 )
+	{
+		kevent.key.code = static_cast<key_code>(result - 32);
+	}
+
+	if ( result >= SDLK_F1 && result <= SDLK_F12 )
+	{
+		kevent.key.code = static_cast<key_code>(result - SDLK_F1 + KEY_F1 );
+	}
+
+	// other recognized codes
+	switch ( result ) 
+	{
+	case SDLK_BACKSPACE    : kevent.key.code = KEY_BACK; break;
+	case SDLK_TAB          : kevent.key.code = KEY_TAB; break;
+	case SDLK_RETURN       : kevent.key.code = KEY_ENTER; break;
+	case SDLK_PAGEUP       : kevent.key.code = KEY_PGUP; break;
+	case SDLK_PAGEDOWN     : kevent.key.code = KEY_PGDOWN; break;
+	case SDLK_END          : kevent.key.code = KEY_END; break;
+	case SDLK_HOME         : kevent.key.code = KEY_HOME; break;
+	case SDLK_LEFT         : kevent.key.code = KEY_LEFT; break;
+	case SDLK_UP           : kevent.key.code = KEY_UP; break;
+	case SDLK_RIGHT        : kevent.key.code = KEY_RIGHT; break;
+	case SDLK_DOWN         : kevent.key.code = KEY_DOWN; break;
+	case SDLK_DELETE       : kevent.key.code = KEY_DELETE; break;
+	case SDLK_INSERT       : kevent.key.code = KEY_INSERT; break;
+	case SDLK_KP5          : kevent.key.code = KEY_CENTER; break;
+	case SDLK_ESCAPE       : kevent.key.code = KEY_ESCAPE; break;
+	case SDLK_QUOTE        : kevent.key.code = KEY_QUOTE; break;
+	case SDLK_COMMA        : kevent.key.code = KEY_COMMA; break;
+	case SDLK_MINUS        : kevent.key.code = KEY_MINUS; break;
+	case SDLK_PERIOD       : kevent.key.code = KEY_PERIOD; break;
+	case SDLK_SLASH        : kevent.key.code = KEY_SLASH; break;
+	case SDLK_SEMICOLON    : kevent.key.code = KEY_SCOLON; break;
+	case SDLK_LEFTBRACKET  : kevent.key.code = KEY_LBRACKET; break;
+	case SDLK_BACKSLASH    : kevent.key.code = KEY_BSLASH; break;
+	case SDLK_RIGHTBRACKET : kevent.key.code = KEY_RBRACKET; break;
+	case SDLK_BACKQUOTE    : kevent.key.code = KEY_BQUOTE; break;
+	default : break;
+	}
+
+	// If key was understood by nv, then it's valid, otherwise ignored
+	return kevent.key.ascii != 0 || kevent.key.code != 0;
+}
+
+static bool sdl_mouse_button_to_io_event( const SDL_MouseButtonEvent& mb, io_event& mevent )
+{
+	mevent.type            = EV_MOUSE_BUTTON;
+	mevent.mbutton.button  = MOUSE_NONE;
+	mevent.mbutton.pressed = (mb.state != SDL_RELEASED);
+	mevent.mbutton.x       = mb.x;
+	mevent.mbutton.y       = mb.y;
+
+	switch ( mb.button )
+	{
+	case SDL_BUTTON_LEFT      : mevent.mbutton.button = MOUSE_LEFT; break;
+	case SDL_BUTTON_MIDDLE    : mevent.mbutton.button = MOUSE_MIDDLE; break;
+	case SDL_BUTTON_RIGHT     : mevent.mbutton.button = MOUSE_RIGHT; break;
+	case SDL_BUTTON_WHEELUP   : mevent.mbutton.button = MOUSE_WHEEL_UP; break;
+	case SDL_BUTTON_WHEELDOWN : mevent.mbutton.button = MOUSE_WHEEL_DOWN; break;
+	default : break;
+	}
+
+	return mevent.mbutton.button != MOUSE_NONE;
+}
+
+static bool sdl_mouse_motion_to_io_event( const SDL_MouseMotionEvent& mm, io_event& mevent )
+{
+	mevent.type          = EV_MOUSE_MOVE;
+	mevent.mmove.pressed = (mm.state != SDL_RELEASED);
+	mevent.mmove.x       = mm.x;
+	mevent.mmove.y       = mm.y;
+	return true;
+}
+
+static bool sdl_event_to_io_event( const SDL_Event& e, io_event& ioevent )
+{
+	switch ( e.type )
+	{
+	case SDL_KEYDOWN         : return sdl_key_event_to_io_event( e.key, ioevent );
+	case SDL_KEYUP           : return sdl_key_event_to_io_event( e.key, ioevent );
+	case SDL_MOUSEMOTION     : return sdl_mouse_motion_to_io_event( e.motion, ioevent );
+	case SDL_MOUSEBUTTONDOWN : return sdl_mouse_button_to_io_event( e.button, ioevent );
+	case SDL_MOUSEBUTTONUP   : return sdl_mouse_button_to_io_event( e.button, ioevent );
+	case SDL_ACTIVEEVENT     : 
+		ioevent.type = EV_ACTIVE; 
+		ioevent.active.gain = (e.active.gain != 0); 
+		return e.active.state == SDL_APPINPUTFOCUS;
+	case SDL_VIDEORESIZE     : 
+		ioevent.type     = EV_RESIZE; 
+		ioevent.resize.x = e.resize.w;
+		ioevent.resize.y = e.resize.h;
+		return true;
+	case SDL_SYSWMEVENT      : ioevent.type = EV_SYSTEM; return true;
+	case SDL_QUIT            : ioevent.type = EV_QUIT;   return true;
+	case SDL_NOEVENT         : return false;
+	case SDL_VIDEOEXPOSE     : return false;
+	case SDL_JOYAXISMOTION   : return false;
+	case SDL_JOYBALLMOTION   : return false;
+	case SDL_JOYHATMOTION    : return false;
+	case SDL_JOYBUTTONDOWN   : return false;
+	case SDL_JOYBUTTONUP     : return false;
+	default : return false;
+	}
+}
+
 
 gl_window::gl_window( uint16 width, uint16 height )
@@ -55,4 +192,21 @@
 }
 
+bool gl_window::is_event_pending()
+{
+	return SDL_PollEvent( nullptr ) != 0;
+}
+
+bool gl_window::poll_event( io_event& event )
+{
+	SDL_Event sdl_event;
+	if ( SDL_PollEvent( &sdl_event ) == 0 ) return false;
+	return sdl_event_to_io_event( sdl_event, event );
+}
+
+void gl_window::swap_buffers()
+{
+	SDL_GL_SwapBuffers();
+}
+
 gl_window::~gl_window()
 {
