diff --git a/src/am_map.c b/src/am_map.c
index ef0ebb88cd33e3d865095015cfd8be09a8487388..24379e2f13d91822c8aed096ae3f972a95a0bfee 100644
--- a/src/am_map.c
+++ b/src/am_map.c
@@ -458,7 +458,7 @@ boolean AM_Responder(event_t *ev)
 	{
 		if (!automapactive)
 		{
-			if (ev->type == ev_keydown && ev->data1 == AM_TOGGLEKEY)
+			if (ev->type == ev_keydown && ev->key == AM_TOGGLEKEY)
 			{
 				//faB: prevent alt-tab in win32 version to activate automap just before
 				//     minimizing the app; doesn't do any harm to the DOS version
@@ -473,7 +473,7 @@ boolean AM_Responder(event_t *ev)
 		else if (ev->type == ev_keydown)
 		{
 			rc = true;
-			switch (ev->data1)
+			switch (ev->key)
 			{
 				case AM_PANRIGHTKEY: // pan right
 					if (!followplayer)
@@ -550,7 +550,7 @@ boolean AM_Responder(event_t *ev)
 		else if (ev->type == ev_keyup)
 		{
 			rc = false;
-			switch (ev->data1)
+			switch (ev->key)
 			{
 				case AM_PANRIGHTKEY:
 					if (!followplayer)
diff --git a/src/console.c b/src/console.c
index 95d6f5fd1ebecaab1b9f5636c4d33b4826a680f8..f01e1824c97a8df1041ab42fe829ad588e058877 100644
--- a/src/console.c
+++ b/src/console.c
@@ -221,7 +221,7 @@ static void CONS_Bind_f(void)
 		for (key = 0; key < NUMINPUTS; key++)
 			if (bindtable[key])
 			{
-				CONS_Printf("%s : \"%s\"\n", G_KeyNumToString(key), bindtable[key]);
+				CONS_Printf("%s : \"%s\"\n", G_KeyNumToName(key), bindtable[key]);
 				na = 1;
 			}
 		if (!na)
@@ -229,7 +229,7 @@ static void CONS_Bind_f(void)
 		return;
 	}
 
-	key = G_KeyStringToNum(COM_Argv(1));
+	key = G_KeyNameToNum(COM_Argv(1));
 	if (key <= 0 || key >= NUMINPUTS)
 	{
 		CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n"));
@@ -913,12 +913,12 @@ boolean CON_Responder(event_t *ev)
 	// let go keyup events, don't eat them
 	if (ev->type != ev_keydown && ev->type != ev_console)
 	{
-		if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1])
+		if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1])
 			consdown = false;
 		return false;
 	}
 
-	key = ev->data1;
+	key = ev->key;
 
 	// check for console toggle key
 	if (ev->type != ev_console)
@@ -926,7 +926,7 @@ boolean CON_Responder(event_t *ev)
 		if (modeattacking || metalrecording || marathonmode)
 			return false;
 
-		if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
+		if (key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1])
 		{
 			if (consdown) // ignore repeat
 				return true;
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index aa7bc8a6cdc37b02f6d711d9d318b60dc9f7de17..b7071320c80d4f0917040e95a68d7870a21755d0 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -43,6 +43,7 @@
 #include "lzf.h"
 #include "lua_script.h"
 #include "lua_hook.h"
+#include "lua_libs.h"
 #include "md5.h"
 #include "m_perfstats.h"
 
@@ -663,14 +664,14 @@ static void Snake_Handle(void)
 	UINT16 i;
 
 	// Handle retry
-	if (snake->gameover && (PLAYER1INPUTDOWN(gc_jump) || gamekeydown[KEY_ENTER]))
+	if (snake->gameover && (PLAYER1INPUTDOWN(GC_JUMP) || gamekeydown[KEY_ENTER]))
 	{
 		Snake_Initialise();
 		snake->pausepressed = true; // Avoid accidental pause on respawn
 	}
 
 	// Handle pause
-	if (PLAYER1INPUTDOWN(gc_pause) || gamekeydown[KEY_ENTER])
+	if (PLAYER1INPUTDOWN(GC_PAUSE) || gamekeydown[KEY_ENTER])
 	{
 		if (!snake->pausepressed)
 			snake->paused = !snake->paused;
@@ -3331,6 +3332,9 @@ static inline void SV_GenContext(void)
 //
 void D_QuitNetGame(void)
 {
+	mousegrabbedbylua = true;
+	I_UpdateMouseGrab();
+
 	if (!netgame || !netbuffer)
 		return;
 
diff --git a/src/d_event.h b/src/d_event.h
index 1fd2e3824251082d6c059fffef8ddbe76f67a15c..c30a8ced2b09cd7887446211cbc2b96622c0aba6 100644
--- a/src/d_event.h
+++ b/src/d_event.h
@@ -33,9 +33,10 @@ typedef enum
 typedef struct
 {
 	evtype_t type;
-	INT32 data1; // keys / mouse/joystick buttons
-	INT32 data2; // mouse/joystick x move
-	INT32 data3; // mouse/joystick y move
+	INT32 key; // keys/mouse/joystick buttons
+	INT32 x; // mouse/joystick x move
+	INT32 y; // mouse/joystick y move
+	boolean repeated; // key repeat
 } event_t;
 
 //
diff --git a/src/d_main.c b/src/d_main.c
index 7866ccbed418bfcd639178637c3b47cc861584d0..89579ea91c2644baffcc4e5ed29306cfcefceebf 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -191,22 +191,22 @@ void D_ProcessEvents(void)
 		if (ev->type == ev_keydown || ev->type == ev_keyup)
 		{
 			// Mouse buttons
-			if ((UINT32)(ev->data1 - KEY_MOUSE1) < MOUSEBUTTONS)
+			if ((UINT32)(ev->key - KEY_MOUSE1) < MOUSEBUTTONS)
 			{
 				if (ev->type == ev_keydown)
-					mouse.buttons |= 1 << (ev->data1 - KEY_MOUSE1);
+					mouse.buttons |= 1 << (ev->key - KEY_MOUSE1);
 				else
-					mouse.buttons &= ~(1 << (ev->data1 - KEY_MOUSE1));
+					mouse.buttons &= ~(1 << (ev->key - KEY_MOUSE1));
 			}
-			else if ((UINT32)(ev->data1 - KEY_2MOUSE1) < MOUSEBUTTONS)
+			else if ((UINT32)(ev->key - KEY_2MOUSE1) < MOUSEBUTTONS)
 			{
 				if (ev->type == ev_keydown)
-					mouse2.buttons |= 1 << (ev->data1 - KEY_2MOUSE1);
+					mouse2.buttons |= 1 << (ev->key - KEY_2MOUSE1);
 				else
-					mouse2.buttons &= ~(1 << (ev->data1 - KEY_2MOUSE1));
+					mouse2.buttons &= ~(1 << (ev->key - KEY_2MOUSE1));
 			}
 			// Scroll (has no keyup event)
-			else switch (ev->data1) {
+			else switch (ev->key) {
 				case KEY_MOUSEWHEELUP:
 					mouse.buttons |= MB_SCROLLUP;
 					break;
diff --git a/src/deh_tables.c b/src/deh_tables.c
index 63e273a6c1f4bc4d605978a577db79550f8340ac..3bced113b83564ce87cdcb310e515137bde3422c 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -5478,49 +5478,49 @@ struct int_const_s const INT_CONST[] = {
 	{"JOYAXISRANGE",JOYAXISRANGE},
 
 	// Game controls
-	{"gc_null",gc_null},
-	{"gc_forward",gc_forward},
-	{"gc_backward",gc_backward},
-	{"gc_strafeleft",gc_strafeleft},
-	{"gc_straferight",gc_straferight},
-	{"gc_turnleft",gc_turnleft},
-	{"gc_turnright",gc_turnright},
-	{"gc_weaponnext",gc_weaponnext},
-	{"gc_weaponprev",gc_weaponprev},
-	{"gc_wepslot1",gc_wepslot1},
-	{"gc_wepslot2",gc_wepslot2},
-	{"gc_wepslot3",gc_wepslot3},
-	{"gc_wepslot4",gc_wepslot4},
-	{"gc_wepslot5",gc_wepslot5},
-	{"gc_wepslot6",gc_wepslot6},
-	{"gc_wepslot7",gc_wepslot7},
-	{"gc_wepslot8",gc_wepslot8},
-	{"gc_wepslot9",gc_wepslot9},
-	{"gc_wepslot10",gc_wepslot10},
-	{"gc_fire",gc_fire},
-	{"gc_firenormal",gc_firenormal},
-	{"gc_tossflag",gc_tossflag},
-	{"gc_spin",gc_spin},
-	{"gc_camtoggle",gc_camtoggle},
-	{"gc_camreset",gc_camreset},
-	{"gc_lookup",gc_lookup},
-	{"gc_lookdown",gc_lookdown},
-	{"gc_centerview",gc_centerview},
-	{"gc_mouseaiming",gc_mouseaiming},
-	{"gc_talkkey",gc_talkkey},
-	{"gc_teamkey",gc_teamkey},
-	{"gc_scores",gc_scores},
-	{"gc_jump",gc_jump},
-	{"gc_console",gc_console},
-	{"gc_pause",gc_pause},
-	{"gc_systemmenu",gc_systemmenu},
-	{"gc_screenshot",gc_screenshot},
-	{"gc_recordgif",gc_recordgif},
-	{"gc_viewpoint",gc_viewpoint},
-	{"gc_custom1",gc_custom1},
-	{"gc_custom2",gc_custom2},
-	{"gc_custom3",gc_custom3},
-	{"num_gamecontrols",num_gamecontrols},
+	{"GC_NULL",GC_NULL},
+	{"GC_FORWARD",GC_FORWARD},
+	{"GC_BACKWARD",GC_BACKWARD},
+	{"GC_STRAFELEFT",GC_STRAFELEFT},
+	{"GC_STRAFERIGHT",GC_STRAFERIGHT},
+	{"GC_TURNLEFT",GC_TURNLEFT},
+	{"GC_TURNRIGHT",GC_TURNRIGHT},
+	{"GC_WEAPONNEXT",GC_WEAPONNEXT},
+	{"GC_WEAPONPREV",GC_WEAPONPREV},
+	{"GC_WEPSLOT1",GC_WEPSLOT1},
+	{"GC_WEPSLOT2",GC_WEPSLOT2},
+	{"GC_WEPSLOT3",GC_WEPSLOT3},
+	{"GC_WEPSLOT4",GC_WEPSLOT4},
+	{"GC_WEPSLOT5",GC_WEPSLOT5},
+	{"GC_WEPSLOT6",GC_WEPSLOT6},
+	{"GC_WEPSLOT7",GC_WEPSLOT7},
+	{"GC_WEPSLOT8",GC_WEPSLOT8},
+	{"GC_WEPSLOT9",GC_WEPSLOT9},
+	{"GC_WEPSLOT10",GC_WEPSLOT10},
+	{"GC_FIRE",GC_FIRE},
+	{"GC_FIRENORMAL",GC_FIRENORMAL},
+	{"GC_TOSSFLAG",GC_TOSSFLAG},
+	{"GC_SPIN",GC_SPIN},
+	{"GC_CAMTOGGLE",GC_CAMTOGGLE},
+	{"GC_CAMRESET",GC_CAMRESET},
+	{"GC_LOOKUP",GC_LOOKUP},
+	{"GC_LOOKDOWN",GC_LOOKDOWN},
+	{"GC_CENTERVIEW",GC_CENTERVIEW},
+	{"GC_MOUSEAIMING",GC_MOUSEAIMING},
+	{"GC_TALKKEY",GC_TALKKEY},
+	{"GC_TEAMKEY",GC_TEAMKEY},
+	{"GC_SCORES",GC_SCORES},
+	{"GC_JUMP",GC_JUMP},
+	{"GC_CONSOLE",GC_CONSOLE},
+	{"GC_PAUSE",GC_PAUSE},
+	{"GC_SYSTEMMENU",GC_SYSTEMMENU},
+	{"GC_SCREENSHOT",GC_SCREENSHOT},
+	{"GC_RECORDGIF",GC_RECORDGIF},
+	{"GC_VIEWPOINT",GC_VIEWPOINT},
+	{"GC_CUSTOM1",GC_CUSTOM1},
+	{"GC_CUSTOM2",GC_CUSTOM2},
+	{"GC_CUSTOM3",GC_CUSTOM3},
+	{"NUM_GAMECONTROLS",NUM_GAMECONTROLS},
 
 	// Mouse buttons
 	{"MB_BUTTON1",MB_BUTTON1},
diff --git a/src/f_finale.c b/src/f_finale.c
index acad7b2481a2a5cf8e57a1c9f4f6a52863d838c6..e5ed272d4ea2d268c7a92d27e09a061b39a604e9 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -1011,7 +1011,7 @@ void F_IntroTicker(void)
 //
 boolean F_IntroResponder(event_t *event)
 {
-	INT32 key = event->data1;
+	INT32 key = event->key;
 
 	// remap virtual keys (mouse & joystick buttons)
 	switch (key)
@@ -1397,7 +1397,7 @@ void F_CreditTicker(void)
 
 boolean F_CreditResponder(event_t *event)
 {
-	INT32 key = event->data1;
+	INT32 key = event->key;
 
 	// remap virtual keys (mouse & joystick buttons)
 	switch (key)
@@ -3821,7 +3821,7 @@ void F_ContinueTicker(void)
 
 boolean F_ContinueResponder(event_t *event)
 {
-	INT32 key = event->data1;
+	INT32 key = event->key;
 
 	if (keypressed)
 		return true;
diff --git a/src/g_game.c b/src/g_game.c
index 8cdeaf079eb125b344801cca9c92e3606689e98e..de1a774f409f2449a75d5616cffdac047cd49045 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -45,6 +45,7 @@
 #include "lua_hook.h"
 #include "b_bot.h"
 #include "m_cond.h" // condition sets
+#include "lua_script.h"
 
 #include "lua_hud.h"
 
@@ -1139,13 +1140,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 		return;
 	}
 
-	turnright = PLAYERINPUTDOWN(ssplayer, gc_turnright);
-	turnleft = PLAYERINPUTDOWN(ssplayer, gc_turnleft);
+	turnright = PLAYERINPUTDOWN(ssplayer, GC_TURNRIGHT);
+	turnleft = PLAYERINPUTDOWN(ssplayer, GC_TURNLEFT);
 
-	straferkey = PLAYERINPUTDOWN(ssplayer, gc_straferight);
-	strafelkey = PLAYERINPUTDOWN(ssplayer, gc_strafeleft);
-	movefkey = PLAYERINPUTDOWN(ssplayer, gc_forward);
-	movebkey = PLAYERINPUTDOWN(ssplayer, gc_backward);
+	straferkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFERIGHT);
+	strafelkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFELEFT);
+	movefkey = PLAYERINPUTDOWN(ssplayer, GC_FORWARD);
+	movebkey = PLAYERINPUTDOWN(ssplayer, GC_BACKWARD);
 
 	if (strafeisturn)
 	{
@@ -1154,7 +1155,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 		straferkey = strafelkey = false;
 	}
 
-	mouseaiming = (PLAYERINPUTDOWN(ssplayer, gc_mouseaiming)) ^
+	mouseaiming = (PLAYERINPUTDOWN(ssplayer, GC_MOUSEAIMING)) ^
 		((chasecam && !player->spectator) ? chasefreelook : alwaysfreelook);
 	analogjoystickmove = usejoystick && !Joystick.bGamepadStyle;
 	gamepadjoystickmove = usejoystick && Joystick.bGamepadStyle;
@@ -1270,11 +1271,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	// forward with key or button
 	if (movefkey || (gamepadjoystickmove && movejoystickvector.yaxis < 0)
 		|| ((player->powers[pw_carry] == CR_NIGHTSMODE)
-			&& (PLAYERINPUTDOWN(ssplayer, gc_lookup) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))))
+			&& (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))))
 		forward = forwardmove[speed];
 	if (movebkey || (gamepadjoystickmove && movejoystickvector.yaxis > 0)
 		|| ((player->powers[pw_carry] == CR_NIGHTSMODE)
-			&& (PLAYERINPUTDOWN(ssplayer, gc_lookdown) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))))
+			&& (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))))
 		forward -= forwardmove[speed];
 
 	if (analogjoystickmove && movejoystickvector.yaxis != 0)
@@ -1287,9 +1288,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	if (strafelkey)
 		side -= sidemove[speed];
 
-	if (PLAYERINPUTDOWN(ssplayer, gc_weaponnext))
+	if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONNEXT))
 		cmd->buttons |= BT_WEAPONNEXT; // Next Weapon
-	if (PLAYERINPUTDOWN(ssplayer, gc_weaponprev))
+	if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONPREV))
 		cmd->buttons |= BT_WEAPONPREV; // Previous Weapon
 
 #if NUM_WEAPONS > 10
@@ -1298,7 +1299,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	//use the four avaliable bits to determine the weapon.
 	cmd->buttons &= ~BT_WEAPONMASK;
 	for (i = 0; i < NUM_WEAPONS; ++i)
-		if (PLAYERINPUTDOWN(ssplayer, gc_wepslot1 + i))
+		if (PLAYERINPUTDOWN(ssplayer, GC_WEPSLOT1 + i))
 		{
 			cmd->buttons |= (UINT16)(i + 1);
 			break;
@@ -1306,34 +1307,34 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 
 	// fire with any button/key
 	axis = PlayerJoyAxis(ssplayer, JA_FIRE);
-	if (PLAYERINPUTDOWN(ssplayer, gc_fire) || (usejoystick && axis > 0))
+	if (PLAYERINPUTDOWN(ssplayer, GC_FIRE) || (usejoystick && axis > 0))
 		cmd->buttons |= BT_ATTACK;
 
 	// fire normal with any button/key
 	axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL);
-	if (PLAYERINPUTDOWN(ssplayer, gc_firenormal) || (usejoystick && axis > 0))
+	if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0))
 		cmd->buttons |= BT_FIRENORMAL;
 
-	if (PLAYERINPUTDOWN(ssplayer, gc_tossflag))
+	if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG))
 		cmd->buttons |= BT_TOSSFLAG;
 
 	// Lua scriptable buttons
-	if (PLAYERINPUTDOWN(ssplayer, gc_custom1))
+	if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM1))
 		cmd->buttons |= BT_CUSTOM1;
-	if (PLAYERINPUTDOWN(ssplayer, gc_custom2))
+	if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM2))
 		cmd->buttons |= BT_CUSTOM2;
-	if (PLAYERINPUTDOWN(ssplayer, gc_custom3))
+	if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM3))
 		cmd->buttons |= BT_CUSTOM3;
 
 	// use with any button/key
 	axis = PlayerJoyAxis(ssplayer, JA_SPIN);
-	if (PLAYERINPUTDOWN(ssplayer, gc_spin) || (usejoystick && axis > 0))
+	if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0))
 		cmd->buttons |= BT_SPIN;
 
 	// Centerview can be a toggle in simple mode!
 	{
 		static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior
-		boolean down = PLAYERINPUTDOWN(ssplayer, gc_centerview);
+		boolean down = PLAYERINPUTDOWN(ssplayer, GC_CENTERVIEW);
 
 		if (!(controlstyle == CS_SIMPLE && cv_cam_centertoggle[forplayer].value))
 			centerviewdown = down;
@@ -1432,7 +1433,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	if (ticcmd_centerviewdown[forplayer] && controlstyle == CS_SIMPLE)
 		controlstyle = CS_LEGACY;
 
-	if (PLAYERINPUTDOWN(ssplayer, gc_camreset))
+	if (PLAYERINPUTDOWN(ssplayer, GC_CAMRESET))
 	{
 		if (thiscam->chase && !resetdown[forplayer])
 			P_ResetCamera(&players[ssplayer == 1 ? displayplayer : secondarydisplayplayer], thiscam);
@@ -1445,7 +1446,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 
 	// jump button
 	axis = PlayerJoyAxis(ssplayer, JA_JUMP);
-	if (PLAYERINPUTDOWN(ssplayer, gc_jump) || (usejoystick && axis > 0))
+	if (PLAYERINPUTDOWN(ssplayer, GC_JUMP) || (usejoystick && axis > 0))
 		cmd->buttons |= BT_JUMP;
 
 	// player aiming shit, ahhhh...
@@ -1475,12 +1476,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 
 		if (!(player->powers[pw_carry] == CR_NIGHTSMODE))
 		{
-			if (PLAYERINPUTDOWN(ssplayer, gc_lookup) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))
+			if (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))
 			{
 				*myaiming += KB_LOOKSPEED * screen_invert;
 				keyboard_look[forplayer] = true;
 			}
-			else if (PLAYERINPUTDOWN(ssplayer, gc_lookdown) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))
+			else if (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))
 			{
 				*myaiming -= KB_LOOKSPEED * screen_invert;
 				keyboard_look[forplayer] = true;
@@ -1959,7 +1960,7 @@ boolean G_Responder(event_t *ev)
 	if (gameaction == ga_nothing && !singledemo &&
 		((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN))
 	{
-		if (ev->type == ev_keydown && ev->data1 != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE))
+		if (ev->type == ev_keydown && ev->key != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE))
 		{
 			M_StartControlPanel();
 			return true;
@@ -2035,7 +2036,7 @@ boolean G_Responder(event_t *ev)
 
 	// allow spy mode changes even during the demo
 	if (gamestate == GS_LEVEL && ev->type == ev_keydown
-		&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
+		&& (ev->key == KEY_F12 || ev->key == gamecontrol[GC_VIEWPOINT][0] || ev->key == gamecontrol[GC_VIEWPOINT][1]))
 	{
 		// ViewpointSwitch Lua hook.
 		UINT8 canSwitchView = 0;
@@ -2108,13 +2109,13 @@ boolean G_Responder(event_t *ev)
 	switch (ev->type)
 	{
 		case ev_keydown:
-			if (ev->data1 == gamecontrol[gc_pause][0]
-				|| ev->data1 == gamecontrol[gc_pause][1]
-				|| ev->data1 == KEY_PAUSE)
+			if (ev->key == gamecontrol[GC_PAUSE][0]
+				|| ev->key == gamecontrol[GC_PAUSE][1]
+				|| ev->key == KEY_PAUSE)
 			{
 				if (modeattacking && !demoplayback && (gamestate == GS_LEVEL))
 				{
-					pausebreakkey = (ev->data1 == KEY_PAUSE);
+					pausebreakkey = (ev->key == KEY_PAUSE);
 					if (menuactive || pausedelay < 0 || leveltime < 2)
 						return true;
 
@@ -2139,8 +2140,8 @@ boolean G_Responder(event_t *ev)
 					}
 				}
 			}
-			if (ev->data1 == gamecontrol[gc_camtoggle][0]
-				|| ev->data1 == gamecontrol[gc_camtoggle][1])
+			if (ev->key == gamecontrol[GC_CAMTOGGLE][0]
+				|| ev->key == gamecontrol[GC_CAMTOGGLE][1])
 			{
 				if (!camtoggledelay)
 				{
@@ -2148,8 +2149,8 @@ boolean G_Responder(event_t *ev)
 					CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1);
 				}
 			}
-			if (ev->data1 == gamecontrolbis[gc_camtoggle][0]
-				|| ev->data1 == gamecontrolbis[gc_camtoggle][1])
+			if (ev->key == gamecontrolbis[GC_CAMTOGGLE][0]
+				|| ev->key == gamecontrolbis[GC_CAMTOGGLE][1])
 			{
 				if (!camtoggledelay2)
 				{
@@ -2185,8 +2186,20 @@ boolean G_Responder(event_t *ev)
 //
 boolean G_LuaResponder(event_t *ev)
 {
-	return (ev->type == ev_keydown && LUA_HookKey(ev->data1, HOOK(KeyDown))) ||
-		(ev->type == ev_keyup && LUA_HookKey(ev->data1, HOOK(KeyUp)));
+	boolean cancelled = false;
+
+	if (ev->type == ev_keydown)
+	{
+		cancelled = LUA_HookKey(ev, HOOK(KeyDown));
+		LUA_InvalidateUserdata(ev);
+	}
+	else if (ev->type == ev_keyup)
+	{
+		cancelled = LUA_HookKey(ev, HOOK(KeyUp));
+		LUA_InvalidateUserdata(ev);
+	}
+
+	return cancelled;
 }
 
 //
@@ -5311,4 +5324,3 @@ INT32 G_TicsToMilliseconds(tic_t tics)
 {
 	return (INT32)((tics%TICRATE) * (1000.00f/TICRATE));
 }
-
diff --git a/src/g_input.c b/src/g_input.c
index 2f7980c647d1eba7b794274200e9f9a11477c8b3..cd4536bbad289e9c239f6fbb736cc8c4cdd645ee 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -41,49 +41,49 @@ INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymo
 UINT8 gamekeydown[NUMINPUTS];
 
 // two key codes (or virtual key) per game control
-INT32 gamecontrol[num_gamecontrols][2];
-INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
-INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention
-INT32 gamecontrolbisdefault[num_gamecontrolschemes][num_gamecontrols][2];
+INT32 gamecontrol[NUM_GAMECONTROLS][2];
+INT32 gamecontrolbis[NUM_GAMECONTROLS][2]; // secondary splitscreen player
+INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2]; // default control storage, use 0 (gcs_custom) for memory retention
+INT32 gamecontrolbisdefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
 
 // lists of GC codes for selective operation
 const INT32 gcl_tutorial_check[num_gcl_tutorial_check] = {
-	gc_forward, gc_backward, gc_strafeleft, gc_straferight,
-	gc_turnleft, gc_turnright
+	GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
+	GC_TURNLEFT, GC_TURNRIGHT
 };
 
 const INT32 gcl_tutorial_used[num_gcl_tutorial_used] = {
-	gc_forward, gc_backward, gc_strafeleft, gc_straferight,
-	gc_turnleft, gc_turnright,
-	gc_jump, gc_spin
+	GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
+	GC_TURNLEFT, GC_TURNRIGHT,
+	GC_JUMP, GC_SPIN
 };
 
 const INT32 gcl_tutorial_full[num_gcl_tutorial_full] = {
-	gc_forward, gc_backward, gc_strafeleft, gc_straferight,
-	gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview,
-	gc_jump, gc_spin,
-	gc_fire, gc_firenormal
+	GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
+	GC_LOOKUP, GC_LOOKDOWN, GC_TURNLEFT, GC_TURNRIGHT, GC_CENTERVIEW,
+	GC_JUMP, GC_SPIN,
+	GC_FIRE, GC_FIRENORMAL
 };
 
 const INT32 gcl_movement[num_gcl_movement] = {
-	gc_forward, gc_backward, gc_strafeleft, gc_straferight
+	GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT
 };
 
 const INT32 gcl_camera[num_gcl_camera] = {
-	gc_turnleft, gc_turnright
+	GC_TURNLEFT, GC_TURNRIGHT
 };
 
 const INT32 gcl_movement_camera[num_gcl_movement_camera] = {
-	gc_forward, gc_backward, gc_strafeleft, gc_straferight,
-	gc_turnleft, gc_turnright
+	GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
+	GC_TURNLEFT, GC_TURNRIGHT
 };
 
-const INT32 gcl_jump[num_gcl_jump] = { gc_jump };
+const INT32 gcl_jump[num_gcl_jump] = { GC_JUMP };
 
-const INT32 gcl_spin[num_gcl_spin] = { gc_spin };
+const INT32 gcl_spin[num_gcl_spin] = { GC_SPIN };
 
 const INT32 gcl_jump_spin[num_gcl_jump_spin] = {
-	gc_jump, gc_spin
+	GC_JUMP, GC_SPIN
 };
 
 typedef struct
@@ -115,54 +115,54 @@ void G_MapEventsToControls(event_t *ev)
 	switch (ev->type)
 	{
 		case ev_keydown:
-			if (ev->data1 < NUMINPUTS)
-				gamekeydown[ev->data1] = 1;
+			if (ev->key < NUMINPUTS)
+				gamekeydown[ev->key] = 1;
 #ifdef PARANOIA
 			else
 			{
-				CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->data1);
+				CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->key);
 			}
 
 #endif
 			break;
 
 		case ev_keyup:
-			if (ev->data1 < NUMINPUTS)
-				gamekeydown[ev->data1] = 0;
+			if (ev->key < NUMINPUTS)
+				gamekeydown[ev->key] = 0;
 #ifdef PARANOIA
 			else
 			{
-				CONS_Debug(DBG_GAMELOGIC, "Bad upkey input %d\n",ev->data1);
+				CONS_Debug(DBG_GAMELOGIC, "Bad upkey input %d\n",ev->key);
 			}
 #endif
 			break;
 
 		case ev_mouse: // buttons are virtual keys
-			mouse.rdx = ev->data2;
-			mouse.rdy = ev->data3;
+			mouse.rdx = ev->x;
+			mouse.rdy = ev->y;
 			break;
 
 		case ev_joystick: // buttons are virtual keys
-			i = ev->data1;
+			i = ev->key;
 			if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
 				break;
-			if (ev->data2 != INT32_MAX) joyxmove[i] = ev->data2;
-			if (ev->data3 != INT32_MAX) joyymove[i] = ev->data3;
+			if (ev->x != INT32_MAX) joyxmove[i] = ev->x;
+			if (ev->y != INT32_MAX) joyymove[i] = ev->y;
 			break;
 
 		case ev_joystick2: // buttons are virtual keys
-			i = ev->data1;
+			i = ev->key;
 			if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
 				break;
-			if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2;
-			if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3;
+			if (ev->x != INT32_MAX) joy2xmove[i] = ev->x;
+			if (ev->y != INT32_MAX) joy2ymove[i] = ev->y;
 			break;
 
 		case ev_mouse2: // buttons are virtual keys
 			if (menuactive || CON_Ready() || chat_on)
 				break;
-			mouse2.rdx = ev->data2;
-			mouse2.rdy = ev->data3;
+			mouse2.rdx = ev->x;
+			mouse2.rdy = ev->y;
 			break;
 
 		default:
@@ -553,9 +553,9 @@ static keyname_t keynames[] =
 
 };
 
-static const char *gamecontrolname[num_gamecontrols] =
+static const char *gamecontrolname[NUM_GAMECONTROLS] =
 {
-	"nothing", // a key/button mapped to gc_null has no effect
+	"nothing", // a key/button mapped to GC_NULL has no effect
 	"forward",
 	"backward",
 	"strafeleft",
@@ -613,7 +613,7 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control)
 void G_ClearAllControlKeys(void)
 {
 	INT32 i;
-	for (i = 0; i < num_gamecontrols; i++)
+	for (i = 0; i < NUM_GAMECONTROLS; i++)
 	{
 		G_ClearControlKeys(gamecontrol, i);
 		G_ClearControlKeys(gamecontrolbis, i);
@@ -624,7 +624,7 @@ void G_ClearAllControlKeys(void)
 // Returns the name of a key (or virtual key for mouse and joy)
 // the input value being an keynum
 //
-const char *G_KeyNumToString(INT32 keynum)
+const char *G_KeyNumToName(INT32 keynum)
 {
 	static char keynamestr[8];
 
@@ -648,7 +648,7 @@ const char *G_KeyNumToString(INT32 keynum)
 	return keynamestr;
 }
 
-INT32 G_KeyStringToNum(const char *keystr)
+INT32 G_KeyNameToNum(const char *keystr)
 {
 	UINT32 j;
 
@@ -676,92 +676,92 @@ void G_DefineDefaultControls(void)
 	INT32 i;
 
 	// FPS game controls (WASD)
-	gamecontroldefault[gcs_fps][gc_forward    ][0] = 'w';
-	gamecontroldefault[gcs_fps][gc_backward   ][0] = 's';
-	gamecontroldefault[gcs_fps][gc_strafeleft ][0] = 'a';
-	gamecontroldefault[gcs_fps][gc_straferight][0] = 'd';
-	gamecontroldefault[gcs_fps][gc_lookup     ][0] = KEY_UPARROW;
-	gamecontroldefault[gcs_fps][gc_lookdown   ][0] = KEY_DOWNARROW;
-	gamecontroldefault[gcs_fps][gc_turnleft   ][0] = KEY_LEFTARROW;
-	gamecontroldefault[gcs_fps][gc_turnright  ][0] = KEY_RIGHTARROW;
-	gamecontroldefault[gcs_fps][gc_centerview ][0] = KEY_END;
-	gamecontroldefault[gcs_fps][gc_jump       ][0] = KEY_SPACE;
-	gamecontroldefault[gcs_fps][gc_spin       ][0] = KEY_LSHIFT;
-	gamecontroldefault[gcs_fps][gc_fire       ][0] = KEY_RCTRL;
-	gamecontroldefault[gcs_fps][gc_fire       ][1] = KEY_MOUSE1+0;
-	gamecontroldefault[gcs_fps][gc_firenormal ][0] = 'c';
+	gamecontroldefault[gcs_fps][GC_FORWARD    ][0] = 'w';
+	gamecontroldefault[gcs_fps][GC_BACKWARD   ][0] = 's';
+	gamecontroldefault[gcs_fps][GC_STRAFELEFT ][0] = 'a';
+	gamecontroldefault[gcs_fps][GC_STRAFERIGHT][0] = 'd';
+	gamecontroldefault[gcs_fps][GC_LOOKUP     ][0] = KEY_UPARROW;
+	gamecontroldefault[gcs_fps][GC_LOOKDOWN   ][0] = KEY_DOWNARROW;
+	gamecontroldefault[gcs_fps][GC_TURNLEFT   ][0] = KEY_LEFTARROW;
+	gamecontroldefault[gcs_fps][GC_TURNRIGHT  ][0] = KEY_RIGHTARROW;
+	gamecontroldefault[gcs_fps][GC_CENTERVIEW ][0] = KEY_END;
+	gamecontroldefault[gcs_fps][GC_JUMP       ][0] = KEY_SPACE;
+	gamecontroldefault[gcs_fps][GC_SPIN       ][0] = KEY_LSHIFT;
+	gamecontroldefault[gcs_fps][GC_FIRE       ][0] = KEY_RCTRL;
+	gamecontroldefault[gcs_fps][GC_FIRE       ][1] = KEY_MOUSE1+0;
+	gamecontroldefault[gcs_fps][GC_FIRENORMAL ][0] = 'c';
 
 	// Platform game controls (arrow keys)
-	gamecontroldefault[gcs_platform][gc_forward    ][0] = KEY_UPARROW;
-	gamecontroldefault[gcs_platform][gc_backward   ][0] = KEY_DOWNARROW;
-	gamecontroldefault[gcs_platform][gc_strafeleft ][0] = 'a';
-	gamecontroldefault[gcs_platform][gc_straferight][0] = 'd';
-	gamecontroldefault[gcs_platform][gc_lookup     ][0] = KEY_PGUP;
-	gamecontroldefault[gcs_platform][gc_lookdown   ][0] = KEY_PGDN;
-	gamecontroldefault[gcs_platform][gc_turnleft   ][0] = KEY_LEFTARROW;
-	gamecontroldefault[gcs_platform][gc_turnright  ][0] = KEY_RIGHTARROW;
-	gamecontroldefault[gcs_platform][gc_centerview ][0] = KEY_END;
-	gamecontroldefault[gcs_platform][gc_jump       ][0] = KEY_SPACE;
-	gamecontroldefault[gcs_platform][gc_spin       ][0] = KEY_LSHIFT;
-	gamecontroldefault[gcs_platform][gc_fire       ][0] = 's';
-	gamecontroldefault[gcs_platform][gc_fire       ][1] = KEY_MOUSE1+0;
-	gamecontroldefault[gcs_platform][gc_firenormal ][0] = 'w';
+	gamecontroldefault[gcs_platform][GC_FORWARD    ][0] = KEY_UPARROW;
+	gamecontroldefault[gcs_platform][GC_BACKWARD   ][0] = KEY_DOWNARROW;
+	gamecontroldefault[gcs_platform][GC_STRAFELEFT ][0] = 'a';
+	gamecontroldefault[gcs_platform][GC_STRAFERIGHT][0] = 'd';
+	gamecontroldefault[gcs_platform][GC_LOOKUP     ][0] = KEY_PGUP;
+	gamecontroldefault[gcs_platform][GC_LOOKDOWN   ][0] = KEY_PGDN;
+	gamecontroldefault[gcs_platform][GC_TURNLEFT   ][0] = KEY_LEFTARROW;
+	gamecontroldefault[gcs_platform][GC_TURNRIGHT  ][0] = KEY_RIGHTARROW;
+	gamecontroldefault[gcs_platform][GC_CENTERVIEW ][0] = KEY_END;
+	gamecontroldefault[gcs_platform][GC_JUMP       ][0] = KEY_SPACE;
+	gamecontroldefault[gcs_platform][GC_SPIN       ][0] = KEY_LSHIFT;
+	gamecontroldefault[gcs_platform][GC_FIRE       ][0] = 's';
+	gamecontroldefault[gcs_platform][GC_FIRE       ][1] = KEY_MOUSE1+0;
+	gamecontroldefault[gcs_platform][GC_FIRENORMAL ][0] = 'w';
 
 	for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
 	{
-		gamecontroldefault[i][gc_weaponnext ][0] = KEY_MOUSEWHEELUP+0;
-		gamecontroldefault[i][gc_weaponprev ][0] = KEY_MOUSEWHEELDOWN+0;
-		gamecontroldefault[i][gc_wepslot1   ][0] = '1';
-		gamecontroldefault[i][gc_wepslot2   ][0] = '2';
-		gamecontroldefault[i][gc_wepslot3   ][0] = '3';
-		gamecontroldefault[i][gc_wepslot4   ][0] = '4';
-		gamecontroldefault[i][gc_wepslot5   ][0] = '5';
-		gamecontroldefault[i][gc_wepslot6   ][0] = '6';
-		gamecontroldefault[i][gc_wepslot7   ][0] = '7';
-		gamecontroldefault[i][gc_wepslot8   ][0] = '8';
-		gamecontroldefault[i][gc_wepslot9   ][0] = '9';
-		gamecontroldefault[i][gc_wepslot10  ][0] = '0';
-		gamecontroldefault[i][gc_tossflag   ][0] = '\'';
-		gamecontroldefault[i][gc_camtoggle  ][0] = 'v';
-		gamecontroldefault[i][gc_camreset   ][0] = 'r';
-		gamecontroldefault[i][gc_talkkey    ][0] = 't';
-		gamecontroldefault[i][gc_teamkey    ][0] = 'y';
-		gamecontroldefault[i][gc_scores     ][0] = KEY_TAB;
-		gamecontroldefault[i][gc_console    ][0] = KEY_CONSOLE;
-		gamecontroldefault[i][gc_pause      ][0] = 'p';
-		gamecontroldefault[i][gc_screenshot ][0] = KEY_F8;
-		gamecontroldefault[i][gc_recordgif  ][0] = KEY_F9;
-		gamecontroldefault[i][gc_viewpoint  ][0] = KEY_F12;
+		gamecontroldefault[i][GC_WEAPONNEXT ][0] = KEY_MOUSEWHEELUP+0;
+		gamecontroldefault[i][GC_WEAPONPREV ][0] = KEY_MOUSEWHEELDOWN+0;
+		gamecontroldefault[i][GC_WEPSLOT1   ][0] = '1';
+		gamecontroldefault[i][GC_WEPSLOT2   ][0] = '2';
+		gamecontroldefault[i][GC_WEPSLOT3   ][0] = '3';
+		gamecontroldefault[i][GC_WEPSLOT4   ][0] = '4';
+		gamecontroldefault[i][GC_WEPSLOT5   ][0] = '5';
+		gamecontroldefault[i][GC_WEPSLOT6   ][0] = '6';
+		gamecontroldefault[i][GC_WEPSLOT7   ][0] = '7';
+		gamecontroldefault[i][GC_WEPSLOT8   ][0] = '8';
+		gamecontroldefault[i][GC_WEPSLOT9   ][0] = '9';
+		gamecontroldefault[i][GC_WEPSLOT10  ][0] = '0';
+		gamecontroldefault[i][GC_TOSSFLAG   ][0] = '\'';
+		gamecontroldefault[i][GC_CAMTOGGLE  ][0] = 'v';
+		gamecontroldefault[i][GC_CAMRESET   ][0] = 'r';
+		gamecontroldefault[i][GC_TALKKEY    ][0] = 't';
+		gamecontroldefault[i][GC_TEAMKEY    ][0] = 'y';
+		gamecontroldefault[i][GC_SCORES     ][0] = KEY_TAB;
+		gamecontroldefault[i][GC_CONSOLE    ][0] = KEY_CONSOLE;
+		gamecontroldefault[i][GC_PAUSE      ][0] = 'p';
+		gamecontroldefault[i][GC_SCREENSHOT ][0] = KEY_F8;
+		gamecontroldefault[i][GC_RECORDGIF  ][0] = KEY_F9;
+		gamecontroldefault[i][GC_VIEWPOINT  ][0] = KEY_F12;
 
 		// Gamepad controls -- same for both schemes
-		gamecontroldefault[i][gc_weaponnext ][1] = KEY_JOY1+1; // B
-		gamecontroldefault[i][gc_weaponprev ][1] = KEY_JOY1+2; // X
-		gamecontroldefault[i][gc_tossflag   ][1] = KEY_JOY1+0; // A
-		gamecontroldefault[i][gc_spin       ][1] = KEY_JOY1+4; // LB
-		gamecontroldefault[i][gc_camtoggle  ][1] = KEY_HAT1+0; // D-Pad Up
-		gamecontroldefault[i][gc_camreset   ][1] = KEY_JOY1+3; // Y
-		gamecontroldefault[i][gc_centerview ][1] = KEY_JOY1+9; // Right Stick
-		gamecontroldefault[i][gc_talkkey    ][1] = KEY_HAT1+2; // D-Pad Left
-		gamecontroldefault[i][gc_scores     ][1] = KEY_HAT1+3; // D-Pad Right
-		gamecontroldefault[i][gc_jump       ][1] = KEY_JOY1+5; // RB
-		gamecontroldefault[i][gc_pause      ][1] = KEY_JOY1+6; // Back
-		gamecontroldefault[i][gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down
-		gamecontroldefault[i][gc_systemmenu ][0] = KEY_JOY1+7; // Start
+		gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_JOY1+1; // B
+		gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_JOY1+2; // X
+		gamecontroldefault[i][GC_TOSSFLAG   ][1] = KEY_JOY1+0; // A
+		gamecontroldefault[i][GC_SPIN       ][1] = KEY_JOY1+4; // LB
+		gamecontroldefault[i][GC_CAMTOGGLE  ][1] = KEY_HAT1+0; // D-Pad Up
+		gamecontroldefault[i][GC_CAMRESET   ][1] = KEY_JOY1+3; // Y
+		gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+9; // Right Stick
+		gamecontroldefault[i][GC_TALKKEY    ][1] = KEY_HAT1+2; // D-Pad Left
+		gamecontroldefault[i][GC_SCORES     ][1] = KEY_HAT1+3; // D-Pad Right
+		gamecontroldefault[i][GC_JUMP       ][1] = KEY_JOY1+5; // RB
+		gamecontroldefault[i][GC_PAUSE      ][1] = KEY_JOY1+6; // Back
+		gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_HAT1+1; // D-Pad Down
+		gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start
 
 		// Second player controls only have joypad defaults
-		gamecontrolbisdefault[i][gc_weaponnext][0] = KEY_2JOY1+1; // B
-		gamecontrolbisdefault[i][gc_weaponprev][0] = KEY_2JOY1+2; // X
-		gamecontrolbisdefault[i][gc_tossflag  ][0] = KEY_2JOY1+0; // A
-		gamecontrolbisdefault[i][gc_spin      ][0] = KEY_2JOY1+4; // LB
-		gamecontrolbisdefault[i][gc_camreset  ][0] = KEY_2JOY1+3; // Y
-		gamecontrolbisdefault[i][gc_centerview][0] = KEY_2JOY1+9; // Right Stick
-		gamecontrolbisdefault[i][gc_jump      ][0] = KEY_2JOY1+5; // RB
-		//gamecontrolbisdefault[i][gc_pause     ][0] = KEY_2JOY1+6; // Back
-		//gamecontrolbisdefault[i][gc_systemmenu][0] = KEY_2JOY1+7; // Start
-		gamecontrolbisdefault[i][gc_camtoggle ][0] = KEY_2HAT1+0; // D-Pad Up
-		gamecontrolbisdefault[i][gc_screenshot][0] = KEY_2HAT1+1; // D-Pad Down
-		//gamecontrolbisdefault[i][gc_talkkey   ][0] = KEY_2HAT1+2; // D-Pad Left
-		//gamecontrolbisdefault[i][gc_scores    ][0] = KEY_2HAT1+3; // D-Pad Right
+		gamecontrolbisdefault[i][GC_WEAPONNEXT][0] = KEY_2JOY1+1; // B
+		gamecontrolbisdefault[i][GC_WEAPONPREV][0] = KEY_2JOY1+2; // X
+		gamecontrolbisdefault[i][GC_TOSSFLAG  ][0] = KEY_2JOY1+0; // A
+		gamecontrolbisdefault[i][GC_SPIN      ][0] = KEY_2JOY1+4; // LB
+		gamecontrolbisdefault[i][GC_CAMRESET  ][0] = KEY_2JOY1+3; // Y
+		gamecontrolbisdefault[i][GC_CENTERVIEW][0] = KEY_2JOY1+9; // Right Stick
+		gamecontrolbisdefault[i][GC_JUMP      ][0] = KEY_2JOY1+5; // RB
+		//gamecontrolbisdefault[i][GC_PAUSE     ][0] = KEY_2JOY1+6; // Back
+		//gamecontrolbisdefault[i][GC_SYSTEMMENU][0] = KEY_2JOY1+7; // Start
+		gamecontrolbisdefault[i][GC_CAMTOGGLE ][0] = KEY_2HAT1+0; // D-Pad Up
+		gamecontrolbisdefault[i][GC_SCREENSHOT][0] = KEY_2HAT1+1; // D-Pad Down
+		//gamecontrolbisdefault[i][GC_TALKKEY   ][0] = KEY_2HAT1+2; // D-Pad Left
+		//gamecontrolbisdefault[i][GC_SCORES    ][0] = KEY_2HAT1+3; // D-Pad Right
 	}
 }
 
@@ -773,7 +773,7 @@ INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gc
 	for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
 	{
 		skipscheme = false;
-		for (j = 0; j < (gclist && gclen ? gclen : num_gamecontrols); j++)
+		for (j = 0; j < (gclist && gclen ? gclen : NUM_GAMECONTROLS); j++)
 		{
 			gc = (gclist && gclen) ? gclist[j] : j;
 			if (((fromcontrols[gc][0] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][0] : true) &&
@@ -796,7 +796,7 @@ void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const I
 {
 	INT32 i, gc;
 
-	for (i = 0; i < (gclist && gclen ? gclen : num_gamecontrols); i++)
+	for (i = 0; i < (gclist && gclen ? gclen : NUM_GAMECONTROLS); i++)
 	{
 		gc = (gclist && gclen) ? gclist[i] : i;
 		setupcontrols[gc][0] = fromcontrols[gc][0];
@@ -808,24 +808,24 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis
 {
 	INT32 i;
 
-	for (i = 1; i < num_gamecontrols; i++)
+	for (i = 1; i < NUM_GAMECONTROLS; i++)
 	{
 		fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i],
-			G_KeyNumToString(fromcontrols[i][0]));
+			G_KeyNumToName(fromcontrols[i][0]));
 
 		if (fromcontrols[i][1])
-			fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrols[i][1]));
+			fprintf(f, " \"%s\"\n", G_KeyNumToName(fromcontrols[i][1]));
 		else
 			fprintf(f, "\n");
 	}
 
-	for (i = 1; i < num_gamecontrols; i++)
+	for (i = 1; i < NUM_GAMECONTROLS; i++)
 	{
 		fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i],
-			G_KeyNumToString(fromcontrolsbis[i][0]));
+			G_KeyNumToName(fromcontrolsbis[i][0]));
 
 		if (fromcontrolsbis[i][1])
-			fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrolsbis[i][1]));
+			fprintf(f, " \"%s\"\n", G_KeyNumToName(fromcontrolsbis[i][1]));
 		else
 			fprintf(f, "\n");
 	}
