Index: /trunk/nv/detail/io_event_list.inc
===================================================================
--- /trunk/nv/detail/io_event_list.inc	(revision 92)
+++ /trunk/nv/detail/io_event_list.inc	(revision 93)
@@ -2,3 +2,6 @@
 NV_IO_EVENT( EV_MOUSE_BUTTON )
 NV_IO_EVENT( EV_MOUSE_MOVE )
+NV_IO_EVENT( EV_ACTIVE )
+NV_IO_EVENT( EV_RESIZE )
 NV_IO_EVENT( EV_SYSTEM )
+NV_IO_EVENT( EV_QUIT )
Index: /trunk/nv/detail/key_list.inc
===================================================================
--- /trunk/nv/detail/key_list.inc	(revision 92)
+++ /trunk/nv/detail/key_list.inc	(revision 93)
@@ -12,9 +12,27 @@
 NV_KEY( KEY_RIGHT   , 20 )
 NV_KEY( KEY_DOWN    , 21 )
+NV_KEY( KEY_DELETE  , 22 )
+NV_KEY( KEY_INSERT  , 23 )
+NV_KEY( KEY_CENTER  , 24 )
 
 NV_KEY( KEY_ESCAPE  , 27 )
 
+NV_KEY( KEY_SPACE   , 32 )
 
-NV_KEY( KEY_SPACE   , 32 )
+NV_KEY( KEY_QUOTE   , 39 )
+
+NV_KEY( KEY_COMMA   , 44 )
+NV_KEY( KEY_MINUS   , 45 )
+NV_KEY( KEY_PERIOD  , 46 )
+NV_KEY( KEY_SLASH   , 47 )
+
+NV_KEY( KEY_SCOLON  , 59 )
+NV_KEY( KEY_EQUALS  , 61 )
+
+NV_KEY( KEY_LBRACKET, 91 )
+NV_KEY( KEY_BSLASH  , 92 )
+NV_KEY( KEY_RBRACKET, 93 )
+
+NV_KEY( KEY_BQUOTE  , 96 )
 
 NV_KEY( KEY_0       , 48 )
@@ -55,2 +73,15 @@
 NV_KEY( KEY_Y       , 89 )
 NV_KEY( KEY_Z       , 90 )
+
+NV_KEY( KEY_F1  , 131 )
+NV_KEY( KEY_F2  , 132 )
+NV_KEY( KEY_F3  , 133 )
+NV_KEY( KEY_F4  , 134 )
+NV_KEY( KEY_F5  , 135 )
+NV_KEY( KEY_F6  , 136 )
+NV_KEY( KEY_F7  , 137 )
+NV_KEY( KEY_F8  , 138 )
+NV_KEY( KEY_F9  , 139 )
+NV_KEY( KEY_F10 , 140 )
+NV_KEY( KEY_F11 , 141 )
+NV_KEY( KEY_F12 , 142 )
Index: /trunk/nv/gl/gl_window.hh
===================================================================
--- /trunk/nv/gl/gl_window.hh	(revision 92)
+++ /trunk/nv/gl/gl_window.hh	(revision 93)
@@ -27,6 +27,9 @@
 		string get_title() const;
 		void set_title( const string& title );
+		virtual bool is_event_pending();
+		virtual bool poll_event( io_event& event );
 		virtual context* get_context() { return m_context; }
-		~gl_window();
+		virtual void swap_buffers();
+		virtual ~gl_window();
 	private:
 		uint16      m_width;
Index: /trunk/nv/interface/window.hh
===================================================================
--- /trunk/nv/interface/window.hh	(revision 92)
+++ /trunk/nv/interface/window.hh	(revision 93)
@@ -15,4 +15,5 @@
 #include <nv/common.hh>
 #include <nv/string.hh>
+#include <nv/io_event.hh>
 
 namespace nv
@@ -27,4 +28,8 @@
 		virtual void set_title( const string& title ) = 0;
 		virtual context* get_context() = 0;
+		virtual bool is_event_pending() = 0;
+		virtual bool poll_event( io_event& event ) = 0;
+		virtual void swap_buffers() = 0;
+		virtual ~window() = 0 {};
 	};
 
Index: /trunk/nv/io_event.hh
===================================================================
--- /trunk/nv/io_event.hh	(revision 92)
+++ /trunk/nv/io_event.hh	(revision 93)
@@ -89,4 +89,15 @@
 	};
 
+	struct resize_event
+	{
+		sint32 x;
+		sint32 y;
+	};
+
+	struct active_event
+	{
+		bool gain;
+	};
+
 	struct system_event
 	{
@@ -104,4 +115,6 @@
 			mouse_button_event mbutton;
 			mouse_move_event   mmove;
+			resize_event       resize;
+			active_event       active;
 			system_event       system;
 		};
Index: /trunk/src/gl/gl_window.cc
===================================================================
--- /trunk/src/gl/gl_window.cc	(revision 92)
+++ /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()
 {
Index: /trunk/tests/render_test/rl.cc
===================================================================
--- /trunk/tests/render_test/rl.cc	(revision 92)
+++ /trunk/tests/render_test/rl.cc	(revision 93)
@@ -1,3 +1,2 @@
-#include <nv/lib/sdl12.hh>
 #include <nv/interface/vertex_buffer.hh>
 #include <nv/gl/gl_device.hh>
@@ -205,22 +204,25 @@
 		m_char_program->set_uniform( "tex", 0 );
 		m_window->get_context()->draw( nv::TRIANGLES, m_render_state, m_char_program, m_char_va, 6 );
-
-		SDL_GL_SwapBuffers();
-		SDL_Event event;
-		while(SDL_PollEvent(&event)) 
+		m_window->swap_buffers();
+
+		nv::io_event event;
+		while(m_window->poll_event(event)) 
 		{      
 			switch (event.type) 
 			{
-			case SDL_QUIT:
+			case nv::EV_QUIT:
 				keypress = 1;
 				break;
-			case SDL_KEYDOWN:
-				switch (event.key.keysym.sym) 
+			case nv::EV_KEY:
+				if (event.key.pressed)
 				{
-				case SDLK_ESCAPE: keypress = 1; break;
-				case SDLK_LEFT: move.x = move.x - 1.0f; break;
-				case SDLK_RIGHT: move.x = move.x + 1.0f; break;
-				case SDLK_UP: move.z = move.z - 1.0f; break;
-				case SDLK_DOWN: move.z = move.z + 1.0f; break;
+					switch (event.key.code) 
+					{
+					case nv::KEY_ESCAPE : keypress = 1; break;
+					case nv::KEY_LEFT   : move.x = move.x - 1.0f; break;
+					case nv::KEY_RIGHT  : move.x = move.x + 1.0f; break;
+					case nv::KEY_UP     : move.z = move.z - 1.0f; break;
+					case nv::KEY_DOWN   : move.z = move.z + 1.0f; break;
+					}
 				}
 				break;
