Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcocoatheme.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <AppKit/AppKit.h>
6
7#include "qcocoatheme.h"
8
9#include <QtCore/QVariant>
10
12#include "qcocoamenuitem.h"
13#include "qcocoamenu.h"
14#include "qcocoamenubar.h"
15#include "qcocoahelpers.h"
16
17#include <QtCore/qfileinfo.h>
18#include <QtCore/qstandardpaths.h>
19#include <QtCore/private/qcore_mac_p.h>
20#include <QtGui/private/qfont_p.h>
21#include <QtGui/private/qguiapplication_p.h>
22#include <QtGui/private/qcoregraphics_p.h>
23#include <QtGui/qpainter.h>
24#include <QtGui/qtextformat.h>
25#include <QtGui/private/qcoretextfontdatabase_p.h>
26#include <QtGui/private/qapplefileiconengine_p.h>
27#include <QtGui/private/qappleiconengine_p.h>
28#include <QtGui/private/qfontengine_coretext_p.h>
29#include <QtGui/private/qabstractfileiconengine_p.h>
30#include <qpa/qplatformdialoghelper.h>
31#include <qpa/qplatformintegration.h>
32#include <qpa/qplatformnativeinterface.h>
33
38
39#include <CoreServices/CoreServices.h>
40#include <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
41
43
45{
46 QColor qc;
47
48 // Standard palette initialization (copied from Qt 4 styles)
49 QBrush backgroundBrush = qt_mac_toQBrush([NSColor windowBackgroundColor]);
50 QColor background = backgroundBrush.color();
51 QColor light(background.lighter(110));
52 QColor dark(background.darker(160));
53 QColor mid(background.darker(140));
54 QPalette *palette = new QPalette(Qt::black, background, light, dark, mid, Qt::black, Qt::white);
55
56 palette->setBrush(QPalette::Window, backgroundBrush);
57
58 palette->setBrush(QPalette::Disabled, QPalette::WindowText, dark);
59 palette->setBrush(QPalette::Disabled, QPalette::Text, dark);
60 palette->setBrush(QPalette::Disabled, QPalette::Base, backgroundBrush);
61 QBrush textBackgroundBrush = qt_mac_toQBrush([NSColor textBackgroundColor]);
62 palette->setBrush(QPalette::Active, QPalette::Base, textBackgroundBrush);
63 palette->setBrush(QPalette::Inactive, QPalette::Base, textBackgroundBrush);
64 palette->setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191));
65 palette->setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191));
66 palette->setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191));
67
68 // System palette initialization:
69 QBrush br = qt_mac_toQBrush([NSColor selectedControlColor]);
70 palette->setBrush(QPalette::Active, QPalette::Highlight, br);
71 const auto inactiveHighlight = qt_mac_toQBrush([NSColor unemphasizedSelectedContentBackgroundColor]);
72 palette->setBrush(QPalette::Inactive, QPalette::Highlight, inactiveHighlight);
73 palette->setBrush(QPalette::Disabled, QPalette::Highlight, inactiveHighlight);
74
75 palette->setBrush(QPalette::Shadow, qt_mac_toQColor([NSColor shadowColor]));
76
77 qc = qt_mac_toQColor([NSColor controlTextColor]);
78 palette->setColor(QPalette::Active, QPalette::Text, qc);
79 palette->setColor(QPalette::Active, QPalette::ButtonText, qc);
80 palette->setColor(QPalette::Active, QPalette::WindowText, qc);
81 palette->setColor(QPalette::Active, QPalette::HighlightedText, qc);
82 palette->setColor(QPalette::Inactive, QPalette::Text, qc);
83 palette->setColor(QPalette::Inactive, QPalette::WindowText, qc);
84 palette->setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
85
86 qc = qt_mac_toQColor([NSColor disabledControlTextColor]);
87 palette->setColor(QPalette::Disabled, QPalette::Text, qc);
88 palette->setColor(QPalette::Disabled, QPalette::ButtonText, qc);
89 palette->setColor(QPalette::Disabled, QPalette::WindowText, qc);
90 palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
91
92 palette->setBrush(QPalette::ToolTipBase, qt_mac_toQBrush([NSColor controlColor]));
93
94 palette->setColor(QPalette::Normal, QPalette::Link, qt_mac_toQColor([NSColor linkColor]));
95
96 qc = qt_mac_toQColor([NSColor placeholderTextColor]);
97 palette->setColor(QPalette::Active, QPalette::PlaceholderText, qc);
98 palette->setColor(QPalette::Inactive, QPalette::PlaceholderText, qc);
99 palette->setColor(QPalette::Disabled, QPalette::PlaceholderText, qc);
100
101 qc = qt_mac_toQColor([NSColor controlAccentColor]);
102 palette->setColor(QPalette::Accent, qc);
103
104 return palette;
105}
106
108 inline QMacPaletteMap(QPlatformTheme::Palette p, NSColor *a, NSColor *i) :
109 active(a), inactive(i), paletteRole(p) { }
110
114};
115
116#define MAC_PALETTE_ENTRY(pal, active, inactive)
117 QMacPaletteMap(pal, [NSColor active], [NSColor inactive])
119 MAC_PALETTE_ENTRY(QPlatformTheme::ToolButtonPalette, controlTextColor, disabledControlTextColor),
120 MAC_PALETTE_ENTRY(QPlatformTheme::ButtonPalette, controlTextColor, disabledControlTextColor),
121 MAC_PALETTE_ENTRY(QPlatformTheme::HeaderPalette, headerTextColor, disabledControlTextColor),
122 MAC_PALETTE_ENTRY(QPlatformTheme::ComboBoxPalette, controlTextColor, disabledControlTextColor),
123 MAC_PALETTE_ENTRY(QPlatformTheme::ItemViewPalette, textColor, disabledControlTextColor),
124 MAC_PALETTE_ENTRY(QPlatformTheme::MessageBoxLabelPalette, textColor, disabledControlTextColor),
125 MAC_PALETTE_ENTRY(QPlatformTheme::TabBarPalette, controlTextColor, disabledControlTextColor),
126 MAC_PALETTE_ENTRY(QPlatformTheme::LabelPalette, textColor, disabledControlTextColor),
127 MAC_PALETTE_ENTRY(QPlatformTheme::GroupBoxPalette, textColor, disabledControlTextColor),
128 MAC_PALETTE_ENTRY(QPlatformTheme::MenuPalette, controlTextColor, disabledControlTextColor),
129 MAC_PALETTE_ENTRY(QPlatformTheme::MenuBarPalette, controlTextColor, disabledControlTextColor),
130 MAC_PALETTE_ENTRY(QPlatformTheme::TextEditPalette, textColor, disabledControlTextColor),
131 MAC_PALETTE_ENTRY(QPlatformTheme::TextLineEditPalette, textColor, disabledControlTextColor)
132};
133#undef MAC_PALETTE_ENTRY
134
135static const int mac_widget_colors_count = sizeof(mac_widget_colors) / sizeof(mac_widget_colors[0]);
136
137static QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
138{
139 QHash<QPlatformTheme::Palette, QPalette*> palettes;
140 QColor qc;
141 for (int i = 0; i < mac_widget_colors_count; i++) {
142 QPalette &pal = *qt_mac_createSystemPalette();
143 if (mac_widget_colors[i].active) {
144 qc = qt_mac_toQColor(mac_widget_colors[i].active);
145 pal.setColor(QPalette::Active, QPalette::Text, qc);
146 pal.setColor(QPalette::Inactive, QPalette::Text, qc);
147 pal.setColor(QPalette::Active, QPalette::WindowText, qc);
148 pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
149 pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
150 pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
151 pal.setColor(QPalette::Active, QPalette::ButtonText, qc);
152 pal.setColor(QPalette::Inactive, QPalette::ButtonText, qc);
153 qc = qt_mac_toQColor(mac_widget_colors[i].inactive);
154 pal.setColor(QPalette::Disabled, QPalette::Text, qc);
155 pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
156 pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
157 pal.setColor(QPalette::Disabled, QPalette::ButtonText, qc);
158 }
159 if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette
160 || mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) {
161 // Cheap approximation for NSVisualEffectView (see deprecation note for selectedMenuItemTextColor)
162 auto selectedMenuItemColor = [[NSColor controlAccentColor] highlightWithLevel:0.3];
163 pal.setBrush(QPalette::Highlight, qt_mac_toQColor(selectedMenuItemColor));
164 qc = qt_mac_toQColor([NSColor labelColor]);
165 pal.setBrush(QPalette::ButtonText, qc);
166 pal.setBrush(QPalette::Text, qc);
167 qc = qt_mac_toQColor([NSColor selectedMenuItemTextColor]);
168 pal.setBrush(QPalette::HighlightedText, qc);
169 qc = qt_mac_toQColor([NSColor disabledControlTextColor]);
170 pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
171 } else if ((mac_widget_colors[i].paletteRole == QPlatformTheme::ButtonPalette)
172 || (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette)
173 || (mac_widget_colors[i].paletteRole == QPlatformTheme::TabBarPalette)) {
174 pal.setColor(QPalette::Disabled, QPalette::ButtonText,
175 pal.color(QPalette::Disabled, QPalette::Text));
176 pal.setColor(QPalette::Inactive, QPalette::ButtonText,
177 pal.color(QPalette::Inactive, QPalette::Text));
178 pal.setColor(QPalette::Active, QPalette::ButtonText,
179 pal.color(QPalette::Active, QPalette::Text));
180 } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) {
181 NSArray<NSColor *> *baseColors = nil;
182 NSColor *activeHighlightColor = nil;
183 baseColors = [NSColor alternatingContentBackgroundColors];
184 activeHighlightColor = [NSColor selectedContentBackgroundColor];
185 pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
186 qt_mac_toQBrush([NSColor unemphasizedSelectedTextColor]));
187 pal.setBrush(QPalette::Base, qt_mac_toQBrush(baseColors[0]));
188 pal.setBrush(QPalette::AlternateBase, qt_mac_toQBrush(baseColors[1]));
189 pal.setBrush(QPalette::Active, QPalette::Highlight,
190 qt_mac_toQBrush(activeHighlightColor));
191 pal.setBrush(QPalette::Active, QPalette::HighlightedText,
192 qt_mac_toQBrush([NSColor alternateSelectedControlTextColor]));
193 pal.setBrush(QPalette::Inactive, QPalette::Text,
194 pal.brush(QPalette::Active, QPalette::Text));
195 } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextEditPalette) {
196 pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor]));
197 pal.setBrush(QPalette::Inactive, QPalette::Text,
198 pal.brush(QPalette::Active, QPalette::Text));
199 pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
200 pal.brush(QPalette::Active, QPalette::Text));
201 } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette
202 || mac_widget_colors[i].paletteRole == QPlatformTheme::ComboBoxPalette) {
203 pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor]));
204 pal.setBrush(QPalette::Disabled, QPalette::Base,
205 pal.brush(QPalette::Active, QPalette::Base));
206 } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::LabelPalette) {
207 qc = qt_mac_toQColor([NSColor labelColor]);
208 pal.setBrush(QPalette::Inactive, QPalette::ToolTipText, qc);
209 }
210 palettes.insert(mac_widget_colors[i].paletteRole, &pal);
211 }
212 return palettes;
213}
214
215const char *QCocoaTheme::name = "cocoa";
216
217QCocoaTheme::QCocoaTheme()
218 : m_systemPalette(nullptr)
219{
220 m_appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] {
221 handleSystemThemeChange();
222 });
223
224 m_systemColorObserver = QMacNotificationObserver(nil,
225 NSSystemColorsDidChangeNotification, [this] {
226 handleSystemThemeChange();
227 });
228
229 updateColorScheme();
230}
231
232QCocoaTheme::~QCocoaTheme()
233{
234 reset();
235}
236
237void QCocoaTheme::reset()
238{
239 delete m_systemPalette;
240 m_systemPalette = nullptr;
241 qDeleteAll(m_palettes);
242 m_palettes.clear();
243}
244
245void QCocoaTheme::handleSystemThemeChange()
246{
247 reset();
248
249 updateColorScheme();
250
251 if (QCoreTextFontEngine::fontSmoothing() == QCoreTextFontEngine::FontSmoothing::Grayscale) {
252 // Re-populate glyph caches based on the new appearance's assumed text fill color
253 QFontCache::instance()->clear();
254 }
255
256 QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
257}
258
259bool QCocoaTheme::usePlatformNativeDialog(DialogType dialogType) const
260{
261 switch (dialogType) {
262 case QPlatformTheme::FileDialog:
263 case QPlatformTheme::ColorDialog:
264 case QPlatformTheme::FontDialog:
265 case QPlatformTheme::MessageDialog:
266 return true;
267 default:
268 return false;
269 }
270}
271
272QPlatformDialogHelper *QCocoaTheme::createPlatformDialogHelper(DialogType dialogType) const
273{
274 switch (dialogType) {
275 case QPlatformTheme::FileDialog:
276 return new QCocoaFileDialogHelper();
277 case QPlatformTheme::ColorDialog:
278 return new QCocoaColorDialogHelper();
279 case QPlatformTheme::FontDialog:
280 return new QCocoaFontDialogHelper();
281 case QPlatformTheme::MessageDialog:
282 return new QCocoaMessageDialog;
283 default:
284 return nullptr;
285 }
286}
287
288#ifndef QT_NO_SYSTEMTRAYICON
289QPlatformSystemTrayIcon *QCocoaTheme::createPlatformSystemTrayIcon() const
290{
291 return new QCocoaSystemTrayIcon;
292}
293#endif
294
295const QPalette *QCocoaTheme::palette(Palette type) const
296{
297 // Note: NSColor resolves its RGB values based on the current
298 // drawing appearance, so we need to propagate the effective
299 // appearance when (re)creating the palettes.
300
301 if (type == SystemPalette) {
302 if (!m_systemPalette) {
303 [NSApp.effectiveAppearance performAsCurrentDrawingAppearance:^{
304 m_systemPalette = qt_mac_createSystemPalette();
305 }];
306 }
307 return m_systemPalette;
308 } else {
309 if (m_palettes.isEmpty()) {
310 [NSApp.effectiveAppearance performAsCurrentDrawingAppearance:^{
311 m_palettes = qt_mac_createRolePalettes();
312 }];
313 }
314 return m_palettes.value(type, nullptr);
315 }
316 return nullptr;
317}
318
319const QFont *QCocoaTheme::font(Font type) const
320{
321 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
322 const auto *coreTextFontDatabase = static_cast<QCoreTextFontDatabase *>(platformIntegration->fontDatabase());
323 return coreTextFontDatabase->themeFont(type);
324}
325
326//! \internal
327QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height)
328{
329 QPixmap ret(width, height);
330 ret.fill(QColor(0, 0, 0, 0));
331
332 CGRect rect = CGRectMake(0, 0, width, height);
333
334 QMacCGContext ctx(&ret);
335 CGAffineTransform old_xform = CGContextGetCTM(ctx);
336 CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform));
337 CGContextConcatCTM(ctx, CGAffineTransformIdentity);
338
339 ::RGBColor b;
340 b.blue = b.green = b.red = 255*255;
341 PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon);
342 return ret;
343}
344
345QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
346{
347 OSType iconType = 0;
348 switch (sp) {
349 case MessageBoxQuestion:
350 iconType = kQuestionMarkIcon;
351 break;
352 case MessageBoxInformation:
353 iconType = kAlertNoteIcon;
354 break;
355 case MessageBoxWarning:
356 iconType = kAlertCautionIcon;
357 break;
358 case MessageBoxCritical:
359 iconType = kAlertStopIcon;
360 break;
361 case DesktopIcon: {
362 auto desktop = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
363 NSImage *icon = [NSWorkspace.sharedWorkspace iconForFile:desktop.toNSString()];
364 return qt_mac_toQPixmap(icon, size);
365 }
366 case DirHomeIcon: {
367 auto home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
368 NSImage *icon = [NSWorkspace.sharedWorkspace iconForFile:home.toNSString()];
369 return qt_mac_toQPixmap(icon, size);
370 }
371 case TrashIcon:
372 iconType = kTrashIcon;
373 break;
374 case ComputerIcon:
375 iconType = kComputerIcon;
376 break;
377 case DriveFDIcon:
378 iconType = kGenericFloppyIcon;
379 break;
380 case DriveHDIcon:
381 iconType = kGenericHardDiskIcon;
382 break;
383 case DriveCDIcon:
384 case DriveDVDIcon:
385 iconType = kGenericCDROMIcon;
386 break;
387 case DriveNetIcon:
388 iconType = kGenericNetworkIcon;
389 break;
390 case DirOpenIcon:
391 case DirLinkOpenIcon:
392 case DirIcon:
393 case DirClosedIcon:
394 case DirLinkIcon: {
395 NSImage *icon = [NSWorkspace.sharedWorkspace iconForContentType:UTTypeFolder];
396 return qt_mac_toQPixmap(icon, size);
397 }
398 case FileLinkIcon:
399 case FileIcon:
400 iconType = kGenericDocumentIcon;
401 break;
402 case ToolBarHorizontalExtensionButton:
403 return QIcon::fromTheme("chevron.forward.2").pixmap(size.toSize());
404 case ToolBarVerticalExtensionButton:
405 return QIcon::fromTheme("chevron.down.2").pixmap(size.toSize());
406 default:
407 break;
408 }
409 if (iconType != 0) {
410 QPixmap pixmap;
411 IconRef icon = nullptr;
412 QT_IGNORE_DEPRECATIONS(GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon));
413
414 if (icon) {
415 pixmap = qt_mac_convert_iconref(icon, size.width(), size.height());
416 QT_IGNORE_DEPRECATIONS(ReleaseIconRef(icon));
417 }
418
419 return pixmap;
420 }
421
422 return QPlatformTheme::standardPixmap(sp, size);
423}
424
425QIcon QCocoaTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const
426{
427 return QIcon(new QAppleFileIconEngine(fileInfo, iconOptions));
428}
429
430QIconEngine *QCocoaTheme::createIconEngine(const QString &iconName) const
431{
432 return new QAppleIconEngine(iconName);
433}
434
435QVariant QCocoaTheme::themeHint(ThemeHint hint) const
436{
437 switch (hint) {
438 case QPlatformTheme::StyleNames:
439 return QStringList(QStringLiteral("macOS"));
440 case QPlatformTheme::DialogButtonBoxLayout:
441 return QVariant(QPlatformDialogHelper::MacLayout);
442 case KeyboardScheme:
443 return QVariant(int(MacKeyboardScheme));
444 case TabFocusBehavior:
445 return QVariant([[NSApplication sharedApplication] isFullKeyboardAccessEnabled] ?
446 int(Qt::TabFocusAllControls) : int(Qt::TabFocusTextControls | Qt::TabFocusListControls));
447 case IconPixmapSizes:
448 return QVariant::fromValue(QAppleIconEngine::availableIconSizes());
449 case QPlatformTheme::PasswordMaskCharacter:
450 return QVariant(QChar(0x2022));
451 case QPlatformTheme::UiEffects:
452 return QVariant(int(HoverEffect));
453 case QPlatformTheme::SpellCheckUnderlineStyle:
454 return QVariant(int(QTextCharFormat::DotLine));
455 case QPlatformTheme::UseFullScreenForPopupMenu:
456 return false;
457 case QPlatformTheme::InteractiveResizeAcrossScreens:
458 return !NSScreen.screensHaveSeparateSpaces;
459 case QPlatformTheme::ShowDirectoriesFirst:
460 return false;
461 case QPlatformTheme::MouseDoubleClickInterval:
462 return NSEvent.doubleClickInterval * 1000;
463 case QPlatformTheme::KeyboardInputInterval:
464 return NSEvent.keyRepeatDelay * 1000;
465 case QPlatformTheme::KeyboardAutoRepeatRate:
466 return 1.0 / NSEvent.keyRepeatInterval;
467 case QPlatformTheme::ShowIconsInMenus:
468 return QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSTahoe;
469 case QPlatformTheme::MenuSelectionWraps:
470 return false;
471 default:
472 break;
473 }
474 return QPlatformTheme::themeHint(hint);
475}
476
477Qt::ColorScheme QCocoaTheme::colorScheme() const
478{
479 return m_colorScheme;
480}
481
482void QCocoaTheme::requestColorScheme(Qt::ColorScheme scheme)
483{
484 NSAppearance *appearance = nil;
485 switch (scheme) {
486 case Qt::ColorScheme::Dark:
487 appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
488 break;
489 case Qt::ColorScheme::Light:
490 appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
491 break;
492 case Qt::ColorScheme::Unknown:
493 break;
494 }
495
496 // Always override the appearance, even if it's the same
497 // as the current effective appearance, as otherwise the
498 // requested appearance won't stick on system theme changes.
499 NSApp.appearance = appearance;
500}
501
502/*
503 Update the theme's color scheme based on the current appearance.
504
505 We can only reference the appearance on the main thread, but the
506 CoreText font engine needs to know the color scheme, and might be
507 used from secondary threads, so we cache the color scheme.
508*/
509void QCocoaTheme::updateColorScheme()
510{
511 auto appearance = [NSApp.effectiveAppearance bestMatchFromAppearancesWithNames:
512 @[ NSAppearanceNameAqua, NSAppearanceNameDarkAqua ]];
513 m_colorScheme = [appearance isEqualToString:NSAppearanceNameDarkAqua] ?
514 Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
515}
516
517Qt::ContrastPreference QCocoaTheme::contrastPreference() const
518{
519 return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldIncreaseContrast ? Qt::ContrastPreference::HighContrast
520 : Qt::ContrastPreference::NoPreference;
521}
522
523QString QCocoaTheme::standardButtonText(int button) const
524{
525 return button == QPlatformDialogHelper::Discard ?
526 QCoreApplication::translate("QCocoaTheme", "Don't Save")
527 : QPlatformTheme::standardButtonText(button);
528}
529
530QKeySequence QCocoaTheme::standardButtonShortcut(int button) const
531{
532 return button == QPlatformDialogHelper::Discard ? QKeySequence(Qt::CTRL | Qt::Key_Delete)
533 : QPlatformTheme::standardButtonShortcut(button);
534}
535
536QPlatformMenuItem *QCocoaTheme::createPlatformMenuItem() const
537{
538 auto *menuItem = new QCocoaMenuItem();
539 qCDebug(lcQpaMenus) << "Created" << menuItem;
540 return menuItem;
541}
542
543QPlatformMenu *QCocoaTheme::createPlatformMenu() const
544{
545 auto *menu = new QCocoaMenu();
546 qCDebug(lcQpaMenus) << "Created" << menu;
547 return menu;
548}
549
550QPlatformMenuBar *QCocoaTheme::createPlatformMenuBar() const
551{
552 static bool haveMenubar = false;
553 if (!haveMenubar) {
554 haveMenubar = true;
555 QObject::connect(qGuiApp, SIGNAL(focusWindowChanged(QWindow*)),
556 QGuiApplicationPrivate::platformIntegration()->nativeInterface(),
557 SLOT(onAppFocusWindowChanged(QWindow*)));
558 }
559
560 auto *menuBar = new QCocoaMenuBar();
561 qCDebug(lcQpaMenus) << "Created" << menuBar;
562 return menuBar;
563}
564
565#ifndef QT_NO_SHORTCUT
566QList<QKeySequence> QCocoaTheme::keyBindings(QKeySequence::StandardKey key) const
567{
568 // The default key bindings in QPlatformTheme all hard-coded to use the Ctrl
569 // modifier, to match other platforms. In the normal case, when translating
570 // those to key sequences, we'll end up with Qt::ControlModifier+X, which is
571 // then matched against incoming key events that have been mapped from the
572 // command key to Qt::ControlModifier, and we'll get a match. If, however,
573 // the AA_MacDontSwapCtrlAndMeta application attribute is set, we need to
574 // fix the resulting key sequence so that it will match against unmapped
575 // key events that contain Qt::MetaModifier.
576 auto bindings = QPlatformTheme::keyBindings(key);
577
578 if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
579 static auto swapCtrlMeta = [](QKeyCombination keyCombination) {
580 const auto originalKeyModifiers = keyCombination.keyboardModifiers();
581 auto newKeyboardModifiers = originalKeyModifiers & ~(Qt::ControlModifier | Qt::MetaModifier);
582 if (originalKeyModifiers & Qt::ControlModifier)
583 newKeyboardModifiers |= Qt::MetaModifier;
584 if (originalKeyModifiers & Qt::MetaModifier)
585 newKeyboardModifiers |= Qt::ControlModifier;
586 return QKeyCombination(newKeyboardModifiers, keyCombination.key());
587 };
588
589 QList<QKeySequence> swappedBindings;
590 for (auto binding : bindings) {
591 Q_ASSERT(binding.count() == 1);
592 swappedBindings.append(QKeySequence(swapCtrlMeta(binding[0])));
593 }
594
595 bindings = swappedBindings;
596 }
597
598 return bindings;
599}
600#endif
601
602QT_END_NAMESPACE
#define MAC_PALETTE_ENTRY(pal, active, inactive)
static QMacPaletteMap mac_widget_colors[]
static QT_BEGIN_NAMESPACE QPalette * qt_mac_createSystemPalette()
QPlatformTheme::Palette paletteRole
QMacPaletteMap(QPlatformTheme::Palette p, NSColor *a, NSColor *i)
NSColor * inactive
NSColor * active