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 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 QMacAutoReleasePool pool;
428 return QIcon(new QAppleFileIconEngine(fileInfo, iconOptions));
429}
430
431QIconEngine *QCocoaTheme::createIconEngine(const QString &iconName) const
432{
433 return new QAppleIconEngine(iconName);
434}
435
436QVariant QCocoaTheme::themeHint(ThemeHint hint) const
437{
438 switch (hint) {
439 case QPlatformTheme::StyleNames:
440 return QStringList(QStringLiteral("macOS"));
441 case QPlatformTheme::DialogButtonBoxLayout:
442 return QVariant(QPlatformDialogHelper::MacLayout);
443 case KeyboardScheme:
444 return QVariant(int(MacKeyboardScheme));
445 case TabFocusBehavior:
446 return QVariant([[NSApplication sharedApplication] isFullKeyboardAccessEnabled] ?
447 int(Qt::TabFocusAllControls) : int(Qt::TabFocusTextControls | Qt::TabFocusListControls));
448 case IconPixmapSizes:
449 return QVariant::fromValue(QAppleIconEngine::availableIconSizes());
450 case QPlatformTheme::PasswordMaskCharacter:
451 return QVariant(QChar(0x2022));
452 case QPlatformTheme::UiEffects:
453 return QVariant(int(HoverEffect));
454 case QPlatformTheme::SpellCheckUnderlineStyle:
455 return QVariant(int(QTextCharFormat::DotLine));
456 case QPlatformTheme::UseFullScreenForPopupMenu:
457 return false;
458 case QPlatformTheme::InteractiveResizeAcrossScreens:
459 return !NSScreen.screensHaveSeparateSpaces;
460 case QPlatformTheme::ShowDirectoriesFirst:
461 return false;
462 case QPlatformTheme::MouseDoubleClickInterval:
463 return NSEvent.doubleClickInterval * 1000;
464 case QPlatformTheme::KeyboardInputInterval:
465 return NSEvent.keyRepeatDelay * 1000;
466 case QPlatformTheme::KeyboardAutoRepeatRate:
467 return 1.0 / NSEvent.keyRepeatInterval;
468 case QPlatformTheme::ShowIconsInMenus:
469 return QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSTahoe;
470 case QPlatformTheme::MenuSelectionWraps:
471 return false;
472 default:
473 break;
474 }
475 return QPlatformTheme::themeHint(hint);
476}
477
478Qt::ColorScheme QCocoaTheme::colorScheme() const
479{
480 return m_colorScheme;
481}
482
483void QCocoaTheme::requestColorScheme(Qt::ColorScheme scheme)
484{
485 QMacAutoReleasePool pool;
486
487 NSAppearance *appearance = nil;
488 switch (scheme) {
489 case Qt::ColorScheme::Dark:
490 appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
491 break;
492 case Qt::ColorScheme::Light:
493 appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
494 break;
495 case Qt::ColorScheme::Unknown:
496 break;
497 }
498
499 // Always override the appearance, even if it's the same
500 // as the current effective appearance, as otherwise the
501 // requested appearance won't stick on system theme changes.
502 NSApp.appearance = appearance;
503}
504
505/*
506 Update the theme's color scheme based on the current appearance.
507
508 We can only reference the appearance on the main thread, but the
509 CoreText font engine needs to know the color scheme, and might be
510 used from secondary threads, so we cache the color scheme.
511*/
512void QCocoaTheme::updateColorScheme()
513{
514 auto appearance = [NSApp.effectiveAppearance bestMatchFromAppearancesWithNames:
515 @[ NSAppearanceNameAqua, NSAppearanceNameDarkAqua ]];
516 m_colorScheme = [appearance isEqualToString:NSAppearanceNameDarkAqua] ?
517 Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
518}
519
520Qt::ContrastPreference QCocoaTheme::contrastPreference() const
521{
522 return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldIncreaseContrast ? Qt::ContrastPreference::HighContrast
523 : Qt::ContrastPreference::NoPreference;
524}
525
526Qt::MotionPreference QCocoaTheme::motionPreference() const
527{
528 return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldReduceMotion ? Qt::MotionPreference::ReducedMotion
529 : Qt::MotionPreference::NoPreference;
530}
531
532QString QCocoaTheme::standardButtonText(int button) const
533{
534 return button == QPlatformDialogHelper::Discard ?
535 QCoreApplication::translate("QCocoaTheme", "Don't Save")
536 : QPlatformTheme::standardButtonText(button);
537}
538
539QKeySequence QCocoaTheme::standardButtonShortcut(int button) const
540{
541 return button == QPlatformDialogHelper::Discard ? QKeySequence(Qt::CTRL | Qt::Key_Delete)
542 : QPlatformTheme::standardButtonShortcut(button);
543}
544
545QPlatformMenuItem *QCocoaTheme::createPlatformMenuItem() const
546{
547 auto *menuItem = new QCocoaMenuItem();
548 qCDebug(lcQpaMenus) << "Created" << menuItem;
549 return menuItem;
550}
551
552QPlatformMenu *QCocoaTheme::createPlatformMenu() const
553{
554 auto *menu = new QCocoaMenu();
555 qCDebug(lcQpaMenus) << "Created" << menu;
556 return menu;
557}
558
559QPlatformMenuBar *QCocoaTheme::createPlatformMenuBar() const
560{
561 static bool haveMenubar = false;
562 if (!haveMenubar) {
563 haveMenubar = true;
564 QObject::connect(qGuiApp, SIGNAL(focusWindowChanged(QWindow*)),
565 QGuiApplicationPrivate::platformIntegration()->nativeInterface(),
566 SLOT(onAppFocusWindowChanged(QWindow*)));
567 }
568
569 auto *menuBar = new QCocoaMenuBar();
570 qCDebug(lcQpaMenus) << "Created" << menuBar;
571 return menuBar;
572}
573
574#ifndef QT_NO_SHORTCUT
575QList<QKeySequence> QCocoaTheme::keyBindings(QKeySequence::StandardKey key) const
576{
577 // The default key bindings in QPlatformTheme all hard-coded to use the Ctrl
578 // modifier, to match other platforms. In the normal case, when translating
579 // those to key sequences, we'll end up with Qt::ControlModifier+X, which is
580 // then matched against incoming key events that have been mapped from the
581 // command key to Qt::ControlModifier, and we'll get a match. If, however,
582 // the AA_MacDontSwapCtrlAndMeta application attribute is set, we need to
583 // fix the resulting key sequence so that it will match against unmapped
584 // key events that contain Qt::MetaModifier.
585 auto bindings = QPlatformTheme::keyBindings(key);
586
587 if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
588 static auto swapCtrlMeta = [](QKeyCombination keyCombination) {
589 const auto originalKeyModifiers = keyCombination.keyboardModifiers();
590 auto newKeyboardModifiers = originalKeyModifiers & ~(Qt::ControlModifier | Qt::MetaModifier);
591 if (originalKeyModifiers & Qt::ControlModifier)
592 newKeyboardModifiers |= Qt::MetaModifier;
593 if (originalKeyModifiers & Qt::MetaModifier)
594 newKeyboardModifiers |= Qt::ControlModifier;
595 return QKeyCombination(newKeyboardModifiers, keyCombination.key());
596 };
597
598 QList<QKeySequence> swappedBindings;
599 for (auto binding : bindings) {
600 Q_ASSERT(binding.count() == 1);
601 swappedBindings.append(QKeySequence(swapCtrlMeta(binding[0])));
602 }
603
604 bindings = swappedBindings;
605 }
606
607 return bindings;
608}
609#endif
610
611QT_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