Apply selected style to window elements on macOS
Qt doesn't apply the proper style to elements such as the title bar or text shadows, so this must be done in native code. Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
This commit is contained in:
parent
0dbaeef8a6
commit
3e65d3a9b5
4 changed files with 91 additions and 0 deletions
|
@ -1178,6 +1178,13 @@ SET(LAUNCHER_SOURCES
|
|||
ui/instanceview/VisualGroup.h
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
set(LAUNCHER_SOURCES
|
||||
${LAUNCHER_SOURCES}
|
||||
ui/themes/ThemeManager.mm
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT Apple)
|
||||
set(LAUNCHER_SOURCES
|
||||
${LAUNCHER_SOURCES}
|
||||
|
|
|
@ -174,6 +174,13 @@ void ThemeManager::initializeWidgets()
|
|||
themeDebugLog() << "<> Widget themes initialized.";
|
||||
}
|
||||
|
||||
#ifndef Q_OS_MACOS
|
||||
void ThemeManager::setTitlebarColorOnMac(WId windowId, QColor color)
|
||||
{}
|
||||
void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color)
|
||||
{}
|
||||
#endif
|
||||
|
||||
QList<IconTheme*> ThemeManager::getValidIconThemes()
|
||||
{
|
||||
QList<IconTheme*> ret;
|
||||
|
@ -247,6 +254,7 @@ void ThemeManager::setApplicationTheme(const QString& name, bool initial)
|
|||
auto& theme = themeIter->second;
|
||||
themeDebugLog() << "applying theme" << theme->name();
|
||||
theme->apply(initial);
|
||||
setTitlebarColorOfAllWindowsOnMac(qApp->palette().window().color());
|
||||
|
||||
m_logColors = theme->logColorScheme();
|
||||
} else {
|
||||
|
|
|
@ -81,6 +81,15 @@ class ThemeManager {
|
|||
void initializeIcons();
|
||||
void initializeWidgets();
|
||||
|
||||
// On non-Mac systems, this is a no-op.
|
||||
void setTitlebarColorOnMac(WId windowId, QColor color);
|
||||
// This also will set the titlebar color of newly opened windows after this method is called.
|
||||
// On non-Mac systems, this is a no-op.
|
||||
void setTitlebarColorOfAllWindowsOnMac(QColor color);
|
||||
#ifdef Q_OS_MACOS
|
||||
NSObject* m_windowTitlebarObserver = nullptr;
|
||||
#endif
|
||||
|
||||
const QStringList builtinIcons{ "pe_colored", "pe_light", "pe_dark", "pe_blue", "breeze_light", "breeze_dark",
|
||||
"OSX", "iOS", "flat", "flat_white", "multimc" };
|
||||
};
|
||||
|
|
67
launcher/ui/themes/ThemeManager.mm
Normal file
67
launcher/ui/themes/ThemeManager.mm
Normal file
|
@ -0,0 +1,67 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2025 Kenneth Chew <79120643+kthchew@users.noreply.github.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ThemeManager.h"
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
void ThemeManager::setTitlebarColorOnMac(WId windowId, QColor color)
|
||||
{
|
||||
if (windowId == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSView* view = (NSView*)windowId;
|
||||
NSWindow* window = [view window];
|
||||
window.titlebarAppearsTransparent = YES;
|
||||
window.backgroundColor = [NSColor colorWithRed:color.redF() green:color.greenF() blue:color.blueF() alpha:color.alphaF()];
|
||||
|
||||
// Unfortunately there seems to be no easy way to set the titlebar text color.
|
||||
// The closest we can do without dubious hacks is set the dark/light mode state based on the brightness of the
|
||||
// background color, which should at least make the text readable even if we can't use the theme's text color.
|
||||
// It's a good idea to set this anyway since it also affects some other UI elements like text shadows (PrismLauncher#3825).
|
||||
if (color.lightnessF() < 0.5) {
|
||||
window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
|
||||
} else {
|
||||
window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeManager::setTitlebarColorOfAllWindowsOnMac(QColor color)
|
||||
{
|
||||
NSArray<NSWindow*>* windows = [NSApp windows];
|
||||
for (NSWindow* window : windows) {
|
||||
setTitlebarColorOnMac((WId)window.contentView, color);
|
||||
}
|
||||
|
||||
// We want to change the titlebar color of newly opened windows as well.
|
||||
// There's no notification for when a new window is opened, but we can set the color when a window switches
|
||||
// from occluded to visible, which also fires on open.
|
||||
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
|
||||
if (m_windowTitlebarObserver) {
|
||||
[center removeObserver:m_windowTitlebarObserver];
|
||||
m_windowTitlebarObserver = nil;
|
||||
}
|
||||
m_windowTitlebarObserver = [center addObserverForName:NSWindowDidChangeOcclusionStateNotification
|
||||
object:nil
|
||||
queue:[NSOperationQueue mainQueue]
|
||||
usingBlock:^(NSNotification* notification) {
|
||||
NSWindow* window = notification.object;
|
||||
setTitlebarColorOnMac((WId)window.contentView, color);
|
||||
}];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue