From 7a308d9e7305a864504ff9eae32c3927643dbf47 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 29 Jul 2018 01:35:36 -0300
Subject: [PATCH] Window related changes (#308)

* Use integer math for touch screen

* Sleep polling thread

* Rework host input

* Add fullscreen with F11 or Alt+Enter

* Address feedback
---
 Ryujinx/Config.cs              | 102 +++++++++------
 Ryujinx/Ui/GLScreen.cs         | 188 +++++++--------------------
 Ryujinx/Ui/JoyConController.cs | 226 +++++++++++++++++++++++++++++----
 Ryujinx/Ui/JoyConKeyboard.cs   |  66 +++++++++-
 4 files changed, 376 insertions(+), 206 deletions(-)

diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs
index 0f346122af..4ed35b3d7e 100644
--- a/Ryujinx/Config.cs
+++ b/Ryujinx/Config.cs
@@ -14,11 +14,6 @@ namespace Ryujinx
         public static JoyConKeyboard   JoyConKeyboard   { get; private set; }
         public static JoyConController JoyConController { get; private set; }
 
-        public static float GamePadDeadzone             { get; private set; }
-        public static bool  GamePadEnable               { get; private set; }
-        public static int   GamePadIndex                { get; private set; }
-        public static float GamePadTriggerThreshold     { get; private set; }
-
         public static void Read(Logger Log)
         {
             string IniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
@@ -37,11 +32,6 @@ namespace Ryujinx
             Log.SetEnable(LogLevel.Warning, Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")));
             Log.SetEnable(LogLevel.Error,   Convert.ToBoolean(Parser.Value("Logging_Enable_Error")));
 
-            GamePadEnable            =        Convert.ToBoolean(Parser.Value("GamePad_Enable"));
-            GamePadIndex             =        Convert.ToInt32  (Parser.Value("GamePad_Index"));
-            GamePadDeadzone          = (float)Convert.ToDouble (Parser.Value("GamePad_Deadzone"),          CultureInfo.InvariantCulture);
-            GamePadTriggerThreshold  = (float)Convert.ToDouble (Parser.Value("GamePad_Trigger_Threshold"), CultureInfo.InvariantCulture);
-
             string[] FilteredLogClasses = Parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries);
 
             //When the classes are specified on the list, we only
@@ -70,9 +60,9 @@ namespace Ryujinx
                 }
             }
 
-            JoyConKeyboard = new JoyConKeyboard
-            {
-                Left = new JoyConKeyboardLeft
+            JoyConKeyboard = new JoyConKeyboard(
+
+                new JoyConKeyboardLeft
                 {
                     StickUp     = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Stick_Up")),
                     StickDown   = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Stick_Down")),
@@ -88,7 +78,7 @@ namespace Ryujinx
                     ButtonZL    = Convert.ToInt16(Parser.Value("Controls_Left_JoyConKeyboard_Button_ZL"))
                 },
 
-                Right = new JoyConKeyboardRight
+                new JoyConKeyboardRight
                 {
                     StickUp     = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Stick_Up")),
                     StickDown   = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Stick_Down")),
@@ -102,37 +92,69 @@ namespace Ryujinx
                     ButtonPlus  = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_Plus")),
                     ButtonR     = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_R")),
                     ButtonZR    = Convert.ToInt16(Parser.Value("Controls_Right_JoyConKeyboard_Button_ZR"))
-                }
-            };
+                });
 
-            JoyConController = new JoyConController
-            {
-                Left = new JoyConControllerLeft
+            JoyConController = new JoyConController(
+
+                       Convert.ToBoolean(Parser.Value("GamePad_Enable")),
+                       Convert.ToInt32  (Parser.Value("GamePad_Index")),
+                (float)Convert.ToDouble (Parser.Value("GamePad_Deadzone"),          CultureInfo.InvariantCulture),
+                (float)Convert.ToDouble (Parser.Value("GamePad_Trigger_Threshold"), CultureInfo.InvariantCulture),
+
+                new JoyConControllerLeft
                 {
-                    Stick       = Parser.Value("Controls_Left_JoyConController_Stick"),
-                    StickButton = Parser.Value("Controls_Left_JoyConController_Stick_Button"),
-                    DPadUp      = Parser.Value("Controls_Left_JoyConController_DPad_Up"),
-                    DPadDown    = Parser.Value("Controls_Left_JoyConController_DPad_Down"),
-                    DPadLeft    = Parser.Value("Controls_Left_JoyConController_DPad_Left"),
-                    DPadRight   = Parser.Value("Controls_Left_JoyConController_DPad_Right"),
-                    ButtonMinus = Parser.Value("Controls_Left_JoyConController_Button_Minus"),
-                    ButtonL     = Parser.Value("Controls_Left_JoyConController_Button_L"),
-                    ButtonZL    = Parser.Value("Controls_Left_JoyConController_Button_ZL")
+                    Stick       = ToID(Parser.Value("Controls_Left_JoyConController_Stick")),
+                    StickButton = ToID(Parser.Value("Controls_Left_JoyConController_Stick_Button")),
+                    DPadUp      = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Up")),
+                    DPadDown    = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Down")),
+                    DPadLeft    = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Left")),
+                    DPadRight   = ToID(Parser.Value("Controls_Left_JoyConController_DPad_Right")),
+                    ButtonMinus = ToID(Parser.Value("Controls_Left_JoyConController_Button_Minus")),
+                    ButtonL     = ToID(Parser.Value("Controls_Left_JoyConController_Button_L")),
+                    ButtonZL    = ToID(Parser.Value("Controls_Left_JoyConController_Button_ZL"))
                 },
 
-                Right = new JoyConControllerRight
+                new JoyConControllerRight
                 {
-                    Stick       = Parser.Value("Controls_Right_JoyConController_Stick"),
-                    StickButton = Parser.Value("Controls_Right_JoyConController_Stick_Button"),
-                    ButtonA     = Parser.Value("Controls_Right_JoyConController_Button_A"),
-                    ButtonB     = Parser.Value("Controls_Right_JoyConController_Button_B"),
-                    ButtonX     = Parser.Value("Controls_Right_JoyConController_Button_X"),
-                    ButtonY     = Parser.Value("Controls_Right_JoyConController_Button_Y"),
-                    ButtonPlus  = Parser.Value("Controls_Right_JoyConController_Button_Plus"),
-                    ButtonR     = Parser.Value("Controls_Right_JoyConController_Button_R"),
-                    ButtonZR    = Parser.Value("Controls_Right_JoyConController_Button_ZR")
-                }
-            };
+                    Stick       = ToID(Parser.Value("Controls_Right_JoyConController_Stick")),
+                    StickButton = ToID(Parser.Value("Controls_Right_JoyConController_Stick_Button")),
+                    ButtonA     = ToID(Parser.Value("Controls_Right_JoyConController_Button_A")),
+                    ButtonB     = ToID(Parser.Value("Controls_Right_JoyConController_Button_B")),
+                    ButtonX     = ToID(Parser.Value("Controls_Right_JoyConController_Button_X")),
+                    ButtonY     = ToID(Parser.Value("Controls_Right_JoyConController_Button_Y")),
+                    ButtonPlus  = ToID(Parser.Value("Controls_Right_JoyConController_Button_Plus")),
+                    ButtonR     = ToID(Parser.Value("Controls_Right_JoyConController_Button_R")),
+                    ButtonZR    = ToID(Parser.Value("Controls_Right_JoyConController_Button_ZR"))
+                });
+        }
+
+        private static ControllerInputID ToID(string Key)
+        {
+            switch (Key.ToUpper())
+            {
+                case "LSTICK":    return ControllerInputID.LStick;
+                case "DPADUP":    return ControllerInputID.DPadUp;
+                case "DPADDOWN":  return ControllerInputID.DPadDown;
+                case "DPADLEFT":  return ControllerInputID.DPadLeft;
+                case "DPADRIGHT": return ControllerInputID.DPadRight;
+                case "BACK":      return ControllerInputID.Back;
+                case "LSHOULDER": return ControllerInputID.LShoulder;
+                case "LTRIGGER":  return ControllerInputID.LTrigger;
+
+                case "RSTICK":    return ControllerInputID.RStick;
+                case "A":         return ControllerInputID.A;
+                case "B":         return ControllerInputID.B;
+                case "X":         return ControllerInputID.X;
+                case "Y":         return ControllerInputID.Y;
+                case "START":     return ControllerInputID.Start;
+                case "RSHOULDER": return ControllerInputID.RShoulder;
+                case "RTRIGGER":  return ControllerInputID.RTrigger;
+
+                case "LJOYSTICK": return ControllerInputID.LJoystick;
+                case "RJOYSTICK": return ControllerInputID.RJoystick;
+
+                default: return ControllerInputID.Invalid;
+            }
         }
     }
 
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index 9b5dda4f0c..dfc0b9a418 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -4,6 +4,7 @@ using OpenTK.Input;
 using Ryujinx.Graphics.Gal;
 using Ryujinx.HLE;
 using Ryujinx.HLE.Input;