@@ -833,11 +833,11 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis
 
 INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify)
 {
-	INT32 result = gc_null;
+	INT32 result = GC_NULL;
 	if (cv_controlperkey.value == 1)
 	{
 		INT32 i;
-		for (i = 0; i < num_gamecontrols; i++)
+		for (i = 0; i < NUM_GAMECONTROLS; i++)
 		{
 			if (gamecontrol[i][0] == keynum)
 			{
@@ -883,11 +883,11 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT
 		return -1; // skip setting control
 
 	if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22
-		numctrl == gc_weaponnext || numctrl == gc_weaponprev || numctrl == gc_tossflag ||
-		numctrl == gc_spin || numctrl == gc_camreset || numctrl == gc_jump ||
-		numctrl == gc_pause || numctrl == gc_systemmenu || numctrl == gc_camtoggle ||
-		numctrl == gc_screenshot || numctrl == gc_talkkey || numctrl == gc_scores ||
-		numctrl == gc_centerview
+		numctrl == GC_WEAPONNEXT || numctrl == GC_WEAPONPREV || numctrl == GC_TOSSFLAG ||
+		numctrl == GC_SPIN || numctrl == GC_CAMRESET || numctrl == GC_JUMP ||
+		numctrl == GC_PAUSE || numctrl == GC_SYSTEMMENU || numctrl == GC_CAMTOGGLE ||
+		numctrl == GC_SCREENSHOT || numctrl == GC_TALKKEY || numctrl == GC_SCORES ||
+		numctrl == GC_CENTERVIEW
 	))
 	{
 		INT32 keynum = 0, existingctrl = 0;
@@ -895,7 +895,7 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT
 		boolean defaultoverride = false;
 
 		// get the default gamecontrol
-		if (player == 0 && numctrl == gc_systemmenu)
+		if (player == 0 && numctrl == GC_SYSTEMMENU)
 			defaultkey = gamecontrol[numctrl][0];
 		else
 			defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]);
@@ -993,16 +993,16 @@ static void setcontrol(INT32 (*gc)[2])
 	// Update me for 2.3
 	namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin";
 
-	for (numctrl = 0; numctrl < num_gamecontrols && stricmp(namectrl, gamecontrolname[numctrl]);
+	for (numctrl = 0; numctrl < NUM_GAMECONTROLS && stricmp(namectrl, gamecontrolname[numctrl]);
 		numctrl++)
 		;
-	if (numctrl == num_gamecontrols)
+	if (numctrl == NUM_GAMECONTROLS)
 	{
 		CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl);
 		return;
 	}
-	keynum1 = G_KeyStringToNum(COM_Argv(2));
-	keynum2 = G_KeyStringToNum(COM_Argv(3));
+	keynum1 = G_KeyNameToNum(COM_Argv(2));
+	keynum2 = G_KeyNameToNum(COM_Argv(3));
 	keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride);
 
 	if (keynum >= 0)
diff --git a/src/g_input.h b/src/g_input.h
index ffd0cb560b5f0921fb3595c970f93b7e5d1ff5f0..2e9f53dcf4e4ff57aa9deccbffc7537ebaa6c261 100644
--- a/src/g_input.h
+++ b/src/g_input.h
@@ -58,49 +58,49 @@ typedef enum
 
 typedef enum
 {
-	gc_null = 0, // a key/button mapped to gc_null has no effect
-	gc_forward,
-	gc_backward,
-	gc_strafeleft,
-	gc_straferight,
-	gc_turnleft,
-	gc_turnright,
-	gc_weaponnext,
-	gc_weaponprev,
-	gc_wepslot1,
-	gc_wepslot2,
-	gc_wepslot3,
-	gc_wepslot4,
-	gc_wepslot5,
-	gc_wepslot6,
-	gc_wepslot7,
-	gc_wepslot8,
-	gc_wepslot9,
-	gc_wepslot10,
-	gc_fire,
-	gc_firenormal,
-	gc_tossflag,
-	gc_spin,
-	gc_camtoggle,
-	gc_camreset,
-	gc_lookup,
-	gc_lookdown,
-	gc_centerview,
-	gc_mouseaiming, // mouse aiming is momentary (toggleable in the menu)
-	gc_talkkey,
-	gc_teamkey,
-	gc_scores,
-	gc_jump,
-	gc_console,
-	gc_pause,
-	gc_systemmenu,
-	gc_screenshot,
-	gc_recordgif,
-	gc_viewpoint,
-	gc_custom1, // Lua scriptable
-	gc_custom2, // Lua scriptable
-	gc_custom3, // Lua scriptable
-	num_gamecontrols
+	GC_NULL = 0, // a key/button mapped to GC_NULL has no effect
+	GC_FORWARD,
+	GC_BACKWARD,
+	GC_STRAFELEFT,
+	GC_STRAFERIGHT,
+	GC_TURNLEFT,
+	GC_TURNRIGHT,
+	GC_WEAPONNEXT,
+	GC_WEAPONPREV,
+	GC_WEPSLOT1,
+	GC_WEPSLOT2,
+	GC_WEPSLOT3,
+	GC_WEPSLOT4,
+	GC_WEPSLOT5,
+	GC_WEPSLOT6,
+	GC_WEPSLOT7,
+	GC_WEPSLOT8,
+	GC_WEPSLOT9,
+	GC_WEPSLOT10,
+	GC_FIRE,
+	GC_FIRENORMAL,
+	GC_TOSSFLAG,
+	GC_SPIN,
+	GC_CAMTOGGLE,
+	GC_CAMRESET,
+	GC_LOOKUP,
+	GC_LOOKDOWN,
+	GC_CENTERVIEW,
+	GC_MOUSEAIMING, // mouse aiming is momentary (toggleable in the menu)
+	GC_TALKKEY,
+	GC_TEAMKEY,
+	GC_SCORES,
+	GC_JUMP,
+	GC_CONSOLE,
+	GC_PAUSE,
+	GC_SYSTEMMENU,
+	GC_SCREENSHOT,
+	GC_RECORDGIF,
+	GC_VIEWPOINT,
+	GC_CUSTOM1, // Lua scriptable
+	GC_CUSTOM2, // Lua scriptable
+	GC_CUSTOM3, // Lua scriptable
+	NUM_GAMECONTROLS
 } gamecontrols_e;
 
 typedef enum
@@ -146,10 +146,10 @@ extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET],
 extern UINT8 gamekeydown[NUMINPUTS];
 
 // two key codes (or virtual key) per game control
-extern INT32 gamecontrol[num_gamecontrols][2];
-extern INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
-extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention
-extern INT32 gamecontrolbisdefault[num_gamecontrolschemes][num_gamecontrols][2];
+extern INT32 gamecontrol[NUM_GAMECONTROLS][2];
+extern INT32 gamecontrolbis[NUM_GAMECONTROLS][2]; // secondary splitscreen player
+extern INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2]; // default control storage, use 0 (gcs_custom) for memory retention
+extern INT32 gamecontrolbisdefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
 #define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]])
 #define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]])
 #define PLAYERINPUTDOWN(p, gc) ((p) == 2 ? PLAYER2INPUTDOWN(gc) : PLAYER1INPUTDOWN(gc))
@@ -181,8 +181,8 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin];
 void G_MapEventsToControls(event_t *ev);
 
 // returns the name of a key
-const char *G_KeyNumToString(INT32 keynum);
-INT32 G_KeyStringToNum(const char *keystr);
+const char *G_KeyNumToName(INT32 keynum);
+INT32 G_KeyNameToNum(const char *keystr);
 
 // detach any keys associated to the given game control
 void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control);
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index e0eaf8fb178f1252b60b93e329d2f14d05858e53..d8891d508269a61af5732649906ada32f7ae769f 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -936,7 +936,7 @@ void HU_Ticker(void)
 	hu_tick++;
 	hu_tick &= 7; // currently only to blink chat input cursor
 
-	if (PLAYER1INPUTDOWN(gc_scores))
+	if (PLAYER1INPUTDOWN(GC_SCORES))
 		hu_showscores = !chat_on;
 	else
 		hu_showscores = false;
@@ -1111,26 +1111,26 @@ boolean HU_Responder(event_t *ev)
 	// (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...)
 	// (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...)
 
-	if (ev->data1 >= KEY_MOUSE1)
+	if (ev->key >= KEY_MOUSE1)
 	{
 		INT32 i;
-		for (i = 0; i < num_gamecontrols; i++)
+		for (i = 0; i < NUM_GAMECONTROLS; i++)
 		{
-			if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1)
+			if (gamecontrol[i][0] == ev->key || gamecontrol[i][1] == ev->key)
 				break;
 		}
 
-		if (i == num_gamecontrols)
+		if (i == NUM_GAMECONTROLS)
 			return false;
 	}*/	//We don't actually care about that unless we get splitscreen netgames. :V
 
 #ifndef NONET
-	c = (INT32)ev->data1;
+	c = (INT32)ev->key;
 
 	if (!chat_on)
 	{
 		// enter chat mode
-		if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1])
+		if ((ev->key == gamecontrol[GC_TALKKEY][0] || ev->key == gamecontrol[GC_TALKKEY][1])
 			&& netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise.
 		{
 			chat_on = true;
@@ -1140,7 +1140,7 @@ boolean HU_Responder(event_t *ev)
 			typelines = 1;
 			return true;
 		}
-		if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1])
+		if ((ev->key == gamecontrol[GC_TEAMKEY][0] || ev->key == gamecontrol[GC_TEAMKEY][1])
 			&& netgame && !OLD_MUTE)
 		{
 			chat_on = true;
@@ -1157,12 +1157,12 @@ boolean HU_Responder(event_t *ev)
 		// Ignore modifier keys
 		// Note that we do this here so users can still set
 		// their chat keys to one of these, if they so desire.
-		if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT
-		 || ev->data1 == KEY_LCTRL || ev->data1 == KEY_RCTRL
-		 || ev->data1 == KEY_LALT || ev->data1 == KEY_RALT)
+		if (ev->key == KEY_LSHIFT || ev->key == KEY_RSHIFT
+		 || ev->key == KEY_LCTRL || ev->key == KEY_RCTRL
+		 || ev->key == KEY_LALT || ev->key == KEY_RALT)
 			return true;
 
-		c = (INT32)ev->data1;
+		c = (INT32)ev->key;
 
 		// I know this looks very messy but this works. If it ain't broke, don't fix it!
 		// shift LETTERS to uppercase if we have capslock or are holding shift
