QMenu: Add support for QWidgetAction on Mac
The implementation follows a similar logic as in Qt 4 making sure we properly interface with the QPA backend. We also make sure to delay moving the action widget to the QPA menu until it's about to show. We still don't support moving the action widget back from QPA world into Qt, as explained in the QWidgetAction documentation. Task-number: QTBUG-19840 Change-Id: I47f6359b0806f967d80c67fbb1f36c3d5ec8603e Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com> Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>bb10
parent
379042b84c
commit
c7ed644fd1
|
|
@ -50,6 +50,9 @@
|
|||
#include "qlayout.h"
|
||||
#include "qpainter.h"
|
||||
#include <qpa/qplatformtheme.h>
|
||||
#ifdef Q_OS_OSX
|
||||
#include "qmacnativewidget_mac.h"
|
||||
#endif
|
||||
#include "qapplication.h"
|
||||
#include "qdesktopwidget.h"
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
|
|
@ -163,7 +166,7 @@ void QMenuPrivate::setPlatformMenu(QPlatformMenu *menu)
|
|||
|
||||
platformMenu = menu;
|
||||
if (!platformMenu.isNull()) {
|
||||
QObject::connect(platformMenu, SIGNAL(aboutToShow()), q, SIGNAL(aboutToShow()));
|
||||
QObject::connect(platformMenu, SIGNAL(aboutToShow()), q, SLOT(_q_platformMenuAboutToShow()));
|
||||
QObject::connect(platformMenu, SIGNAL(aboutToHide()), q, SIGNAL(aboutToHide()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1104,6 +1107,8 @@ void QMenuPrivate::_q_actionTriggered()
|
|||
Q_Q(QMenu);
|
||||
if (QAction *action = qobject_cast<QAction *>(q->sender())) {
|
||||
QPointer<QAction> actionGuard = action;
|
||||
if (platformMenu && widgetItems.value(action))
|
||||
platformMenu->dismiss();
|
||||
emit q->triggered(action);
|
||||
if (!activationRecursionGuard && actionGuard) {
|
||||
//in case the action has not been activated by the mouse
|
||||
|
|
@ -1134,6 +1139,24 @@ void QMenuPrivate::_q_actionHovered()
|
|||
}
|
||||
}
|
||||
|
||||
void QMenuPrivate::_q_platformMenuAboutToShow()
|
||||
{
|
||||
Q_Q(QMenu);
|
||||
|
||||
#ifdef Q_OS_OSX
|
||||
if (platformMenu)
|
||||
Q_FOREACH (QAction *action, q->actions())
|
||||
if (QWidget *widget = widgetItems.value(const_cast<QAction *>(action)))
|
||||
if (widget->parent() == q) {
|
||||
QPlatformMenuItem *menuItem = platformMenu->menuItemForTag(reinterpret_cast<quintptr>(action));
|
||||
moveWidgetToPlatformItem(widget, menuItem);
|
||||
platformMenu->syncMenuItem(menuItem);
|
||||
}
|
||||
#endif
|
||||
|
||||
emit q->aboutToShow();
|
||||
}
|
||||
|
||||
bool QMenuPrivate::hasMouseMoved(const QPoint &globalPos)
|
||||
{
|
||||
//determines if the mouse has moved (ie its initial position has
|
||||
|
|
@ -2996,8 +3019,19 @@ void QMenu::actionEvent(QActionEvent *e)
|
|||
if (e->action() == d->currentAction)
|
||||
d->currentAction = 0;
|
||||
if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
|
||||
if (QWidget *widget = d->widgetItems.value(wa))
|
||||
if (QWidget *widget = d->widgetItems.value(wa)) {
|
||||
#ifdef Q_OS_OSX
|
||||
QWidget *p = widget->parentWidget();
|
||||
if (p != this && qobject_cast<QMacNativeWidget *>(p)) {
|
||||
// This widget was reparented into a native Mac view
|
||||
// (see QMenuPrivate::moveWidgetToPlatformItem).
|
||||
// Reset the parent and delete the native widget.
|
||||
widget->setParent(this);
|
||||
p->deleteLater();
|
||||
}
|
||||
#endif
|
||||
wa->releaseWidget(widget);
|
||||
}
|
||||
}
|
||||
d->widgetItems.remove(e->action());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ private:
|
|||
Q_PRIVATE_SLOT(d_func(), void _q_actionTriggered())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_actionHovered())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_overrideMenuActionDestroyed())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_platformMenuAboutToShow())
|
||||
|
||||
protected:
|
||||
QMenu(QMenuPrivate &dd, QWidget* parent = 0);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
|
||||
#include "qmenu.h"
|
||||
#include "qmenubar.h"
|
||||
#include "qmenubar_p.h"
|
||||
#include "qmacnativewidget_mac.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
|
@ -115,6 +117,23 @@ void QMenu::setAsDockMenu()
|
|||
\sa QMenu:setAsDockMenu()
|
||||
*/
|
||||
|
||||
void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem* item)
|
||||
{
|
||||
QMacNativeWidget *container = new QMacNativeWidget;
|
||||
QObject::connect(platformMenu, SIGNAL(destroyed()), container, SLOT(deleteLater()));
|
||||
container->resize(widget->sizeHint());
|
||||
widget->setParent(container);
|
||||
|
||||
NSView *containerView = container->nativeView();
|
||||
QWindow *containerWindow = container->windowHandle();
|
||||
Qt::WindowFlags wf = containerWindow->flags();
|
||||
containerWindow->setFlags(wf | Qt::SubWindow);
|
||||
[(NSView *)widget->winId() setAutoresizingMask:NSViewWidthSizable];
|
||||
|
||||
item->setNativeContents((WId)containerView);
|
||||
container->show();
|
||||
}
|
||||
|
||||
#endif //QT_NO_MENU
|
||||
|
||||
#ifndef QT_NO_MENUBAR
|
||||
|
|
|
|||
|
|
@ -110,6 +110,9 @@ public:
|
|||
void init();
|
||||
void setPlatformMenu(QPlatformMenu *menu);
|
||||
void syncPlatformMenu();
|
||||
#ifdef Q_OS_OSX
|
||||
void moveWidgetToPlatformItem(QWidget *w, QPlatformMenuItem* item);
|
||||
#endif
|
||||
|
||||
static QMenuPrivate *get(QMenu *m) { return m->d_func(); }
|
||||
int scrollerHeight() const;
|
||||
|
|
@ -223,6 +226,7 @@ public:
|
|||
|
||||
void _q_actionTriggered();
|
||||
void _q_actionHovered();
|
||||
void _q_platformMenuAboutToShow();
|
||||
|
||||
bool hasMouseMoved(const QPoint &globalPos);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue