diff --git a/src/citra_qt/configure_input.cpp b/src/citra_qt/configure_input.cpp
index d321db71fd5de14c691a85e19366830a091fe23d..3e6803b8ad1468d8c9633aef5767e71f3e5c37d4 100644
--- a/src/citra_qt/configure_input.cpp
+++ b/src/citra_qt/configure_input.cpp
@@ -5,15 +5,33 @@
 #include <memory>
 #include <utility>
 #include <QTimer>
+#include "citra_qt/config.h"
 #include "citra_qt/configure_input.h"
 
+static QString getKeyName(Qt::Key key_code) {
+    switch (key_code) {
+    case Qt::Key_Shift:
+        return QObject::tr("Shift");
+    case Qt::Key_Control:
+        return QObject::tr("Ctrl");
+    case Qt::Key_Alt:
+        return QObject::tr("Alt");
+    case Qt::Key_Meta:
+    case -1:
+        return "";
+    default:
+        return QKeySequence(key_code).toString();
+    }
+}
+
 ConfigureInput::ConfigureInput(QWidget* parent)
-    : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
+    : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()),
+      timer(std::make_unique<QTimer>()) {
 
     ui->setupUi(this);
+    setFocusPolicy(Qt::ClickFocus);
 
-    // Initialize mapping of input enum to UI button.
-    input_mapping = {
+    button_map = {
         {Settings::NativeInput::Values::A, ui->buttonA},
         {Settings::NativeInput::Values::B, ui->buttonB},
         {Settings::NativeInput::Values::X, ui->buttonX},
@@ -40,114 +58,89 @@ ConfigureInput::ConfigureInput(QWidget* parent)
         {Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod},
     };
 
-    // Attach handle click method to each button click.
-    for (const auto& entry : input_mapping) {
-        connect(entry.second, SIGNAL(released()), this, SLOT(handleClick()));
+    for (const auto& entry : button_map) {
+        const Settings::NativeInput::Values input_id = entry.first;
+        connect(entry.second, &QPushButton::released,
+                [this, input_id]() { handleClick(input_id); });
     }
-    connect(ui->buttonRestoreDefaults, SIGNAL(released()), this, SLOT(restoreDefaults()));
-    setFocusPolicy(Qt::ClickFocus);
-    timer = new QTimer(this);
+
+    connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); });
+
     timer->setSingleShot(true);