@@ -1234,8 +1234,8 @@ boolean HU_Responder(event_t *ev)
 			I_UpdateMouseGrab();
 		}
 		else if (c == KEY_ESCAPE
-			|| ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1]
-			|| c == gamecontrol[gc_teamkey][0] || c == gamecontrol[gc_teamkey][1])
+			|| ((c == gamecontrol[GC_TALKKEY][0] || c == gamecontrol[GC_TALKKEY][1]
+			|| c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1])
 			&& c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle.
 		{
 			chat_on = false;
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 223b83c61f7d9c35a451a3ea217344a341fe7126..55f3bb81763d43d0d283548493af7b67be06dcd4 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -13,6 +13,7 @@
 #include "r_defs.h"
 #include "d_player.h"
 #include "s_sound.h"
+#include "d_event.h"
 
 /*
 Do you know what an 'X Macro' is? Such a macro is called over each element of
@@ -107,7 +108,7 @@ void LUA_HookInt(INT32 integer, int hook);
 void LUA_HookBool(boolean value, int hook);
 int  LUA_HookPlayer(player_t *, int hook);
 int  LUA_HookTiccmd(player_t *, ticcmd_t *, int hook);
-int  LUA_HookKey(INT32 keycode, int hook); // Hooks for key events
+int  LUA_HookKey(event_t *event, int hook); // Hooks for key events
 
 void LUA_HookThinkFrame(void);
 int  LUA_HookMobjLineCollide(mobj_t *, line_t *);
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index d1b0d3bdd21b26184f49079c622ae16ec23f5f87..1e04621264097ff10bbc9467f501d712bc941067 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -588,12 +588,12 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type)
 	return hook.status;
 }
 
-int LUA_HookKey(INT32 keycode, int hook_type)
+int LUA_HookKey(event_t *event, int hook_type)
 {
 	Hook_State hook;
 	if (prepare_hook(&hook, false, hook_type))
 	{
-		lua_pushinteger(gL, keycode);
+		LUA_PushUserdata(gL, event, META_KEYEVENT);
 		call_hooks(&hook, 1, 1, res_true);
 	}
 	return hook.status;
diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c
index 71eb1033f7fa8467f54fa9d936665d192051dd8b..661d9364166f4e2eec28d281dd0711dfbd45480a 100644
--- a/src/lua_inputlib.c
+++ b/src/lua_inputlib.c
@@ -19,6 +19,8 @@
 #include "lua_script.h"
 #include "lua_libs.h"
 
+boolean mousegrabbedbylua = true;
+
 ///////////////
 // FUNCTIONS //
 ///////////////
@@ -26,8 +28,8 @@
 static int lib_gameControlDown(lua_State *L)
 {
 	int i = luaL_checkinteger(L, 1);
-	if (i < 0 || i >= num_gamecontrols)
-		return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
+	if (i < 0 || i >= NUM_GAMECONTROLS)
+		return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
 	lua_pushinteger(L, PLAYER1INPUTDOWN(i));
 	return 1;
 }
@@ -35,8 +37,8 @@ static int lib_gameControlDown(lua_State *L)
 static int lib_gameControl2Down(lua_State *L)
 {
 	int i = luaL_checkinteger(L, 1);
-	if (i < 0 || i >= num_gamecontrols)
-		return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
+	if (i < 0 || i >= NUM_GAMECONTROLS)
+		return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
 	lua_pushinteger(L, PLAYER2INPUTDOWN(i));
 	return 1;
 }
@@ -44,8 +46,8 @@ static int lib_gameControl2Down(lua_State *L)
 static int lib_gameControlToKeyNum(lua_State *L)
 {
 	int i = luaL_checkinteger(L, 1);
-	if (i < 0 || i >= num_gamecontrols)
-		return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
+	if (i < 0 || i >= NUM_GAMECONTROLS)
+		return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
 	lua_pushinteger(L, gamecontrol[i][0]);
 	lua_pushinteger(L, gamecontrol[i][1]);
 	return 2;
@@ -54,8 +56,8 @@ static int lib_gameControlToKeyNum(lua_State *L)
 static int lib_gameControl2ToKeyNum(lua_State *L)
 {
 	int i = luaL_checkinteger(L, 1);
-	if (i < 0 || i >= num_gamecontrols)
-		return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1);
+	if (i < 0 || i >= NUM_GAMECONTROLS)
+		return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
 	lua_pushinteger(L, gamecontrolbis[i][0]);
 	lua_pushinteger(L, gamecontrolbis[i][1]);
 	return 2;
@@ -75,17 +77,17 @@ static int lib_joy2Axis(lua_State *L)
 	return 1;
 }
 
-static int lib_keyNumToString(lua_State *L)
+static int lib_keyNumToName(lua_State *L)
 {
 	int i = luaL_checkinteger(L, 1);
-	lua_pushstring(L, G_KeyNumToString(i));
+	lua_pushstring(L, G_KeyNumToName(i));
 	return 1;
 }
 
-static int lib_keyStringToNum(lua_State *L)
+static int lib_keyNameToNum(lua_State *L)
 {
 	const char *str = luaL_checkstring(L, 1);
-	lua_pushinteger(L, G_KeyStringToNum(str));
+	lua_pushinteger(L, G_KeyNameToNum(str));
 	return 1;
 }
 
@@ -106,14 +108,14 @@ static int lib_shiftKeyNum(lua_State *L)
 
 static int lib_getMouseGrab(lua_State *L)
 {
-	lua_pushboolean(L, I_GetMouseGrab());
+	lua_pushboolean(L, mousegrabbedbylua);
 	return 1;
 }
 
 static int lib_setMouseGrab(lua_State *L)
 {
-	boolean grab = luaL_checkboolean(L, 1);
-	I_SetMouseGrab(grab);
+	mousegrabbedbylua = luaL_checkboolean(L, 1);
+	I_UpdateMouseGrab();
 	return 0;
 }
 
@@ -127,19 +129,19 @@ static int lib_getCursorPosition(lua_State *L)
 }
 
 static luaL_Reg lib[] = {
-	{"G_GameControlDown", lib_gameControlDown},
-	{"G_GameControl2Down", lib_gameControl2Down},
-	{"G_GameControlToKeyNum", lib_gameControlToKeyNum},
-	{"G_GameControl2ToKeyNum", lib_gameControl2ToKeyNum},
-	{"G_JoyAxis", lib_joyAxis},
-	{"G_Joy2Axis", lib_joy2Axis},
-	{"G_KeyNumToString", lib_keyNumToString},
-	{"G_KeyStringToNum", lib_keyStringToNum},
-	{"HU_KeyNumPrintable", lib_keyNumPrintable},
-	{"HU_ShiftKeyNum", lib_shiftKeyNum},
-	{"I_GetMouseGrab", lib_getMouseGrab},
-	{"I_SetMouseGrab", lib_setMouseGrab},
-	{"I_GetCursorPosition", lib_getCursorPosition},
+	{"gameControlDown", lib_gameControlDown},
+	{"gameControl2Down", lib_gameControl2Down},
+	{"gameControlToKeyNum", lib_gameControlToKeyNum},
+	{"gameControl2ToKeyNum", lib_gameControl2ToKeyNum},
+	{"joyAxis", lib_joyAxis},
+	{"joy2Axis", lib_joy2Axis},
+	{"keyNumToName", lib_keyNumToName},
+	{"keyNameToNum", lib_keyNameToNum},
+	{"keyNumPrintable", lib_keyNumPrintable},
+	{"shiftKeyNum", lib_shiftKeyNum},
+	{"getMouseGrab", lib_getMouseGrab},
+	{"setMouseGrab", lib_setMouseGrab},
+	{"getCursorPosition", lib_getCursorPosition},
 	{NULL, NULL}
 };
 
@@ -172,6 +174,29 @@ static int lib_lenGameKeyDown(lua_State *L)
 	return 1;
 }
 
+///////////////
+// KEY EVENT //
+///////////////
+
+static int keyevent_get(lua_State *L)
+{
+	event_t *event = *((event_t **)luaL_checkudata(L, 1, META_KEYEVENT));
+	const char *field = luaL_checkstring(L, 2);
+
+	I_Assert(event != NULL);
+
+	if (fastcmp(field,"name"))
+		lua_pushstring(L, G_KeyNumToName(event->key));
+	else if (fastcmp(field,"num"))
+		lua_pushinteger(L, event->key);
+	else if (fastcmp(field,"repeated"))
+		lua_pushboolean(L, event->repeated);
+	else
+		return luaL_error(L, "keyevent_t has no field named %s", field);
+
+	return 1;
+}
+
 ///////////
 // MOUSE //
 ///////////
@@ -227,6 +252,11 @@ int LUA_InputLib(lua_State *L)
 		lua_setmetatable(L, -2);
 	lua_setglobal(L, "gamekeydown");
 
+	luaL_newmetatable(L, META_KEYEVENT);
+		lua_pushcfunction(L, keyevent_get);
+		lua_setfield(L, -2, "__index");
+	lua_pop(L, 1);
+
 	luaL_newmetatable(L, META_MOUSE);
 		lua_pushcfunction(L, mouse_get);
 		lua_setfield(L, -2, "__index");
@@ -235,8 +265,6 @@ int LUA_InputLib(lua_State *L)
 		lua_setfield(L, -2, "__len");
 	lua_pop(L, 1);
 
-	// Set global functions
-	lua_pushvalue(L, LUA_GLOBALSINDEX);
-	luaL_register(L, NULL, lib);
+	luaL_register(L, "input", lib);
 	return 0;
 }
diff --git a/src/lua_libs.h b/src/lua_libs.h
index 668eb99b001f4cb0607351969028392ee2e9cded..8903834e861c32c72dc9eaf2f22c864cefc218a7 100644
--- a/src/lua_libs.h
+++ b/src/lua_libs.h
@@ -12,6 +12,8 @@
 
 extern lua_State *gL;
 
+extern boolean mousegrabbedbylua;
+
 #define MUTABLE_TAGS
 
 #define LREG_VALID "VALID_USERDATA"
@@ -88,6 +90,7 @@ extern lua_State *gL;
 
 #define META_LUABANKS "LUABANKS[]*"
 
+#define META_KEYEVENT "KEYEVENT_T*"
 #define META_MOUSE "MOUSE_T*"
 
 boolean luaL_checkboolean(lua_State *L, int narg);
diff --git a/src/m_cheat.c b/src/m_cheat.c
index c958bb4a4de31450276067e730c8c77442b0c800..ef896c9911975550905069813394f7c4a4e654d1 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -203,11 +203,11 @@ boolean cht_Responder(event_t *ev)
 	if (ev->type != ev_keydown)
 		return false;
 
-	if (ev->data1 > 0xFF)
+	if (ev->key > 0xFF)
 	{
 		// map some fake (joy) inputs into keys
 		// map joy inputs into keys
-		switch (ev->data1)
+		switch (ev->key)
 		{
 			case KEY_JOY1:
 			case KEY_JOY1 + 2:
@@ -231,7 +231,7 @@ boolean cht_Responder(event_t *ev)
 		}
 	}
 	else
-		ch = (UINT8)ev->data1;
+		ch = (UINT8)ev->key;
 
 	ret += cht_CheckCheat(&cheat_ultimate, (char)ch);
 	ret += cht_CheckCheat(&cheat_ultimate_joy, (char)ch);
diff --git a/src/m_menu.c b/src/m_menu.c
index 2086ac53e2d38389036abe0cbcd9c47babbad741..7a82fd8fb1a81009590b8495e90d6a8f41102fa7 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -1106,55 +1106,55 @@ static menuitem_t OP_ChangeControlsMenu[] =
 {
 	{IT_HEADER, NULL, "Movement", NULL, 0},
 	{IT_SPACE, NULL, NULL, NULL, 0}, // padding
-	{IT_CALL | IT_STRING2, NULL, "Move Forward",     M_ChangeControl, gc_forward     },
-	{IT_CALL | IT_STRING2, NULL, "Move Backward",    M_ChangeControl, gc_backward    },
-	{IT_CALL | IT_STRING2, NULL, "Move Left",        M_ChangeControl, gc_strafeleft  },
-	{IT_CALL | IT_STRING2, NULL, "Move Right",       M_ChangeControl, gc_straferight },
-	{IT_CALL | IT_STRING2, NULL, "Jump",             M_ChangeControl, gc_jump      },
-	{IT_CALL | IT_STRING2, NULL, "Spin",             M_ChangeControl, gc_spin     },
+	{IT_CALL | IT_STRING2, NULL, "Move Forward",     M_ChangeControl, GC_FORWARD     },
+	{IT_CALL | IT_STRING2, NULL, "Move Backward",    M_ChangeControl, GC_BACKWARD    },
+	{IT_CALL | IT_STRING2, NULL, "Move Left",        M_ChangeControl, GC_STRAFELEFT  },
+	{IT_CALL | IT_STRING2, NULL, "Move Right",       M_ChangeControl, GC_STRAFERIGHT },
+	{IT_CALL | IT_STRING2, NULL, "Jump",             M_ChangeControl, GC_JUMP      },
+	{IT_CALL | IT_STRING2, NULL, "Spin",             M_ChangeControl, GC_SPIN     },
 	{IT_HEADER, NULL, "Camera", NULL, 0},
 	{IT_SPACE, NULL, NULL, NULL, 0}, // padding
-	{IT_CALL | IT_STRING2, NULL, "Look Up",        M_ChangeControl, gc_lookup      },
-	{IT_CALL | IT_STRING2, NULL, "Look Down",      M_ChangeControl, gc_lookdown    },
-	{IT_CALL | IT_STRING2, NULL, "Look Left",      M_ChangeControl, gc_turnleft    },
-	{IT_CALL | IT_STRING2, NULL, "Look Right",     M_ChangeControl, gc_turnright   },
-	{IT_CALL | IT_STRING2, NULL, "Center View",      M_ChangeControl, gc_centerview  },
-	{IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming },
-	{IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle},
-	{IT_CALL | IT_STRING2, NULL, "Reset Camera",     M_ChangeControl, gc_camreset    },
+	{IT_CALL | IT_STRING2, NULL, "Look Up",        M_ChangeControl, GC_LOOKUP      },
+	{IT_CALL | IT_STRING2, NULL, "Look Down",      M_ChangeControl, GC_LOOKDOWN    },
+	{IT_CALL | IT_STRING2, NULL, "Look Left",      M_ChangeControl, GC_TURNLEFT    },
+	{IT_CALL | IT_STRING2, NULL, "Look Right",     M_ChangeControl, GC_TURNRIGHT   },
+	{IT_CALL | IT_STRING2, NULL, "Center View",      M_ChangeControl, GC_CENTERVIEW  },
+	{IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, GC_MOUSEAIMING },
+	{IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, GC_CAMTOGGLE},
+	{IT_CALL | IT_STRING2, NULL, "Reset Camera",     M_ChangeControl, GC_CAMRESET    },
 	{IT_HEADER, NULL, "Meta", NULL, 0},
 	{IT_SPACE, NULL, NULL, NULL, 0}, // padding
 	{IT_CALL | IT_STRING2, NULL, "Game Status",
-    M_ChangeControl, gc_scores      },
-	{IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, gc_pause      },
-	{IT_CALL | IT_STRING2, NULL, "Screenshot",            M_ChangeControl, gc_screenshot },
-	{IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording",  M_ChangeControl, gc_recordgif  },
-	{IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, gc_systemmenu },
-	{IT_CALL | IT_STRING2, NULL, "Change Viewpoint",      M_ChangeControl, gc_viewpoint  },
-	{IT_CALL | IT_STRING2, NULL, "Console",          M_ChangeControl, gc_console     },
+    M_ChangeControl, GC_SCORES      },
+	{IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, GC_PAUSE      },
+	{IT_CALL | IT_STRING2, NULL, "Screenshot",            M_ChangeControl, GC_SCREENSHOT },
+	{IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording",  M_ChangeControl, GC_RECORDGIF  },
+	{IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, GC_SYSTEMMENU },
+	{IT_CALL | IT_STRING2, NULL, "Change Viewpoint",      M_ChangeControl, GC_VIEWPOINT  },
+	{IT_CALL | IT_STRING2, NULL, "Console",          M_ChangeControl, GC_CONSOLE     },
 	{IT_HEADER, NULL, "Multiplayer", NULL, 0},
 	{IT_SPACE, NULL, NULL, NULL, 0}, // padding
-	{IT_CALL | IT_STRING2, NULL, "Talk",             M_ChangeControl, gc_talkkey     },
-	{IT_CALL | IT_STRING2, NULL, "Talk (Team only)", M_ChangeControl, gc_teamkey     },
+	{IT_CALL | IT_STRING2, NULL, "Talk",             M_ChangeControl, GC_TALKKEY     },
+	{IT_CALL | IT_STRING2, NULL, "Talk (Team only)", M_ChangeControl, GC_TEAMKEY     },
 	{IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 0},
 	{IT_SPACE, NULL, NULL, NULL, 0}, // padding
-	{IT_CALL | IT_STRING2, NULL, "Fire",             M_ChangeControl, gc_fire        },
-	{IT_CALL | IT_STRING2, NULL, "Fire Normal",      M_ChangeControl, gc_firenormal  },
-	{IT_CALL | IT_STRING2, NULL, "Toss Flag",        M_ChangeControl, gc_tossflag    },
-	{IT_CALL | IT_STRING2, NULL, "Next Weapon",      M_ChangeControl, gc_weaponnext  },
-	{IT_CALL | IT_STRING2, NULL, "Prev Weapon",      M_ChangeControl, gc_weaponprev  },
-	{IT_CALL | IT_STRING2, NULL, "Normal / Infinity",   M_ChangeControl, gc_wepslot1    },
-	{IT_CALL | IT_STRING2, NULL, "Automatic",        M_ChangeControl, gc_wepslot2    },
-	{IT_CALL | IT_STRING2, NULL, "Bounce",           M_ChangeControl, gc_wepslot3    },
-	{IT_CALL | IT_STRING2, NULL, "Scatter",          M_ChangeControl, gc_wepslot4    },
-	{IT_CALL | IT_STRING2, NULL, "Grenade",          M_ChangeControl, gc_wepslot5    },
-	{IT_CALL | IT_STRING2, NULL, "Explosion",        M_ChangeControl, gc_wepslot6    },
-	{IT_CALL | IT_STRING2, NULL, "Rail",             M_ChangeControl, gc_wepslot7    },
+	{IT_CALL | IT_STRING2, NULL, "Fire",             M_ChangeControl, GC_FIRE        },
+	{IT_CALL | IT_STRING2, NULL, "Fire Normal",      M_ChangeControl, GC_FIRENORMAL  },
+	{IT_CALL | IT_STRING2, NULL, "Toss Flag",        M_ChangeControl, GC_TOSSFLAG    },
+	{IT_CALL | IT_STRING2, NULL, "Next Weapon",      M_ChangeControl, GC_WEAPONNEXT  },
+	{IT_CALL | IT_STRING2, NULL, "Prev Weapon",      M_ChangeControl, GC_WEAPONPREV  },
+	{IT_CALL | IT_STRING2, NULL, "Normal / Infinity",   M_ChangeControl, GC_WEPSLOT1    },
+	{IT_CALL | IT_STRING2, NULL, "Automatic",        M_ChangeControl, GC_WEPSLOT2    },
+	{IT_CALL | IT_STRING2, NULL, "Bounce",           M_ChangeControl, GC_WEPSLOT3    },
+	{IT_CALL | IT_STRING2, NULL, "Scatter",          M_ChangeControl, GC_WEPSLOT4    },
+	{IT_CALL | IT_STRING2, NULL, "Grenade",          M_ChangeControl, GC_WEPSLOT5    },
+	{IT_CALL | IT_STRING2, NULL, "Explosion",        M_ChangeControl, GC_WEPSLOT6    },
+	{IT_CALL | IT_STRING2, NULL, "Rail",             M_ChangeControl, GC_WEPSLOT7    },
 	{IT_HEADER, NULL, "Add-ons", NULL, 0},
 	{IT_SPACE, NULL, NULL, NULL, 0}, // padding
-	{IT_CALL | IT_STRING2, NULL, "Custom Action 1",  M_ChangeControl, gc_custom1     },
-	{IT_CALL | IT_STRING2, NULL, "Custom Action 2",  M_ChangeControl, gc_custom2     },
-	{IT_CALL | IT_STRING2, NULL, "Custom Action 3",  M_ChangeControl, gc_custom3     },
+	{IT_CALL | IT_STRING2, NULL, "Custom Action 1",  M_ChangeControl, GC_CUSTOM1     },
+	{IT_CALL | IT_STRING2, NULL, "Custom Action 2",  M_ChangeControl, GC_CUSTOM2     },
+	{IT_CALL | IT_STRING2, NULL, "Custom Action 3",  M_ChangeControl, GC_CUSTOM3     },
 };
 
 static menuitem_t OP_Joystick1Menu[] =
@@ -3229,7 +3229,7 @@ boolean M_Responder(event_t *ev)
 		if (ev->type == ev_keydown)
 		{
 			keydown++;
-			ch = ev->data1;
+			ch = ev->key;
 
 			// added 5-2-98 remap virtual keys (mouse & joystick buttons)
 			switch (ch)
@@ -3262,44 +3262,44 @@ boolean M_Responder(event_t *ev)
 					break;
 			}
 		}
-		else if (ev->type == ev_joystick  && ev->data1 == 0 && joywait < I_GetTime())
+		else if (ev->type == ev_joystick  && ev->key == 0 && joywait < I_GetTime())
 		{
 			const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT;
-			if (ev->data3 != INT32_MAX)
+			if (ev->y != INT32_MAX)
 			{
-				if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone)
+				if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone)
 				{
-					if (ev->data3 < 0 && pjoyy >= 0)
+					if (ev->y < 0 && pjoyy >= 0)
 					{
 						ch = KEY_UPARROW;
 						joywait = I_GetTime() + NEWTICRATE/7;
 					}
-					else if (ev->data3 > 0 && pjoyy <= 0)
+					else if (ev->y > 0 && pjoyy <= 0)
 					{
 						ch = KEY_DOWNARROW;
 						joywait = I_GetTime() + NEWTICRATE/7;
 					}
-					pjoyy = ev->data3;
+					pjoyy = ev->y;
 				}
 				else
 					pjoyy = 0;
 			}
 
-			if (ev->data2 != INT32_MAX)
+			if (ev->x != INT32_MAX)
 			{
-				if (Joystick.bGamepadStyle || abs(ev->data2) > jdeadzone)
+				if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone)
 				{
-					if (ev->data2 < 0 && pjoyx >= 0)
+					if (ev->x < 0 && pjoyx >= 0)
 					{
 						ch = KEY_LEFTARROW;
 						joywait = I_GetTime() + NEWTICRATE/17;
 					}
-					else if (ev->data2 > 0 && pjoyx <= 0)
+					else if (ev->x > 0 && pjoyx <= 0)
 					{
 						ch = KEY_RIGHTARROW;
 						joywait = I_GetTime() + NEWTICRATE/17;
 					}
-					pjoyx = ev->data2;
+					pjoyx = ev->x;
 				}
 				else
 					pjoyx = 0;
@@ -3307,7 +3307,7 @@ boolean M_Responder(event_t *ev)
 		}
 		else if (ev->type == ev_mouse && mousewait < I_GetTime())
 		{
-			pmousey -= ev->data3;
+			pmousey -= ev->y;
 			if (pmousey < lasty-30)
 			{
 				ch = KEY_DOWNARROW;
@@ -3321,7 +3321,7 @@ boolean M_Responder(event_t *ev)
 				pmousey = lasty += 30;
 			}
 
-			pmousex += ev->data2;
+			pmousex += ev->x;
 			if (pmousex < lastx - 30)
 			{
 				ch = KEY_LEFTARROW;
@@ -3339,11 +3339,11 @@ boolean M_Responder(event_t *ev)
 			keydown = 0;
 	}
 	else if (ev->type == ev_keydown) // Preserve event for other responders
-		ch = ev->data1;
+		ch = ev->key;
 
 	if (ch == -1)
 		return false;
-	else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key
+	else if (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1]) // allow remappable ESC key
 		ch = KEY_ESCAPE;
 
 	// F-Keys
@@ -12826,13 +12826,13 @@ static void M_DrawControl(void)
 			else
 			{
 				if (keys[0] != KEY_NULL)
-					strcat (tmp, G_KeyNumToString (keys[0]));
+					strcat (tmp, G_KeyNumToName (keys[0]));
 
 				if (keys[0] != KEY_NULL && keys[1] != KEY_NULL)
 					strcat(tmp," or ");
 
 				if (keys[1] != KEY_NULL)
-					strcat (tmp, G_KeyNumToString (keys[1]));
+					strcat (tmp, G_KeyNumToName (keys[1]));
 
 
 			}
@@ -12859,7 +12859,7 @@ static void M_ChangecontrolResponse(event_t *ev)
 {
 	INT32        control;
 	INT32        found;
-	INT32        ch = ev->data1;
+	INT32        ch = ev->key;
 
 	// ESCAPE cancels; dummy out PAUSE
 	if (ch != KEY_ESCAPE && ch != KEY_PAUSE)
@@ -12878,7 +12878,7 @@ static void M_ChangecontrolResponse(event_t *ev)
 			// keypad arrows are converted for the menu in cursor arrows
 			// so use the event instead of ch
 			case ev_keydown:
-				ch = ev->data1;
+				ch = ev->key;
 			break;
 
 			default:
@@ -12929,7 +12929,7 @@ static void M_ChangecontrolResponse(event_t *ev)
 		static char tmp[158];
 		menu_t *prev = currentMenu->prevMenu;
 
-		if (controltochange == gc_pause)
+		if (controltochange == GC_PAUSE)
 			sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit cannot be used to retry runs \nduring Record Attack. \n\nHit another key for\n%s\nESC for Cancel"),
 				controltochangetext);
 		else
diff --git a/src/m_misc.c b/src/m_misc.c
index 4100a8f170fa48f022771abe9982f919cdfe5095..61f0f8a5b652a23154548d6112761e4d15ad8690 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -1631,14 +1631,14 @@ boolean M_ScreenshotResponder(event_t *ev)
 	if (dedicated || ev->type != ev_keydown)
 		return false;
 
-	ch = ev->data1;
+	ch = ev->key;
 
 	if (ch >= KEY_MOUSE1 && menuactive) // If it's not a keyboard key, then don't allow it in the menus!
 		return false;
 
-	if (ch == KEY_F8 || ch == gamecontrol[gc_screenshot][0] || ch == gamecontrol[gc_screenshot][1]) // remappable F8
+	if (ch == KEY_F8 || ch == gamecontrol[GC_SCREENSHOT][0] || ch == gamecontrol[GC_SCREENSHOT][1]) // remappable F8
 		M_ScreenShot();
-	else if (ch == KEY_F9 || ch == gamecontrol[gc_recordgif][0] || ch == gamecontrol[gc_recordgif][1]) // remappable F9
+	else if (ch == KEY_F9 || ch == gamecontrol[GC_RECORDGIF][0] || ch == gamecontrol[GC_RECORDGIF][1]) // remappable F9
 		((moviemode) ? M_StopMovie : M_StartMovie)();
 	else
 		return false;
diff --git a/src/p_user.c b/src/p_user.c
index 198db44066bd08ab5bc9f3d9b01c2d612cf85005..0ff268b8bbb0021c5ec8356d62900b17c04920f1 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -5357,9 +5357,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 						// disabled because it seemed to disorient people and Z-targeting exists now
 						/*if (!demoplayback)
 						{
-							if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(PLAYER1INPUTDOWN(gc_turnleft) || PLAYER1INPUTDOWN(gc_turnright)))
+							if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(PLAYER1INPUTDOWN(GC_TURNLEFT) || PLAYER1INPUTDOWN(GC_TURNRIGHT)))
 								P_SetPlayerAngle(player, player->mo->angle);;
-							else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(PLAYER2INPUTDOWN(gc_turnleft) || PLAYER2INPUTDOWN(gc_turnright)))
+							else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(PLAYER2INPUTDOWN(GC_TURNLEFT) || PLAYER2INPUTDOWN(GC_TURNRIGHT)))
 								P_SetPlayerAngle(player, player->mo->angle);
 						}*/
 					}
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index d68e3e435bb6c749b8e770e0cc604aba96206185..a3908c57015a92f079d14a545bc24097a66e032f 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -572,7 +572,7 @@ void I_GetConsoleEvents(void)
 			tty_con.buffer[tty_con.cursor] = '\0';
 			tty_Back();
 		}
-		ev.data1 = KEY_BACKSPACE;
+		ev.key = KEY_BACKSPACE;
 	}
 	else if (key < ' ') // check if this is a control char
 	{
@@ -580,19 +580,19 @@ void I_GetConsoleEvents(void)
 		{
 			tty_Clear();
 			tty_con.cursor = 0;
-			ev.data1 = KEY_ENTER;
+			ev.key = KEY_ENTER;
 		}
 		else return;
 	}
 	else
 	{
 		// push regular character
-		ev.data1 = tty_con.buffer[tty_con.cursor] = key;
+		ev.key = tty_con.buffer[tty_con.cursor] = key;
 		tty_con.cursor++;
 		// print the current line (this is differential)
 		d = write(STDOUT_FILENO, &key, 1);
 	}
-	if (ev.data1) D_PostEvent(&ev);
+	if (ev.key) D_PostEvent(&ev);
 	//tty_FlushIn();
 	(void)d;
 }
@@ -626,18 +626,18 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
 		{
 			case VK_ESCAPE:
 			case VK_TAB:
-				event.data1 = KEY_NULL;
+				event.key = KEY_NULL;
 				break;
 			case VK_RETURN:
 				entering_con_command = false;
 				/* FALLTHRU */
 			default:
-				//event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
-				event.data1 = evt.uChar.AsciiChar;
+				//event.key = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
+				event.key = evt.uChar.AsciiChar;
 		}
 		if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t))
 		{
-			if (event.data1 && event.data1 != KEY_LSHIFT && event.data1 != KEY_RSHIFT)
+			if (event.key && event.key != KEY_LSHIFT && event.key != KEY_RSHIFT)
 			{
 #ifdef _UNICODE
 				WriteConsole(co, &evt.uChar.UnicodeChar, 1, &t, NULL);
@@ -652,7 +652,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
 			}
 		}
 	}
-	if (event.data1) D_PostEvent(&event);
+	if (event.key) D_PostEvent(&event);
 }
 
 void I_GetConsoleEvents(void)
@@ -917,7 +917,7 @@ INT32 I_GetKey (void)
 		ev = &events[eventtail];
 		if (ev->type == ev_keydown || ev->type == ev_console)
 		{
-			rc = ev->data1;
+			rc = ev->key;
 			continue;
 		}
 	}
@@ -977,22 +977,22 @@ void I_ShutdownJoystick(void)
 	INT32 i;
 	event_t event;
 	event.type=ev_keyup;
-	event.data2 = 0;
-	event.data3 = 0;
+	event.x = 0;
+	event.y = 0;
 
 	lastjoybuttons = lastjoyhats = 0;
 
 	// emulate the up of all joystick buttons
 	for (i=0;i<JOYBUTTONS;i++)
 	{
-		event.data1=KEY_JOY1+i;
+		event.key=KEY_JOY1+i;
 		D_PostEvent(&event);
 	}
 
 	// emulate the up of all joystick hats
 	for (i=0;i<JOYHATS*4;i++)
 	{
-		event.data1=KEY_HAT1+i;
+		event.key=KEY_HAT1+i;
 		D_PostEvent(&event);
 	}
 
@@ -1000,7 +1000,7 @@ void I_ShutdownJoystick(void)
 	event.type = ev_joystick;
 	for (i=0;i<JOYAXISSET; i++)
 	{
-		event.data1 = i;
+		event.key = i;
 		D_PostEvent(&event);
 	}
 
@@ -1012,7 +1012,7 @@ void I_ShutdownJoystick(void)
 
 void I_GetJoystickEvents(void)
 {
-	static event_t event = {0,0,0,0};
+	static event_t event = {0,0,0,0,false};
 	INT32 i = 0;
 	UINT64 joyhats = 0;
 #if 0
@@ -1049,7 +1049,7 @@ void I_GetJoystickEvents(void)
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_JOY1 + i;
+				event.key = KEY_JOY1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -1080,7 +1080,7 @@ void I_GetJoystickEvents(void)
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_HAT1 + i;
+				event.key = KEY_HAT1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -1092,7 +1092,7 @@ void I_GetJoystickEvents(void)
 
 	for (i = JOYAXISSET - 1; i >= 0; i--)
 	{
-		event.data1 = i;
+		event.key = i;
 		if (i*2 + 1 <= JoyInfo.axises)
 			axisx = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 0);
 		else axisx = 0;
@@ -1110,15 +1110,15 @@ void I_GetJoystickEvents(void)
 		{
 			// gamepad control type, on or off, live or die
 			if (axisx < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (axisx > (JOYAXISRANGE/2))
-				event.data2 = 1;
-			else event.data2 = 0;
+				event.x = 1;
+			else event.x = 0;
 			if (axisy < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (axisy > (JOYAXISRANGE/2))
-				event.data3 = 1;
-			else event.data3 = 0;
+				event.y = 1;
+			else event.y = 0;
 		}
 		else
 		{
@@ -1132,8 +1132,8 @@ void I_GetJoystickEvents(void)
 #endif
 
 			// analog control style , just send the raw data
-			event.data2 = axisx; // x axis
-			event.data3 = axisy; // y axis
+			event.x = axisx; // x axis
+			event.y = axisy; // y axis
 		}
 		D_PostEvent(&event);
 	}
@@ -1247,22 +1247,22 @@ void I_ShutdownJoystick2(void)
 	INT32 i;
 	event_t event;
 	event.type = ev_keyup;
-	event.data2 = 0;
-	event.data3 = 0;
+	event.x = 0;
+	event.y = 0;
 
 	lastjoy2buttons = lastjoy2hats = 0;
 
 	// emulate the up of all joystick buttons
 	for (i = 0; i < JOYBUTTONS; i++)
 	{
-		event.data1 = KEY_2JOY1 + i;
+		event.key = KEY_2JOY1 + i;
 		D_PostEvent(&event);
 	}
 
 	// emulate the up of all joystick hats
 	for (i = 0; i < JOYHATS*4; i++)
 	{
-		event.data1 = KEY_2HAT1 + i;
+		event.key = KEY_2HAT1 + i;
 		D_PostEvent(&event);
 	}
 
@@ -1270,7 +1270,7 @@ void I_ShutdownJoystick2(void)
 	event.type = ev_joystick2;
 	for (i = 0; i < JOYAXISSET; i++)
 	{
-		event.data1 = i;
+		event.key = i;
 		D_PostEvent(&event);
 	}
 
@@ -1282,7 +1282,7 @@ void I_ShutdownJoystick2(void)
 
 void I_GetJoystick2Events(void)
 {
-	static event_t event = {0,0,0,0};
+	static event_t event = {0,0,0,0,false};
 	INT32 i = 0;
 	UINT64 joyhats = 0;
 #if 0
@@ -1321,7 +1321,7 @@ void I_GetJoystick2Events(void)
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_2JOY1 + i;
+				event.key = KEY_2JOY1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -1352,7 +1352,7 @@ void I_GetJoystick2Events(void)
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_2HAT1 + i;
+				event.key = KEY_2HAT1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -1364,7 +1364,7 @@ void I_GetJoystick2Events(void)
 
 	for (i = JOYAXISSET - 1; i >= 0; i--)
 	{
-		event.data1 = i;
+		event.key = i;
 		if (i*2 + 1 <= JoyInfo2.axises)
 			axisx = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 0);
 		else axisx = 0;
@@ -1380,17 +1380,17 @@ void I_GetJoystick2Events(void)
 		{
 			// gamepad control type, on or off, live or die
 			if (axisx < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (axisx > (JOYAXISRANGE/2))
-				event.data2 = 1;
+				event.x = 1;
 			else
-				event.data2 = 0;
+				event.x = 0;
 			if (axisy < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (axisy > (JOYAXISRANGE/2))
-				event.data3 = 1;
+				event.y = 1;
 			else
-				event.data3 = 0;
+				event.y = 0;
 		}
 		else
 		{
@@ -1404,8 +1404,8 @@ void I_GetJoystick2Events(void)
 #endif
 
 			// analog control style , just send the raw data
-			event.data2 = axisx; // x axis
-			event.data3 = axisy; // y axis
+			event.x = axisx; // x axis
+			event.y = axisy; // y axis
 		}
 		D_PostEvent(&event);
 	}
@@ -1804,7 +1804,7 @@ void I_GetMouseEvents(void)
 					if (!(button & (1<<j))) //keyup
 					{
 						event.type = ev_keyup;
-						event.data1 = KEY_2MOUSE1+j;
+						event.key = KEY_2MOUSE1+j;
 						D_PostEvent(&event);
 						om2b ^= 1 << j;
 					}
@@ -1814,18 +1814,18 @@ void I_GetMouseEvents(void)
 					if (button & (1<<j))
 					{
 						event.type = ev_keydown;
-						event.data1 = KEY_2MOUSE1+j;
+						event.key = KEY_2MOUSE1+j;
 						D_PostEvent(&event);
 						om2b ^= 1 << j;
 					}
 				}
 			}
-			event.data2 = ((SINT8)mdata[1])+((SINT8)mdata[3]);
-			event.data3 = ((SINT8)mdata[2])+((SINT8)mdata[4]);
-			if (event.data2 && event.data3)
+			event.x = ((SINT8)mdata[1])+((SINT8)mdata[3]);
+			event.y = ((SINT8)mdata[2])+((SINT8)mdata[4]);
+			if (event.x && event.y)
 			{
 				event.type = ev_mouse2;
-				event.data1 = 0;
+				event.key = 0;
 				D_PostEvent(&event);
 			}
 		}
@@ -1867,7 +1867,7 @@ static void I_ShutdownMouse2(void)
 	for (i = 0; i < MOUSEBUTTONS; i++)
 	{
 		event.type = ev_keyup;
-		event.data1 = KEY_2MOUSE1+i;
+		event.key = KEY_2MOUSE1+i;
 		D_PostEvent(&event);
 	}
 
@@ -1958,7 +1958,7 @@ void I_GetMouseEvents(void)
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_2MOUSE1+i;
+				event.key = KEY_2MOUSE1+i;
 				D_PostEvent(&event);
 			}
 	}
@@ -1966,10 +1966,10 @@ void I_GetMouseEvents(void)
 	if (handlermouse2x != 0 || handlermouse2y != 0)
 	{
 		event.type = ev_mouse2;
-		event.data1 = 0;
-//		event.data1 = buttons; // not needed
-		event.data2 = handlermouse2x << 1;
-		event.data3 = handlermouse2y << 1;
+		event.key = 0;
+//		event.key = buttons; // not needed
+		event.x = handlermouse2x << 1;
+		event.y = handlermouse2y << 1;
 		handlermouse2x = 0;
 		handlermouse2y = 0;
 
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 819589eaff1a5d856da1cf76d5aaaf47352f8ab1..97e4a7214b420a2b4a3764eb5b505f500f161799 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -73,6 +73,8 @@
 #include "../console.h"
 #include "../command.h"
 #include "../r_main.h"
+#include "../lua_script.h"
+#include "../lua_libs.h"
 #include "../lua_hook.h"
 #include "sdlmain.h"
 #ifdef HWRENDER
@@ -372,6 +374,8 @@ static boolean IgnoreMouse(void)
 	if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION &&
 			gamestate != GS_CONTINUING && gamestate != GS_CUTSCENE)
 		return true;
+	if (!mousegrabbedbylua)
+		return true;
 	return false;
 }
 
@@ -663,8 +667,9 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
 	{
 		return;
 	}
-	event.data1 = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
-	if (event.data1) D_PostEvent(&event);
+	event.key = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
+	event.repeated = (evt.repeat != 0);
+	if (event.key) D_PostEvent(&event);
 }
 
 static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
@@ -742,15 +747,15 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
 		}
 		else return;
 		if (evt.button == SDL_BUTTON_MIDDLE)
-			event.data1 = KEY_MOUSE1+2;
+			event.key = KEY_MOUSE1+2;
 		else if (evt.button == SDL_BUTTON_RIGHT)
-			event.data1 = KEY_MOUSE1+1;
+			event.key = KEY_MOUSE1+1;
 		else if (evt.button == SDL_BUTTON_LEFT)
-			event.data1 = KEY_MOUSE1;
+			event.key = KEY_MOUSE1;
 		else if (evt.button == SDL_BUTTON_X1)
-			event.data1 = KEY_MOUSE1+3;
+			event.key = KEY_MOUSE1+3;
 		else if (evt.button == SDL_BUTTON_X2)
-			event.data1 = KEY_MOUSE1+4;
+			event.key = KEY_MOUSE1+4;
 		if (event.type == ev_keyup || event.type == ev_keydown)
 		{
 			D_PostEvent(&event);
@@ -766,17 +771,17 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt)
 
 	if (evt.y > 0)
 	{
-		event.data1 = KEY_MOUSEWHEELUP;
+		event.key = KEY_MOUSEWHEELUP;
 		event.type = ev_keydown;
 	}
 	if (evt.y < 0)
 	{
-		event.data1 = KEY_MOUSEWHEELDOWN;
+		event.key = KEY_MOUSEWHEELDOWN;
 		event.type = ev_keydown;
 	}
 	if (evt.y == 0)
 	{
-		event.data1 = 0;
+		event.key = 0;
 		event.type = ev_keyup;
 	}
 	if (event.type == ev_keyup || event.type == ev_keydown)
@@ -795,7 +800,7 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
 	joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
 
 	evt.axis++;
-	event.data1 = event.data2 = event.data3 = INT32_MAX;
+	event.key = event.x = event.y = INT32_MAX;
 
 	if (evt.which == joyid[0])
 	{
@@ -812,14 +817,14 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
 	//vaule
 	if (evt.axis%2)
 	{
-		event.data1 = evt.axis / 2;
-		event.data2 = SDLJoyAxis(evt.value, event.type);
+		event.key = evt.axis / 2;
+		event.x = SDLJoyAxis(evt.value, event.type);
 	}
 	else
 	{
 		evt.axis--;
-		event.data1 = evt.axis / 2;
-		event.data3 = SDLJoyAxis(evt.value, event.type);
+		event.key = evt.axis / 2;
+		event.y = SDLJoyAxis(evt.value, event.type);
 	}
 	D_PostEvent(&event);
 }
@@ -839,11 +844,11 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt)
 
 	if (evt.which == joyid[0])
 	{
-		event.data1 = KEY_HAT1 + (evt.hat*4);
+		event.key = KEY_HAT1 + (evt.hat*4);
 	}
 	else if (evt.which == joyid[1])
 	{
-		event.data1 = KEY_2HAT1 + (evt.hat*4);
+		event.key = KEY_2HAT1 + (evt.hat*4);
 	}
 	else return;
 
@@ -862,11 +867,11 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
 
 	if (evt.which == joyid[0])
 	{
-		event.data1 = KEY_JOY1;
+		event.key = KEY_JOY1;
 	}
 	else if (evt.which == joyid[1])
 	{
-		event.data1 = KEY_2JOY1;
+		event.key = KEY_2JOY1;
 	}
 	else return;
 	if (type == SDL_JOYBUTTONUP)
@@ -880,7 +885,7 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
 	else return;
 	if (evt.button < JOYBUTTONS)
 	{
-		event.data1 += evt.button;
+		event.key += evt.button;
 	}
 	else return;
 
@@ -1084,9 +1089,9 @@ void I_GetEvent(void)
 		SDL_GetWindowSize(window, &wwidth, &wheight);
 		//SDL_memset(&event, 0, sizeof(event_t));
 		event.type = ev_mouse;
-		event.data1 = 0;
-		event.data2 = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
-		event.data3 = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
+		event.key = 0;
+		event.x = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
+		event.y = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
 		D_PostEvent(&event);
 	}
 
diff --git a/src/win32/win_main.c b/src/win32/win_main.c
index e1d90881ba4fac766c3720eb318c0a3b58cfbfe6..a5ebf32113f2723dbb5786c0eda8ae79a710d61b 100644
--- a/src/win32/win_main.c
+++ b/src/win32/win_main.c
@@ -188,11 +188,11 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 			ev.type = ev_keydown;
 
 	handleKeyDoom:
-			ev.data1 = 0;
+			ev.key = 0;
 			if (wParam == VK_PAUSE)
 			// intercept PAUSE key
 			{
-				ev.data1 = KEY_PAUSE;
+				ev.key = KEY_PAUSE;
 			}
 			else if (!keyboard_started)
 			// post some keys during the game startup
@@ -201,14 +201,14 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 			{
 				switch (wParam)
 				{
-					case VK_ESCAPE: ev.data1 = KEY_ESCAPE;  break;
-					case VK_RETURN: ev.data1 = KEY_ENTER;   break;
-					case VK_SHIFT:  ev.data1 = KEY_LSHIFT;  break;
-					default: ev.data1 = MapVirtualKey((DWORD)wParam,2); // convert in to char
+					case VK_ESCAPE: ev.key = KEY_ESCAPE;  break;
+					case VK_RETURN: ev.key = KEY_ENTER;   break;
+					case VK_SHIFT:  ev.key = KEY_LSHIFT;  break;
+					default: ev.key = MapVirtualKey((DWORD)wParam,2); // convert in to char
 				}
 			}
 
-			if (ev.data1)
+			if (ev.key)
 				D_PostEvent (&ev);
 
 			return 0;
@@ -240,7 +240,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 			if (nodinput)
 			{
 				ev.type = ev_keyup;
-				ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam);
+				ev.key = KEY_MOUSE1 + 3 + HIWORD(wParam);
 				D_PostEvent(&ev);
 				return TRUE;
 			}
@@ -249,7 +249,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 			if (nodinput)
 			{
 				ev.type = ev_keydown;
-				ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam);
+				ev.key = KEY_MOUSE1 + 3 + HIWORD(wParam);
 				D_PostEvent(&ev);
 				return TRUE;
 			}
@@ -258,9 +258,9 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 			//I_OutputMsg("MW_WHEEL dispatched.\n");
 			ev.type = ev_keydown;
 			if ((INT16)HIWORD(wParam) > 0)
-				ev.data1 = KEY_MOUSEWHEELUP;
+				ev.key = KEY_MOUSEWHEELUP;
 			else
-				ev.data1 = KEY_MOUSEWHEELDOWN;
+				ev.key = KEY_MOUSEWHEELDOWN;
 			D_PostEvent(&ev);
 			break;
 
@@ -271,7 +271,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 
 		case WM_CLOSE:
 			PostQuitMessage(0);         //to quit while in-game
-			ev.data1 = KEY_ESCAPE;      //to exit network synchronization
+			ev.key = KEY_ESCAPE;      //to exit network synchronization
 			ev.type = ev_keydown;
 			D_PostEvent (&ev);
 			return 0;
diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c
index da0d5b47ee3c26699b4d538575a22b8dc7420218..ff443935fa7f5a925e3539508b2fe5ce18244e09 100644
--- a/src/win32/win_sys.c
+++ b/src/win32/win_sys.c
@@ -322,20 +322,20 @@ static inline VOID I_GetConsoleEvents(VOID)
 					{
 						case VK_ESCAPE:
 						case VK_TAB:
-							ev.data1 = KEY_NULL;
+							ev.key = KEY_NULL;
 							break;
 						case VK_SHIFT:
-							ev.data1 = KEY_LSHIFT;
+							ev.key = KEY_LSHIFT;
 							break;
 						case VK_RETURN:
 							entering_con_command = false;
 							/* FALLTHRU */
 						default:
-							ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char
+							ev.key = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char
 					}
 					if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t))
 					{
-						if (ev.data1 && ev.data1 != KEY_LSHIFT && ev.data1 != KEY_RSHIFT)
+						if (ev.key && ev.key != KEY_LSHIFT && ev.key != KEY_RSHIFT)
 						{
 #ifdef UNICODE
 							WriteConsole(co, &input.Event.KeyEvent.uChar.UnicodeChar, 1, &t, NULL);
@@ -356,13 +356,13 @@ static inline VOID I_GetConsoleEvents(VOID)
 					switch (input.Event.KeyEvent.wVirtualKeyCode)
 					{
 						case VK_SHIFT:
-							ev.data1 = KEY_LSHIFT;
+							ev.key = KEY_LSHIFT;
 							break;
 						default:
 							break;
 					}
 				}
-				if (ev.data1) D_PostEvent(&ev);
+				if (ev.key) D_PostEvent(&ev);
 				break;
 			case MOUSE_EVENT:
 			case WINDOW_BUFFER_SIZE_EVENT:
@@ -945,7 +945,7 @@ static void I_ShutdownMouse2(VOID)
 		for (i = 0; i < MOUSEBUTTONS; i++)
 		{
 			event.type = ev_keyup;
-			event.data1 = KEY_2MOUSE1 + i;
+			event.key = KEY_2MOUSE1 + i;
 			D_PostEvent(&event);
 		}
 
@@ -1135,14 +1135,14 @@ VOID I_GetSysMouseEvents(INT mouse_state)
 		if ((mouse_state & (1 << i)) && !(old_mouse_state & (1 << i)))
 		{
 			event.type = ev_keydown;
-			event.data1 = KEY_MOUSE1 + i;
+			event.key = KEY_MOUSE1 + i;
 			D_PostEvent(&event);
 		}
 		// check if button released
 		if (!(mouse_state & (1 << i)) && (old_mouse_state & (1 << i)))
 		{
 			event.type = ev_keyup;
-			event.data1 = KEY_MOUSE1 + i;
+			event.key = KEY_MOUSE1 + i;
 			D_PostEvent(&event);
 		}
 	}
