Refactor icon unread counter painting.

This commit is contained in:
John Preston 2021-11-02 17:10:40 +04:00
parent 87af865604
commit aef45b3a1d
15 changed files with 300 additions and 258 deletions

View File

@ -141,12 +141,7 @@ Application::Application(not_null<Launcher*> launcher)
, _langpack(std::make_unique<Lang::Instance>()) , _langpack(std::make_unique<Lang::Instance>())
, _langCloudManager(std::make_unique<Lang::CloudManager>(langpack())) , _langCloudManager(std::make_unique<Lang::CloudManager>(langpack()))
, _emojiKeywords(std::make_unique<ChatHelpers::EmojiKeywords>()) , _emojiKeywords(std::make_unique<ChatHelpers::EmojiKeywords>())
, _logo(Window::LoadLogo())
, _logoNoMargin(Window::LoadLogoNoMargin())
, _autoLockTimer([=] { checkAutoLock(); }) { , _autoLockTimer([=] { checkAutoLock(); }) {
Expects(!_logo.isNull());
Expects(!_logoNoMargin.isNull());
Ui::Integration::Set(&_private->uiIntegration); Ui::Integration::Set(&_private->uiIntegration);
passcodeLockChanges( passcodeLockChanges(

View File

@ -145,12 +145,6 @@ public:
bool hideMediaView(); bool hideMediaView();
[[nodiscard]] QPoint getPointForCallPanelCenter() const; [[nodiscard]] QPoint getPointForCallPanelCenter() const;
[[nodiscard]] QImage logo() const {
return _logo;
}
[[nodiscard]] QImage logoNoMargin() const {
return _logoNoMargin;
}
void startSettingsAndBackground(); void startSettingsAndBackground();
[[nodiscard]] Settings &settings() { [[nodiscard]] Settings &settings() {
@ -354,9 +348,6 @@ private:
Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr; Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr;
Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr; Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr;
const QImage _logo;
const QImage _logoNoMargin;
rpl::variable<bool> _passcodeLock; rpl::variable<bool> _passcodeLock;
bool _screenIsLocked = false; bool _screenIsLocked = false;

View File

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/main_window.h" // Window::LogoNoMargin.
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/empty_userpic.h" #include "ui/empty_userpic.h"
#include "ui/text/text_options.h" #include "ui/text/text_options.h"
@ -302,7 +303,7 @@ Image *PeerData::currentUserpic(
_userpicEmpty = nullptr; _userpicEmpty = nullptr;
} else if (isNotificationsUser()) { } else if (isNotificationsUser()) {
static auto result = Image( static auto result = Image(
Core::App().logoNoMargin().scaledToWidth( Window::LogoNoMargin().scaledToWidth(
kUserpicSize, kUserpicSize,
Qt::SmoothTransformation)); Qt::SmoothTransformation));
return &result; return &result;

View File

@ -81,17 +81,6 @@ void FeedLangTestingKey(int key) {
MainWindow::MainWindow(not_null<Window::Controller*> controller) MainWindow::MainWindow(not_null<Window::Controller*> controller)
: Platform::MainWindow(controller) { : Platform::MainWindow(controller) {
auto logo = Core::App().logo();
icon16 = logo.scaledToWidth(16, Qt::SmoothTransformation);
icon32 = logo.scaledToWidth(32, Qt::SmoothTransformation);
icon64 = logo.scaledToWidth(64, Qt::SmoothTransformation);
auto logoNoMargin = Core::App().logoNoMargin();
iconbig16 = logoNoMargin.scaledToWidth(16, Qt::SmoothTransformation);
iconbig32 = logoNoMargin.scaledToWidth(32, Qt::SmoothTransformation);
iconbig64 = logoNoMargin.scaledToWidth(64, Qt::SmoothTransformation);
resize(st::windowDefaultWidth, st::windowDefaultHeight); resize(st::windowDefaultWidth, st::windowDefaultHeight);
setLocale(QLocale(QLocale::English, QLocale::UnitedStates)); setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
@ -842,122 +831,6 @@ void MainWindow::updateControlsGeometry() {
if (_main) _main->checkMainSectionToLayer(); if (_main) _main->checkMainSectionToLayer();
} }
void MainWindow::placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) {
QPainter p(&img);
QString cnt = (count < 100) ? QString("%1").arg(count) : QString("..%1").arg(count % 10, 1, 10, QChar('0'));
int32 cntSize = cnt.size();
p.setBrush(bg->b);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::Antialiasing);
int32 fontSize;
if (size == 16) {
fontSize = 8;
} else if (size == 32) {
fontSize = (cntSize < 2) ? 12 : 12;
} else {
fontSize = (cntSize < 2) ? 22 : 22;
}
style::font f = { fontSize, 0, 0 };
int32 w = f->width(cnt), d, r;
if (size == 16) {
d = (cntSize < 2) ? 2 : 1;
r = (cntSize < 2) ? 4 : 3;
} else if (size == 32) {
d = (cntSize < 2) ? 5 : 2;
r = (cntSize < 2) ? 8 : 7;
} else {
d = (cntSize < 2) ? 9 : 4;
r = (cntSize < 2) ? 16 : 14;
}
p.drawRoundedRect(QRect(shift.x() + size - w - d * 2, shift.y() + size - f->height, w + d * 2, f->height), r, r);
p.setFont(f->f);
p.setPen(color->p);
p.drawText(shift.x() + size - w - d, shift.y() + size - f->height + f->ascent, cnt);
}
QImage MainWindow::iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) {
bool layer = false;
if (size < 0) {
size = -size;
layer = true;
}
if (layer) {
if (size != 16 && size != 20 && size != 24) size = 32;
// platform/linux/main_window_linux depends on count used the same
// way for all the same (count % 1000) values.
QString cnt = (count < 1000) ? QString("%1").arg(count) : QString("..%1").arg(count % 100, 2, 10, QChar('0'));
QImage result(size, size, QImage::Format_ARGB32);
int32 cntSize = cnt.size();
result.fill(Qt::transparent);
{
QPainter p(&result);
p.setBrush(bg);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::Antialiasing);
int32 fontSize;
if (size == 16) {
fontSize = (cntSize < 2) ? 11 : ((cntSize < 3) ? 11 : 8);
} else if (size == 20) {
fontSize = (cntSize < 2) ? 14 : ((cntSize < 3) ? 13 : 10);
} else if (size == 24) {
fontSize = (cntSize < 2) ? 17 : ((cntSize < 3) ? 16 : 12);
} else {
fontSize = (cntSize < 2) ? 22 : ((cntSize < 3) ? 20 : 16);
}
style::font f = { fontSize, 0, 0 };
int32 w = f->width(cnt), d, r;
if (size == 16) {
d = (cntSize < 2) ? 5 : ((cntSize < 3) ? 2 : 1);
r = (cntSize < 2) ? 8 : ((cntSize < 3) ? 7 : 3);
} else if (size == 20) {
d = (cntSize < 2) ? 6 : ((cntSize < 3) ? 2 : 1);
r = (cntSize < 2) ? 10 : ((cntSize < 3) ? 9 : 5);
} else if (size == 24) {
d = (cntSize < 2) ? 7 : ((cntSize < 3) ? 3 : 1);
r = (cntSize < 2) ? 12 : ((cntSize < 3) ? 11 : 6);
} else {
d = (cntSize < 2) ? 9 : ((cntSize < 3) ? 4 : 2);
r = (cntSize < 2) ? 16 : ((cntSize < 3) ? 14 : 8);
}
p.drawRoundedRect(QRect(size - w - d * 2, size - f->height, w + d * 2, f->height), r, r);
p.setFont(f);
p.setPen(fg);
p.drawText(size - w - d, size - f->height + f->ascent, cnt);
}
return result;
} else {
if (size != 16 && size != 32) size = 64;
}
QImage img(smallIcon ? ((size == 16) ? iconbig16 : (size == 32 ? iconbig32 : iconbig64)) : ((size == 16) ? icon16 : (size == 32 ? icon32 : icon64)));
if (const auto controller = sessionController()) {
if (controller->session().supportMode()) {
Window::ConvertIconToBlack(img);
}
}
if (!count) return img;
if (smallIcon) {
placeSmallCounter(img, size, count, bg, QPoint(), fg);
} else {
QPainter p(&img);
p.drawPixmap(
size / 2,
size / 2,
Ui::PixmapFromImage(
iconWithCounter(-size / 2, count, bg, fg, false)));
}
return img;
}
void MainWindow::sendPaths() { void MainWindow::sendPaths() {
if (controller().locked()) { if (controller().locked()) {
return; return;

View File

@ -71,9 +71,6 @@ public:
void sendPaths(); void sendPaths();
QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) override;
void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) override;
bool contentOverlapped(const QRect &globalRect); bool contentOverlapped(const QRect &globalRect);
bool contentOverlapped(QWidget *w, QPaintEvent *e) { bool contentOverlapped(QWidget *w, QPaintEvent *e) {
return contentOverlapped(QRect(w->mapToGlobal(e->rect().topLeft()), e->rect().size())); return contentOverlapped(QRect(w->mapToGlobal(e->rect().topLeft()), e->rect().size()));
@ -148,8 +145,6 @@ private:
std::unique_ptr<Media::SystemMediaControlsManager> _mediaControlsManager; std::unique_ptr<Media::SystemMediaControlsManager> _mediaControlsManager;
QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64;
crl::time _lastTrayClickTime = 0; crl::time _lastTrayClickTime = 0;
QPoint _lastMousePosition; QPoint _lastMousePosition;
bool _activeForTrayIconAction = true; bool _activeForTrayIconAction = true;

View File

@ -305,7 +305,7 @@ QIcon TrayIconGen(int counter, bool muted) {
} }
} }
} else { } else {
currentImageBack = Core::App().logo(); currentImageBack = Window::Logo();
} }
if (dprSize(currentImageBack) != desiredSize) { if (dprSize(currentImageBack) != desiredSize) {
@ -324,20 +324,19 @@ QIcon TrayIconGen(int counter, bool muted) {
: st::trayCounterBg; : st::trayCounterBg;
const auto &fg = st::trayCounterFg; const auto &fg = st::trayCounterFg;
if (iconSize >= 22) { if (iconSize >= 22) {
auto layerSize = -16; const auto layerSize = (iconSize >= 48)
if (iconSize >= 48) { ? 32
layerSize = -32; : (iconSize >= 36)
} else if (iconSize >= 36) { ? 24
layerSize = -24; : (iconSize >= 32)
} else if (iconSize >= 32) { ? 20
layerSize = -20; : 16;
} const auto layer = Window::GenerateCounterLayer({
const auto layer = App::wnd()->iconWithCounter( .size = layerSize,
layerSize, .count = counter,
counter, .bg = bg,
bg, .fg = fg,
fg, });
false);
QPainter p(&iconImage); QPainter p(&iconImage);
p.drawImage( p.drawImage(
@ -345,13 +344,12 @@ QIcon TrayIconGen(int counter, bool muted) {
iconImage.height() - layer.height() - 1, iconImage.height() - layer.height() - 1,
layer); layer);
} else { } else {
App::wnd()->placeSmallCounter( iconImage = Window::WithSmallCounter(std::move(iconImage), {
iconImage, .size = 16,
16, .count = counter,
counter, .bg = bg,
bg, .fg = fg,
QPoint(), });
fg);
} }
} }

View File

@ -20,13 +20,6 @@ class MainWindow : public Window::MainWindow {
public: public:
explicit MainWindow(not_null<Window::Controller*> controller); explicit MainWindow(not_null<Window::Controller*> controller);
virtual QImage iconWithCounter(
int size,
int count,
style::color bg,
style::color fg,
bool smallIcon) = 0;
void psShowTrayMenu(); void psShowTrayMenu();
bool trayAvailable() { bool trayAvailable() {
@ -54,14 +47,6 @@ protected:
void psTrayMenuUpdated(); void psTrayMenuUpdated();
void psSetupTrayIcon(); void psSetupTrayIcon();
virtual void placeSmallCounter(
QImage &img,
int size,
int count,
style::color bg,
const QPoint &shift,
style::color color) = 0;
private: private:
class Private; class Private;
friend class Private; friend class Private;

View File

@ -25,8 +25,6 @@ public:
bool psFilterNativeEvent(void *event); bool psFilterNativeEvent(void *event);
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
int getCustomTitleHeight() const { int getCustomTitleHeight() const {
return _customTitleHeight; return _customTitleHeight;
} }
@ -77,7 +75,6 @@ protected:
void psTrayMenuUpdated(); void psTrayMenuUpdated();
void psSetupTrayIcon(); void psSetupTrayIcon();
virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0;
void closeWithoutDestroy() override; void closeWithoutDestroy() override;
void createGlobalMenu() override; void createGlobalMenu() override;

View File

@ -13,7 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/win/windows_dlls.h" #include "platform/win/windows_dlls.h"
#include "platform/win/windows_event_filter.h" #include "platform/win/windows_event_filter.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "window/window_session_controller.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "main/main_session.h"
#include "base/crc32hash.h" #include "base/crc32hash.h"
#include "base/platform/win/base_windows_wrl.h" #include "base/platform/win/base_windows_wrl.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
@ -59,47 +61,77 @@ constexpr auto kKeepActiveForTrayIcon = crl::time(500);
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
HICON createHIconFromQIcon(const QIcon &icon, int xSize, int ySize) { [[nodiscard]] HICON NativeIcon(const QIcon &icon, QSize size) {
if (!icon.isNull()) { if (!icon.isNull()) {
const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize))); const auto pixmap = icon.pixmap(icon.actualSize(size));
if (!pm.isNull()) { if (!pixmap.isNull()) {
return qt_pixmapToWinHICON(pm); return qt_pixmapToWinHICON(pixmap);
} }
} }
return nullptr; return nullptr;
} }
HWND createTaskbarHider() { [[nodiscard]] QImage IconWithCounter(
HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); Window::CounterLayerArgs &&args,
HWND hWnd = 0; Main::Session *session,
bool smallIcon) {
static constexpr auto kCount = 3;
static auto ScaledLogo = std::array<QImage, kCount>();
static auto ScaledLogoNoMargin = std::array<QImage, kCount>();
QString cn = QString("TelegramTaskbarHider"); struct Dimensions {
LPCWSTR _cn = (LPCWSTR)cn.utf16(); int index = 0;
WNDCLASSEX wc; int size = 0;
};
const auto d = [&]() -> Dimensions {
switch (args.size) {
case 16:
return {
.index = 0,
.size = 16,
};
case 32:
return {
.index = 1,
.size = 32,
};
default:
return {
.index = 2,
.size = 64,
};
}
}();
Assert(d.index < kCount);
wc.cbSize = sizeof(wc); auto &scaled = smallIcon ? ScaledLogoNoMargin : ScaledLogo;
wc.style = 0; auto result = [&] {
wc.lpfnWndProc = DefWindowProc; auto &image = scaled[d.index];
wc.cbClsExtra = 0; if (image.isNull()) {
wc.cbWndExtra = 0; image = (smallIcon
wc.hInstance = appinst; ? Window::LogoNoMargin()
wc.hIcon = 0; : Window::Logo()).scaledToWidth(
wc.hCursor = 0; d.size,
wc.hbrBackground = 0; Qt::SmoothTransformation);
wc.lpszMenuName = NULL; }
wc.lpszClassName = _cn; return image;
wc.hIconSm = 0; }();
if (!RegisterClassEx(&wc)) { if (session && session->supportMode()) {
DEBUG_LOG(("Application Error: could not register taskbar hider window class, error: %1").arg(GetLastError())); Window::ConvertIconToBlack(result);
return hWnd;
} }
if (!args.count) {
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0); return result;
if (!hWnd) { } else if (smallIcon) {
DEBUG_LOG(("Application Error: could not create taskbar hider window class, error: %1").arg(GetLastError())); return Window::WithSmallCounter(std::move(result), std::move(args));
return hWnd;
} }
return hWnd; QPainter p(&result);
const auto half = d.size / 2;
args.size = half;
p.drawPixmap(
half,
half,
Ui::PixmapFromImage(Window::GenerateCounterLayer(std::move(args))));
return result;
} }
ComPtr<ITaskbarList3> taskbarList; ComPtr<ITaskbarList3> taskbarList;
@ -202,7 +234,8 @@ void MainWindow::psSetupTrayIcon() {
if (!trayIcon) { if (!trayIcon) {
trayIcon = new QSystemTrayIcon(this); trayIcon = new QSystemTrayIcon(this);
auto icon = QIcon(Ui::PixmapFromImage(Core::App().logoNoMargin())); const auto icon = QIcon(Ui::PixmapFromImage(
QImage(Window::LogoNoMargin())));
trayIcon->setIcon(icon); trayIcon->setIcon(icon);
connect( connect(
@ -327,47 +360,72 @@ void MainWindow::unreadCounterChangedHook() {
void MainWindow::updateIconCounters() { void MainWindow::updateIconCounters() {
const auto counter = Core::App().unreadBadge(); const auto counter = Core::App().unreadBadge();
const auto muted = Core::App().unreadBadgeMuted(); const auto muted = Core::App().unreadBadgeMuted();
const auto controller = sessionController();
const auto session = controller ? &controller->session() : nullptr;
auto iconSizeSmall = QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); const auto iconSizeSmall = QSize(
auto iconSizeBig = QSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON));
const auto iconSizeBig = QSize(
GetSystemMetrics(SM_CXICON),
GetSystemMetrics(SM_CYICON));
auto &bg = (muted ? st::trayCounterBgMute : st::trayCounterBg); const auto &bg = muted ? st::trayCounterBgMute : st::trayCounterBg;
auto &fg = st::trayCounterFg; const auto &fg = st::trayCounterFg;
auto iconSmallPixmap16 = Ui::PixmapFromImage( const auto counterArgs = [&](int size, int counter) {
iconWithCounter(16, counter, bg, fg, true)); return Window::CounterLayerArgs{
auto iconSmallPixmap32 = Ui::PixmapFromImage( .size = size,
iconWithCounter(32, counter, bg, fg, true)); .count = counter,
.bg = bg,
.fg = fg,
};
};
const auto iconWithCounter = [&](int size, int counter, bool smallIcon) {
return Ui::PixmapFromImage(IconWithCounter(
counterArgs(size, counter),
session,
smallIcon));
};
auto iconSmallPixmap16 = iconWithCounter(16, counter, true);
auto iconSmallPixmap32 = iconWithCounter(32, counter, true);
QIcon iconSmall, iconBig; QIcon iconSmall, iconBig;
iconSmall.addPixmap(iconSmallPixmap16); iconSmall.addPixmap(iconSmallPixmap16);
iconSmall.addPixmap(iconSmallPixmap32); iconSmall.addPixmap(iconSmallPixmap32);
iconBig.addPixmap(Ui::PixmapFromImage( const auto bigCounter = taskbarList.Get() ? 0 : counter;
iconWithCounter(32, taskbarList.Get() ? 0 : counter, bg, fg, false))); iconBig.addPixmap(iconWithCounter(32, bigCounter, false));
iconBig.addPixmap(Ui::PixmapFromImage( iconBig.addPixmap(iconWithCounter(64, bigCounter, false));
iconWithCounter(64, taskbarList.Get() ? 0 : counter, bg, fg, false)));
if (trayIcon) { if (trayIcon) {
// Force Qt to use right icon size, not the larger one. // Force Qt to use right icon size, not the larger one.
QIcon forTrayIcon; QIcon forTrayIcon;
forTrayIcon.addPixmap(iconSizeSmall.width() >= 20 ? iconSmallPixmap32 : iconSmallPixmap16); forTrayIcon.addPixmap(iconSizeSmall.width() >= 20
? iconSmallPixmap32
: iconSmallPixmap16);
trayIcon->setIcon(forTrayIcon); trayIcon->setIcon(forTrayIcon);
} }
psDestroyIcons(); psDestroyIcons();
ps_iconSmall = createHIconFromQIcon(iconSmall, iconSizeSmall.width(), iconSizeSmall.height()); ps_iconSmall = NativeIcon(iconSmall, iconSizeSmall);
ps_iconBig = createHIconFromQIcon(iconBig, iconSizeBig.width(), iconSizeBig.height()); ps_iconBig = NativeIcon(iconBig, iconSizeBig);
SendMessage(ps_hWnd, WM_SETICON, 0, (LPARAM)ps_iconSmall); SendMessage(ps_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)ps_iconSmall);
SendMessage(ps_hWnd, WM_SETICON, 1, (LPARAM)(ps_iconBig ? ps_iconBig : ps_iconSmall)); SendMessage(ps_hWnd, WM_SETICON, ICON_BIG, (LPARAM)(ps_iconBig ? ps_iconBig : ps_iconSmall));
if (taskbarList.Get()) { if (taskbarList) {
if (counter > 0) { if (counter > 0) {
const auto pixmap = [&](int size) {
return Ui::PixmapFromImage(Window::GenerateCounterLayer(
counterArgs(size, counter)));
};
QIcon iconOverlay; QIcon iconOverlay;
iconOverlay.addPixmap(Ui::PixmapFromImage( iconOverlay.addPixmap(pixmap(16));
iconWithCounter(-16, counter, bg, fg, false))); iconOverlay.addPixmap(pixmap(32));
iconOverlay.addPixmap(Ui::PixmapFromImage( ps_iconOverlay = NativeIcon(iconOverlay, iconSizeSmall);
iconWithCounter(-32, counter, bg, fg, false)));
ps_iconOverlay = createHIconFromQIcon(iconOverlay, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
} }
auto description = (counter > 0) ? tr::lng_unread_bar(tr::now, lt_count, counter) : QString(); const auto description = (counter > 0)
taskbarList->SetOverlayIcon(ps_hWnd, ps_iconOverlay, description.toStdWString().c_str()); ? tr::lng_unread_bar(tr::now, lt_count, counter).toStdWString()
: std::wstring();
taskbarList->SetOverlayIcon(ps_hWnd, ps_iconOverlay, description.c_str());
} }
psDestroyIcons();
SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
} }

View File

@ -30,8 +30,6 @@ public:
void psRefreshTaskbarIcon(); void psRefreshTaskbarIcon();
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
[[nodiscard]] static uint32 TaskbarCreatedMsgId(); [[nodiscard]] static uint32 TaskbarCreatedMsgId();
static void TaskbarCreated(); static void TaskbarCreated();
@ -59,7 +57,6 @@ protected:
void psTrayMenuUpdated(); void psTrayMenuUpdated();
void psSetupTrayIcon(); void psSetupTrayIcon();
virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0;
void showTrayTooltip() override; void showTrayTooltip() override;

View File

@ -258,7 +258,7 @@ void NotificationsCount::prepareNotificationSampleSmall() {
void NotificationsCount::prepareNotificationSampleUserpic() { void NotificationsCount::prepareNotificationSampleUserpic() {
if (_notificationSampleUserpic.isNull()) { if (_notificationSampleUserpic.isNull()) {
_notificationSampleUserpic = Ui::PixmapFromImage( _notificationSampleUserpic = Ui::PixmapFromImage(
Core::App().logoNoMargin().scaled( Window::LogoNoMargin().scaled(
st::notifyPhotoSize * cIntRetinaFactor(), st::notifyPhotoSize * cIntRetinaFactor(),
st::notifyPhotoSize * cIntRetinaFactor(), st::notifyPhotoSize * cIntRetinaFactor(),
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,

View File

@ -49,12 +49,14 @@ constexpr auto kSaveWindowPositionTimeout = crl::time(1000);
} // namespace } // namespace
QImage LoadLogo() { const QImage &Logo() {
return QImage(qsl(":/gui/art/logo_256.png")); static const auto result = QImage(u":/gui/art/logo_256.png"_q);
return result;
} }
QImage LoadLogoNoMargin() { const QImage &LogoNoMargin() {
return QImage(qsl(":/gui/art/logo_256_no_margin.png")); static const auto result = QImage(u":/gui/art/logo_256_no_margin.png"_q);
return result;
} }
void ConvertIconToBlack(QImage &image) { void ConvertIconToBlack(QImage &image) {
@ -105,7 +107,7 @@ void ConvertIconToBlack(QImage &image) {
} }
QIcon CreateOfficialIcon(Main::Session *session) { QIcon CreateOfficialIcon(Main::Session *session) {
auto image = Core::IsAppLaunched() ? Core::App().logo() : LoadLogo(); auto image = Logo();
if (session && session->supportMode()) { if (session && session->supportMode()) {
ConvertIconToBlack(image); ConvertIconToBlack(image);
} }
@ -156,6 +158,144 @@ QIcon CreateIcon(Main::Session *session) {
return result; return result;
} }
QImage GenerateCounterLayer(CounterLayerArgs &&args) {
// platform/linux/main_window_linux depends on count used the same
// way for all the same (count % 1000) values.
const auto count = args.count.value();
const auto text = (count < 1000)
? QString::number(count)
: u"..%1"_q.arg(count % 100, 2, 10, QChar('0'));
const auto textSize = text.size();
struct Dimensions {
int size = 0;
int font = 0;
int delta = 0;
int radius = 0;
};
const auto d = [&]() -> Dimensions {
switch (args.size.value()) {
case 16:
return {
.size = 16,
.font = ((textSize < 2) ? 11 : (textSize < 3) ? 11 : 8),
.delta = ((textSize < 2) ? 5 : (textSize < 3) ? 2 : 1),
.radius = ((textSize < 2) ? 8 : (textSize < 3) ? 7 : 3),
};
case 20:
return {
.size = 20,
.font = ((textSize < 2) ? 14 : (textSize < 3) ? 13 : 10),
.delta = ((textSize < 2) ? 6 : (textSize < 3) ? 2 : 1),
.radius = ((textSize < 2) ? 10 : (textSize < 3) ? 9 : 5),
};
case 24:
return {
.size = 24,
.font = ((textSize < 2) ? 17 : (textSize < 3) ? 16 : 12),
.delta = ((textSize < 2) ? 7 : (textSize < 3) ? 3 : 1),
.radius = ((textSize < 2) ? 12 : (textSize < 3) ? 11 : 6),
};
default:
return {
.size = 32,
.font = ((textSize < 2) ? 22 : (textSize < 3) ? 20 : 16),
.delta = ((textSize < 2) ? 9 : (textSize < 3) ? 4 : 2),
.radius = ((textSize < 2) ? 16 : (textSize < 3) ? 14 : 8),
};
}
}();
auto result = QImage(d.size, d.size, QImage::Format_ARGB32);
result.fill(Qt::transparent);
auto p = QPainter(&result);
auto hq = PainterHighQualityEnabler(p);
const auto f = style::font{ d.font, 0, 0 };
const auto w = f->width(text);
p.setBrush(args.bg.value());
p.setPen(Qt::NoPen);
p.drawRoundedRect(
QRect(
d.size - w - d.delta * 2,
d.size - f->height,
w + d.delta * 2,
f->height),
d.radius,
d.radius);
p.setFont(f);
p.setPen(args.fg.value());
p.drawText(d.size - w - d.delta, d.size - f->height + f->ascent, text);
p.end();
return result;
}
QImage WithSmallCounter(QImage image, CounterLayerArgs &&args) {
const auto count = args.count.value();
const auto text = (count < 100)
? QString::number(count)
: QString("..%1").arg(count % 10, 1, 10, QChar('0'));
const auto textSize = text.size();
struct Dimensions {
int size = 0;
int font = 0;
int delta = 0;
int radius = 0;
};
const auto d = [&]() -> Dimensions {
switch (args.size.value()) {
case 16:
return {
.size = 16,
.font = 8,
.delta = ((textSize < 2) ? 2 : 1),
.radius = ((textSize < 2) ? 4 : 3),
};
case 32:
return {
.size = 32,
.font = 12,
.delta = ((textSize < 2) ? 5 : 2),
.radius = ((textSize < 2) ? 8 : 7),
};
default:
return {
.size = 64,
.font = 22,
.delta = ((textSize < 2) ? 9 : 4),
.radius = ((textSize < 2) ? 16 : 14),
};
}
}();
auto p = QPainter(&image);
auto hq = PainterHighQualityEnabler(p);
const auto f = style::font{ d.font, 0, 0 };
const auto w = f->width(text);
p.setBrush(args.bg.value());
p.setPen(Qt::NoPen);
p.drawRoundedRect(
QRect(
d.size - w - d.delta * 2,
d.size - f->height,
w + d.delta * 2,
f->height),
d.radius,
d.radius);
p.setFont(f);
p.setPen(args.fg.value());
p.drawText(d.size - w - d.delta, d.size - f->height + f->ascent, text);
p.end();
return image;
}
MainWindow::MainWindow(not_null<Controller*> controller) MainWindow::MainWindow(not_null<Controller*> controller)
: _controller(controller) : _controller(controller)
, _positionUpdatedTimer([=] { savePosition(); }) , _positionUpdatedTimer([=] { savePosition(); })

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h" #include "base/timer.h"
#include "base/object_ptr.h" #include "base/object_ptr.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "base/required.h"
#include <QtWidgets/QSystemTrayIcon> #include <QtWidgets/QSystemTrayIcon>
@ -35,11 +36,21 @@ class SessionController;
class TitleWidget; class TitleWidget;
struct TermsLock; struct TermsLock;
QImage LoadLogo(); [[nodiscard]] const QImage &Logo();
QImage LoadLogoNoMargin(); [[nodiscard]] const QImage &LogoNoMargin();
QIcon CreateIcon(Main::Session *session = nullptr); [[nodiscard]] QIcon CreateIcon(Main::Session *session = nullptr);
void ConvertIconToBlack(QImage &image); void ConvertIconToBlack(QImage &image);
struct CounterLayerArgs {
base::required<int> size = 16;
base::required<int> count = 1;
base::required<style::color> bg;
base::required<style::color> fg;
};
[[nodiscard]] QImage GenerateCounterLayer(CounterLayerArgs &&args);
[[nodiscard]] QImage WithSmallCounter(QImage image, CounterLayerArgs &&args);
class MainWindow : public Ui::RpWindow { class MainWindow : public Ui::RpWindow {
public: public:
explicit MainWindow(not_null<Controller*> controller); explicit MainWindow(not_null<Controller*> controller);

View File

@ -87,7 +87,7 @@ Manager::QueuedNotification::QueuedNotification(
QPixmap Manager::hiddenUserpicPlaceholder() const { QPixmap Manager::hiddenUserpicPlaceholder() const {
if (_hiddenUserpicPlaceholder.isNull()) { if (_hiddenUserpicPlaceholder.isNull()) {
_hiddenUserpicPlaceholder = Ui::PixmapFromImage( _hiddenUserpicPlaceholder = Ui::PixmapFromImage(
Core::App().logoNoMargin().scaled( LogoNoMargin().scaled(
st::notifyPhotoSize, st::notifyPhotoSize,
st::notifyPhotoSize, st::notifyPhotoSize,
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "window/notifications_utilities.h" #include "window/notifications_utilities.h"
#include "window/main_window.h"
#include "base/platform/base_platform_file_utilities.h" #include "base/platform/base_platform_file_utilities.h"
#include "base/random.h" #include "base/random.h"
#include "core/application.h" #include "core/application.h"
@ -79,7 +80,7 @@ QString CachedUserpics::get(
peer->saveUserpic(view, v.path, st::notifyMacPhotoSize); peer->saveUserpic(view, v.path, st::notifyMacPhotoSize);
} }
} else { } else {
Core::App().logoNoMargin().save(v.path, "PNG"); LogoNoMargin().save(v.path, "PNG");
} }
i = _images.insert(key, v); i = _images.insert(key, v);
_someSavedFlag = true; _someSavedFlag = true;