macOS: use correct icon pixmaps in native menus

When creating an NSImage from a QIcon to show the icon of the action in
native menus, then we so far didn't take the state (on/off) or mode
(normal/disabled) of the UI element into account. This resulted in a
menu item showing the Normal/Off icon of an action, even if the
underlying action was disabled or checked.

Icons in menus are not common on macOS, but since we have the
information we need in QCocoaMenuItem, we might just as well use it to
get the right pixmap from the QIcon (even if that pixmap is generated
from the Normal/Off pixmap).

Add an overload to our NSImage::imageFromQIcon helpers that takes a mode
and state, call that from the existing overload, and use it in
QCocoaMenuItem::sync.

Pick-to: 6.8
Fixes: QTBUG-135934
Change-Id: Ifce73daf49ce34c874fa5bf652d84b3102a06709
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 84da5450c342655a7e426c5bb07d9accf7a222a1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2025-04-15 15:58:17 +02:00 committed by Qt Cherry-pick Bot
parent 679dc18c43
commit 9db5beae71
3 changed files with 20 additions and 3 deletions

View File

@ -122,6 +122,14 @@ QT_END_NAMESPACE
}
+ (instancetype)imageFromQIcon:(const QIcon &)icon withSize:(int)size
{
return [NSImage imageFromQIcon:icon withSize:0 withMode:QIcon::Normal withState:QIcon::Off];
}
+ (instancetype)imageFromQIcon:(const QIcon &)icon withSize:(int)size withMode:(QIcon::Mode)mode
withState:(QIcon::State)state
{
if (icon.isNull())
return nil;
@ -133,7 +141,7 @@ QT_END_NAMESPACE
auto nsImage = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease];
for (QSize size : std::as_const(availableSizes)) {
QImage image = icon.pixmap(size).toImage();
const QImage image = icon.pixmap(size, mode, state).toImage();
if (image.isNull())
continue;

View File

@ -18,8 +18,9 @@
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/private/qtguiglobal_p.h>
#include <QtGui/qregion.h>
#include <QtGui/qicon.h>
#include <QtGui/qpalette.h>
#include <QtGui/qregion.h>
#include <CoreGraphics/CoreGraphics.h>
@ -52,6 +53,10 @@ QT_END_NAMESPACE
+ (instancetype)imageFromQImage:(const QT_PREPEND_NAMESPACE(QImage) &)image;
+ (instancetype)imageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon;
+ (instancetype)imageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon withSize:(int)size;
+ (instancetype)imageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon
withSize:(int)size
withMode:(QT_PREPEND_NAMESPACE(QIcon)::Mode)mode
withState:(QT_PREPEND_NAMESPACE(QIcon)::State)state;
@end
QT_BEGIN_NAMESPACE

View File

@ -372,7 +372,11 @@ NSMenuItem *QCocoaMenuItem::sync()
m_native.keyEquivalentModifierMask = NSEventModifierFlagCommand;
}
m_native.image = [NSImage imageFromQIcon:m_icon withSize:m_iconSize];
const QIcon::Mode mode = m_enabled ? QIcon::Normal : QIcon::Disabled;
const QIcon::State state = m_checked ? QIcon::On : QIcon::Off;
m_native.image = [NSImage imageFromQIcon:m_icon withSize:m_iconSize
withMode:mode
withState:state];
m_native.state = m_checked ? NSControlStateValueOn : NSControlStateValueOff;
return m_native;