+using Ryujinx.UI.Input;
 using System;
 using System.Threading;
 
@@ -16,9 +17,6 @@ namespace Ryujinx
         private const int TouchScreenWidth  = 1280;
         private const int TouchScreenHeight = 720;
 
-        private const float TouchScreenRatioX = (float)TouchScreenWidth  / TouchScreenHeight;
-        private const float TouchScreenRatioY = (float)TouchScreenHeight / TouchScreenWidth;
-
         private const int TargetFPS = 60;
 
         private Switch Ns;
@@ -49,10 +47,6 @@ namespace Ryujinx
             Location = new Point(
                 (DisplayDevice.Default.Width  / 2) - (Width  / 2),
                 (DisplayDevice.Default.Height / 2) - (Height / 2));
-
-            ResizeEvent = false;
-
-            TitleEvent = false;
         }
 
         private void RenderLoop()
@@ -127,60 +121,9 @@ namespace Ryujinx
                         Title = NewTitle;
                     }
                 }
-            }
-        }
-        
-        private bool IsGamePadButtonPressedFromString(GamePadState GamePad, string Button)
-        {
-            if (Button.ToUpper() == "LTRIGGER" || Button.ToUpper() == "RTRIGGER")
-            {
-                return GetGamePadTriggerFromString(GamePad, Button) >= Config.GamePadTriggerThreshold;
-            }
-            else
-            {
-                return (GetGamePadButtonFromString(GamePad, Button) == ButtonState.Pressed);
-            }
-        }
 
-        private ButtonState GetGamePadButtonFromString(GamePadState GamePad, string Button)
-        {
-            switch (Button.ToUpper())
-            {
-                case "A":         return GamePad.Buttons.A;
-                case "B":         return GamePad.Buttons.B;
-                case "X":         return GamePad.Buttons.X;
-                case "Y":         return GamePad.Buttons.Y;
-                case "LSTICK":    return GamePad.Buttons.LeftStick;
-                case "RSTICK":    return GamePad.Buttons.RightStick;
-                case "LSHOULDER": return GamePad.Buttons.LeftShoulder;
-                case "RSHOULDER": return GamePad.Buttons.RightShoulder;
-                case "DPADUP":    return GamePad.DPad.Up;
-                case "DPADDOWN":  return GamePad.DPad.Down;
-                case "DPADLEFT":  return GamePad.DPad.Left;
-                case "DPADRIGHT": return GamePad.DPad.Right;
-                case "START":     return GamePad.Buttons.Start;
-                case "BACK":      return GamePad.Buttons.Back;
-                default:          throw  new ArgumentException();
-            }
-        }
-
-        private float GetGamePadTriggerFromString(GamePadState GamePad, string Trigger)
-        {
-            switch (Trigger.ToUpper())
-            {
-                case "LTRIGGER": return GamePad.Triggers.Left;
-                case "RTRIGGER": return GamePad.Triggers.Right;
-                default:         throw  new ArgumentException();
-            }
-        }
-
-        private Vector2 GetJoystickAxisFromString(GamePadState GamePad, string Joystick)
-        {
-            switch (Joystick.ToUpper())
-            {
-                case "LJOYSTICK": return GamePad.ThumbSticks.Left;
-                case "RJOYSTICK": return new Vector2(-GamePad.ThumbSticks.Right.Y, -GamePad.ThumbSticks.Right.X);
-                default:          throw  new ArgumentException();
+                //Polling becomes expensive if it's not slept
+                Thread.Sleep(1);
             }
         }
 
@@ -190,95 +133,37 @@ namespace Ryujinx
             HidJoystickPosition  LeftJoystick;
             HidJoystickPosition  RightJoystick;
 
-            int LeftJoystickDX        = 0;
-            int LeftJoystickDY        = 0;
-            int RightJoystickDX       = 0;
-            int RightJoystickDY       = 0;
-            float AnalogStickDeadzone = Config.GamePadDeadzone;
+            int LeftJoystickDX  = 0;
+            int LeftJoystickDY  = 0;
+            int RightJoystickDX = 0;
+            int RightJoystickDY = 0;
 
             //Keyboard Input
             if (Keyboard.HasValue)
             {
                 KeyboardState Keyboard = this.Keyboard.Value;
 
-                if (Keyboard[Key.Escape]) this.Exit();
+                CurrentButton = Config.JoyConKeyboard.GetButtons(Keyboard);
 
-                //LeftJoystick
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.StickUp])    LeftJoystickDY = short.MaxValue;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.StickDown])  LeftJoystickDY = -short.MaxValue;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.StickLeft])  LeftJoystickDX = -short.MaxValue;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.StickRight]) LeftJoystickDX = short.MaxValue;
+                (LeftJoystickDX, LeftJoystickDY) = Config.JoyConKeyboard.GetLeftStick(Keyboard);
 
