|
|
|
@ -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() {
|
|
|
|
|