Update icon on macOS, allow changing back.

This commit is contained in:
John Preston 2023-02-28 20:49:45 +04:00
parent c575e61853
commit aa9e56c633
35 changed files with 157 additions and 8 deletions

View File

@ -1448,6 +1448,13 @@ PRIVATE
numbers.txt
)
if (APPLE AND NOT build_macstore)
nice_target_sources(Telegram ${res_loc}
PRIVATE
qrc/telegram/mac_icons.qrc
)
endif()
if (WIN32)
# message(${CMAKE_GENERATOR})
# mt.exe -manifest "${res_loc}/winrc/Telegram.manifest" "-inputresource:\"$<TARGET_FILE:Telegram>\";#1" "-outputresource:\"$<TARGET_FILE:Telegram>\";#1" >NUL

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -497,6 +497,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_open_system_settings" = "Open Settings";
"lng_settings_add_sendto" = "Place Telegram in \"Send to\" menu";
"lng_settings_mac_warn_before_quit" = "Show warning before quitting with {text}";
"lng_settings_mac_round_icon" = "Round application icon";
"lng_settings_experimental" = "Experimental settings";
"lng_settings_experimental_about" = "Warning! Those are experimental settings. Some may not work. Others may break the app. Any of them may disappear in the next version without a trace. Use at your own risk.";

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/gui">
<file alias="art/icon_round512@2x.png">../../art/icon_round512@2x.png</file>
</qresource>
</RCC>

View File

@ -1653,16 +1653,27 @@ void Application::quitDelayed() {
}
}
void Application::refreshApplicationIcon() {
const auto session = (domain().started() && domain().active().sessionExists())
? &domain().active().session()
: nullptr;
refreshApplicationIcon(session);
}
void Application::refreshApplicationIcon(Main::Session *session) {
const auto support = session && session->supportMode();
Shortcuts::ToggleSupportShortcuts(support);
Platform::SetApplicationIcon(Window::CreateIcon(
session,
Platform::IsMac()));
}
void Application::startShortcuts() {
Shortcuts::Start();
_domain->activeSessionChanges(
) | rpl::start_with_next([=](Main::Session *session) {
const auto support = session && session->supportMode();
Shortcuts::ToggleSupportShortcuts(support);
Platform::SetApplicationIcon(Window::CreateIcon(
session,
Platform::IsMac()));
refreshApplicationIcon(session);
}, _lifetime);
Shortcuts::Requests(

View File

@ -304,6 +304,7 @@ public:
// Sandbox interface.
void postponeCall(FnMut<void()> &&callable);
void refreshGlobalProxy();
void refreshApplicationIcon();
void quitPreventFinished();
@ -349,6 +350,7 @@ private:
void enumerateWindows(
Fn<void(not_null<Window::Controller*>)> callback) const;
void processCreatedWindow(not_null<Window::Controller*> window);
void refreshApplicationIcon(Main::Session *session);
friend void QuitAttempt();
void quitDelayed();

View File

@ -198,7 +198,8 @@ QByteArray Settings::serialize() const {
+ sizeof(quint64)
+ sizeof(qint32) * 3
+ Serialize::bytearraySize(mediaViewPosition)
+ sizeof(qint32);
+ sizeof(qint32)
+ sizeof(quint64);
auto result = QByteArray();
result.reserve(size);
@ -331,7 +332,8 @@ QByteArray Settings::serialize() const {
<< qint32(_windowTitleContent.current().hideAccountName ? 1 : 0)
<< qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0)
<< mediaViewPosition
<< qint32(_ignoreBatterySaving.current() ? 1 : 0);
<< qint32(_ignoreBatterySaving.current() ? 1 : 0)
<< quint64(_macRoundIconDigest.value_or(0));
}
return result;
}
@ -436,6 +438,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 hideTotalUnread = _windowTitleContent.current().hideTotalUnread ? 1 : 0;
QByteArray mediaViewPosition;
qint32 ignoreBatterySaving = _ignoreBatterySaving.current() ? 1 : 0;
quint64 macRoundIconDigest = _macRoundIconDigest.value_or(0);
stream >> themesAccentColors;
if (!stream.atEnd()) {
@ -667,6 +670,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) {
stream >> ignoreBatterySaving;
}
if (!stream.atEnd()) {
stream >> macRoundIconDigest;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
@ -864,6 +870,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
}
}
_ignoreBatterySaving = (ignoreBatterySaving == 1);
_macRoundIconDigest = macRoundIconDigest ? macRoundIconDigest : std::optional<uint64>();
}
QString Settings::getSoundPath(const QString &key) const {

View File

@ -786,6 +786,12 @@ public:
void setIgnoreBatterySavingValue(bool value) {
_ignoreBatterySaving = value;
}
void setMacRoundIconDigest(std::optional<uint64> value) {
_macRoundIconDigest = value;
}
[[nodiscard]] std::optional<uint64> macRoundIconDigest() const {
return _macRoundIconDigest;
}
[[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
@ -910,6 +916,7 @@ private:
bool _rememberedDeleteMessageOnlyForYou = false;
WindowPosition _mediaViewPosition = { .maximized = 2 };
rpl::variable<bool> _ignoreBatterySaving = false;
std::optional<uint64> _macRoundIconDigest;
bool _tabbedReplacedWithInfo = false; // per-window
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window

View File

@ -852,6 +852,10 @@ void NewVersionLaunched(int oldVersion) {
}
}
QImage DefaultApplicationIcon() {
return Window::Logo();
}
namespace ThirdParty {
void start() {

View File

@ -36,6 +36,51 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <mach-o/dyld.h>
#include <AVFoundation/AVFoundation.h>
namespace {
[[nodiscard]] QImage ImageFromNS(NSImage *icon) {
CGImageRef image = [icon CGImageForProposedRect:NULL context:nil hints:nil];
const int width = CGImageGetWidth(image);
const int height = CGImageGetHeight(image);
auto result = QImage(width, height, QImage::Format_ARGB32_Premultiplied);
result.fill(Qt::transparent);
CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
CGBitmapInfo info = CGBitmapInfo(kCGImageAlphaPremultipliedFirst) | kCGBitmapByteOrder32Host;
CGContextRef context = CGBitmapContextCreate(
result.bits(),
width,
height,
8,
result.bytesPerLine(),
space,
info);
CGRect rect = CGRectMake(0, 0, width, height);
CGContextDrawImage(context, rect, image);
CFRelease(space);
CFRelease(context);
return result;
}
[[nodiscard]] QImage ResolveBundleIconDefault() {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *icon = [path stringByAppendingString:@"/Contents/Resources/Icon.icns"];
NSImage *image = [[NSImage alloc] initWithContentsOfFile:icon];
if (!image) {
return Window::Logo();
}
auto result = ImageFromNS(image);
[image release];
return result;
}
} // namespace
QString psAppDataPath() {
return objc_appDataPath();
}
@ -188,6 +233,11 @@ bool AutostartSkip() {
void NewVersionLaunched(int oldVersion) {
}
QImage DefaultApplicationIcon() {
static auto result = ResolveBundleIconDefault();
return result;
}
bool PreventsQuit(Core::QuitReason reason) {
// Thanks Chromium, see
// chromium.org/developers/design-documents/confirm-to-quit-experiment

View File

@ -47,6 +47,8 @@ bool SkipTaskbarSupported();
void WriteCrashDumpDetails();
void NewVersionLaunched(int oldVersion);
[[nodiscard]] QImage DefaultApplicationIcon();
[[nodiscard]] bool PreventsQuit(Core::QuitReason reason);
[[nodiscard]] std::optional<bool> IsDarkMode();

View File

@ -651,6 +651,10 @@ void NewVersionLaunched(int oldVersion) {
}
}
QImage DefaultApplicationIcon() {
return Window::Logo();
}
} // namespace Platform
void psSendToMenu(bool send, bool silent) {

View File

@ -20,11 +20,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper
#include "ui/text/format_values.h"
#include "ui/boxes/single_choice_box.h"
#include "ui/painter.h"
#include "boxes/connection_box.h"
#include "boxes/about_box.h"
#include "ui/boxes/confirm_box.h"
#include "platform/platform_specific.h"
#include "ui/platform/ui_platform_window.h"
#include "base/platform/base_platform_custom_app_icon.h"
#include "base/platform/base_platform_info.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h"
@ -52,6 +54,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#endif // !TDESKTOP_DISABLE_SPELLCHECK
namespace Settings {
namespace {
[[nodiscard]] const QImage &IconMacRound() {
static const auto result = QImage(u":/gui/art/icon_round512@2x.png"_q);
return result;
}
} // namespace
void SetupConnectionType(
not_null<Window::Controller*> controller,
@ -528,6 +538,32 @@ void SetupSystemIntegrationContent(
Core::App().settings().setMacWarnBeforeQuit(checked);
Core::App().saveSettingsDelayed();
}, warnBeforeQuit->lifetime());
#ifndef OS_MAC_STORE
const auto enabled = [] {
const auto digest = base::Platform::CurrentCustomAppIconDigest();
return digest && (Core::App().settings().macRoundIconDigest() == digest);
};
const auto roundIcon = addCheckbox(
tr::lng_settings_mac_round_icon(),
enabled());
roundIcon->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked != enabled());
}) | rpl::start_with_next([=](bool checked) {
const auto digest = checked
? base::Platform::SetCustomAppIcon(IconMacRound())
: std::optional<uint64>();
if (!checked) {
base::Platform::ClearCustomAppIcon();
}
Window::OverrideApplicationIcon(checked ? IconMacRound() : QImage());
Core::App().refreshApplicationIcon();
Core::App().settings().setMacRoundIconDigest(digest);
Core::App().saveSettings();
}, roundIcon->lifetime());
#endif // OS_MAC_STORE
#else // Q_OS_MAC
const auto closeToTaskbar = addSlidingCheckbox(
tr::lng_settings_close_to_taskbar(),

View File

@ -64,6 +64,11 @@ using Core::WindowPosition;
return { skipx, skipy };
}
[[nodiscard]] QImage &OverridenIcon() {
static auto result = QImage();
return result;
}
} // namespace
const QImage &Logo() {
@ -123,12 +128,19 @@ void ConvertIconToBlack(QImage &image) {
}
}
void OverrideApplicationIcon(QImage image) {
OverridenIcon() = std::move(image);
}
QIcon CreateOfficialIcon(Main::Session *session) {
const auto support = (session && session->supportMode());
if (!support) {
return QIcon();
}
auto image = Logo();
auto overriden = OverridenIcon();
auto image = overriden.isNull()
? Platform::DefaultApplicationIcon()
: overriden;
ConvertIconToBlack(image);
return QIcon(Ui::PixmapFromImage(std::move(image)));
}

View File

@ -37,6 +37,7 @@ struct TermsLock;
[[nodiscard]] const QImage &Logo();
[[nodiscard]] const QImage &LogoNoMargin();
void OverrideApplicationIcon(QImage image);
[[nodiscard]] QIcon CreateIcon(
Main::Session *session = nullptr,
bool returnNullIfDefault = false);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 70 KiB