@@ -1156,9 +1156,9 @@ VOID I_GetSysMouseEvents(INT mouse_state)
 	if (xmickeys || ymickeys)
 	{
 		event.type  = ev_mouse;
-		event.data1 = 0;
-		event.data2 = xmickeys;
-		event.data3 = -ymickeys;
+		event.key = 0;
+		event.x = xmickeys;
+		event.y = -ymickeys;
 		D_PostEvent(&event);
 		SetCursorPos(center_x, center_y);
 	}
@@ -1240,7 +1240,7 @@ static void I_ShutdownMouse(void)
 	for (i = 0; i < MOUSEBUTTONS; i++)
 	{
 		event.type = ev_keyup;
-		event.data1 = KEY_MOUSE1 + i;
+		event.key = KEY_MOUSE1 + i;
 		D_PostEvent(&event);
 	}
 	if (nodinput)
@@ -1281,7 +1281,7 @@ void I_GetMouseEvents(void)
 						event.type = ev_keydown;
 					else
 						event.type = ev_keyup;
-					event.data1 = KEY_2MOUSE1 + i;
+					event.key = KEY_2MOUSE1 + i;
 					D_PostEvent(&event);
 				}
 		}
@@ -1289,9 +1289,9 @@ void I_GetMouseEvents(void)
 		if (handlermouse2x || handlermouse2y)
 		{
 			event.type = ev_mouse2;
-			event.data1 = 0;
-			event.data2 = handlermouse2x<<1;
-			event.data3 = -handlermouse2y<<1;
+			event.key = 0;
+			event.x = handlermouse2x<<1;
+			event.y = -handlermouse2y<<1;
 			handlermouse2x = 0;
 			handlermouse2y = 0;
 
@@ -1330,7 +1330,7 @@ getBufferedData:
 				else
 					event.type = ev_keyup; // Button up
 
-				event.data1 = rgdod[d].dwOfs - DIMOFS_BUTTON0 + KEY_MOUSE1;
+				event.key = rgdod[d].dwOfs - DIMOFS_BUTTON0 + KEY_MOUSE1;
 				D_PostEvent(&event);
 			}
 			else if (rgdod[d].dwOfs == DIMOFS_X)
@@ -1342,9 +1342,9 @@ getBufferedData:
 			{
 				// z-axes the wheel
 				if ((int)rgdod[d].dwData > 0)
-					event.data1 = KEY_MOUSEWHEELUP;
+					event.key = KEY_MOUSEWHEELUP;
 				else
-					event.data1 = KEY_MOUSEWHEELDOWN;
+					event.key = KEY_MOUSEWHEELDOWN;
 				event.type = ev_keydown;
 				D_PostEvent(&event);
 			}
@@ -1354,9 +1354,9 @@ getBufferedData:
 		if (xmickeys || ymickeys)
 		{
 			event.type = ev_mouse;
-			event.data1 = 0;
-			event.data2 = xmickeys;
-			event.data3 = -ymickeys;
+			event.key = 0;
+			event.x = xmickeys;
+			event.y = -ymickeys;
 			D_PostEvent(&event);
 		}
 	}
@@ -2395,14 +2395,14 @@ static VOID I_ShutdownJoystick(VOID)
 	// emulate the up of all joystick buttons
 	for (i = 0;i < JOYBUTTONS;i++)
 	{
-		event.data1 = KEY_JOY1+i;
+		event.key = KEY_JOY1+i;
 		D_PostEvent(&event);
 	}
 
 	// emulate the up of all joystick hats
 	for (i = 0;i < JOYHATS*4;i++)
 	{
-		event.data1 = KEY_HAT1+i;
+		event.key = KEY_HAT1+i;
 		D_PostEvent(&event);
 	}
 
@@ -2410,7 +2410,7 @@ static VOID I_ShutdownJoystick(VOID)
 	event.type = ev_joystick;
 	for (i = 0;i < JOYAXISSET; i++)
 	{
-		event.data1 = i;
+		event.key = i;
 		D_PostEvent(&event);
 	}
 
@@ -2460,14 +2460,14 @@ static VOID I_ShutdownJoystick2(VOID)
 	// emulate the up of all joystick buttons
 	for (i = 0;i < JOYBUTTONS;i++)
 	{
-		event.data1 = KEY_2JOY1+i;
+		event.key = KEY_2JOY1+i;
 		D_PostEvent(&event);
 	}
 
 	// emulate the up of all joystick hats
 	for (i = 0;i < JOYHATS*4;i++)
 	{
-		event.data1 = KEY_2HAT1+i;
+		event.key = KEY_2HAT1+i;
 		D_PostEvent(&event);
 	}
 
@@ -2475,7 +2475,7 @@ static VOID I_ShutdownJoystick2(VOID)
 	event.type = ev_joystick2;
 	for (i = 0;i < JOYAXISSET; i++)
 	{
-		event.data1 = i;
+		event.key = i;
 		D_PostEvent(&event);
 	}
 
@@ -2598,7 +2598,7 @@ acquire:
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_JOY1 + i;
+				event.key = KEY_JOY1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -2618,7 +2618,7 @@ acquire:
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_HAT1 + i;
+				event.key = KEY_HAT1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -2627,7 +2627,7 @@ acquire:
 
 	// send joystick axis positions
 	event.type = ev_joystick;
-	event.data1 = event.data2 = event.data3 = 0;
+	event.key = event.x = event.y = 0;
 
 	if (Joystick.bGamepadStyle)
 	{
@@ -2635,29 +2635,29 @@ acquire:
 		if (JoyInfo.X)
 		{
 			if (js.lX < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.lX > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo.Y)
 		{
 			if (js.lY < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.lY > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo.X)  event.data2 = js.lX; // x axis
-		if (JoyInfo.Y)  event.data3 = js.lY; // y axis
+		if (JoyInfo.X)  event.x = js.lX; // x axis
+		if (JoyInfo.Y)  event.y = js.lY; // y axis
 	}
 
 	D_PostEvent(&event);
 #if JOYAXISSET > 1
-	event.data1 = 1;
-	event.data2 = event.data3 = 0;
+	event.key = 1;
+	event.x = event.y = 0;
 
 	if (Joystick.bGamepadStyle)
 	{
@@ -2665,30 +2665,30 @@ acquire:
 		if (JoyInfo.Z)
 		{
 			if (js.lZ < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.lZ > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo.Rx)
 		{
 			if (js.lRx < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.lRx > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo.Z)  event.data2 = js.lZ;  // z axis
-		if (JoyInfo.Rx) event.data3 = js.lRx; // rx axis
+		if (JoyInfo.Z)  event.x = js.lZ;  // z axis
+		if (JoyInfo.Rx) event.y = js.lRx; // rx axis
 	}
 
 	D_PostEvent(&event);
 #endif
 #if JOYAXISSET > 2
-	event.data1 = 2;
-	event.data2 = event.data3 = 0;
+	event.key = 2;
+	event.x = event.y = 0;
 
 	if (Joystick.bGamepadStyle)
 	{
@@ -2696,53 +2696,53 @@ acquire:
 		if (JoyInfo.Rx)
 		{
 			if (js.lRy < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.lRy > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo.Rz)
 		{
 			if (js.lRz < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.lRz > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo.Ry) event.data2 = js.lRy; // ry axis
-		if (JoyInfo.Rz) event.data3 = js.lRz; // rz axis
+		if (JoyInfo.Ry) event.x = js.lRy; // ry axis
+		if (JoyInfo.Rz) event.y = js.lRz; // rz axis
 	}
 
 	D_PostEvent(&event);
 #endif
 #if JOYAXISSET > 3
-	event.data1 = 3;
-	event.data2 = event.data3 = 0;
+	event.key = 3;
+	event.x = event.y = 0;
 	if (Joystick.bGamepadStyle)
 	{
 		// gamepad control type, on or off, live or die
 		if (JoyInfo.U)
 		{
 			if (js.rglSlider[0] < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.rglSlider[0] > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo.V)
 		{
 			if (js.rglSlider[1] < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.rglSlider[1] > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo.U)  event.data2 = js.rglSlider[0]; // U axis
-		if (JoyInfo.V)  event.data3 = js.rglSlider[1]; // V axis
+		if (JoyInfo.U)  event.x = js.rglSlider[0]; // U axis
+		if (JoyInfo.V)  event.y = js.rglSlider[1]; // V axis
 	}
 	D_PostEvent(&event);
 #endif
@@ -2842,7 +2842,7 @@ acquire:
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_2JOY1 + i;
+				event.key = KEY_2JOY1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -2862,7 +2862,7 @@ acquire:
 					event.type = ev_keydown;
 				else
 					event.type = ev_keyup;
-				event.data1 = KEY_2HAT1 + i;
+				event.key = KEY_2HAT1 + i;
 				D_PostEvent(&event);
 			}
 		}
@@ -2871,7 +2871,7 @@ acquire:
 
 	// send joystick axis positions
 	event.type = ev_joystick2;
-	event.data1 = event.data2 = event.data3 = 0;
+	event.key = event.x = event.y = 0;
 
 	if (Joystick2.bGamepadStyle)
 	{
@@ -2879,29 +2879,29 @@ acquire:
 		if (JoyInfo2.X)
 		{
 			if (js.lX < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.lX > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo2.Y)
 		{
 			if (js.lY < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.lY > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo2.X)  event.data2 = js.lX; // x axis
-		if (JoyInfo2.Y)  event.data3 = js.lY; // y axis
+		if (JoyInfo2.X)  event.x = js.lX; // x axis
+		if (JoyInfo2.Y)  event.y = js.lY; // y axis
 	}
 
 	D_PostEvent(&event);
 #if JOYAXISSET > 1
-	event.data1 = 1;
-	event.data2 = event.data3 = 0;
+	event.key = 1;
+	event.x = event.y = 0;
 
 	if (Joystick2.bGamepadStyle)
 	{
@@ -2909,30 +2909,30 @@ acquire:
 		if (JoyInfo2.Z)
 		{
 			if (js.lZ < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.lZ > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo2.Rx)
 		{
 			if (js.lRx < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.lRx > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo2.Z)  event.data2 = js.lZ;  // z axis
-		if (JoyInfo2.Rx) event.data3 = js.lRx; // rx axis
+		if (JoyInfo2.Z)  event.x = js.lZ;  // z axis
+		if (JoyInfo2.Rx) event.y = js.lRx; // rx axis
 	}
 
 	D_PostEvent(&event);
 #endif
 #if JOYAXISSET > 2
-	event.data1 = 2;
-	event.data2 = event.data3 = 0;
+	event.key = 2;
+	event.x = event.y = 0;
 
 	if (Joystick2.bGamepadStyle)
 	{
@@ -2940,53 +2940,53 @@ acquire:
 		if (JoyInfo2.Rx)
 		{
 			if (js.lRy < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.lRy > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo2.Rz)
 		{
 			if (js.lRz < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.lRz > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo2.Ry) event.data2 = js.lRy; // ry axis
-		if (JoyInfo2.Rz) event.data3 = js.lRz; // rz axis
+		if (JoyInfo2.Ry) event.x = js.lRy; // ry axis
+		if (JoyInfo2.Rz) event.y = js.lRz; // rz axis
 	}
 
 	D_PostEvent(&event);
 #endif
 #if JOYAXISSET > 3
-	event.data1 = 3;
-	event.data2 = event.data3 = 0;
+	event.key = 3;
+	event.x = event.y = 0;
 	if (Joystick2.bGamepadStyle)
 	{
 		// gamepad control type, on or off, live or die
 		if (JoyInfo2.U)
 		{
 			if (js.rglSlider[0] < -(JOYAXISRANGE/2))
-				event.data2 = -1;
+				event.x = -1;
 			else if (js.rglSlider[0] > JOYAXISRANGE/2)
-				event.data2 = 1;
+				event.x = 1;
 		}
 		if (JoyInfo2.V)
 		{
 			if (js.rglSlider[1] < -(JOYAXISRANGE/2))
-				event.data3 = -1;
+				event.y = -1;
 			else if (js.rglSlider[1] > JOYAXISRANGE/2)
-				event.data3 = 1;
+				event.y = 1;
 		}
 	}
 	else
 	{
 		// analog control style, just send the raw data
-		if (JoyInfo2.U)  event.data2 = js.rglSlider[0]; // U axis
-		if (JoyInfo2.V)  event.data3 = js.rglSlider[1]; // V axis
+		if (JoyInfo2.U)  event.x = js.rglSlider[0]; // U axis
+		if (JoyInfo2.V)  event.y = js.rglSlider[1]; // V axis
 	}
 	D_PostEvent(&event);
 #endif
@@ -3194,7 +3194,7 @@ INT32 I_GetKey(void)
 		ev = &events[eventtail];
 		eventtail = (eventtail+1) & (MAXEVENTS-1);
 		if (ev->type == ev_keydown || ev->type == ev_console)
-			return ev->data1;
+			return ev->key;
 		else
 			return 0;
 	}
@@ -3308,7 +3308,7 @@ static VOID I_GetKeyboardEvents(VOID)
 	if (!appActive && RepeatKeyCode) // Stop when lost focus
 	{
 		event.type = ev_keyup;
-		event.data1 = RepeatKeyCode;
+		event.key = RepeatKeyCode;
 		D_PostEvent(&event);
 		RepeatKeyCode = 0;
 	}
@@ -3363,9 +3363,9 @@ getBufferedData:
 
 			ch = rgdod[d].dwOfs & 0xFF;
 			if (ASCIINames[ch])
-				event.data1 = ASCIINames[ch];
+				event.key = ASCIINames[ch];
 			else
-				event.data1 = 0x80;
+				event.key = 0x80;
 
 			D_PostEvent(&event);
 		}
@@ -3378,7 +3378,7 @@ getBufferedData:
 			// delay is tripled for first repeating key
 			RepeatKeyTics = hacktics + (KEY_REPEAT_DELAY*3);
 			if (event.type == ev_keydown) // use the last event!
-				RepeatKeyCode = event.data1;
+				RepeatKeyCode = event.key;
 		}
 		else
 		{
@@ -3386,7 +3386,7 @@ getBufferedData:
 			if (RepeatKeyCode && hacktics - RepeatKeyTics > KEY_REPEAT_DELAY)
 			{
 				event.type = ev_keydown;
-				event.data1 = RepeatKeyCode;
+				event.key = RepeatKeyCode;
 				D_PostEvent(&event);
 
 				RepeatKeyTics = hacktics;