Update icon on macOS, allow changing back.
@ -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
|
||||
|
BIN
Telegram/Resources/art/icon_round512@2x.png
Normal file
After Width: | Height: | Size: 82 KiB |
@ -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.";
|
||||
|
5
Telegram/Resources/qrc/telegram/mac_icons.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/gui">
|
||||
<file alias="art/icon_round512@2x.png">../../art/icon_round512@2x.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -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(
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -852,6 +852,10 @@ void NewVersionLaunched(int oldVersion) {
|
||||
}
|
||||
}
|
||||
|
||||
QImage DefaultApplicationIcon() {
|
||||
return Window::Logo();
|
||||
}
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
void start() {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -651,6 +651,10 @@ void NewVersionLaunched(int oldVersion) {
|
||||
}
|
||||
}
|
||||
|
||||
QImage DefaultApplicationIcon() {
|
||||
return Window::Logo();
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
void psSendToMenu(bool send, bool silent) {
|
||||
|
@ -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(),
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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);
|
||||
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 763 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 763 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 70 KiB |