Skip to content

Commit

Permalink
menubar: toggle with Alt key
Browse files Browse the repository at this point in the history
  • Loading branch information
ronso0 committed Dec 25, 2023
1 parent 0569b43 commit 17dd1f4
Show file tree
Hide file tree
Showing 11 changed files with 378 additions and 16 deletions.
49 changes: 41 additions & 8 deletions src/controllers/keyboard/keyboardeventfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ KeyboardEventFilter::KeyboardEventFilter(ConfigObject<ConfigValueKbd>* pKbdConfi
QObject* parent,
const char* name)
: QObject(parent),
#ifndef __APPLE__
m_altPressedWithoutKey(false),
#endif
m_pKbdConfigObject(nullptr) {
setObjectName(name);
setKeyboardConfig(pKbdConfigObject);
Expand Down Expand Up @@ -42,6 +45,9 @@ bool KeyboardEventFilter::eventFilter(QObject*, QEvent* e) {

QKeySequence ks = getKeySeq(ke);
if (!ks.isEmpty()) {
#ifndef __APPLE__
m_altPressedWithoutKey = false;
#endif
ConfigValueKbd ksv(ks);
// Check if a shortcut is defined
bool result = false;
Expand All @@ -68,10 +74,32 @@ bool KeyboardEventFilter::eventFilter(QObject*, QEvent* e) {
}
}
return result;
#ifndef __APPLE__
} else {
// getKeySeq() returns empty string if the press was a modifier only
if ((ke->modifiers() & Qt::AltModifier) && !m_altPressedWithoutKey) {
// on Linux pressing Alt sends Alt+Qt::Key_Alt, so checking for
// Alt modifier is sufficient.
// Activate this in case there are issues on Windows
// || ke->key() == Qt::Key_Alt) {
m_altPressedWithoutKey = true;
}
#endif
}
} else if (e->type() == QEvent::KeyRelease) {
QKeyEvent* ke = (QKeyEvent*)e;

#ifndef __APPLE__
// QAction hotkeys are consumed by the object the created them, so we will
// not receive those here, for example WMainMenuBar hotkeys.
// However, it may happen that we receive an Alt+[key] combo RELEASE for
// which no [key] PRESS was registered.
if (m_altPressedWithoutKey && ke->key() == Qt::Key_Alt) {
emit altPressedWithoutKeys();
}
m_altPressedWithoutKey = false;
#endif

#ifdef __APPLE__
// On Mac OSX the nativeScanCode is empty
int keyId = ke->key();
Expand Down Expand Up @@ -119,9 +147,16 @@ bool KeyboardEventFilter::eventFilter(QObject*, QEvent* e) {
}

QKeySequence KeyboardEventFilter::getKeySeq(QKeyEvent* e) {
QString modseq;
QKeySequence k;

if ((e->key() >= Qt::Key_Shift && e->key() <= Qt::Key_Alt) ||
e->key() == Qt::Key_AltGr) {
// Do not act on Modifier only, Shift, Ctrl, Meta, Alt and AltGr
// avoid returning "khmer vowel sign ie (U+17C0)"
return k;
}

QString modseq;
// TODO(XXX) check if we may simply return QKeySequence(e->modifiers()+e->key())

if (e->modifiers() & Qt::ShiftModifier) {
Expand All @@ -140,17 +175,15 @@ QKeySequence KeyboardEventFilter::getKeySeq(QKeyEvent* e) {
modseq += "Meta+";
}

if (e->key() >= 0x01000020 && e->key() <= 0x01000023) {
// Do not act on Modifier only
// avoid returning "khmer vowel sign ie (U+17C0)"
return k;
}

QString keyseq = QKeySequence(e->key()).toString();
k = QKeySequence(modseq + keyseq);

if (CmdlineArgs::Instance().getDeveloper()) {
qDebug() << "keyboard press: " << k.toString();
if (e->type() == QEvent::KeyPress) {
qDebug() << "keyboard press: " << k.toString();
} else if (e->type() == QEvent::KeyRelease) {
qDebug() << "keyboard release: " << k.toString();
}
}
return k;
}
Expand Down
9 changes: 9 additions & 0 deletions src/controllers/keyboard/keyboardeventfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class KeyboardEventFilter : public QObject {
void setKeyboardConfig(ConfigObject<ConfigValueKbd> *pKbdConfigObject);
ConfigObject<ConfigValueKbd>* getKeyboardConfig();

#ifndef __APPLE__
signals:
void altPressedWithoutKeys();
#endif

private:
struct KeyDownInformation {
KeyDownInformation(int keyId, int modifiers, ControlObject* pControl)
Expand All @@ -38,6 +43,10 @@ class KeyboardEventFilter : public QObject {
ControlObject* pControl;
};

#ifndef __APPLE__
bool m_altPressedWithoutKey;
#endif

// Returns a valid QString with modifier keys from a QKeyEvent
QKeySequence getKeySeq(QKeyEvent *e);

Expand Down
105 changes: 104 additions & 1 deletion src/mixxxmainwindow.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "mixxxmainwindow.h"

#include <QCheckBox>
#include <QCloseEvent>
#include <QDebug>
#include <QDesktopServices>
Expand Down Expand Up @@ -81,6 +82,9 @@ inline bool supportsGlobalMenu() {
return false;
}
#endif

const ConfigKey kHideMenuBarConfigKey = ConfigKey("[Config]", "hide_menubar");
const ConfigKey kMenuBarHintConfigKey = ConfigKey("[Config]", "show_menubar_hint");
} // namespace

MixxxMainWindow::MixxxMainWindow(std::shared_ptr<mixxx::CoreServices> pCoreServices)
Expand Down Expand Up @@ -302,8 +306,15 @@ void MixxxMainWindow::initialize() {
this,
&MixxxMainWindow::rebootMixxxView,
Qt::DirectConnection);
#ifndef __APPLE__
connect(m_pPrefDlg,
&DlgPreferences::menuBarAutoHideChanged,
this,
&MixxxMainWindow::slotUpdateMenuBarAltKeyConnection,
Qt::DirectConnection);
#endif

// Connect signals to the menubar. Should be done before emit newSkinLoaded.
// Connect signals to the menubar. Should be done before emit skinLoaded.
connectMenuBar();

QWidget* oldWidget = m_pCentralWidget;
Expand Down Expand Up @@ -377,6 +388,21 @@ void MixxxMainWindow::initialize() {
// corrupted. See bug 521509 -- bkgood ?? -- vrince
setCentralWidget(m_pCentralWidget);

#ifndef __APPLE__
// Ask for permission to auto-hide the menu bar if applicable.
#ifdef __LINUX__
// This makes no sense When starting in windowed mode with a global menu,
// we''l ask when going fullscreen
if (!m_supportsGlobalMenuBar || isFullScreen()) {
alwaysHideMenuBarDlg();
slotUpdateMenuBarAltKeyConnection();
}
#else
alwaysHideMenuBarDlg();
slotUpdateMenuBarAltKeyConnection();
#endif
#endif

// Show the menubar after the launch image is replaced by the skin widget,
// otherwise it would shift the launch image shortly before the skin is visible.
m_pMenuBar->show();
Expand Down Expand Up @@ -529,6 +555,54 @@ void MixxxMainWindow::initializeWindow() {
slotUpdateWindowTitle(TrackPointer());
}

#ifndef __APPLE__
void MixxxMainWindow::alwaysHideMenuBarDlg() {
if (!m_pCoreServices->getSettings()->getValue<bool>(
kMenuBarHintConfigKey, true)) {
return;
}

// TODO(ronso0) Use radio buttons instead?

//: Always show the menu bar
QString hideBtnLabel = tr("Hide");
QString showBtnLabel = tr("Always show");
QString title = tr("Allow Mixxx to hide the menu bar?");
//: Keep formatting tags <b> (bold text) and <br> (linebreak).
//: %1 is the placeholder for the 'Always show' button label
QString desc = tr(
"The Mixxx menu bar is hidden and can be toggled with a single press "
"of the <b>Alt</b> key.<br><br>"
"Click <b>%1</b> to agree.<br><br>"
"Click <b>%2</b> to disable that, for example if you don't use Mixxx "
"with a keyboard.<br><br>"
"You can change this setting any time in Preferences -> Interface."
"<br>") // some extra margin to the checkbox
.arg(hideBtnLabel, showBtnLabel);

QMessageBox msg;
msg.setIcon(QMessageBox::Question);
msg.setWindowTitle(title);
msg.setText(desc);
QCheckBox askAgainCheckBox;
askAgainCheckBox.setText(tr("Ask me again"));
askAgainCheckBox.setCheckState(Qt::Checked);
msg.setCheckBox(&askAgainCheckBox);
QPushButton* pHideBtn = msg.addButton(hideBtnLabel, QMessageBox::AcceptRole);
QPushButton* pShowBtn = msg.addButton(showBtnLabel, QMessageBox::RejectRole);
msg.setDefaultButton(pShowBtn);
msg.exec();

m_pCoreServices->getSettings()->setValue(
kMenuBarHintConfigKey,
askAgainCheckBox.checkState() == Qt::Checked ? 1 : 0);

m_pCoreServices->getSettings()->setValue(
kHideMenuBarConfigKey,
msg.clickedButton() == pHideBtn ? 1 : 0);
}
#endif

QDialog::DialogCode MixxxMainWindow::soundDeviceErrorDlg(
const QString &title, const QString &text, bool* retryClicked) {
QMessageBox msgBox;
Expand Down Expand Up @@ -887,6 +961,29 @@ void MixxxMainWindow::connectMenuBar() {
#endif
}

#ifndef __APPLE__
void MixxxMainWindow::slotUpdateMenuBarAltKeyConnection() {
if (!m_pCoreServices->getKeyboardEventFilter() || !m_pMenuBar) {
return;
}

if (m_pCoreServices->getSettings()->getValue<bool>(kHideMenuBarConfigKey, false)) {
connect(m_pCoreServices->getKeyboardEventFilter().get(),
&KeyboardEventFilter::altPressedWithoutKeys,
m_pMenuBar,
&WMainMenuBar::slotToggleMenuBar,
Qt::UniqueConnection);
m_pMenuBar->hideMenuBar();
} else {
disconnect(m_pCoreServices->getKeyboardEventFilter().get(),
&KeyboardEventFilter::altPressedWithoutKeys,
m_pMenuBar,
&WMainMenuBar::slotToggleMenuBar);
m_pMenuBar->showMenuBar();
}
}
#endif

void MixxxMainWindow::slotFileLoadSongPlayer(int deck) {
QString group = PlayerManager::groupForDeck(deck - 1);

Expand Down Expand Up @@ -1199,6 +1296,12 @@ bool MixxxMainWindow::eventFilter(QObject* obj, QEvent* event) {
QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, isFullScreenNow);
createMenuBar();
connectMenuBar();
if (isFullScreenNow) {
// With a global menu we didn't show the menubar auto-hide dialog
// during (windowed) startup, so ask now.
alwaysHideMenuBarDlg();
}
slotUpdateMenuBarAltKeyConnection();
}
#endif
// This will toggle the Fullscreen checkbox and hide the menubar if
Expand Down
9 changes: 9 additions & 0 deletions src/mixxxmainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ class MixxxMainWindow : public QMainWindow {
void slotNoAuxiliaryInputConfigured();
void slotNoDeckPassthroughInputConfigured();
void slotNoVinylControlInputConfigured();
#ifndef __APPLE__
/// Update whether the menubar is toggled pressing the Alt key and show/hide
/// it accordingly
void slotUpdateMenuBarAltKeyConnection();
#endif

void initializationProgressUpdate(int progress, const QString& serviceName);

Expand All @@ -104,6 +109,10 @@ class MixxxMainWindow : public QMainWindow {
bool loadConfiguredSkin();

bool confirmExit();
#ifndef __APPLE__
void alwaysHideMenuBarDlg();
#endif

QDialog::DialogCode soundDeviceErrorDlg(
const QString &title, const QString &text, bool* retryClicked);
QDialog::DialogCode soundDeviceBusyDlg(bool* retryClicked);
Expand Down
5 changes: 5 additions & 0 deletions src/preferences/dialog/dlgpreferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ DlgPreferences::DlgPreferences(
this,
&DlgPreferences::reloadUserInterface,
Qt::DirectConnection);
connect(pInterfacePage,
&DlgPrefInterface::menuBarAutoHideChanged,
this,
&DlgPreferences::menuBarAutoHideChanged,
Qt::DirectConnection);
addPageWidget(PreferencesPage(pInterfacePage,
new QTreeWidgetItem(
contentsTreeWidget, QTreeWidgetItem::Type)),
Expand Down
2 changes: 1 addition & 1 deletion src/preferences/dialog/dlgpreferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ class DlgPreferences : public QDialog, public Ui::DlgPreferencesDlg {
// Emitted if the user clicks Reset to Defaults.
void resetToDefaults();

signals:
void reloadUserInterface();
void tooltipModeChanged(mixxx::TooltipsPreference tooltipMode);
void menuBarAutoHideChanged();

protected:
bool eventFilter(QObject*, QEvent*);
Expand Down
21 changes: 19 additions & 2 deletions src/preferences/dialog/dlgprefinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ const QString kSchemeKey = QStringLiteral("Scheme");
const QString kResizableSkinKey = QStringLiteral("ResizableSkin");
const QString kLocaleKey = QStringLiteral("Locale");
const QString kTooltipsKey = QStringLiteral("Tooltips");
const QString kHideMenuBarKey = QStringLiteral("hide_menubar");

// TODO move these to a common *_defs.h file, some are also used by e.g. MixxxMainWindow
const bool kStartInFullscreenDefault = false;
const bool kHideMenuBarDefault = true;

} // namespace

Expand Down Expand Up @@ -273,7 +278,10 @@ void DlgPrefInterface::slotUpdate() {
spinBoxScaleFactor->setMinimum(m_minScaleFactor * 100);

checkBoxStartFullScreen->setChecked(m_pConfig->getValue(
ConfigKey(kConfigGroup, kStartInFullscreenKey), false));
ConfigKey(kConfigGroup, kStartInFullscreenKey), kStartInFullscreenDefault));

checkBoxHideMenuBar->setChecked(m_pConfig->getValue(
ConfigKey(kConfigGroup, kHideMenuBarKey), kHideMenuBarDefault));

loadTooltipPreferenceFromConfig();

Expand All @@ -296,7 +304,12 @@ void DlgPrefInterface::slotResetToDefaults() {
spinBoxScaleFactor->setValue(100);

// Don't start in full screen.
checkBoxStartFullScreen->setChecked(false);
checkBoxStartFullScreen->setChecked(kStartInFullscreenDefault);

// Always show the menu bar
checkBoxHideMenuBar->setChecked(kHideMenuBarDefault);
// Also show the menu bar hint again on next start?
// Use bool member to set [Config],show_menubar_hint to 1 in slotApply()

// Inhibit the screensaver
comboBoxScreensaver->setCurrentIndex(comboBoxScreensaver->findData(
Expand Down Expand Up @@ -405,6 +418,10 @@ void DlgPrefInterface::slotApply() {
m_pConfig->set(ConfigKey(kConfigGroup, kStartInFullscreenKey),
ConfigValue(checkBoxStartFullScreen->isChecked()));

m_pConfig->set(ConfigKey(kConfigGroup, kHideMenuBarKey),
ConfigValue(checkBoxHideMenuBar->isChecked()));
emit menuBarAutoHideChanged();

m_pConfig->set(ConfigKey(kControlsGroup, kTooltipsKey),
ConfigValue(static_cast<int>(m_tooltipMode)));
emit tooltipModeChanged(m_tooltipMode);
Expand Down
1 change: 1 addition & 0 deletions src/preferences/dialog/dlgprefinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class DlgPrefInterface : public DlgPreferencePage, public Ui::DlgPrefControlsDlg

signals:
void reloadUserInterface();
void menuBarAutoHideChanged();
void tooltipModeChanged(mixxx::TooltipsPreference tooltipMode);

private:
Expand Down
Loading

0 comments on commit 17dd1f4

Please sign in to comment.