-                //LeftButtons
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.StickButton]) CurrentButton |= HidControllerButtons.KEY_LSTICK;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.DPadUp])      CurrentButton |= HidControllerButtons.KEY_DUP;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.DPadDown])    CurrentButton |= HidControllerButtons.KEY_DDOWN;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.DPadLeft])    CurrentButton |= HidControllerButtons.KEY_DLEFT;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.DPadRight])   CurrentButton |= HidControllerButtons.KEY_DRIGHT;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.ButtonMinus]) CurrentButton |= HidControllerButtons.KEY_MINUS;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.ButtonL])     CurrentButton |= HidControllerButtons.KEY_L;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Left.ButtonZL])    CurrentButton |= HidControllerButtons.KEY_ZL;
-
-                //RightJoystick
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.StickUp])    RightJoystickDY = short.MaxValue;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.StickDown])  RightJoystickDY = -short.MaxValue;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.StickLeft])  RightJoystickDX = -short.MaxValue;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.StickRight]) RightJoystickDX = short.MaxValue;
-
-                //RightButtons
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.StickButton]) CurrentButton |= HidControllerButtons.KEY_RSTICK;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.ButtonA])     CurrentButton |= HidControllerButtons.KEY_A;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.ButtonB])     CurrentButton |= HidControllerButtons.KEY_B;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.ButtonX])     CurrentButton |= HidControllerButtons.KEY_X;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.ButtonY])     CurrentButton |= HidControllerButtons.KEY_Y;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.ButtonPlus])  CurrentButton |= HidControllerButtons.KEY_PLUS;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.ButtonR])     CurrentButton |= HidControllerButtons.KEY_R;
-                if (Keyboard[(Key)Config.JoyConKeyboard.Right.ButtonZR])    CurrentButton |= HidControllerButtons.KEY_ZR;
+                (RightJoystickDX, RightJoystickDY) = Config.JoyConKeyboard.GetRightStick(Keyboard);
             }
 
             //Controller Input
-            if (Config.GamePadEnable)
+            CurrentButton |= Config.JoyConController.GetButtons();
+                
+            //Keyboard has priority stick-wise
+            if (LeftJoystickDX == 0 && LeftJoystickDY == 0)
             {
-                GamePadState GamePad = OpenTK.Input.GamePad.GetState(Config.GamePadIndex);
-                //LeftButtons
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.DPadUp))       CurrentButton |= HidControllerButtons.KEY_DUP;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.DPadDown))     CurrentButton |= HidControllerButtons.KEY_DDOWN;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.DPadLeft))     CurrentButton |= HidControllerButtons.KEY_DLEFT;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.DPadRight))    CurrentButton |= HidControllerButtons.KEY_DRIGHT;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.StickButton))  CurrentButton |= HidControllerButtons.KEY_LSTICK;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.ButtonMinus))  CurrentButton |= HidControllerButtons.KEY_MINUS;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.ButtonL))      CurrentButton |= HidControllerButtons.KEY_L;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Left.ButtonZL))     CurrentButton |= HidControllerButtons.KEY_ZL;
-
-                //RightButtons
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.ButtonA))     CurrentButton |= HidControllerButtons.KEY_A;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.ButtonB))     CurrentButton |= HidControllerButtons.KEY_B;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.ButtonX))     CurrentButton |= HidControllerButtons.KEY_X;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.ButtonY))     CurrentButton |= HidControllerButtons.KEY_Y;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.StickButton)) CurrentButton |= HidControllerButtons.KEY_RSTICK;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.ButtonPlus))  CurrentButton |= HidControllerButtons.KEY_PLUS;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.ButtonR))     CurrentButton |= HidControllerButtons.KEY_R;
-                if (IsGamePadButtonPressedFromString(GamePad, Config.JoyConController.Right.ButtonZR))    CurrentButton |= HidControllerButtons.KEY_ZR;
-
-                //LeftJoystick
-                if (GetJoystickAxisFromString(GamePad, Config.JoyConController.Left.Stick).X >= AnalogStickDeadzone
-                 || GetJoystickAxisFromString(GamePad, Config.JoyConController.Left.Stick).X <= -AnalogStickDeadzone)
-                    LeftJoystickDX = (int)(GetJoystickAxisFromString(GamePad, Config.JoyConController.Left.Stick).X * short.MaxValue);
-
-                if (GetJoystickAxisFromString(GamePad, Config.JoyConController.Left.Stick).Y >= AnalogStickDeadzone
-                 || GetJoystickAxisFromString(GamePad, Config.JoyConController.Left.Stick).Y <= -AnalogStickDeadzone)
-                    LeftJoystickDY = (int)(GetJoystickAxisFromString(GamePad, Config.JoyConController.Left.Stick).Y * short.MaxValue);
-
-                //RightJoystick
-                if (GetJoystickAxisFromString(GamePad, Config.JoyConController.Right.Stick).X >= AnalogStickDeadzone
-                 || GetJoystickAxisFromString(GamePad, Config.JoyConController.Right.Stick).X <= -AnalogStickDeadzone)
-                    RightJoystickDX = (int)(GetJoystickAxisFromString(GamePad, Config.JoyConController.Right.Stick).X * short.MaxValue);
-
-                if (GetJoystickAxisFromString(GamePad, Config.JoyConController.Right.Stick).Y >= AnalogStickDeadzone
-                 || GetJoystickAxisFromString(GamePad, Config.JoyConController.Right.Stick).Y <= -AnalogStickDeadzone)
-                    RightJoystickDY = (int)(GetJoystickAxisFromString(GamePad, Config.JoyConController.Right.Stick).Y * short.MaxValue);
+                (LeftJoystickDX, LeftJoystickDY) = Config.JoyConController.GetLeftStick();
             }
 
+            if (RightJoystickDX == 0 && RightJoystickDY == 0)
+            {
+                (RightJoystickDX, RightJoystickDY) = Config.JoyConController.GetRightStick();
+            }
+            
             LeftJoystick = new HidJoystickPosition
             {
                 DX = LeftJoystickDX,
@@ -302,13 +187,13 @@ namespace Ryujinx
                 int ScrnWidth  = Width;
                 int ScrnHeight = Height;
 
-                if (Width > Height * TouchScreenRatioX)
+                if (Width > (Height * TouchScreenWidth) / TouchScreenHeight)
                 {
-                    ScrnWidth = (int)(Height * TouchScreenRatioX);
+                    ScrnWidth = (Height * TouchScreenWidth) / TouchScreenHeight;
                 }
                 else
                 {
-                    ScrnHeight = (int)(Width * TouchScreenRatioY);
+                    ScrnHeight = (Width * TouchScreenHeight) / TouchScreenWidth;
                 }
 
                 int StartX = (Width  - ScrnWidth)  >> 1;
@@ -325,8 +210,8 @@ namespace Ryujinx
                     int ScrnMouseX = Mouse.X - StartX;
                     int ScrnMouseY = Mouse.Y - StartY;
 
-                    int MX = (int)(((float)ScrnMouseX / ScrnWidth)  * TouchScreenWidth);
-                    int MY = (int)(((float)ScrnMouseY / ScrnHeight) * TouchScreenHeight);
+                    int MX = (ScrnMouseX * TouchScreenWidth)  / ScrnWidth;
+                    int MY = (ScrnMouseY * TouchScreenHeight) / ScrnHeight;
 
                     HidTouchPoint CurrentPoint = new HidTouchPoint
                     {
@@ -397,6 +282,29 @@ namespace Ryujinx
 
         protected override void OnKeyDown(KeyboardKeyEventArgs e)
         {
+            bool ToggleFullscreen = e.Key == Key.F11 ||
+                (e.Modifiers.HasFlag(KeyModifiers.Alt) && e.Key == Key.Enter);
+
+            if (WindowState == WindowState.Fullscreen)
+            {
+                if (e.Key == Key.Escape || ToggleFullscreen)
+                {
+                    WindowState = WindowState.Normal;
+                }
+            }
+            else
+            {
+                if (e.Key == Key.Escape)
+                {
+                    Exit();
+                }
+
+                if (ToggleFullscreen)
+                {
+                    WindowState = WindowState.Fullscreen;
+                }
+            }
+
             Keyboard = e.Keyboard;
         }
 
diff --git a/Ryujinx/Ui/JoyConController.cs b/Ryujinx/Ui/JoyConController.cs
index e525017d3e..aac8efd7c4 100644
--- a/Ryujinx/Ui/JoyConController.cs
+++ b/Ryujinx/Ui/JoyConController.cs
@@ -1,38 +1,216 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
+using OpenTK;
+using OpenTK.Input;
+using Ryujinx.HLE.Input;
+using System;
 
 namespace Ryujinx.UI.Input
 {
+    public enum ControllerInputID
+    {
+        Invalid,
+
+        LStick,
+        DPadUp,
+        DPadDown,
+        DPadLeft,
+        DPadRight,
+        Back,
+        LShoulder,
+
+        RStick,
+        A,
+        B,
+        X,
+        Y,
+        Start,
+        RShoulder,
+
+        LTrigger,
+        RTrigger,
+
+        LJoystick,
+        RJoystick
+    }
+
     public struct JoyConControllerLeft
     {
-        public string Stick;
-        public string StickButton;
-        public string DPadUp;
-        public string DPadDown;
-        public string DPadLeft;
-        public string DPadRight;
-        public string ButtonMinus;
-        public string ButtonL;
-        public string ButtonZL;
+        public ControllerInputID Stick;
+        public ControllerInputID StickButton;
+        public ControllerInputID DPadUp;
+        public ControllerInputID DPadDown;
+        public ControllerInputID DPadLeft;
+        public ControllerInputID DPadRight;
+        public ControllerInputID ButtonMinus;
+        public ControllerInputID ButtonL;
+        public ControllerInputID ButtonZL;
     }
 
     public struct JoyConControllerRight
     {
-        public string Stick;
-        public string StickButton;
-        public string ButtonA;
-        public string ButtonB;
-        public string ButtonX;
-        public string ButtonY;
-        public string ButtonPlus;
-        public string ButtonR;
-        public string ButtonZR;
+        public ControllerInputID Stick;
+        public ControllerInputID StickButton;
+        public ControllerInputID ButtonA;
+        public ControllerInputID ButtonB;
+        public ControllerInputID ButtonX;
+        public ControllerInputID ButtonY;
+        public ControllerInputID ButtonPlus;
+        public ControllerInputID ButtonR;
+        public ControllerInputID ButtonZR;
     }
 
-    public struct JoyConController
+    public class JoyConController
     {
-        public JoyConControllerLeft Left;
-        public JoyConControllerRight Right;
+        public bool  Enabled          { private set; get; }
+        public int   Index            { private set; get; }
+        public float Deadzone         { private set; get; }
+        public float TriggerThreshold { private set; get; }
+
+        public JoyConControllerLeft  Left  { private set; get; }
+        public JoyConControllerRight Right { private set; get; }
+
+        public JoyConController(
+            bool                  Enabled,
+            int                   Index,
+            float                 Deadzone,
+            float                 TriggerThreshold,
+            JoyConControllerLeft  Left,
+            JoyConControllerRight Right)
+        {
+            this.Enabled          = Enabled;
+            this.Index            = Index;
+            this.Deadzone         = Deadzone;
+            this.TriggerThreshold = TriggerThreshold;
+            this.Left             = Left;
+            this.Right            = Right;
+
+            //Unmapped controllers are problematic, skip them
+            if (GamePad.GetName(Index) == "Unmapped Controller")
+            {
+                this.Enabled = false;
+            }
+        }
+
+        public HidControllerButtons GetButtons()
+        {
+            if (!Enabled)
+            {
+                return 0;
+            }
+
+            GamePadState GpState = GamePad.GetState(Index);
+
+            HidControllerButtons Buttons = 0;
+
+            if (IsPressed(GpState, Left.DPadUp))       Buttons |= HidControllerButtons.KEY_DUP;
+            if (IsPressed(GpState, Left.DPadDown))     Buttons |= HidControllerButtons.KEY_DDOWN;
+            if (IsPressed(GpState, Left.DPadLeft))     Buttons |= HidControllerButtons.KEY_DLEFT;
+            if (IsPressed(GpState, Left.DPadRight))    Buttons |= HidControllerButtons.KEY_DRIGHT;
+            if (IsPressed(GpState, Left.StickButton))  Buttons |= HidControllerButtons.KEY_LSTICK;
+            if (IsPressed(GpState, Left.ButtonMinus))  Buttons |= HidControllerButtons.KEY_MINUS;
+            if (IsPressed(GpState, Left.ButtonL))      Buttons |= HidControllerButtons.KEY_L;
+            if (IsPressed(GpState, Left.ButtonZL))     Buttons |= HidControllerButtons.KEY_ZL;
+
+            if (IsPressed(GpState, Right.ButtonA))     Buttons |= HidControllerButtons.KEY_A;
+            if (IsPressed(GpState, Right.ButtonB))     Buttons |= HidControllerButtons.KEY_B;
+            if (IsPressed(GpState, Right.ButtonX))     Buttons |= HidControllerButtons.KEY_X;
+            if (IsPressed(GpState, Right.ButtonY))     Buttons |= HidControllerButtons.KEY_Y;
+            if (IsPressed(GpState, Right.StickButton)) Buttons |= HidControllerButtons.KEY_RSTICK;
+            if (IsPressed(GpState, Right.ButtonPlus))  Buttons |= HidControllerButtons.KEY_PLUS;
+            if (IsPressed(GpState, Right.ButtonR))     Buttons |= HidControllerButtons.KEY_R;
+            if (IsPressed(GpState, Right.ButtonZR))    Buttons |= HidControllerButtons.KEY_ZR;
+
+            return Buttons;
+        }
+
+        public (short, short) GetLeftStick()
+        {
+            if (!Enabled)
+            {
+                return (0, 0);
+            }
+
+            return GetStick(Left.Stick);
+        }
+
+        public (short, short) GetRightStick()
+        {
+            if (!Enabled)
+            {
+                return (0, 0);
+            }
+
+            return GetStick(Right.Stick);
+        }
+
+        private (short, short) GetStick(ControllerInputID Joystick)
+        {
+            GamePadState GpState = GamePad.GetState(Index);
+
+            switch (Joystick)
+            {
+                case ControllerInputID.LJoystick:
+                    return ApplyDeadzone(GpState.ThumbSticks.Left);
+
+                case ControllerInputID.RJoystick:
+                    return ApplyDeadzone(GpState.ThumbSticks.Right);
+
+                default:
+                    return (0, 0);
+            }
+        }
+
+        private (short, short) ApplyDeadzone(Vector2 Axis)
+        {
+            return (ClampAxis(MathF.Abs(Axis.X) > Deadzone ? Axis.X : 0f),
+                    ClampAxis(MathF.Abs(Axis.Y) > Deadzone ? Axis.Y : 0f));
+        }
+
+        private static short ClampAxis(float Value)
+        {
+            if (Value <= -short.MaxValue)
+            {
+                return -short.MaxValue;
+            }
+            else
+            {
+                return (short)(Value * short.MaxValue);
+            }
+        }
+
+        private bool IsPressed(GamePadState GpState, ControllerInputID Button)
+        {
+            switch (Button)
+            {
+                case ControllerInputID.A:         return GpState.Buttons.A             == ButtonState.Pressed;
+                case ControllerInputID.B:         return GpState.Buttons.B             == ButtonState.Pressed;
+                case ControllerInputID.X:         return GpState.Buttons.X             == ButtonState.Pressed;
+                case ControllerInputID.Y:         return GpState.Buttons.Y             == ButtonState.Pressed;
+                case ControllerInputID.LStick:    return GpState.Buttons.LeftStick     == ButtonState.Pressed;
+                case ControllerInputID.RStick:    return GpState.Buttons.RightStick    == ButtonState.Pressed;
+                case ControllerInputID.LShoulder: return GpState.Buttons.LeftShoulder  == ButtonState.Pressed;
+                case ControllerInputID.RShoulder: return GpState.Buttons.RightShoulder == ButtonState.Pressed;
+                case ControllerInputID.DPadUp:    return GpState.DPad.Up               == ButtonState.Pressed;
+                case ControllerInputID.DPadDown:  return GpState.DPad.Down             == ButtonState.Pressed;
+                case ControllerInputID.DPadLeft:  return GpState.DPad.Left             == ButtonState.Pressed;
+                case ControllerInputID.DPadRight: return GpState.DPad.Right            == ButtonState.Pressed;
+                case ControllerInputID.Start:     return GpState.Buttons.Start         == ButtonState.Pressed;
+                case ControllerInputID.Back:      return GpState.Buttons.Back          == ButtonState.Pressed;
+
+                case ControllerInputID.LTrigger: return GpState.Triggers.Left  >= TriggerThreshold;
+                case ControllerInputID.RTrigger: return GpState.Triggers.Right >= TriggerThreshold;
+
+                //Using thumbsticks as buttons is not common, but it would be nice not to ignore them
+                case ControllerInputID.LJoystick:
+                    return GpState.ThumbSticks.Left.X >= Deadzone ||
+                           GpState.ThumbSticks.Left.Y >= Deadzone;
+
+                case ControllerInputID.RJoystick:
+                    return GpState.ThumbSticks.Right.X >= Deadzone ||
+                           GpState.ThumbSticks.Right.Y >= Deadzone;
+
+                default:
+                    return false;
+            }
+        }
     }
 }
diff --git a/Ryujinx/Ui/JoyConKeyboard.cs b/Ryujinx/Ui/JoyConKeyboard.cs
index b329d9ecd1..ea9645539a 100644
--- a/Ryujinx/Ui/JoyConKeyboard.cs
+++ b/Ryujinx/Ui/JoyConKeyboard.cs
@@ -1,3 +1,6 @@
+using OpenTK.Input;
+using Ryujinx.HLE.Input;
+
 namespace Ryujinx.UI.Input
 {
     public struct JoyConKeyboardLeft
@@ -32,9 +35,68 @@ namespace Ryujinx.UI.Input
         public int ButtonZR;
     }
 
-    public struct JoyConKeyboard
+    public class JoyConKeyboard
     {
-        public JoyConKeyboardLeft Left;
+        public JoyConKeyboardLeft  Left;
         public JoyConKeyboardRight Right;
+
+        public JoyConKeyboard(
+            JoyConKeyboardLeft  Left,
+            JoyConKeyboardRight Right)
+        {
+            this.Left  = Left;
+            this.Right = Right;
+        }
+
+        public HidControllerButtons GetButtons(KeyboardState Keyboard)
+        {
+            HidControllerButtons Buttons = 0;
+
+            if (Keyboard[(Key)Left.StickButton]) Buttons |= HidControllerButtons.KEY_LSTICK;
+            if (Keyboard[(Key)Left.DPadUp])      Buttons |= HidControllerButtons.KEY_DUP;
+            if (Keyboard[(Key)Left.DPadDown])    Buttons |= HidControllerButtons.KEY_DDOWN;
+            if (Keyboard[(Key)Left.DPadLeft])    Buttons |= HidControllerButtons.KEY_DLEFT;
+            if (Keyboard[(Key)Left.DPadRight])   Buttons |= HidControllerButtons.KEY_DRIGHT;
+            if (Keyboard[(Key)Left.ButtonMinus]) Buttons |= HidControllerButtons.KEY_MINUS;
+            if (Keyboard[(Key)Left.ButtonL])     Buttons |= HidControllerButtons.KEY_L;
+            if (Keyboard[(Key)Left.ButtonZL])    Buttons |= HidControllerButtons.KEY_ZL;
+            
+            if (Keyboard[(Key)Right.StickButton]) Buttons |= HidControllerButtons.KEY_RSTICK;
+            if (Keyboard[(Key)Right.ButtonA])     Buttons |= HidControllerButtons.KEY_A;
+            if (Keyboard[(Key)Right.ButtonB])     Buttons |= HidControllerButtons.KEY_B;
+            if (Keyboard[(Key)Right.ButtonX])     Buttons |= HidControllerButtons.KEY_X;
+            if (Keyboard[(Key)Right.ButtonY])     Buttons |= HidControllerButtons.KEY_Y;
+            if (Keyboard[(Key)Right.ButtonPlus])  Buttons |= HidControllerButtons.KEY_PLUS;
+            if (Keyboard[(Key)Right.ButtonR])     Buttons |= HidControllerButtons.KEY_R;
+            if (Keyboard[(Key)Right.ButtonZR])    Buttons |= HidControllerButtons.KEY_ZR;
+
+            return Buttons;
+        }
+
+        public (short, short) GetLeftStick(KeyboardState Keyboard)
+        {
+            short DX = 0;
+            short DY = 0;
+            
+            if (Keyboard[(Key)Left.StickUp])    DY =  short.MaxValue;
+            if (Keyboard[(Key)Left.StickDown])  DY = -short.MaxValue;
+            if (Keyboard[(Key)Left.StickLeft])  DX = -short.MaxValue;
+            if (Keyboard[(Key)Left.StickRight]) DX =  short.MaxValue;
+
+            return (DX, DY);
+        }
+
+        public (short, short) GetRightStick(KeyboardState Keyboard)
+        {
+            short DX = 0;
+            short DY = 0;
+
+            if (Keyboard[(Key)Right.StickUp])    DY =  short.MaxValue;
+            if (Keyboard[(Key)Right.StickDown])  DY = -short.MaxValue;
+            if (Keyboard[(Key)Right.StickLeft])  DX = -short.MaxValue;
+            if (Keyboard[(Key)Right.StickRight]) DX =  short.MaxValue;
+
+            return (DX, DY);
+        }
     }
 }