Make shortcuts work for platform menu bars

When a platform menu bar is used, the QMenuBar is hidden, so shortcuts
for QActions attached only to it do not work.

Extend the macOS-specific code to treat such menubars as visible to
other platforms, to make the shortcuts work.

The exception is made for internal QMenuBar shortcuts, which are
forwarded to the platform menu. A follow-up change will add support
for this to QDBusPlatformMenu. The updateGeometries() method is called
for platform menu bars too to make sure the internal shortcuts are
registered even if the global menu is in use.

Add two cases to the tst_QMenuBar::activatedCount() test to test
both native and non-native menu bars when possible (it now passes with
native menu bars too).

Change-Id: I2d7128512719ac199cd3f8f7ba28333d04d84ed4
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Dmitry Shachnev 2016-11-02 10:51:39 +03:00 committed by Shawn Rutledge
parent 3e31b71b9c
commit 287f548d4c
3 changed files with 33 additions and 13 deletions

View File

@ -141,9 +141,11 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context)
static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window)
{
bool visible = w->isVisible();
#if defined(Q_OS_DARWIN) && !defined(QT_NO_MENUBAR)
if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
visible = true;
#ifndef QT_NO_MENUBAR
if (QMenuBar *menuBar = qobject_cast<QMenuBar *>(w)) {
if (menuBar->isNativeMenuBar())
visible = true;
}
#endif
if (!visible || !w->isEnabled())

View File

@ -1271,10 +1271,12 @@ void QMenuBar::actionEvent(QActionEvent *e)
} else if(e->type() == QEvent::ActionRemoved) {
e->action()->disconnect(this);
}
if (isVisible()) {
// updateGeometries() is also needed for native menu bars because
// it updates shortcutIndexMap
if (isVisible() || isNativeMenuBar())
d->updateGeometries();
if (isVisible())
update();
}
}
/*!
@ -1686,6 +1688,13 @@ void QMenuBarPrivate::_q_internalShortcutActivated(int id)
{
Q_Q(QMenuBar);
QAction *act = actions.at(id);
if (act && act->menu()) {
if (QPlatformMenu *platformMenu = act->menu()->platformMenu()) {
platformMenu->showPopup(q->windowHandle(), actionRects.at(id), Q_NULLPTR);
return;
}
}
setCurrentAction(act, true, true);
if (act && !act->menu()) {
activateAction(act, QAction::Trigger);

View File

@ -93,6 +93,7 @@ private slots:
#if !defined(Q_OS_DARWIN)
void accel();
void activatedCount();
void activatedCount_data();
void check_accelKeys();
void check_cursorKeys1();
@ -144,8 +145,8 @@ protected slots:
void slotForTaskQTBUG53205();
private:
TestMenu initSimpleMenuBar(QMenuBar *mb);
TestMenu initWindowWithSimpleMenuBar(QMainWindow &w);
TestMenu initSimpleMenuBar(QMenuBar *mb, bool forceNonNative = true);
TestMenu initWindowWithSimpleMenuBar(QMainWindow &w, bool forceNonNative = true);
QAction *createCharacterAction(QMenu *menu, char lowerAscii);
QMenu *addNumberedMenu(QMenuBar *mb, int n);
TestMenu initComplexMenuBar(QMenuBar *mb);
@ -213,10 +214,10 @@ void tst_QMenuBar::cleanup()
// Create a simple menu bar and connect its actions to onSimpleActivated().
TestMenu tst_QMenuBar::initSimpleMenuBar(QMenuBar *mb)
{
TestMenu tst_QMenuBar::initSimpleMenuBar(QMenuBar *mb, bool forceNonNative) {
TestMenu result;
mb->setNativeMenuBar(false);
if (forceNonNative)
mb->setNativeMenuBar(false);
connect(mb, SIGNAL(triggered(QAction*)), this, SLOT(onSimpleActivated(QAction*)));
QMenu *menu = mb->addMenu(QStringLiteral("&accel"));
QAction *action = menu->addAction(QStringLiteral("menu1") );
@ -239,11 +240,11 @@ TestMenu tst_QMenuBar::initSimpleMenuBar(QMenuBar *mb)
return result;
}
inline TestMenu tst_QMenuBar::initWindowWithSimpleMenuBar(QMainWindow &w)
inline TestMenu tst_QMenuBar::initWindowWithSimpleMenuBar(QMainWindow &w, bool forceNonNative)
{
w.resize(200, 200);
centerOnScreen(&w);
return initSimpleMenuBar(w.menuBar());
return initSimpleMenuBar(w.menuBar(), forceNonNative);
}
// add a menu with number n, set number as data.
@ -341,7 +342,8 @@ void tst_QMenuBar::activatedCount()
{
// create a popup menu with menu items set the accelerators later...
QMainWindow w;
initWindowWithSimpleMenuBar(w);
QFETCH( bool, forceNonNative );
initWindowWithSimpleMenuBar(w, forceNonNative);
w.show();
QApplication::setActiveWindow(&w);
QVERIFY(QTest::qWaitForWindowActive(&w));
@ -350,6 +352,13 @@ void tst_QMenuBar::activatedCount()
//wait(5000);
QCOMPARE( m_simpleActivatedCount, 2 ); //1 from the popupmenu and 1 from the menubar
}
void tst_QMenuBar::activatedCount_data()
{
QTest::addColumn<bool>("forceNonNative");
QTest::newRow( "forcing non-native menubar" ) << true;
QTest::newRow( "not forcing non-native menubar" ) << false;
}
#endif
void tst_QMenuBar::clear()