summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2016-10-14 16:16:02 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2016-10-16 14:10:29 +0000
commit063997f44ffc1b6650ef6d67832674d5511fdb63 (patch)
tree17849c39210b9f28db930ebd67c2acf6059eae63 /src/widgets
parent0cc2a75ad8c96d2c2bc3117c6291d964e215aca2 (diff)
QMenu: don't force platform instance creation on construction
There's a conflict between QGtk3Menu and QDbusPlatformMenuBar. The problem is that on Unity the type of the platform menu instance must be different depending on whether the menu is in the global menubar or a standalone context menu. Since QMenu creates a platform menu instance at construction time, it does not yet know whether it will be added into a menubar. QMenuBar checks that the QMenu already has a platform menu instance, and passes it to the platform menubar. As a result, a QGtk3Menu instance is passed to QDbusPlatformMenuBar. Currently, a standalone QMenu does not use the native platform menu instance. Only menus that are added to a QMenuBar do. Therefore we don't need to create the platform instance when QMenu is constructed, but only after it is added to QMenuBar. The platform menu instance creation is implemented in QMenuBarPrivate::getPlatformMenu(), and QMenu::setPlatformMenu() calls syncPlatformMenu() to take care of syncing the QMenu properties and actions to the new platform menu instance. The macOS-specific methods QMenu::toNSMenu() and QMenu::setAsDockMenu() rely on the platform menu instance, and must therefore create it on demand. This is a hot fix for the release blocker, not a long term solution. In the future, if standalone QMenus are made to use native platform menu instances, the instance must be created lazily when the menu is about to be made visible. Task-number: QTBUG-56526 Change-Id: I044933cabb1639406fe47908dfc4b1903af214d1 Reviewed-by: Dmitry Shachnev <mitya57@gmail.com> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/widgets/qmenu.cpp9
-rw-r--r--src/widgets/widgets/qmenu_mac.mm6
-rw-r--r--src/widgets/widgets/qmenu_p.h1
-rw-r--r--src/widgets/widgets/qmenubar.cpp4
4 files changed, 17 insertions, 3 deletions
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index d957dda162..a983dc6fde 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -153,12 +153,19 @@ void QMenuPrivate::init()
scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
}
- setPlatformMenu(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
sloppyState.initialize(q);
delayState.initialize(q);
mousePopupDelay = q->style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, q);
}
+QPlatformMenu *QMenuPrivate::createPlatformMenu()
+{
+ Q_Q(QMenu);
+ if (platformMenu.isNull())
+ q->setPlatformMenu(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
+ return platformMenu.data();
+}
+
void QMenuPrivate::setPlatformMenu(QPlatformMenu *menu)
{
Q_Q(QMenu);
diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm
index fef1eb2cf4..f9f3ad08dc 100644
--- a/src/widgets/widgets/qmenu_mac.mm
+++ b/src/widgets/widgets/qmenu_mac.mm
@@ -80,11 +80,12 @@ inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePla
*/
NSMenu *QMenu::toNSMenu()
{
+ Q_D(QMenu);
// Call into the cocoa platform plugin: qMenuToNSMenu(platformMenu())
QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("qmenutonsmenu");
if (function) {
typedef void* (*QMenuToNSMenuFunction)(QPlatformMenu *platformMenu);
- return reinterpret_cast<NSMenu *>(reinterpret_cast<QMenuToNSMenuFunction>(function)(platformMenu()));
+ return reinterpret_cast<NSMenu *>(reinterpret_cast<QMenuToNSMenuFunction>(function)(d->createPlatformMenu()));
}
return nil;
}
@@ -98,11 +99,12 @@ NSMenu *QMenu::toNSMenu()
*/
void QMenu::setAsDockMenu()
{
+ Q_D(QMenu);
// Call into the cocoa platform plugin: setDockMenu(platformMenu())
QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("setdockmenu");
if (function) {
typedef void (*SetDockMenuFunction)(QPlatformMenu *platformMenu);
- reinterpret_cast<SetDockMenuFunction>(function)(platformMenu());
+ reinterpret_cast<SetDockMenuFunction>(function)(d->createPlatformMenu());
}
}
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index 2b0dc482da..3166e6f6cd 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -286,6 +286,7 @@ public:
delete platformMenu.data();
}
void init();
+ QPlatformMenu *createPlatformMenu();
void setPlatformMenu(QPlatformMenu *menu);
void syncPlatformMenu();
#ifdef Q_OS_OSX
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index a77c0f9753..63fe09f77e 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1192,6 +1192,10 @@ QPlatformMenu *QMenuBarPrivate::getPlatformMenu(QAction *action)
QPlatformMenu *platformMenu = action->menu()->platformMenu();
if (!platformMenu && platformMenuBar) {
platformMenu = platformMenuBar->createMenu();
+ // QPlatformMenuBar::createMenu() was introduced in Qt 5.7. Not all third party
+ // platform themes are using it, so fallback to QPlatformTheme::createPlatformMenu().
+ if (!platformMenu)
+ platformMenu = QGuiApplicationPrivate::platformTheme()->createPlatformMenu();
if (platformMenu)
action->menu()->setPlatformMenu(platformMenu);
}