mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-01 00:08:02 +00:00
Paint native title instead of using custom.
This commit is contained in:
parent
4e1b94d37d
commit
7fdeab829f
@ -65,6 +65,7 @@ public slots:
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *evt) override;
|
||||
|
||||
void handleActiveChangedHook() override;
|
||||
void stateChangedHook(Qt::WindowState state) override;
|
||||
void initHook() override;
|
||||
void updateWindowIcon() override;
|
||||
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
#include "history/history_inner_widget.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "window/notifications_manager_default.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "boxes/about_box.h"
|
||||
@ -44,6 +45,17 @@ namespace {
|
||||
// fullscreen mode, after that we'll hide the window no matter what.
|
||||
constexpr auto kHideAfterFullscreenTimeoutMs = 3000;
|
||||
|
||||
id FindClassInSubviews(NSView *parent, NSString *className) {
|
||||
for (NSView *child in [parent subviews]) {
|
||||
if ([child isKindOfClass:NSClassFromString(className)]) {
|
||||
return child;
|
||||
} else if (id inchild = FindClassInSubviews(child, className)) {
|
||||
return inchild;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@interface MainWindowObserver : NSObject {
|
||||
@ -65,7 +77,10 @@ class MainWindow::Private {
|
||||
public:
|
||||
Private(MainWindow *window);
|
||||
|
||||
void setNativeWindow(NSWindow *window, NSView *view);
|
||||
void setWindowBadge(const QString &str);
|
||||
void setWindowTitle(const QString &str);
|
||||
void updateNativeTitle();
|
||||
|
||||
void enableShadow(WId winId);
|
||||
|
||||
@ -74,16 +89,29 @@ public:
|
||||
void willEnterFullScreen();
|
||||
void willExitFullScreen();
|
||||
|
||||
void initCustomTitle(NSWindow *window, NSView *view);
|
||||
|
||||
bool clipboardHasText();
|
||||
|
||||
~Private();
|
||||
|
||||
private:
|
||||
void initCustomTitle();
|
||||
void refreshWeakTitleReferences();
|
||||
|
||||
MainWindow *_public;
|
||||
friend class MainWindow;
|
||||
|
||||
#ifdef OS_MAC_OLD
|
||||
NSWindow *_nativeWindow = nil;
|
||||
NSView *_nativeView = nil;
|
||||
#else // OS_MAC_OLD
|
||||
NSWindow * __weak _nativeWindow = nil;
|
||||
NSView * __weak _nativeView = nil;
|
||||
id __weak _nativeTitleWrapWeak = nil;
|
||||
id __weak _nativeTitleWeak = nil;
|
||||
#endif // !OS_MAC_OLD
|
||||
bool _useNativeTitle = false;
|
||||
bool _inFullScreen = false;
|
||||
|
||||
MainWindowObserver *_observer;
|
||||
NSPasteboard *_generalPasteboard = nullptr;
|
||||
int _generalPasteboardChangeCount = -1;
|
||||
@ -160,16 +188,107 @@ void MainWindow::Private::setWindowBadge(const QString &str) {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::Private::initCustomTitle(NSWindow *window, NSView *view) {
|
||||
[window setStyleMask:[window styleMask] | NSFullSizeContentViewWindowMask];
|
||||
[window setTitlebarAppearsTransparent:YES];
|
||||
auto inner = [window contentLayoutRect];
|
||||
auto full = [view frame];
|
||||
_public->_customTitleHeight = qMax(qRound(full.size.height - inner.size.height), 0);
|
||||
void MainWindow::Private::setWindowTitle(const QString &str) {
|
||||
_public->setWindowTitle(str);
|
||||
updateNativeTitle();
|
||||
}
|
||||
|
||||
void MainWindow::Private::setNativeWindow(NSWindow *window, NSView *view) {
|
||||
_nativeWindow = window;
|
||||
_nativeView = view;
|
||||
initCustomTitle();
|
||||
}
|
||||
|
||||
void MainWindow::Private::initCustomTitle() {
|
||||
#ifndef OS_MAC_OLD
|
||||
if (![_nativeWindow respondsToSelector:@selector(contentLayoutRect)]
|
||||
|| ![_nativeWindow respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
|
||||
return;
|
||||
}
|
||||
[_nativeWindow setTitlebarAppearsTransparent:YES];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:_nativeWindow];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:_nativeWindow];
|
||||
|
||||
// Qt has bug with layer-backed widgets containing QOpenGLWidgets.
|
||||
// See https://bugreports.qt.io/browse/QTBUG-64494
|
||||
// Emulate custom title instead (code below).
|
||||
// [window setStyleMask:[window styleMask] | NSFullSizeContentViewWindowMask];
|
||||
// auto inner = [window contentLayoutRect];
|
||||
// auto full = [view frame];
|
||||
// _public->_customTitleHeight = qMax(qRound(full.size.height - inner.size.height), 0);
|
||||
|
||||
_useNativeTitle = true;
|
||||
setWindowTitle(qsl("Telegram"));
|
||||
#endif // !OS_MAC_OLD
|
||||
}
|
||||
|
||||
void MainWindow::Private::refreshWeakTitleReferences() {
|
||||
if (!_nativeWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
|
||||
@autoreleasepool {
|
||||
|
||||
if (NSView *parent = [[_nativeWindow contentView] superview]) {
|
||||
if (id titleWrap = FindClassInSubviews(parent, Q2NSString(strTitleWrapClass()))) {
|
||||
if ([titleWrap respondsToSelector:@selector(setBackgroundColor:)]) {
|
||||
if (id title = FindClassInSubviews(titleWrap, Q2NSString(strTitleClass()))) {
|
||||
if ([title respondsToSelector:@selector(setAttributedStringValue:)]) {
|
||||
_nativeTitleWrapWeak = titleWrap;
|
||||
_nativeTitleWeak = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif // !OS_MAC_OLD
|
||||
}
|
||||
|
||||
void MainWindow::Private::updateNativeTitle() {
|
||||
if (!_useNativeTitle) {
|
||||
return;
|
||||
}
|
||||
#ifndef OS_MAC_OLD
|
||||
if (!_nativeTitleWrapWeak || !_nativeTitleWeak) {
|
||||
refreshWeakTitleReferences();
|
||||
}
|
||||
if (_nativeTitleWrapWeak && _nativeTitleWeak) {
|
||||
@autoreleasepool {
|
||||
|
||||
auto convertColor = [](QColor color) {
|
||||
return [NSColor colorWithDeviceRed:color.redF() green:color.greenF() blue:color.blueF() alpha:color.alphaF()];
|
||||
};
|
||||
auto adjustFg = [](const style::color &st) {
|
||||
// Weird thing with NSTextField taking NSAttributedString with
|
||||
// NSForegroundColorAttributeName set to colorWithDeviceRed:green:blue
|
||||
// with components all equal to 128 - it ignores it and prints black text!
|
||||
auto color = st->c;
|
||||
return (color.red() == 128 && color.green() == 128 && color.blue() == 128)
|
||||
? QColor(129, 129, 129, color.alpha())
|
||||
: color;
|
||||
};
|
||||
|
||||
auto active = _public->isActiveWindow();
|
||||
auto bgColor = (active ? st::titleBgActive : st::titleBg)->c;
|
||||
auto fgColor = adjustFg(active ? st::titleFgActive : st::titleFg);
|
||||
|
||||
auto bgConverted = convertColor(bgColor);
|
||||
auto fgConverted = convertColor(fgColor);
|
||||
[_nativeTitleWrapWeak setBackgroundColor:bgConverted];
|
||||
|
||||
auto title = Q2NSString(_public->windowTitle());
|
||||
NSDictionary *attributes = _inFullScreen
|
||||
? nil
|
||||
: [NSDictionary dictionaryWithObjectsAndKeys: fgConverted, NSForegroundColorAttributeName, bgConverted, NSBackgroundColorAttributeName, nil];
|
||||
NSAttributedString *string = [[NSAttributedString alloc] initWithString:title attributes:attributes];
|
||||
[_nativeTitleWeak setAttributedStringValue:string];
|
||||
|
||||
}
|
||||
}
|
||||
#endif // !OS_MAC_OLD
|
||||
}
|
||||
|
||||
@ -183,10 +302,12 @@ bool MainWindow::Private::clipboardHasText() {
|
||||
}
|
||||
|
||||
void MainWindow::Private::willEnterFullScreen() {
|
||||
_inFullScreen = true;
|
||||
_public->setTitleVisible(false);
|
||||
}
|
||||
|
||||
void MainWindow::Private::willExitFullScreen() {
|
||||
_inFullScreen = false;
|
||||
_public->setTitleVisible(true);
|
||||
}
|
||||
|
||||
@ -222,6 +343,12 @@ MainWindow::MainWindow()
|
||||
trayImgSel = st::macTrayIcon.instance(QColor(255, 255, 255), dbisOne);
|
||||
|
||||
_hideAfterFullScreenTimer.setCallback([this] { hideAndDeactivate(); });
|
||||
|
||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &data) {
|
||||
if (data.paletteChanged()) {
|
||||
_private->updateNativeTitle();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::closeWithoutDestroy() {
|
||||
@ -242,14 +369,15 @@ void MainWindow::stateChangedHook(Qt::WindowState state) {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::handleActiveChangedHook() {
|
||||
InvokeQueued(this, [this] { _private->updateNativeTitle(); });
|
||||
}
|
||||
|
||||
void MainWindow::initHook() {
|
||||
_customTitleHeight = 0;
|
||||
if (auto view = reinterpret_cast<NSView*>(winId())) {
|
||||
if (auto window = [view window]) {
|
||||
if ([window respondsToSelector:@selector(contentLayoutRect)]
|
||||
&& [window respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
|
||||
_private->initCustomTitle(window, view);
|
||||
}
|
||||
_private->setNativeWindow(window, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,7 +473,8 @@ void _placeCounter(QImage &img, int size, int count, style::color bg, style::col
|
||||
}
|
||||
|
||||
void MainWindow::updateTitleCounter() {
|
||||
setWindowTitle(titleVisible() ? QString() : titleText());
|
||||
//setWindowTitle(titleVisible() ? QString() : titleText());
|
||||
_private->setWindowTitle(titleText());
|
||||
}
|
||||
|
||||
void MainWindow::unreadCounterChangedHook() {
|
||||
|
@ -122,5 +122,7 @@ QString strNotificationAboutThemeChange();
|
||||
QString strNotificationAboutScreenLocked();
|
||||
QString strNotificationAboutScreenUnlocked();
|
||||
QString strStyleOfInterface();
|
||||
QString strTitleWrapClass();
|
||||
QString strTitleClass();
|
||||
|
||||
bool psLaunchMaps(const LocationCoords &coords);
|
||||
|
@ -467,3 +467,13 @@ QString strStyleOfInterface() {
|
||||
const uint32 letters[] = { 0xEF004041, 0x4C007F70, 0x1F007A70, 0x9E00A76C, 0x8500D165, 0x2E003749, 0x7B00526E, 0x3400E774, 0x3C00FA65, 0x6200B172, 0xF7001D66, 0x0B002961, 0x71008C63, 0x86005465, 0xA3006F53, 0x11006174, 0xCD001779, 0x8200556C, 0x6C009B65 };
|
||||
return strMakeFromLetters(letters);
|
||||
}
|
||||
|
||||
QString strTitleWrapClass() {
|
||||
const uint32 letters[] = { 0x4B00F54E, 0x2500A853, 0x2D008154, 0x4600EF69, 0x15006B74, 0xB900E86C, 0x66008A65, 0x3200B262, 0x9F00DC61, 0xA0009E72, 0xCF00EE43, 0x5600316F, 0x9100A76E, 0xBB000A74, 0xB6002661, 0xC7000769, 0x6200386E, 0x6B006D65, 0x1200C572, 0x41009156, 0x3D005569, 0xFE008C65, 0xB800D477 };
|
||||
return strMakeFromLetters(letters);
|
||||
}
|
||||
|
||||
QString strTitleClass() {
|
||||
const uint32 letters[] = { 0xF900894E, 0xF300BF53, 0x63009554, 0xEA008965, 0xEB004A78, 0x2E006074, 0xEC008446, 0x5C00DB69, 0x3C00CC65, 0x6F005D6C, 0x6400A064 };
|
||||
return strMakeFromLetters(letters);
|
||||
}
|
||||
|
@ -173,6 +173,7 @@ void MainWindow::handleActiveChanged() {
|
||||
}
|
||||
App::CallDelayed(1, this, [this] {
|
||||
updateTrayMenu();
|
||||
handleActiveChangedHook();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,9 @@ protected:
|
||||
virtual void updateIsActiveHook() {
|
||||
}
|
||||
|
||||
virtual void handleActiveChangedHook() {
|
||||
}
|
||||
|
||||
void clearWidgets();
|
||||
virtual void clearWidgetsHook() {
|
||||
}
|
||||
|
@ -100,6 +100,7 @@
|
||||
}, {
|
||||
'xcode_settings': {
|
||||
'CLANG_CXX_LIBRARY': 'libc++',
|
||||
'CLANG_ENABLE_OBJC_WEAK': 'YES',
|
||||
'OTHER_LDFLAGS': [
|
||||
'-framework', 'VideoToolbox',
|
||||
'-framework', 'VideoDecodeAcceleration',
|
||||
|
Loading…
Reference in New Issue
Block a user