-    connect(timer, &QTimer::timeout, this, [&]() {
-        key_pressed = Qt::Key_Escape;
-        setKey();
+    connect(timer.get(), &QTimer::timeout, [this]() {
+        releaseKeyboard();
+        releaseMouse();
+        current_input_id = boost::none;
+        updateButtonLabels();
     });
-    this->setConfiguration();
-}
 
-void ConfigureInput::handleClick() {
-    QPushButton* sender = qobject_cast<QPushButton*>(QObject::sender());
-    previous_mapping = sender->text();
-    sender->setText(tr("[waiting]"));
-    sender->setFocus();
-    grabKeyboard();
-    grabMouse();
-    changing_button = sender;
-    timer->start(5000); // Cancel after 5 seconds
+    this->loadConfiguration();
 }
 
 void ConfigureInput::applyConfiguration() {
-    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
-        int value = getKeyValue(input_mapping[Settings::NativeInput::Values(i)]->text());
-        Settings::values.input_mappings[Settings::NativeInput::All[i]] = value;
+    for (const auto& input_id : Settings::NativeInput::All) {
+        const size_t index = static_cast<size_t>(input_id);
+        Settings::values.input_mappings[index] = static_cast<int>(key_map[input_id]);
     }
     Settings::Apply();
 }
 
-void ConfigureInput::setConfiguration() {
-    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
-        QString keyValue = getKeyName(Settings::values.input_mappings[i]);
-        input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
+void ConfigureInput::loadConfiguration() {
+    for (const auto& input_id : Settings::NativeInput::All) {
+        const size_t index = static_cast<size_t>(input_id);
+        key_map[input_id] = static_cast<Qt::Key>(Settings::values.input_mappings[index]);
     }
+    updateButtonLabels();
 }
 
-void ConfigureInput::keyPressEvent(QKeyEvent* event) {
-    if (!changing_button)
-        return;
-    if (!event || event->key() == Qt::Key_unknown)
-        return;
-    key_pressed = event->key();
-    timer->stop();
-    setKey();
+void ConfigureInput::restoreDefaults() {
+    for (const auto& input_id : Settings::NativeInput::All) {
+        const size_t index = static_cast<size_t>(input_id);
+        key_map[input_id] = static_cast<Qt::Key>(Config::defaults[index].toInt());
+    }
+    updateButtonLabels();
+    applyConfiguration();
 }
 
-void ConfigureInput::setKey() {
-    const QString key_value = getKeyName(key_pressed);
-    if (key_pressed == Qt::Key_Escape)
-        changing_button->setText(previous_mapping);
-    else
-        changing_button->setText(key_value);
-    removeDuplicates(key_value);
-    key_pressed = Qt::Key_unknown;
-    releaseKeyboard();
-    releaseMouse();
-    changing_button = nullptr;
-    previous_mapping = nullptr;
+void ConfigureInput::updateButtonLabels() {
+    for (const auto& input_id : Settings::NativeInput::All) {
+        button_map[input_id]->setText(getKeyName(key_map[input_id]));
+    }
 }
 
-QString ConfigureInput::getKeyName(int key_code) const {
-    if (key_code == Qt::Key_Shift)
-        return tr("Shift");
-    if (key_code == Qt::Key_Control)
-        return tr("Ctrl");
-    if (key_code == Qt::Key_Alt)
-        return tr("Alt");
-    if (key_code == Qt::Key_Meta)
-        return "";
-    if (key_code == -1)
-        return "";
+void ConfigureInput::handleClick(Settings::NativeInput::Values input_id) {
+    QPushButton* button = button_map[input_id];
+    button->setText(tr("[press key]"));
+    button->setFocus();
 
-    return QKeySequence(key_code).toString();
-}
+    current_input_id = input_id;
 
-Qt::Key ConfigureInput::getKeyValue(const QString& text) const {
-    if (text == "Shift")
-        return Qt::Key_Shift;
-    if (text == "Ctrl")
-        return Qt::Key_Control;
-    if (text == "Alt")
-        return Qt::Key_Alt;
-    if (text == "Meta")
-        return Qt::Key_unknown;
-    if (text == "")
-        return Qt::Key_unknown;
-
-    return Qt::Key(QKeySequence(text)[0]);
+    grabKeyboard();
+    grabMouse();
+    timer->start(5000); // Cancel after 5 seconds
 }
 
-void ConfigureInput::removeDuplicates(const QString& newValue) {
-    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
-        if (changing_button != input_mapping[Settings::NativeInput::Values(i)]) {
-            const QString oldValue = input_mapping[Settings::NativeInput::Values(i)]->text();
-            if (newValue == oldValue)
-                input_mapping[Settings::NativeInput::Values(i)]->setText("");
-        }
-    }
+void ConfigureInput::keyPressEvent(QKeyEvent* event) {
+    releaseKeyboard();
+    releaseMouse();
+
+    if (!current_input_id || !event)
+        return;
+
+    if (event->key() != Qt::Key_Escape)
+        setInput(*current_input_id, static_cast<Qt::Key>(event->key()));
+
+    updateButtonLabels();
+    current_input_id = boost::none;
+    timer->stop();
 }
 
-void ConfigureInput::restoreDefaults() {
-    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
-        const QString keyValue = getKeyName(Config::defaults[i].toInt());
-        input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
+void ConfigureInput::setInput(Settings::NativeInput::Values input_id, Qt::Key key_pressed) {
+    // Remove duplicates
+    for (auto& pair : key_map) {
+        if (pair.second == key_pressed)
+            pair.second = Qt::Key_unknown;
     }
+
+    key_map[input_id] = key_pressed;
 }
diff --git a/src/citra_qt/configure_input.h b/src/citra_qt/configure_input.h
index 5183b904d7c87f702530be656081c807c35c8349..bc343db83002625afeb6432a87b1c53832ea5560 100644
--- a/src/citra_qt/configure_input.h
+++ b/src/citra_qt/configure_input.h
@@ -7,7 +7,7 @@
 #include <memory>
 #include <QKeyEvent>
 #include <QWidget>
-#include "citra_qt/config.h"
+#include <boost/optional.hpp>
 #include "core/settings.h"
 #include "ui_configure_input.h"
 
@@ -30,35 +30,28 @@ public:
 
 private:
     std::unique_ptr<Ui::ConfigureInput> ui;
-    std::map<Settings::NativeInput::Values, QPushButton*> input_mapping;
-    int key_pressed;
-    QPushButton* changing_button = nullptr; ///< button currently waiting for key press.
-    QString previous_mapping;
-    QTimer* timer;
 
-    /// Load configuration settings into button text
-    void setConfiguration();
+    /// This input is currently awaiting configuration.
+    /// (i.e.: its corresponding QPushButton has been pressed.)
+    boost::optional<Settings::NativeInput::Values> current_input_id;
+    std::unique_ptr<QTimer> timer;
 
-    /// Check all inputs for duplicate keys. Clears out any other button with the same value as this
-    /// button's new value.
-    void removeDuplicates(const QString& newValue);
-
-    /// Handle key press event for input tab when a button is 'waiting'.
-    void keyPressEvent(QKeyEvent* event) override;
-
-    /// Convert key ASCII value to its' letter/name
-    QString getKeyName(int key_code) const;
-
-    /// Convert letter/name of key to its ASCII value.
-    Qt::Key getKeyValue(const QString& text) const;
-
-    /// Set button text to name of key pressed.
-    void setKey();
-
-private slots:
-    /// Event handler for all button released() event.
-    void handleClick();
+    /// Each input is represented by a QPushButton.
+    std::map<Settings::NativeInput::Values, QPushButton*> button_map;
+    /// Each input is configured to respond to the press of a Qt::Key.
+    std::map<Settings::NativeInput::Values, Qt::Key> key_map;
 
+    /// Load configuration settings.
+    void loadConfiguration();
     /// Restore all buttons to their default values.
     void restoreDefaults();
+    /// Update UI to reflect current configuration.
+    void updateButtonLabels();
+
+    /// Called when the button corresponding to input_id was pressed.
+    void handleClick(Settings::NativeInput::Values input_id);
+    /// Handle key press events.
+    void keyPressEvent(QKeyEvent* event) override;
+    /// Configure input input_id to respond to key key_pressed.
+    void setInput(Settings::NativeInput::Values input_id, Qt::Key key_pressed);
 };