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 QMacAutoReleasePool pool;
248
249 reset();
250
251 updateColorScheme();
252
253 if (QCoreTextFontEngine::fontSmoothing() == QCoreTextFontEngine::FontSmoothing::Grayscale) {
254 // Re-populate glyph caches based on the new appearance's assumed text fill color
255 QFontCache::instance()->clear();
256 }
257
258 QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
259}
260
261bool QCocoaTheme::usePlatformNativeDialog(DialogType dialogType) const
262{
263 switch (dialogType) {
264 case QPlatformTheme::FileDialog:
265 case QPlatformTheme::ColorDialog:
266 case QPlatformTheme::FontDialog:
267 case QPlatformTheme::MessageDialog:
268 return true;
269 default:
270 return false;
271 }
272}
273
274QPlatformDialogHelper *QCocoaTheme::createPlatformDialogHelper(DialogType dialogType) const
275{
276 switch (dialogType) {
277 case QPlatformTheme::FileDialog:
278 return new QCocoaFileDialogHelper();
279 case QPlatformTheme::ColorDialog:
280 return new QCocoaColorDialogHelper();
281 case QPlatformTheme::FontDialog:
282 return new QCocoaFontDialogHelper();
283 case QPlatformTheme::MessageDialog:
284 return new QCocoaMessageDialog;
285 default:
286 return nullptr;
287 }
288}
289
290#ifndef QT_NO_SYSTEMTRAYICON
291QPlatformSystemTrayIcon *QCocoaTheme::createPlatformSystemTrayIcon() const
292{
293 return new QCocoaSystemTrayIcon;
294}
295#endif
296
297const QPalette *QCocoaTheme::palette(Palette type) const
298{
299 QMacAutoReleasePool pool;
300
301 // Note: NSColor resolves its RGB values based on the current
302 // drawing appearance, so we need to propagate the effective
303 // appearance when (re)creating the palettes.
304
305 if (type == SystemPalette) {
306 if (!m_systemPalette) {
307 [NSApp.effectiveAppearance performAsCurrentDrawingAppearance:^{
308 m_systemPalette = qt_mac_createSystemPalette();
309 }];
310 }
311 return m_systemPalette;
312 } else {
313 if (m_palettes.isEmpty()) {
314 [NSApp.effectiveAppearance performAsCurrentDrawingAppearance:^{
315 m_palettes = qt_mac_createRolePalettes();
316 }];
317 }
318 return m_palettes.value(type, nullptr);
319 }
320 return nullptr;
321}
322
323const QFont *QCocoaTheme::font(Font type) const
324{
325 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
326 const auto *coreTextFontDatabase = static_cast<QCoreTextFontDatabase *>(platformIntegration->fontDatabase());
327 return coreTextFontDatabase->themeFont(type);
328}
329
330//! \internal
331QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height)
332{
333 QPixmap ret(width, height);
334 ret.fill(QColor(0, 0, 0, 0));
335
336 CGRect rect = CGRectMake(0, 0, width, height);
337
338 QMacCGContext ctx(&ret);
339 CGAffineTransform old_xform = CGContextGetCTM(ctx);
340 CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform));
341 CGContextConcatCTM(ctx, CGAffineTransformIdentity);
342
343 ::RGBColor b;
344 b.blue = b.green = b.red = 255*255;
345 PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon);
346 return ret;
347}
348
349QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
350{
351 OSType iconType = 0;
352 switch (sp) {
353 case MessageBoxQuestion:
354 iconType = kQuestionMarkIcon;
355 break;
356 case MessageBoxInformation:
357 iconType = kAlertNoteIcon;
358 break;
359 case MessageBoxWarning:
360 iconType = kAlertCautionIcon;
361 break;
362 case MessageBoxCritical:
363 iconType = kAlertStopIcon;
364 break;
365 case DesktopIcon: {
366 auto desktop = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
367 NSImage *icon = [NSWorkspace.sharedWorkspace iconForFile:desktop.toNSString()];
368 return qt_mac_toQPixmap(icon, size);
369 }
370 case DirHomeIcon: {
371 auto home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
372 NSImage *icon = [NSWorkspace.sharedWorkspace iconForFile:home.toNSString()];
373 return qt_mac_toQPixmap(icon, size);
374 }
375 case TrashIcon:
376 iconType = kTrashIcon;
377 break;
378 case ComputerIcon:
379 iconType = kComputerIcon;
380 break;
381 case DriveFDIcon:
382 iconType = kGenericFloppyIcon;
383 break;
384 case DriveHDIcon:
385 iconType = kGenericHardDiskIcon;
386 break;
387 case DriveCDIcon:
388 case DriveDVDIcon:
389 iconType = kGenericCDROMIcon;
390 break;
391 case DriveNetIcon:
392 iconType = kGenericNetworkIcon;
393 break;
394 case DirOpenIcon:
395 case DirLinkOpenIcon:
396 case DirIcon:
397 case DirClosedIcon:
398 case DirLinkIcon: {
399 NSImage *icon = [NSWorkspace.sharedWorkspace iconForContentType:UTTypeFolder];
400 return qt_mac_toQPixmap(icon, size);
401 }
402 case FileLinkIcon:
403 case FileIcon:
404 iconType = kGenericDocumentIcon;
405 break;
406 case ToolBarHorizontalExtensionButton:
407 return QAppleIconEngine::fromTheme("chevron.forward.2").pixmap(size.toSize());
408 case ToolBarVerticalExtensionButton:
409 return QAppleIconEngine::fromTheme("chevron.down.2").pixmap(size.toSize());
410 default:
411 break;
412 }
413 if (iconType != 0) {
414 QPixmap pixmap;
415 IconRef icon = nullptr;
416 QT_IGNORE_DEPRECATIONS(GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon));
417
418 if (icon) {
419 pixmap = qt_mac_convert_iconref(icon, size.width(), size.height());
420 QT_IGNORE_DEPRECATIONS(ReleaseIconRef(icon));
421 }
422
423 return pixmap;
424 }
425
426 return QPlatformTheme::standardPixmap(sp, size);
427}
428
429QIcon QCocoaTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const
430{
431 QMacAutoReleasePool pool;
432 return QIcon(new QAppleFileIconEngine(fileInfo, iconOptions));
433}
434
435QIconEngine *QCocoaTheme::createIconEngine(const QString &iconName) const
436{
437 return new QAppleIconEngine(iconName);
438}
439
440QVariant QCocoaTheme::themeHint(ThemeHint hint) const
441{
442 switch (hint) {
443 case QPlatformTheme::StyleNames:
444 return QStringList(QStringLiteral("macOS"));
445 case QPlatformTheme::DialogButtonBoxLayout:
446 return QVariant(QPlatformDialogHelper::MacLayout);
447 case KeyboardScheme:
448 return QVariant(int(MacKeyboardScheme));
449 case TabFocusBehavior:
450 return QVariant([[NSApplication sharedApplication] isFullKeyboardAccessEnabled] ?
451 int(Qt::TabFocusAllControls) : int(Qt::TabFocusTextControls | Qt::TabFocusListControls));
452 case IconPixmapSizes:
453 return QVariant::fromValue(QAppleIconEngine::availableIconSizes());
454 case QPlatformTheme::PasswordMaskCharacter:
455 return QVariant(QChar(0x2022));
456 case QPlatformTheme::UiEffects:
457 return QVariant(int(HoverEffect));
458 case QPlatformTheme::SpellCheckUnderlineStyle:
459 return QVariant(int(QTextCharFormat::DotLine));
460 case QPlatformTheme::UseFullScreenForPopupMenu:
461 return false;
462 case QPlatformTheme::InteractiveResizeAcrossScreens:
463 return !NSScreen.screensHaveSeparateSpaces;
464 case QPlatformTheme::ShowDirectoriesFirst:
465 return false;
466 case QPlatformTheme::MouseDoubleClickInterval:
467 return NSEvent.doubleClickInterval * 1000;
468 case QPlatformTheme::KeyboardInputInterval:
469 return NSEvent.keyRepeatDelay * 1000;
470 case QPlatformTheme::KeyboardAutoRepeatRate:
471 return 1.0 / NSEvent.keyRepeatInterval;
472 case QPlatformTheme::ShowIconsInMenus:
473 return QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSTahoe;
474 case QPlatformTheme::MenuSelectionWraps:
475 return false;
476 default:
477 break;
478 }
479 return QPlatformTheme::themeHint(hint);
480}
481
482Qt::ColorScheme QCocoaTheme::colorScheme() const
483{
484 return m_colorScheme;
485}
486
487void QCocoaTheme::requestColorScheme(Qt::ColorScheme scheme)
488{
489 QMacAutoReleasePool pool;
490
491 NSAppearance *appearance = nil;
492 switch (scheme) {
493 case Qt::ColorScheme::Dark:
494 appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
495 break;
496 case Qt::ColorScheme::Light:
497 appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
498 break;
499 case Qt::ColorScheme::Unknown:
500 break;
501 }
502
503 // Always override the appearance, even if it's the same
504 // as the current effective appearance, as otherwise the
505 // requested appearance won't stick on system theme changes.
506 NSApp.appearance = appearance;
507}
508
509/*
510 Update the theme's color scheme based on the current appearance.
511
512 We can only reference the appearance on the main thread, but the
513 CoreText font engine needs to know the color scheme, and might be
514 used from secondary threads, so we cache the color scheme.
515*/
516void QCocoaTheme::updateColorScheme()
517{
518 auto appearance = [NSApp.effectiveAppearance bestMatchFromAppearancesWithNames:
519 @[ NSAppearanceNameAqua, NSAppearanceNameDarkAqua ]];
520 m_colorScheme = [appearance isEqualToString:NSAppearanceNameDarkAqua] ?
521 Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
522}
523
524Qt::ContrastPreference QCocoaTheme::contrastPreference() const
525{
526 return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldIncreaseContrast ? Qt::ContrastPreference::HighContrast
527 : Qt::ContrastPreference::NoPreference;
528}
529
530QString QCocoaTheme::standardButtonText(int button) const
531{
532 return button == QPlatformDialogHelper::Discard ?
533 QCoreApplication::translate("QCocoaTheme", "Don't Save")
534 : QPlatformTheme::standardButtonText(button);
535}
536
537QKeySequence QCocoaTheme::standardButtonShortcut(int button) const
538{
539 return button == QPlatformDialogHelper::Discard ? QKeySequence(Qt::CTRL | Qt::Key_Delete)
540 : QPlatformTheme::standardButtonShortcut(button);
541}
542
543QPlatformMenuItem *QCocoaTheme::createPlatformMenuItem() const
544{
545 auto *menuItem = new QCocoaMenuItem();
546 qCDebug(lcQpaMenus) << "Created" << menuItem;
547 return menuItem;
548}
549
550QPlatformMenu *QCocoaTheme::createPlatformMenu() const
551{
552 auto *menu = new QCocoaMenu();
553 qCDebug(lcQpaMenus) << "Created" << menu;
554 return menu;
555}
556
557QPlatformMenuBar *QCocoaTheme::createPlatformMenuBar() const
558{
559 static bool haveMenubar = false;
560 if (!haveMenubar) {
561 haveMenubar = true;
562 QObject::connect(qGuiApp, SIGNAL(focusWindowChanged(QWindow*)),
563 QGuiApplicationPrivate::platformIntegration()->nativeInterface(),
564 SLOT(onAppFocusWindowChanged(QWindow*)));
565 }
566
567 auto *menuBar = new QCocoaMenuBar();
568 qCDebug(lcQpaMenus) << "Created" << menuBar;
569 return menuBar;
570}
571
572#ifndef QT_NO_SHORTCUT
573QList<QKeySequence> QCocoaTheme::keyBindings(QKeySequence::StandardKey key) const
574{
575 // The default key bindings in QPlatformTheme all hard-coded to use the Ctrl
576 // modifier, to match other platforms. In the normal case, when translating
577 // those to key sequences, we'll end up with Qt::ControlModifier+X, which is
578 // then matched against incoming key events that have been mapped from the
579 // command key to Qt::ControlModifier, and we'll get a match. If, however,
580 // the AA_MacDontSwapCtrlAndMeta application attribute is set, we need to
581 // fix the resulting key sequence so that it will match against unmapped
582 // key events that contain Qt::MetaModifier.
583 auto bindings = QPlatformTheme::keyBindings(key);
584
585 if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
586 static auto swapCtrlMeta = [](QKeyCombination keyCombination) {
587 const auto originalKeyModifiers = keyCombination.keyboardModifiers();
588 auto newKeyboardModifiers = originalKeyModifiers & ~(Qt::ControlModifier | Qt::MetaModifier);
589 if (originalKeyModifiers & Qt::ControlModifier)
590 newKeyboardModifiers |= Qt::MetaModifier;
591 if (originalKeyModifiers & Qt::MetaModifier)
592 newKeyboardModifiers |= Qt::ControlModifier;
593 return QKeyCombination(newKeyboardModifiers, keyCombination.key());
594 };
595
596 QList<QKeySequence> swappedBindings;
597 for (auto binding : bindings) {
598 Q_ASSERT(binding.count() == 1);
599 swappedBindings.append(QKeySequence(swapCtrlMeta(binding[0])));
600 }
601
602 bindings = swappedBindings;
603 }
604
605 return bindings;
606}
607#endif
608
609QT_END_NAMESPACE
Combined button and popup list for selecting options.
#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