Fixed Return and Enter being treated as different keys on Mac OS (#6729)
Co-authored-by: Chad Gorman <nevicar@Chads-Mini.localdomain> Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
This commit is contained in:
@@ -44,6 +44,7 @@
|
|||||||
- Bugfix: Fixed <kbd>CMD</kbd> + <kbd>DELETE</kbd> behavior in the user notes editing dialog for macOS. (#6676)
|
- Bugfix: Fixed <kbd>CMD</kbd> + <kbd>DELETE</kbd> behavior in the user notes editing dialog for macOS. (#6676)
|
||||||
- Bugfix: Fixed a potential crash when closing Chatterino with a slow network connection. (#6645)
|
- Bugfix: Fixed a potential crash when closing Chatterino with a slow network connection. (#6645)
|
||||||
- Bugfix: Disable "Sort Tabs Alphabetically" action when notebook layout is locked. (#6710)
|
- Bugfix: Disable "Sort Tabs Alphabetically" action when notebook layout is locked. (#6710)
|
||||||
|
- Bugfix: Fixed Return and Enter being treated as different keys on Mac OS. (#6726)
|
||||||
- Dev: Update release documentation. (#6498)
|
- Dev: Update release documentation. (#6498)
|
||||||
- Dev: Make code sanitizers opt in with the `CHATTERINO_SANITIZER_SUPPORT` CMake option. After that's enabled, use the `SANITIZE_*` flag to enable individual sanitizers. (#6493)
|
- Dev: Make code sanitizers opt in with the `CHATTERINO_SANITIZER_SUPPORT` CMake option. After that's enabled, use the `SANITIZE_*` flag to enable individual sanitizers. (#6493)
|
||||||
- Dev: Remove unused QTextCodec includes. (#6487)
|
- Dev: Remove unused QTextCodec includes. (#6487)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "util/RapidJsonSerializeQString.hpp" // IWYU pragma: keep
|
#include "util/RapidJsonSerializeQString.hpp" // IWYU pragma: keep
|
||||||
|
|
||||||
#include <pajlada/settings.hpp>
|
#include <pajlada/settings.hpp>
|
||||||
|
#include <QKeyCombination>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
@@ -138,14 +139,27 @@ std::vector<QShortcut *> HotkeyController::shortcutsForCategory(
|
|||||||
};
|
};
|
||||||
auto qs = QKeySequence(hotkey->keySequence());
|
auto qs = QKeySequence(hotkey->keySequence());
|
||||||
|
|
||||||
auto stringified = qs.toString(QKeySequence::NativeText);
|
// Create shortcut for the original key sequence
|
||||||
if (stringified.contains("Return"))
|
|
||||||
{
|
|
||||||
stringified.replace("Return", "Enter");
|
|
||||||
auto copy = QKeySequence(stringified, QKeySequence::NativeText);
|
|
||||||
createShortcutFromKeySeq(copy);
|
|
||||||
}
|
|
||||||
createShortcutFromKeySeq(qs);
|
createShortcutFromKeySeq(qs);
|
||||||
|
|
||||||
|
// Qt treats Key_Return (main keyboard) and Key_Enter (numpad) as different keys, but they are expect to behave identically.
|
||||||
|
// Create a duplicate shortcut with the alternate key.
|
||||||
|
for (int i = 0; i < qs.count(); i++)
|
||||||
|
{
|
||||||
|
auto combo = qs[i];
|
||||||
|
if (combo.key() == Qt::Key_Return)
|
||||||
|
{
|
||||||
|
QKeyCombination enterCombo(combo.keyboardModifiers(),
|
||||||
|
Qt::Key_Enter);
|
||||||
|
createShortcutFromKeySeq(QKeySequence(enterCombo));
|
||||||
|
}
|
||||||
|
else if (combo.key() == Qt::Key_Enter)
|
||||||
|
{
|
||||||
|
QKeyCombination returnCombo(combo.keyboardModifiers(),
|
||||||
|
Qt::Key_Return);
|
||||||
|
createShortcutFromKeySeq(QKeySequence(returnCombo));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
#include "controllers/hotkeys/ActionNames.hpp"
|
#include "controllers/hotkeys/ActionNames.hpp"
|
||||||
#include "controllers/hotkeys/HotkeyCategory.hpp"
|
#include "controllers/hotkeys/HotkeyCategory.hpp"
|
||||||
|
|
||||||
|
#include <QKeyCombination>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
@@ -52,4 +54,61 @@ std::optional<ActionDefinition> findHotkeyActionDefinition(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QKeySequence normalizeKeySequence(const QKeySequence &seq)
|
||||||
|
{
|
||||||
|
if (seq.isEmpty())
|
||||||
|
{
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, check if any normalization is needed
|
||||||
|
bool needsNormalization = false;
|
||||||
|
for (int i = 0; i < seq.count(); i++)
|
||||||
|
{
|
||||||
|
if (seq[i].key() == Qt::Key_Enter)
|
||||||
|
{
|
||||||
|
needsNormalization = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!needsNormalization)
|
||||||
|
{
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build normalized key combinations, preserving all keys in the sequence
|
||||||
|
// QKeySequence supports up to 4 key combinations
|
||||||
|
std::array<QKeyCombination, 4> combos{};
|
||||||
|
int count = seq.count();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
auto combo = seq[i];
|
||||||
|
if (combo.key() == Qt::Key_Enter)
|
||||||
|
{
|
||||||
|
combos.at(i) =
|
||||||
|
QKeyCombination(combo.keyboardModifiers(), Qt::Key_Return);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combos.at(i) = combo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct QKeySequence with the appropriate number of keys
|
||||||
|
switch (count)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return {combos.at(0)};
|
||||||
|
case 2:
|
||||||
|
return {combos.at(0), combos.at(1)};
|
||||||
|
case 3:
|
||||||
|
return {combos.at(0), combos.at(1), combos.at(2)};
|
||||||
|
case 4:
|
||||||
|
default:
|
||||||
|
return {combos.at(0), combos.at(1), combos.at(2), combos.at(3)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "controllers/hotkeys/ActionNames.hpp"
|
#include "controllers/hotkeys/ActionNames.hpp"
|
||||||
|
|
||||||
|
#include <QKeySequence>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -17,4 +18,7 @@ std::vector<QString> parseHotkeyArguments(QString argumentString);
|
|||||||
std::optional<ActionDefinition> findHotkeyActionDefinition(
|
std::optional<ActionDefinition> findHotkeyActionDefinition(
|
||||||
HotkeyCategory category, const QString &action);
|
HotkeyCategory category, const QString &action);
|
||||||
|
|
||||||
|
// convert key_enter to key_return so that both keys function the same. preserves multi-key sequences and combinations.
|
||||||
|
QKeySequence normalizeKeySequence(const QKeySequence &seq);
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include "controllers/hotkeys/HotkeyHelpers.hpp"
|
#include "controllers/hotkeys/HotkeyHelpers.hpp"
|
||||||
#include "ui_EditHotkeyDialog.h"
|
#include "ui_EditHotkeyDialog.h"
|
||||||
|
|
||||||
|
#include <QSignalBlocker>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
EditHotkeyDialog::EditHotkeyDialog(const std::shared_ptr<Hotkey> hotkey,
|
EditHotkeyDialog::EditHotkeyDialog(const std::shared_ptr<Hotkey> hotkey,
|
||||||
@@ -21,6 +23,18 @@ EditHotkeyDialog::EditHotkeyDialog(const std::shared_ptr<Hotkey> hotkey,
|
|||||||
, data_(hotkey)
|
, data_(hotkey)
|
||||||
{
|
{
|
||||||
this->ui_->setupUi(this);
|
this->ui_->setupUi(this);
|
||||||
|
// normalize Key_Enter (numpad) to Key_Return so both Enter keys display and behave identically
|
||||||
|
QObject::connect(
|
||||||
|
this->ui_->keyComboEdit, &QKeySequenceEdit::keySequenceChanged, this,
|
||||||
|
[this](const QKeySequence &keySequence) {
|
||||||
|
auto normalized = normalizeKeySequence(keySequence);
|
||||||
|
if (normalized != keySequence)
|
||||||
|
{
|
||||||
|
// Block signals to prevent infinite loop
|
||||||
|
QSignalBlocker blocker(this->ui_->keyComboEdit);
|
||||||
|
this->ui_->keyComboEdit->setKeySequence(normalized);
|
||||||
|
}
|
||||||
|
});
|
||||||
this->setStyleSheet(R"(QToolTip {
|
this->setStyleSheet(R"(QToolTip {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "common/QLogging.hpp"
|
#include "common/QLogging.hpp"
|
||||||
#include "controllers/hotkeys/Hotkey.hpp"
|
#include "controllers/hotkeys/Hotkey.hpp"
|
||||||
#include "controllers/hotkeys/HotkeyController.hpp"
|
#include "controllers/hotkeys/HotkeyController.hpp"
|
||||||
|
#include "controllers/hotkeys/HotkeyHelpers.hpp"
|
||||||
#include "controllers/hotkeys/HotkeyModel.hpp"
|
#include "controllers/hotkeys/HotkeyModel.hpp"
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "widgets/dialogs/EditHotkeyDialog.hpp"
|
#include "widgets/dialogs/EditHotkeyDialog.hpp"
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
#include <QKeySequenceEdit>
|
#include <QKeySequenceEdit>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QSignalBlocker>
|
||||||
#include <QTableView>
|
#include <QTableView>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -94,8 +96,16 @@ KeyboardSettingsPage::KeyboardSettingsPage()
|
|||||||
auto *searchText = new QLabel("Search keybind:", this);
|
auto *searchText = new QLabel("Search keybind:", this);
|
||||||
|
|
||||||
QObject::connect(keySequenceInput, &QKeySequenceEdit::keySequenceChanged,
|
QObject::connect(keySequenceInput, &QKeySequenceEdit::keySequenceChanged,
|
||||||
[view](const QKeySequence &keySequence) {
|
this,
|
||||||
view->filterSearchResultsHotkey(keySequence);
|
[view, keySequenceInput](const QKeySequence &keySequence) {
|
||||||
|
// Normalize Key_Enter (numpad) to Key_Return for consistent search
|
||||||
|
auto normalized = normalizeKeySequence(keySequence);
|
||||||
|
if (normalized != keySequence)
|
||||||
|
{
|
||||||
|
QSignalBlocker blocker(keySequenceInput);
|
||||||
|
keySequenceInput->setKeySequence(normalized);
|
||||||
|
}
|
||||||
|
view->filterSearchResultsHotkey(normalized);
|
||||||
});
|
});
|
||||||
view->addCustomButton(searchText);
|
view->addCustomButton(searchText);
|
||||||
view->addCustomButton(keySequenceInput);
|
view->addCustomButton(keySequenceInput);
|
||||||
|
|||||||
Reference in New Issue
Block a user