Updated TDesktop sources to 2.1.18 beta

This commit is contained in:
Eric Kotato 2020-07-10 12:08:50 +03:00
commit d920a689e3
45 changed files with 465 additions and 758 deletions

View file

@ -338,6 +338,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_update_fail" = "Update check failed :("; "lng_settings_update_fail" = "Update check failed :(";
"lng_settings_workmode_tray" = "Show tray icon"; "lng_settings_workmode_tray" = "Show tray icon";
"lng_settings_workmode_window" = "Show taskbar icon"; "lng_settings_workmode_window" = "Show taskbar icon";
"lng_settings_native_frame" = "Use system window frame";
"lng_settings_auto_start" = "Launch Telegram when system starts"; "lng_settings_auto_start" = "Launch Telegram when system starts";
"lng_settings_start_min" = "Launch minimized"; "lng_settings_start_min" = "Launch minimized";
"lng_settings_add_sendto" = "Place Telegram in \"Send to\" menu"; "lng_settings_add_sendto" = "Place Telegram in \"Send to\" menu";
@ -2444,7 +2445,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"ktg_net_speed_boost_big" = "Big"; "ktg_net_speed_boost_big" = "Big";
"ktg_settings_system" = "System"; "ktg_settings_system" = "System";
"ktg_settings_use_native_decorations" = "Native window decorations";
"ktg_settings_other" = "Other"; "ktg_settings_other" = "Other";
"ktg_profile_copy_id" = "Copy ID"; "ktg_profile_copy_id" = "Copy ID";

View file

@ -67,7 +67,6 @@
"ktg_net_speed_boost_medium": "Medium", "ktg_net_speed_boost_medium": "Medium",
"ktg_net_speed_boost_big": "Big", "ktg_net_speed_boost_big": "Big",
"ktg_settings_system": "System", "ktg_settings_system": "System",
"ktg_settings_use_native_decorations": "Native window decorations",
"ktg_settings_other": "Other", "ktg_settings_other": "Other",
"ktg_profile_copy_id": "Copy ID", "ktg_profile_copy_id": "Copy ID",
"ktg_profile_bot_id": "Bot ID", "ktg_profile_bot_id": "Bot ID",

View file

@ -67,7 +67,6 @@
"ktg_net_speed_boost_medium": "Średnie", "ktg_net_speed_boost_medium": "Średnie",
"ktg_net_speed_boost_big": "Duże", "ktg_net_speed_boost_big": "Duże",
"ktg_settings_system": "System", "ktg_settings_system": "System",
"ktg_settings_use_native_decorations": "Natywne dekoracje okna",
"ktg_settings_other": "Inne", "ktg_settings_other": "Inne",
"ktg_profile_copy_id": "Kopiuj ID", "ktg_profile_copy_id": "Kopiuj ID",
"ktg_profile_bot_id": "ID Bota", "ktg_profile_bot_id": "ID Bota",

View file

@ -66,7 +66,6 @@
"ktg_net_speed_boost_medium": "Среднее", "ktg_net_speed_boost_medium": "Среднее",
"ktg_net_speed_boost_big": "Высокое", "ktg_net_speed_boost_big": "Высокое",
"ktg_settings_system": "Система", "ktg_settings_system": "Система",
"ktg_settings_use_native_decorations": "Системная рамка окна",
"ktg_settings_other": "Прочие", "ktg_settings_other": "Прочие",
"ktg_profile_copy_id": "Копировать ID", "ktg_profile_copy_id": "Копировать ID",
"ktg_profile_bot_id": "ID бота", "ktg_profile_bot_id": "ID бота",

View file

@ -67,7 +67,6 @@
"ktg_net_speed_boost_medium": "orta", "ktg_net_speed_boost_medium": "orta",
"ktg_net_speed_boost_big": "Güçlü", "ktg_net_speed_boost_big": "Güçlü",
"ktg_settings_system": "sistem", "ktg_settings_system": "sistem",
"ktg_settings_use_native_decorations": "Yerel pencere süslemeleri",
"ktg_settings_other": "Başka", "ktg_settings_other": "Başka",
"ktg_profile_copy_id": "ID kopyala", "ktg_profile_copy_id": "ID kopyala",
"ktg_profile_bot_id": "Bot ID", "ktg_profile_bot_id": "Bot ID",

View file

@ -66,7 +66,6 @@
"ktg_net_speed_boost_medium": "Середнє", "ktg_net_speed_boost_medium": "Середнє",
"ktg_net_speed_boost_big": "Високе", "ktg_net_speed_boost_big": "Високе",
"ktg_settings_system": "Система", "ktg_settings_system": "Система",
"ktg_settings_use_native_decorations": "Системна рамка вікна",
"ktg_settings_other": "Інші", "ktg_settings_other": "Інші",
"ktg_profile_copy_id": "Копіювати ID", "ktg_profile_copy_id": "Копіювати ID",
"ktg_profile_bot_id": "ID бота", "ktg_profile_bot_id": "ID бота",

View file

@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop" <Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE" ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="2.1.17.0" /> Version="2.1.18.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName> <PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>

View file

@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,1,17,0 FILEVERSION 2,1,18,0
PRODUCTVERSION 2,1,17,0 PRODUCTVERSION 2,1,18,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -62,10 +62,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Telegram FZ-LLC" VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop" VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "2.1.17.0" VALUE "FileVersion", "2.1.18.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "LegalCopyright", "Copyright (C) 2014-2020"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.1.17.0" VALUE "ProductVersion", "2.1.18.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,1,17,0 FILEVERSION 2,1,18,0
PRODUCTVERSION 2,1,17,0 PRODUCTVERSION 2,1,18,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -53,10 +53,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Telegram FZ-LLC" VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater" VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "2.1.17.0" VALUE "FileVersion", "2.1.18.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "LegalCopyright", "Copyright (C) 2014-2020"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.1.17.0" VALUE "ProductVersion", "2.1.18.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -85,7 +85,6 @@ namespace App {
void setLaunchState(LaunchState state); void setLaunchState(LaunchState state);
void restart(); void restart();
constexpr auto kFileSizeLimit = 1500 * 1024 * 1024; // Load files up to 1500mb
constexpr auto kImageSizeLimit = 64 * 1024 * 1024; // Open images up to 64mb jpg/png/gif constexpr auto kImageSizeLimit = 64 * 1024 * 1024; // Open images up to 64mb jpg/png/gif
QImage readImage(QByteArray data, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr); QImage readImage(QByteArray data, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr);
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0); QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0);

View file

@ -61,7 +61,17 @@ std::map<int, const char*> BetaLogs() {
"- Fix high definition GIF animations opening in media viewer.\n" "- Fix high definition GIF animations opening in media viewer.\n"
"- Multiple crash fixes." "- Multiple crash fixes."
} },
{
2001018,
"- Fix a possible crash in Picture-in-Picture video player.\n"
"- Fix copying links from message texts.\n"
"- Raise file size limit to 2000 MB.\n"
"- Allow using system window frame in Windows and Linux."
},
}; };
}; };

View file

@ -105,7 +105,8 @@ QByteArray Settings::serialize() const {
1000000)) 1000000))
<< qint32(_thirdColumnWidth.current()) << qint32(_thirdColumnWidth.current())
<< qint32(_thirdSectionExtendedBy) << qint32(_thirdSectionExtendedBy)
<< qint32(_notifyFromAll ? 1 : 0); << qint32(_notifyFromAll ? 1 : 0)
<< qint32(_nativeWindowFrame.current() ? 1 : 0);
} }
return result; return result;
} }
@ -169,6 +170,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 thirdColumnWidth = _thirdColumnWidth.current(); qint32 thirdColumnWidth = _thirdColumnWidth.current();
qint32 thirdSectionExtendedBy = _thirdSectionExtendedBy; qint32 thirdSectionExtendedBy = _thirdSectionExtendedBy;
qint32 notifyFromAll = _notifyFromAll ? 1 : 0; qint32 notifyFromAll = _notifyFromAll ? 1 : 0;
qint32 nativeWindowFrame = _nativeWindowFrame.current() ? 1 : 0;
stream >> themesAccentColors; stream >> themesAccentColors;
if (!stream.atEnd()) { if (!stream.atEnd()) {
@ -243,6 +245,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
>> notifyFromAll; >> notifyFromAll;
dialogsWidthRatio = snap(dialogsWidthRatioInt / 1000000., 0., 1.); dialogsWidthRatio = snap(dialogsWidthRatioInt / 1000000., 0., 1.);
} }
if (!stream.atEnd()) {
stream >> nativeWindowFrame;
}
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("App Error: " LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()")); "Bad data for Core::Settings::constructFromSerialized()"));
@ -335,6 +340,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
_tabbedSelectorSectionEnabled = false; _tabbedSelectorSectionEnabled = false;
} }
_notifyFromAll = (notifyFromAll == 1); _notifyFromAll = (notifyFromAll == 1);
_nativeWindowFrame = (nativeWindowFrame == 1);
} }
bool Settings::chatWide() const { bool Settings::chatWide() const {

View file

@ -407,6 +407,15 @@ public:
[[nodiscard]] bool notifyFromAll() const { [[nodiscard]] bool notifyFromAll() const {
return _notifyFromAll; return _notifyFromAll;
} }
void setNativeWindowFrame(bool value) {
_nativeWindowFrame = value;
}
[[nodiscard]] bool nativeWindowFrame() const {
return _nativeWindowFrame.current();
}
[[nodiscard]] rpl::producer<bool> nativeWindowFrameChanges() const {
return _nativeWindowFrame.changes();
}
[[nodiscard]] static bool ThirdColumnByDefault(); [[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] float64 DefaultDialogsWidthRatio(); [[nodiscard]] float64 DefaultDialogsWidthRatio();
@ -474,6 +483,7 @@ private:
rpl::variable<float64> _dialogsWidthRatio; // per-window rpl::variable<float64> _dialogsWidthRatio; // per-window
rpl::variable<int> _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w rpl::variable<int> _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w
bool _notifyFromAll = true; bool _notifyFromAll = true;
rpl::variable<bool> _nativeWindowFrame = false;
bool _tabbedReplacedWithInfo = false; // per-window bool _tabbedReplacedWithInfo = false; // per-window
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window

View file

@ -23,7 +23,7 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs; constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Kotatogram Desktop"_cs; constexpr auto AppName = "Kotatogram Desktop"_cs;
constexpr auto AppFile = "Kotatogram"_cs; constexpr auto AppFile = "Kotatogram"_cs;
constexpr auto AppVersion = 2001017; constexpr auto AppVersion = 2001018;
constexpr auto AppVersionStr = "2.1.17"; constexpr auto AppVersionStr = "2.1.18";
constexpr auto AppBetaVersion = true; constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View file

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data { namespace Data {
namespace AutoDownload { namespace AutoDownload {
constexpr auto kMaxBytesLimit = 3000 * 512 * 1024; constexpr auto kMaxBytesLimit = 4000 * 512 * 1024;
enum class Source { enum class Source {
User = 0x00, User = 0x00,

View file

@ -27,7 +27,7 @@ constexpr auto kFileNextRequestDelay = crl::time(20);
constexpr auto kChatsSliceLimit = 100; constexpr auto kChatsSliceLimit = 100;
constexpr auto kMessagesSliceLimit = 100; constexpr auto kMessagesSliceLimit = 100;
constexpr auto kTopPeerSliceLimit = 100; constexpr auto kTopPeerSliceLimit = 100;
constexpr auto kFileMaxSize = 1500 * 1024 * 1024; constexpr auto kFileMaxSize = 2000 * 1024 * 1024;
constexpr auto kLocationCacheSize = 100'000; constexpr auto kLocationCacheSize = 100'000;
struct LocationKey { struct LocationKey {

View file

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Export { namespace Export {
namespace { namespace {
constexpr auto kMaxFileSize = 1500 * 1024 * 1024; constexpr auto kMaxFileSize = 2000 * 1024 * 1024;
} // namespace } // namespace

View file

@ -88,21 +88,18 @@ int SizeLimitByIndex(int index) {
const auto megabytes = [&] { const auto megabytes = [&] {
if (index <= 10) { if (index <= 10) {
return index; return index;
} } else if (index <= 30) {
else if (index <= 30) {
return 10 + (index - 10) * 2; return 10 + (index - 10) * 2;
} } else if (index <= 40) {
else if (index <= 40) {
return 50 + (index - 30) * 5; return 50 + (index - 30) * 5;
} } else if (index <= 60) {
else if (index <= 60) {
return 100 + (index - 40) * 10; return 100 + (index - 40) * 10;
} } else if (index <= 70) {
else if (index <= 70) {
return 300 + (index - 60) * 20; return 300 + (index - 60) * 20;
} } else if (index <= 80) {
else { return 500 + (index - 70) * 50;
return 500 + (index - 70) * 100; } else {
return 1000 + (index - 80) * 100;
} }
}(); }();
return megabytes * kMegabyte; return megabytes * kMegabyte;

View file

@ -25,7 +25,7 @@ class Session;
namespace Export { namespace Export {
namespace View { namespace View {
constexpr auto kSizeValueCount = 80; constexpr auto kSizeValueCount = 90;
int SizeLimitByIndex(int index); int SizeLimitByIndex(int index);
class SettingsWidget : public Ui::RpWidget { class SettingsWidget : public Ui::RpWidget {

View file

@ -437,12 +437,12 @@ void SetupKotatoSystem(
AddSkip(container); AddSkip(container);
AddSubsectionTitle(container, tr::ktg_settings_system()); AddSubsectionTitle(container, tr::ktg_settings_system());
#if defined Q_OS_WIN || defined Q_OS_MAC || QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED #if defined Q_OS_MAC
const auto useNativeDecorationsToggled = Ui::CreateChild<rpl::event_stream<bool>>( const auto useNativeDecorationsToggled = Ui::CreateChild<rpl::event_stream<bool>>(
container.get()); container.get());
AddButton( AddButton(
container, container,
tr::ktg_settings_use_native_decorations(), tr::lng_settings_native_frame(),
st::settingsButton st::settingsButton
)->toggleOn( )->toggleOn(
useNativeDecorationsToggled->events_starting_with_copy(cUseNativeDecorations()) useNativeDecorationsToggled->events_starting_with_copy(cUseNativeDecorations())
@ -464,7 +464,7 @@ void SetupKotatoSystem(
confirmed, confirmed,
cancelled)); cancelled));
}, container->lifetime()); }, container->lifetime());
#endif // Q_OS_WIN || Q_OS_MAC || Qt >= 5.15 || DESKTOP_APP_QT_PATCHED #endif // Q_OS_MAC
AddButton( AddButton(
container, container,

View file

@ -2185,13 +2185,19 @@ void MainWidget::updateControlsGeometry() {
auto mainSectionWidth = width() - dialogsWidth - thirdSectionWidth; auto mainSectionWidth = width() - dialogsWidth - thirdSectionWidth;
_dialogs->setGeometryWithTopMoved({ 0, 0, dialogsWidth, height() }, _contentScrollAddToY); _dialogs->setGeometryWithTopMoved({ 0, 0, dialogsWidth, height() }, _contentScrollAddToY);
_sideShadow->setGeometryToLeft(dialogsWidth, 0, st::lineWidth, height()); const auto shadowTop = _controller->window().verticalShadowTop();
const auto shadowHeight = height() - shadowTop;
_sideShadow->setGeometryToLeft(
dialogsWidth,
shadowTop,
st::lineWidth,
shadowHeight);
if (_thirdShadow) { if (_thirdShadow) {
_thirdShadow->setGeometryToLeft( _thirdShadow->setGeometryToLeft(
width() - thirdSectionWidth - st::lineWidth, width() - thirdSectionWidth - st::lineWidth,
0, shadowTop,
st::lineWidth, st::lineWidth,
height()); shadowHeight);
} }
if (_callTopBar) { if (_callTopBar) {
_callTopBar->resizeToWidth(mainSectionWidth); _callTopBar->resizeToWidth(mainSectionWidth);

View file

@ -63,8 +63,6 @@ public:
void checkHistoryActivation(); void checkHistoryActivation();
void fixOrder();
void sendPaths(); void sendPaths();
QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) override; QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) override;
@ -79,6 +77,7 @@ public:
void showMainMenu(); void showMainMenu();
void updateTrayMenu(bool force = false) override; void updateTrayMenu(bool force = false) override;
void fixOrder() override;
void showSpecialLayer( void showSpecialLayer(
object_ptr<Ui::LayerWidget> layer, object_ptr<Ui::LayerWidget> layer,

View file

@ -16,7 +16,7 @@ namespace Streaming {
namespace { namespace {
// This is the maximum file size in Telegram API. // This is the maximum file size in Telegram API.
constexpr auto kMaxFileSize = 3000 * 512 * 1024; constexpr auto kMaxFileSize = 4000 * 512 * 1024;
int ValidateLocalSize(int64 size) { int ValidateLocalSize(int64 size) {
return (size > 0 && size <= kMaxFileSize) ? int(size) : 0; return (size > 0 && size <= kMaxFileSize) ? int(size) : 0;

View file

@ -598,6 +598,7 @@ void PipPanel::mousePressEvent(QMouseEvent *e) {
if (e->button() != Qt::LeftButton) { if (e->button() != Qt::LeftButton) {
return; return;
} }
updateOverState(e->pos());
_pressState = _overState; _pressState = _overState;
_pressPoint = e->globalPos(); _pressPoint = e->globalPos();
} }

View file

@ -22,14 +22,22 @@ void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palet
namespace Platform { namespace Platform {
inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) { inline bool AllowNativeWindowFrameToggle() {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
if (!DesktopEnvironment::IsUnity()) { return !DesktopEnvironment::IsUnity();
return object_ptr<Window::TitleWidgetQt>(parent); #else // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
} return false;
#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED #endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
}
return { nullptr }; inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
return AllowNativeWindowFrameToggle()
? object_ptr<Window::TitleWidgetQt>(parent)
: object_ptr<Window::TitleWidgetQt>{ nullptr };
}
inline bool NativeTitleRequiresShadow() {
return false;
} }
inline int PreviewTitleHeight() { inline int PreviewTitleHeight() {

View file

@ -32,8 +32,16 @@ private:
}; };
inline bool AllowNativeWindowFrameToggle() {
return false;
}
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent); object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent);
inline bool NativeTitleRequiresShadow() {
return false;
}
int PreviewTitleHeight(); int PreviewTitleHeight();
void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth); void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth);

View file

@ -14,7 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform { namespace Platform {
bool AllowNativeWindowFrameToggle();
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent); object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent);
bool NativeTitleRequiresShadow();
int PreviewTitleHeight(); int PreviewTitleHeight();
void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth); void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth);
@ -33,12 +35,22 @@ void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRe
namespace Platform { namespace Platform {
inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) { inline bool AllowNativeWindowFrameToggle() {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
return object_ptr<Window::TitleWidgetQt>(parent); return true;
#else // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
return false;
#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED #endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
}
return { nullptr }; inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
return AllowNativeWindowFrameToggle()
? object_ptr<Window::TitleWidgetQt>(parent)
: object_ptr<Window::TitleWidgetQt>{ nullptr };
}
inline bool NativeTitleRequiresShadow() {
return false;
} }
inline int PreviewTitleHeight() { inline int PreviewTitleHeight() {

View file

@ -38,28 +38,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <Windowsx.h> #include <Windowsx.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) < (b) ? (b) : (a))
#include <gdiplus.h>
#undef min
#undef max
// WM_POINTER support from Windows 8 onwards (WINVER >= 0x0602)
#ifndef WM_POINTERUPDATE
# define WM_NCPOINTERUPDATE 0x0241
# define WM_NCPOINTERDOWN 0x0242
# define WM_NCPOINTERUP 0x0243
# define WM_POINTERUPDATE 0x0245
# define WM_POINTERDOWN 0x0246
# define WM_POINTERUP 0x0247
# define WM_POINTERENTER 0x0249
# define WM_POINTERLEAVE 0x024A
# define WM_POINTERACTIVATE 0x024B
# define WM_POINTERCAPTURECHANGED 0x024C
# define WM_POINTERWHEEL 0x024E
# define WM_POINTERHWHEEL 0x024F
#endif // WM_POINTERUPDATE
HICON qt_pixmapToWinHICON(const QPixmap &); HICON qt_pixmapToWinHICON(const QPixmap &);
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
@ -112,515 +90,6 @@ HWND createTaskbarHider() {
return hWnd; return hWnd;
} }
enum {
_PsInitHor = 0x01,
_PsInitVer = 0x02,
};
int32 _psSize = 0;
class _PsShadowWindows {
public:
using Change = MainWindow::ShadowsChange;
using Changes = MainWindow::ShadowsChanges;
_PsShadowWindows() : screenDC(0), noKeyColor(RGB(255, 255, 255)) {
for (int i = 0; i < 4; ++i) {
dcs[i] = 0;
bitmaps[i] = 0;
hwnds[i] = 0;
}
}
void setColor(QColor c) {
r = c.red();
g = c.green();
b = c.blue();
if (!hwnds[0]) return;
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
for (int i = 0; i < 4; ++i) {
Gdiplus::Graphics graphics(dcs[i]);
graphics.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
if ((i % 2) && _h || !(i % 2) && _w) {
graphics.FillRectangle(&brush, 0, 0, (i % 2) ? _size : _w, (i % 2) ? _h : _size);
}
}
initCorners();
_x = _y = _w = _h = 0;
update(Change::Moved | Change::Resized);
}
bool init(not_null<MainWindow*> window, QColor c) {
_window = window;
_fullsize = st::windowShadow.width();
_shift = st::windowShadowShift;
auto cornersImage = QImage(_fullsize, _fullsize, QImage::Format_ARGB32_Premultiplied);
{
Painter p(&cornersImage);
p.setCompositionMode(QPainter::CompositionMode_Source);
st::windowShadow.paint(p, 0, 0, _fullsize, QColor(0, 0, 0));
}
if (rtl()) cornersImage = cornersImage.mirrored(true, false);
_metaSize = _fullsize + 2 * _shift;
_alphas.reserve(_metaSize);
_colors.reserve(_metaSize * _metaSize);
for (int32 j = 0; j < _metaSize; ++j) {
for (int32 i = 0; i < _metaSize; ++i) {
_colors.push_back((i < 2 * _shift || j < 2 * _shift) ? 1 : qMax(BYTE(1), BYTE(cornersImage.pixel(QPoint(i - 2 * _shift, j - 2 * _shift)) >> 24)));
}
}
uchar prev = 0;
for (int32 i = 0; i < _metaSize; ++i) {
uchar a = _colors[(_metaSize - 1) * _metaSize + i];
if (a < prev) break;
_alphas.push_back(a);
prev = a;
}
_psSize = _size = _alphas.size() - 2 * _shift;
setColor(c);
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::Status gdiRes = Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if (gdiRes != Gdiplus::Ok) {
LOG(("Application Error: could not init GDI+, error: %1").arg((int)gdiRes));
return false;
}
blend.AlphaFormat = AC_SRC_ALPHA;
blend.SourceConstantAlpha = 255;
blend.BlendFlags = 0;
blend.BlendOp = AC_SRC_OVER;
screenDC = GetDC(0);
if (!screenDC) {
LOG(("Application Error: could not GetDC(0), error: %2").arg(GetLastError()));
return false;
}
const auto avail = QApplication::desktop()->availableGeometry();
max_w = avail.width();
accumulate_max(max_w, st::windowMinWidth);
max_h = avail.height();
accumulate_max(max_h, st::defaultWindowTitle.height + st::windowMinHeight);
HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
HWND hwnd = _window ? _window->psHwnd() : nullptr;
for (int i = 0; i < 4; ++i) {
QString cn = QString("KotatogramShadow%1").arg(i);
LPCWSTR _cn = (LPCWSTR)cn.utf16();
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.lpfnWndProc = wndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = appinst;
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = _cn;
wc.hIconSm = 0;
if (!RegisterClassEx(&wc)) {
LOG(("Application Error: could not register shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}
hwnds[i] = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0);
if (!hwnds[i]) {
LOG(("Application Error: could not create shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}
SetWindowLongPtr(hwnds[i], GWLP_HWNDPARENT, (LONG)hwnd);
dcs[i] = CreateCompatibleDC(screenDC);
if (!dcs[i]) {
LOG(("Application Error: could not create dc for shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}
bitmaps[i] = CreateCompatibleBitmap(screenDC, (i % 2) ? _size : max_w, (i % 2) ? max_h : _size);
if (!bitmaps[i]) {
LOG(("Application Error: could not create bitmap for shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}
SelectObject(dcs[i], bitmaps[i]);
}
QStringList alphasForLog;
for_const (auto alpha, _alphas) {
alphasForLog.append(QString::number(alpha));
}
LOG(("Window Shadow: %1").arg(alphasForLog.join(", ")));
initCorners();
return true;
}
void initCorners(int directions = (_PsInitHor | _PsInitVer)) {
bool hor = (directions & _PsInitHor), ver = (directions & _PsInitVer);
Gdiplus::Graphics graphics0(dcs[0]), graphics1(dcs[1]), graphics2(dcs[2]), graphics3(dcs[3]);
graphics0.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
graphics1.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
graphics2.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
graphics3.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
if (hor) graphics0.FillRectangle(&brush, 0, 0, _fullsize - (_size - _shift), 2 * _shift);
if (ver) {
graphics1.FillRectangle(&brush, 0, 0, _size, 2 * _shift);
graphics3.FillRectangle(&brush, 0, 0, _size, 2 * _shift);
graphics1.FillRectangle(&brush, _size - _shift, 2 * _shift, _shift, _fullsize);
graphics3.FillRectangle(&brush, 0, 2 * _shift, _shift, _fullsize);
}
if (hor) {
for (int j = 2 * _shift; j < _size; ++j) {
for (int k = 0; k < _fullsize - (_size - _shift); ++k) {
brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b));
graphics0.FillRectangle(&brush, k, j, 1, 1);
graphics2.FillRectangle(&brush, k, _size - (j - 2 * _shift) - 1, 1, 1);
}
}
for (int j = _size; j < _size + 2 * _shift; ++j) {
for (int k = 0; k < _fullsize - (_size - _shift); ++k) {
brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b));
graphics2.FillRectangle(&brush, k, _size - (j - 2 * _shift) - 1, 1, 1);
}
}
}
if (ver) {
for (int j = 2 * _shift; j < _fullsize + 2 * _shift; ++j) {
for (int k = _shift; k < _size; ++k) {
brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + (k + _shift)], r, g, b));
graphics1.FillRectangle(&brush, _size - k - 1, j, 1, 1);
graphics3.FillRectangle(&brush, k, j, 1, 1);
}
}
}
}
void verCorners(int h, Gdiplus::Graphics *pgraphics1, Gdiplus::Graphics *pgraphics3) {
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
pgraphics1->FillRectangle(&brush, _size - _shift, h - _fullsize, _shift, _fullsize);
pgraphics3->FillRectangle(&brush, 0, h - _fullsize, _shift, _fullsize);
for (int j = 0; j < _fullsize; ++j) {
for (int k = _shift; k < _size; ++k) {
brush.SetColor(Gdiplus::Color(_colors[(j + 2 * _shift) * _metaSize + k + _shift], r, g, b));
pgraphics1->FillRectangle(&brush, _size - k - 1, h - j - 1, 1, 1);
pgraphics3->FillRectangle(&brush, k, h - j - 1, 1, 1);
}
}
}
void horCorners(int w, Gdiplus::Graphics *pgraphics0, Gdiplus::Graphics *pgraphics2) {
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
pgraphics0->FillRectangle(&brush, w - 2 * _size - (_fullsize - (_size - _shift)), 0, _fullsize - (_size - _shift), 2 * _shift);
for (int j = 2 * _shift; j < _size; ++j) {
for (int k = 0; k < _fullsize - (_size - _shift); ++k) {
brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b));
pgraphics0->FillRectangle(&brush, w - 2 * _size - k - 1, j, 1, 1);
pgraphics2->FillRectangle(&brush, w - 2 * _size - k - 1, _size - (j - 2 * _shift) - 1, 1, 1);
}
}
for (int j = _size; j < _size + 2 * _shift; ++j) {
for (int k = 0; k < _fullsize - (_size - _shift); ++k) {
brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b));
pgraphics2->FillRectangle(&brush, w - 2 * _size - k - 1, _size - (j - 2 * _shift) - 1, 1, 1);
}
}
}
void update(Changes changes, WINDOWPOS *pos = 0) {
HWND hwnd = _window ? _window->psHwnd() : 0;
if (!hwnd || !hwnds[0]) return;
if (changes == Changes(Change::Activate)) {
for (int i = 0; i < 4; ++i) {
SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
return;
}
if (changes & Change::Hidden) {
if (!hidden) {
for (int i = 0; i < 4; ++i) {
hidden = true;
ShowWindow(hwnds[i], SW_HIDE);
}
}
return;
}
if (!_window->positionInited()) return;
int x = _x, y = _y, w = _w, h = _h;
if (pos && (!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE) || !(pos->flags & SWP_NOREPOSITION))) {
if (!(pos->flags & SWP_NOMOVE)) {
x = pos->x - _size;
y = pos->y - _size;
} else if (pos->flags & SWP_NOSIZE) {
for (int i = 0; i < 4; ++i) {
SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
return;
}
if (!(pos->flags & SWP_NOSIZE)) {
w = pos->cx + 2 * _size;
h = pos->cy + 2 * _size;
}
} else {
RECT r;
GetWindowRect(hwnd, &r);
x = r.left - _size;
y = r.top - _size;
w = r.right + _size - x;
h = r.bottom + _size - y;
}
if (h < 2 * _fullsize + 2 * _shift) {
h = 2 * _fullsize + 2 * _shift;
}
if (w < 2 * (_fullsize + _shift)) {
w = 2 * (_fullsize + _shift);
}
if (w != _w) {
int from = (_w > 2 * (_fullsize + _shift)) ? (_w - _size - _fullsize - _shift) : (_fullsize - (_size - _shift));
int to = w - _size - _fullsize - _shift;
if (w > max_w) {
from = _fullsize - (_size - _shift);
max_w *= 2;
for (int i = 0; i < 4; i += 2) {
DeleteObject(bitmaps[i]);
bitmaps[i] = CreateCompatibleBitmap(screenDC, max_w, _size);
SelectObject(dcs[i], bitmaps[i]);
}
initCorners(_PsInitHor);
}
Gdiplus::Graphics graphics0(dcs[0]), graphics2(dcs[2]);
graphics0.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
graphics2.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
if (to > from) {
graphics0.FillRectangle(&brush, from, 0, to - from, 2 * _shift);
for (int i = 2 * _shift; i < _size; ++i) {
Gdiplus::Pen pen(Gdiplus::Color(_alphas[i], r, g, b));
graphics0.DrawLine(&pen, from, i, to, i);
graphics2.DrawLine(&pen, from, _size - (i - 2 * _shift) - 1, to, _size - (i - 2 * _shift) - 1);
}
for (int i = _size; i < _size + 2 * _shift; ++i) {
Gdiplus::Pen pen(Gdiplus::Color(_alphas[i], r, g, b));
graphics2.DrawLine(&pen, from, _size - (i - 2 * _shift) - 1, to, _size - (i - 2 * _shift) - 1);
}
}
if (_w > w) {
graphics0.FillRectangle(&brush, w - _size - _fullsize - _shift, 0, _fullsize - (_size - _shift), _size);
graphics2.FillRectangle(&brush, w - _size - _fullsize - _shift, 0, _fullsize - (_size - _shift), _size);
}
horCorners(w, &graphics0, &graphics2);
POINT p0 = { x + _size, y }, p2 = { x + _size, y + h - _size }, f = { 0, 0 };
SIZE s = { w - 2 * _size, _size };
updateWindow(0, &p0, &s);
updateWindow(2, &p2, &s);
} else if (x != _x || y != _y) {
POINT p0 = { x + _size, y }, p2 = { x + _size, y + h - _size };
updateWindow(0, &p0);
updateWindow(2, &p2);
} else if (h != _h) {
POINT p2 = { x + _size, y + h - _size };
updateWindow(2, &p2);
}
if (h != _h) {
int from = (_h > 2 * _fullsize + 2 * _shift) ? (_h - _fullsize) : (_fullsize + 2 * _shift);
int to = h - _fullsize;
if (h > max_h) {
from = (_fullsize + 2 * _shift);
max_h *= 2;
for (int i = 1; i < 4; i += 2) {
DeleteObject(bitmaps[i]);
bitmaps[i] = CreateCompatibleBitmap(dcs[i], _size, max_h);
SelectObject(dcs[i], bitmaps[i]);
}
initCorners(_PsInitVer);
}
Gdiplus::Graphics graphics1(dcs[1]), graphics3(dcs[3]);
graphics1.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
graphics3.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
if (to > from) {
graphics1.FillRectangle(&brush, _size - _shift, from, _shift, to - from);
graphics3.FillRectangle(&brush, 0, from, _shift, to - from);
for (int i = 2 * _shift; i < _size + _shift; ++i) {
Gdiplus::Pen pen(Gdiplus::Color(_alphas[i], r, g, b));
graphics1.DrawLine(&pen, _size + _shift - i - 1, from, _size + _shift - i - 1, to);
graphics3.DrawLine(&pen, i - _shift, from, i - _shift, to);
}
}
if (_h > h) {
graphics1.FillRectangle(&brush, 0, h - _fullsize, _size, _fullsize);
graphics3.FillRectangle(&brush, 0, h - _fullsize, _size, _fullsize);
}
verCorners(h, &graphics1, &graphics3);
POINT p1 = { x + w - _size, y }, p3 = { x, y }, f = { 0, 0 };
SIZE s = { _size, h };
updateWindow(1, &p1, &s);
updateWindow(3, &p3, &s);
} else if (x != _x || y != _y) {
POINT p1 = { x + w - _size, y }, p3 = { x, y };
updateWindow(1, &p1);
updateWindow(3, &p3);
} else if (w != _w) {
POINT p1 = { x + w - _size, y };
updateWindow(1, &p1);
}
_x = x;
_y = y;
_w = w;
_h = h;
if (hidden && (changes & Change::Shown)) {
for (int i = 0; i < 4; ++i) {
SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
}
hidden = false;
}
}
void updateWindow(int i, POINT *p, SIZE *s = 0) {
static POINT f = { 0, 0 };
if (s) {
UpdateLayeredWindow(hwnds[i], (s ? screenDC : 0), p, s, (s ? dcs[i] : 0), (s ? (&f) : 0), noKeyColor, &blend, ULW_ALPHA);
} else {
SetWindowPos(hwnds[i], 0, p->x, p->y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
}
}
void destroy() {
for (int i = 0; i < 4; ++i) {
if (dcs[i]) DeleteDC(dcs[i]);
if (bitmaps[i]) DeleteObject(bitmaps[i]);
if (hwnds[i]) DestroyWindow(hwnds[i]);
dcs[i] = 0;
bitmaps[i] = 0;
hwnds[i] = 0;
}
if (screenDC) ReleaseDC(0, screenDC);
}
MainWindow *window() const {
return _window;
}
private:
int _x = 0, _y = 0, _w = 0, _h = 0;
int _metaSize = 0, _fullsize = 0, _size = 0, _shift = 0;
QVector<BYTE> _alphas, _colors;
MainWindow *_window = nullptr;
bool hidden = true;
HWND hwnds[4];
HDC dcs[4], screenDC;
HBITMAP bitmaps[4];
int max_w = 0, max_h = 0;
BLENDFUNCTION blend;
BYTE r = 0, g = 0, b = 0;
COLORREF noKeyColor;
static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
_PsShadowWindows _psShadowWindows;
LRESULT CALLBACK _PsShadowWindows::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
const auto window = _psShadowWindows.window();
if (!window || !window->shadowsWorking()) {
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int i;
for (i = 0; i < 4; ++i) {
if (_psShadowWindows.hwnds[i] && hwnd == _psShadowWindows.hwnds[i]) {
break;
}
}
if (i == 4) return DefWindowProc(hwnd, msg, wParam, lParam);
switch (msg) {
case WM_CLOSE:
window->close();
break;
case WM_NCHITTEST: {
int32 xPos = GET_X_LPARAM(lParam), yPos = GET_Y_LPARAM(lParam);
switch (i) {
case 0: return HTTOP;
case 1: return (yPos < _psShadowWindows._y + _psSize) ? HTTOPRIGHT : ((yPos >= _psShadowWindows._y + _psShadowWindows._h - _psSize) ? HTBOTTOMRIGHT : HTRIGHT);
case 2: return HTBOTTOM;
case 3: return (yPos < _psShadowWindows._y + _psSize) ? HTTOPLEFT : ((yPos >= _psShadowWindows._y + _psShadowWindows._h - _psSize) ? HTBOTTOMLEFT : HTLEFT);
}
return HTTRANSPARENT;
} break;
case WM_NCACTIVATE: return DefWindowProc(hwnd, msg, wParam, lParam);
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCLBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCMBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_NCRBUTTONDBLCLK:
case WM_NCXBUTTONDOWN:
case WM_NCXBUTTONUP:
case WM_NCXBUTTONDBLCLK:
case WM_NCMOUSEHOVER:
case WM_NCMOUSELEAVE:
case WM_NCMOUSEMOVE:
case WM_NCPOINTERUPDATE:
case WM_NCPOINTERDOWN:
case WM_NCPOINTERUP:
if (window && window->psHwnd()) {
if (msg == WM_NCLBUTTONDOWN) {
::SetForegroundWindow(window->psHwnd());
}
LRESULT res = SendMessage(window->psHwnd(), msg, wParam, lParam);
return res;
}
return 0;
break;
case WM_ACTIVATE:
if (window && window->psHwnd() && wParam == WA_ACTIVE) {
if ((HWND)lParam != window->psHwnd()) {
::SetForegroundWindow(hwnd);
::SetWindowPos(window->psHwnd(), hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
ComPtr<ITaskbarList3> taskbarList; ComPtr<ITaskbarList3> taskbarList;
bool handleSessionNotification = false; bool handleSessionNotification = false;
@ -638,13 +107,17 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
if (!_taskbarCreatedMsgId) { if (!_taskbarCreatedMsgId) {
_taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); _taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated");
} }
if (!UseNativeDecorations()) { subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) { if (_shadow && update.paletteChanged()) {
if (update.paletteChanged()) { _shadow->setColor(st::windowShadowFg->c);
_psShadowWindows.setColor(st::windowShadowFg->c); }
} });
}); Core::App().settings().nativeWindowFrameChanges(
} ) | rpl::start_with_next([=] {
initShadows();
validateWindowTheme();
fixMaximizedWindow();
}, lifetime());
} }
void MainWindow::TaskbarCreated() { void MainWindow::TaskbarCreated() {
@ -654,23 +127,21 @@ void MainWindow::TaskbarCreated() {
} }
} }
void MainWindow::shadowsUpdate(ShadowsChanges changes, WINDOWPOS *position) { void MainWindow::shadowsUpdate(
if (!UseNativeDecorations()) { Ui::Platform::WindowShadow::Changes changes,
_psShadowWindows.update(changes, position); WINDOWPOS *position) {
if (_shadow) {
_shadow->update(changes, position);
} }
} }
void MainWindow::shadowsActivate() { void MainWindow::shadowsActivate() {
if (!UseNativeDecorations()) { // _shadow->setColor(_shActive);
// _psShadowWindows.setColor(_shActive); shadowsUpdate(Ui::Platform::WindowShadow::Change::Activate);
shadowsUpdate(ShadowsChange::Activate);
}
} }
void MainWindow::shadowsDeactivate() { void MainWindow::shadowsDeactivate() {
// if (!UseNativeDecorations()) { // _shadow->setColor(_shInactive);
// _psShadowWindows.setColor(_shInactive);
// }
} }
void MainWindow::psShowTrayMenu() { void MainWindow::psShowTrayMenu() {
@ -768,6 +239,10 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
} }
} }
void MainWindow::updateWindowIcon() {
updateIconCounters();
}
void MainWindow::unreadCounterChangedHook() { void MainWindow::unreadCounterChangedHook() {
setWindowTitle(titleText()); setWindowTitle(titleText());
updateIconCounters(); updateIconCounters();
@ -840,17 +315,22 @@ void MainWindow::initHook() {
} }
void MainWindow::initShadows() { void MainWindow::initShadows() {
if (!UseNativeDecorations()) { if (Core::App().settings().nativeWindowFrame()) {
_psShadowWindows.init(this, st::windowShadowFg->c); _shadow.reset();
_shadowsWorking = true; } else {
psUpdateMargins(); _shadow.emplace(this, st::windowShadowFg->c);
shadowsUpdate(ShadowsChange::Hidden);
} }
updateCustomMargins();
firstShadowsUpdate();
} }
void MainWindow::firstShadowsUpdate() { void MainWindow::firstShadowsUpdate() {
if (!UseNativeDecorations() && !(windowState() & Qt::WindowMinimized) && !isHidden()) { using Change = Ui::Platform::WindowShadow::Change;
shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized | ShadowsChange::Shown); if ((windowState() & (Qt::WindowMinimized | Qt::WindowMaximized))
|| isHidden()) {
shadowsUpdate(Change::Hidden);
} else {
shadowsUpdate(Change::Moved | Change::Resized | Change::Shown);
} }
} }
@ -907,19 +387,40 @@ void MainWindow::updateSystemMenu(Qt::WindowState state) {
} }
} }
void MainWindow::psUpdateMargins() { void MainWindow::updateCustomMargins() {
if (!ps_hWnd || _inUpdateMargins) return; if (!ps_hWnd || _inUpdateMargins) {
return;
}
_inUpdateMargins = true; _inUpdateMargins = true;
RECT r, a; const auto margins = computeCustomMargins();
if (const auto native = QGuiApplication::platformNativeInterface()) {
native->setWindowProperty(
windowHandle()->handle(),
qsl("WindowsCustomMargins"),
QVariant::fromValue<QMargins>(margins));
}
if (!_themeInited) {
_themeInited = true;
validateWindowTheme();
}
_inUpdateMargins = false;
}
QMargins MainWindow::computeCustomMargins() {
if (Core::App().settings().nativeWindowFrame()) {
_deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0;
return QMargins();
}
auto r = RECT();
GetClientRect(ps_hWnd, &r); GetClientRect(ps_hWnd, &r);
a = r;
LONG style = GetWindowLongPtr(ps_hWnd, GWL_STYLE), styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE); auto a = r;
const auto style = GetWindowLongPtr(ps_hWnd, GWL_STYLE);
const auto styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE);
AdjustWindowRectEx(&a, style, false, styleEx); AdjustWindowRectEx(&a, style, false, styleEx);
QMargins margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom); auto margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom);
if (style & WS_MAXIMIZE) { if (style & WS_MAXIMIZE) {
RECT w, m; RECT w, m;
GetWindowRect(ps_hWnd, &w); GetWindowRect(ps_hWnd, &w);
@ -948,23 +449,39 @@ void MainWindow::psUpdateMargins() {
SetWindowPos(ps_hWnd, 0, 0, 0, w.right - w.left - _deltaLeft - _deltaRight, w.bottom - w.top - _deltaBottom - _deltaTop, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION); SetWindowPos(ps_hWnd, 0, 0, 0, w.right - w.left - _deltaLeft - _deltaRight, w.bottom - w.top - _deltaBottom - _deltaTop, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
_deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0; _deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0;
} }
return margins;
}
if (const auto native = QGuiApplication::platformNativeInterface()) { void MainWindow::validateWindowTheme() {
native->setWindowProperty( if (IsWindows8OrGreater()) {
windowHandle()->handle(), return;
qsl("WindowsCustomMargins"), } else if (Dlls::SetWindowTheme != nullptr) {
QVariant::fromValue<QMargins>(margins)); if (Core::App().settings().nativeWindowFrame()) {
Dlls::SetWindowTheme(ps_hWnd, nullptr, nullptr);
} else {
Dlls::SetWindowTheme(ps_hWnd, L" ", L" ");
}
QApplication::setStyle(QStyleFactory::create(qsl("Windows")));
} }
if (!_themeInited) { }
_themeInited = true;
if (!IsWindows8OrGreater()) { void MainWindow::fixMaximizedWindow() {
if (Dlls::SetWindowTheme != nullptr) { auto r = RECT();
Dlls::SetWindowTheme(ps_hWnd, L" ", L" "); GetClientRect(ps_hWnd, &r);
QApplication::setStyle(QStyleFactory::create(qsl("Windows"))); const auto style = GetWindowLongPtr(ps_hWnd, GWL_STYLE);
} const auto styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE);
AdjustWindowRectEx(&r, style, false, styleEx);
if (style & WS_MAXIMIZE) {
auto w = RECT();
GetWindowRect(ps_hWnd, &w);
if (const auto hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST)) {
MONITORINFO mi;
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
const auto m = mi.rcWork;
SetWindowPos(ps_hWnd, 0, 0, 0, m.right - m.left - _deltaLeft - _deltaRight, m.bottom - m.top - _deltaTop - _deltaBottom, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
} }
} }
_inUpdateMargins = false;
} }
HWND MainWindow::psHwnd() const { HWND MainWindow::psHwnd() const {
@ -1000,10 +517,6 @@ MainWindow::~MainWindow() {
if (ps_menu) DestroyMenu(ps_menu); if (ps_menu) DestroyMenu(ps_menu);
psDestroyIcons(); psDestroyIcons();
if (!UseNativeDecorations()) {
_shadowsWorking = false;
_psShadowWindows.destroy();
}
if (ps_tbHider_hWnd) DestroyWindow(ps_tbHider_hWnd); if (ps_tbHider_hWnd) DestroyWindow(ps_tbHider_hWnd);
EventFilter::Destroy(); EventFilter::Destroy();

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "platform/platform_main_window.h" #include "platform/platform_main_window.h"
#include "ui/platform/win/ui_window_shadow_win.h"
#include "base/platform/win/base_windows_h.h" #include "base/platform/win/base_windows_h.h"
#include "base/flags.h" #include "base/flags.h"
@ -30,7 +31,9 @@ public:
void psInitSysMenu(); void psInitSysMenu();
void updateSystemMenu(Qt::WindowState state); void updateSystemMenu(Qt::WindowState state);
void psUpdateMargins(); void updateCustomMargins();
void updateWindowIcon() override;
void psRefreshTaskbarIcon(); void psRefreshTaskbarIcon();
@ -42,22 +45,11 @@ public:
static void TaskbarCreated(); static void TaskbarCreated();
// Custom shadows. // Custom shadows.
enum class ShadowsChange {
Moved = (1 << 0),
Resized = (1 << 1),
Shown = (1 << 2),
Hidden = (1 << 3),
Activate = (1 << 4),
};
using ShadowsChanges = base::flags<ShadowsChange>;
friend inline constexpr auto is_flag_type(ShadowsChange) { return true; };
bool shadowsWorking() const {
return _shadowsWorking;
}
void shadowsActivate(); void shadowsActivate();
void shadowsDeactivate(); void shadowsDeactivate();
void shadowsUpdate(ShadowsChanges changes, WINDOWPOS *position = nullptr); void shadowsUpdate(
Ui::Platform::WindowShadow::Changes changes,
WINDOWPOS *position = nullptr);
int deltaLeft() const { int deltaLeft() const {
return _deltaLeft; return _deltaLeft;
@ -99,12 +91,15 @@ protected:
private: private:
void updateIconCounters(); void updateIconCounters();
QMargins computeCustomMargins();
void validateWindowTheme();
void psDestroyIcons(); void psDestroyIcons();
void fixMaximizedWindow();
static UINT _taskbarCreatedMsgId; static UINT _taskbarCreatedMsgId;
bool _shadowsWorking = false; std::optional<Ui::Platform::WindowShadow> _shadow;
bool _themeInited = false; bool _themeInited = false;
bool _inUpdateMargins = false; bool _inUpdateMargins = false;

View file

@ -59,10 +59,18 @@ private:
}; };
inline bool AllowNativeWindowFrameToggle() {
return true;
}
inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) { inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
return object_ptr<TitleWidget>(parent); return object_ptr<TitleWidget>(parent);
} }
inline bool NativeTitleRequiresShadow() {
return true;
}
inline int PreviewTitleHeight() { inline int PreviewTitleHeight() {
return Window::Theme::DefaultPreviewTitleHeight(); return Window::Theme::DefaultPreviewTitleHeight();
} }

View file

@ -78,56 +78,13 @@ bool EventFilter::nativeEventFilter(
}); });
} }
bool EventFilter::mainWindowEvent( bool EventFilter::customWindowFrameEvent(
HWND hWnd, HWND hWnd,
UINT msg, UINT msg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam, LPARAM lParam,
LRESULT *result) { LRESULT *result) {
using ShadowsChange = MainWindow::ShadowsChange;
if (const auto tbCreatedMsgId = Platform::MainWindow::TaskbarCreatedMsgId()) {
if (msg == tbCreatedMsgId) {
Platform::MainWindow::TaskbarCreated();
}
}
if (UseNativeDecorations()) {
return false;
}
switch (msg) { switch (msg) {
case WM_TIMECHANGE: {
Core::App().checkAutoLockIn(100);
} return false;
case WM_WTSSESSION_CHANGE: {
if (wParam == WTS_SESSION_LOGOFF || wParam == WTS_SESSION_LOCK) {
setSessionLoggedOff(true);
} else if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK) {
setSessionLoggedOff(false);
}
} return false;
case WM_DESTROY: {
App::quit();
} return false;
case WM_ACTIVATE: {
if (LOWORD(wParam) == WA_CLICKACTIVE) {
Ui::MarkInactivePress(_window, true);
}
if (LOWORD(wParam) != WA_INACTIVE) {
_window->shadowsActivate();
} else {
_window->shadowsDeactivate();
}
if (Global::started()) {
_window->update();
}
} return false;
case WM_NCPAINT: { case WM_NCPAINT: {
if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false;
if (result) *result = 0; if (result) *result = 0;
@ -162,47 +119,6 @@ bool EventFilter::mainWindowEvent(
} }
} return true; } return true;
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED: {
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(hWnd, &wp) && (wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) {
_window->shadowsUpdate(ShadowsChange::Hidden);
} else {
_window->shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized, (WINDOWPOS*)lParam);
}
} return false;
case WM_SIZE: {
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) {
if (wParam != SIZE_RESTORED || _window->windowState() != Qt::WindowNoState) {
Qt::WindowState state = Qt::WindowNoState;
if (wParam == SIZE_MAXIMIZED) {
state = Qt::WindowMaximized;
} else if (wParam == SIZE_MINIMIZED) {
state = Qt::WindowMinimized;
}
emit _window->windowHandle()->windowStateChanged(state);
} else {
_window->positionUpdated();
}
_window->psUpdateMargins();
MainWindow::ShadowsChanges changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? ShadowsChange::Hidden : (ShadowsChange::Resized | ShadowsChange::Shown);
_window->shadowsUpdate(changes);
}
} return false;
case WM_SHOWWINDOW: {
LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
auto changes = ShadowsChange::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? ShadowsChange::Shown : ShadowsChange::Hidden);
_window->shadowsUpdate(changes);
} return false;
case WM_MOVE: {
_window->shadowsUpdate(ShadowsChange::Moved);
_window->positionUpdated();
} return false;
case WM_NCHITTEST: { case WM_NCHITTEST: {
if (!result) return false; if (!result) return false;
@ -230,6 +146,103 @@ bool EventFilter::mainWindowEvent(
case WM_NCRBUTTONUP: { case WM_NCRBUTTONUP: {
SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
} return true; } return true;
}
return false;
}
bool EventFilter::mainWindowEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result) {
using Change = Ui::Platform::WindowShadow::Change;
if (const auto tbCreatedMsgId = Platform::MainWindow::TaskbarCreatedMsgId()) {
if (msg == tbCreatedMsgId) {
Platform::MainWindow::TaskbarCreated();
}
}
if (!Core::App().settings().nativeWindowFrame()) {
if (customWindowFrameEvent(hWnd, msg, wParam, lParam, result)) {
return true;
}
}
switch (msg) {
case WM_TIMECHANGE: {
Core::App().checkAutoLockIn(100);
} return false;
case WM_WTSSESSION_CHANGE: {
if (wParam == WTS_SESSION_LOGOFF || wParam == WTS_SESSION_LOCK) {
setSessionLoggedOff(true);
} else if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK) {
setSessionLoggedOff(false);
}
} return false;
case WM_DESTROY: {
App::quit();
} return false;
case WM_ACTIVATE: {
if (LOWORD(wParam) == WA_CLICKACTIVE) {
Ui::MarkInactivePress(_window, true);
}
if (LOWORD(wParam) != WA_INACTIVE) {
_window->shadowsActivate();
} else {
_window->shadowsDeactivate();
}
if (Global::started()) {
_window->update();
}
} return false;
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED: {
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(hWnd, &wp) && (wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) {
_window->shadowsUpdate(Change::Hidden);
} else {
_window->shadowsUpdate(Change::Moved | Change::Resized, (WINDOWPOS*)lParam);
}
} return false;
case WM_SIZE: {
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) {
if (wParam != SIZE_RESTORED || _window->windowState() != Qt::WindowNoState) {
Qt::WindowState state = Qt::WindowNoState;
if (wParam == SIZE_MAXIMIZED) {
state = Qt::WindowMaximized;
} else if (wParam == SIZE_MINIMIZED) {
state = Qt::WindowMinimized;
}
emit _window->windowHandle()->windowStateChanged(state);
} else {
_window->positionUpdated();
}
_window->updateCustomMargins();
const auto changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? Change::Hidden : (Change::Resized | Change::Shown);
_window->shadowsUpdate(changes);
}
} return false;
case WM_SHOWWINDOW: {
LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
const auto changes = Change::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? Change::Shown : Change::Hidden);
_window->shadowsUpdate(changes);
} return false;
case WM_MOVE: {
_window->shadowsUpdate(Change::Moved);
_window->positionUpdated();
} return false;
case WM_SYSCOMMAND: { case WM_SYSCOMMAND: {
if (wParam == SC_MOUSEMENU) { if (wParam == SC_MOUSEMENU) {

View file

@ -34,6 +34,13 @@ public:
private: private:
explicit EventFilter(not_null<MainWindow*> window); explicit EventFilter(not_null<MainWindow*> window);
bool customWindowFrameEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result);
not_null<MainWindow*> _window; not_null<MainWindow*> _window;
bool _sessionLoggedOff = false; bool _sessionLoggedOff = false;

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/about_box.h" #include "boxes/about_box.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
#include "platform/platform_window_title.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -407,6 +408,20 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
}, taskbar->lifetime()); }, taskbar->lifetime());
} }
if (Platform::AllowNativeWindowFrameToggle()) {
const auto nativeFrame = addCheckbox(
"Use system window frame",
Core::App().settings().nativeWindowFrame());
nativeFrame->checkedChanges(
) | rpl::filter([](bool checked) {
return (checked != Core::App().settings().nativeWindowFrame());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setNativeWindowFrame(checked);
Core::App().saveSettingsDelayed();
}, nativeFrame->lifetime());
}
if (Platform::AutostartSupported()) { if (Platform::AutostartSupported()) {
const auto minimizedToggled = [] { const auto minimizedToggled = [] {
return cStartMinimized() && !Global::LocalPasscode(); return cStartMinimized() && !Global::LocalPasscode();

View file

@ -776,7 +776,7 @@ void FileLoadTask::process() {
} }
_result->filesize = (int32)qMin(filesize, qint64(INT_MAX)); _result->filesize = (int32)qMin(filesize, qint64(INT_MAX));
if (!filesize || filesize > App::kFileSizeLimit) { if (!filesize || filesize > kFileSizeLimit) {
return; return;
} }
@ -963,7 +963,7 @@ void FileLoadTask::finish() {
tr::lng_send_image_empty(tr::now, lt_name, _filepath)), tr::lng_send_image_empty(tr::now, lt_name, _filepath)),
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
removeFromAlbum(); removeFromAlbum();
} else if (_result->filesize > App::kFileSizeLimit) { } else if (_result->filesize > kFileSizeLimit) {
Ui::show( Ui::show(
Box<InformBox>( Box<InformBox>(
tr::lng_send_image_too_large(tr::now, lt_name, _filepath)), tr::lng_send_image_too_large(tr::now, lt_name, _filepath)),

View file

@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/variant.h" #include "base/variant.h"
#include "api/api_common.h" #include "api/api_common.h"
constexpr auto kFileSizeLimit = 2000 * 1024 * 1024; // Load files up to 1500mb
enum class CompressConfirm { enum class CompressConfirm {
Auto, Auto,
Yes, Yes,

View file

@ -190,7 +190,7 @@ MimeDataState ComputeMimeDataState(const QMimeData *data) {
} }
const auto filesize = info.size(); const auto filesize = info.size();
if (filesize > App::kFileSizeLimit) { if (filesize > kFileSizeLimit) {
return MimeDataState::None; return MimeDataState::None;
} else if (allAreSmallImages) { } else if (allAreSmallImages) {
if (filesize > App::kImageSizeLimit) { if (filesize > App::kImageSizeLimit) {
@ -237,7 +237,7 @@ PreparedList PrepareMediaList(const QStringList &files, int previewWidth) {
PreparedList::Error::EmptyFile, PreparedList::Error::EmptyFile,
file file
}; };
} else if (filesize > App::kFileSizeLimit) { } else if (filesize > kFileSizeLimit) {
return { return {
PreparedList::Error::TooLargeFile, PreparedList::Error::TooLargeFile,
file file

View file

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/crc32hash.h" #include "base/crc32hash.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/widgets/shadow.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -265,9 +266,14 @@ void MainWindow::init() {
updatePalette(); updatePalette();
if (!UseNativeDecorations() && (_title = Platform::CreateTitleWidget(this))) { if (Platform::AllowNativeWindowFrameToggle()) {
_title->init(); Core::App().settings().nativeWindowFrameChanges(
) | rpl::start_with_next([=](bool native) {
refreshTitleWidget();
recountGeometryConstraints();
}, lifetime());
} }
refreshTitleWidget();
initSize(); initSize();
updateUnreadCounter(); updateUnreadCounter();
@ -340,9 +346,34 @@ int MainWindow::computeMinHeight() const {
return title + outdated + st::windowMinHeight; return title + outdated + st::windowMinHeight;
} }
void MainWindow::initSize() { void MainWindow::refreshTitleWidget() {
if (Platform::AllowNativeWindowFrameToggle()
&& Core::App().settings().nativeWindowFrame()) {
_title.destroy();
if (Platform::NativeTitleRequiresShadow()) {
_titleShadow.create(this);
_titleShadow->show();
}
} else if ((_title = Platform::CreateTitleWidget(this))) {
_title->show();
_title->init();
_titleShadow.destroy();
}
}
void MainWindow::updateMinimumSize() {
setMinimumWidth(computeMinWidth()); setMinimumWidth(computeMinWidth());
setMinimumHeight(computeMinHeight()); setMinimumHeight(computeMinHeight());
}
void MainWindow::recountGeometryConstraints() {
updateMinimumSize();
updateControlsGeometry();
fixOrder();
}
void MainWindow::initSize() {
updateMinimumSize();
auto position = cWindowPos(); auto position = cWindowPos();
DEBUG_LOG(("Window Pos: Initializing first %1, %2, %3, %4 (maximized %5)").arg(position.x).arg(position.y).arg(position.w).arg(position.h).arg(Logs::b(position.maximized))); DEBUG_LOG(("Window Pos: Initializing first %1, %2, %3, %4 (maximized %5)").arg(position.x).arg(position.y).arg(position.w).arg(position.h).arg(Logs::b(position.maximized)));
@ -455,6 +486,9 @@ void MainWindow::updateControlsGeometry() {
_title->setGeometry(0, bodyTop, width(), _title->height()); _title->setGeometry(0, bodyTop, width(), _title->height());
bodyTop += _title->height(); bodyTop += _title->height();
} }
if (_titleShadow) {
_titleShadow->setGeometry(0, bodyTop, width(), st::lineWidth);
}
if (_outdated) { if (_outdated) {
Ui::SendPendingMoveResizeEvents(_outdated.data()); Ui::SendPendingMoveResizeEvents(_outdated.data());
_outdated->resizeToWidth(width()); _outdated->resizeToWidth(width());
@ -637,6 +671,8 @@ void MainWindow::launchDrag(std::unique_ptr<QMimeData> data) {
} }
} }
MainWindow::~MainWindow() = default; MainWindow::~MainWindow() {
_title.destroy();
}
} // namespace Window } // namespace Window

View file

@ -21,6 +21,7 @@ class Account;
namespace Ui { namespace Ui {
class BoxContent; class BoxContent;
class PlainShadow;
} // namespace Ui } // namespace Ui
namespace Window { namespace Window {
@ -81,6 +82,8 @@ public:
virtual void updateTrayMenu(bool force = false) { virtual void updateTrayMenu(bool force = false) {
} }
virtual void fixOrder() {
}
virtual ~MainWindow(); virtual ~MainWindow();
@ -102,6 +105,7 @@ public:
int computeMinWidth() const; int computeMinWidth() const;
int computeMinHeight() const; int computeMinHeight() const;
void recountGeometryConstraints();
virtual void updateControlsGeometry(); virtual void updateControlsGeometry();
public slots: public slots:
@ -174,6 +178,8 @@ protected:
void updateUnreadCounter(); void updateUnreadCounter();
private: private:
void refreshTitleWidget();
void updateMinimumSize();
void updatePalette(); void updatePalette();
void initSize(); void initSize();
@ -185,6 +191,7 @@ private:
bool _positionInited = false; bool _positionInited = false;
object_ptr<TitleWidget> _title = { nullptr }; object_ptr<TitleWidget> _title = { nullptr };
object_ptr<Ui::PlainShadow> _titleShadow = { nullptr };
object_ptr<Ui::RpWidget> _outdated; object_ptr<Ui::RpWidget> _outdated;
object_ptr<Ui::RpWidget> _body; object_ptr<Ui::RpWidget> _body;
object_ptr<TWidget> _rightColumn = { nullptr }; object_ptr<TWidget> _rightColumn = { nullptr };

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_updates.h" #include "api/api_updates.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "platform/platform_window_title.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_domain.h" #include "main/main_domain.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -241,6 +242,13 @@ void Controller::showSettings() {
_widget.showSettings(); _widget.showSettings();
} }
int Controller::verticalShadowTop() const {
return (Platform::NativeTitleRequiresShadow()
&& Core::App().settings().nativeWindowFrame())
? st::lineWidth
: 0;
}
void Controller::showToast(const QString &text) { void Controller::showToast(const QString &text) {
Ui::Toast::Show(_widget.bodyWidget(), text); Ui::Toast::Show(_widget.bodyWidget(), text);
} }
@ -257,9 +265,7 @@ void Controller::showRightColumn(object_ptr<TWidget> widget) {
} }
void Controller::sideBarChanged() { void Controller::sideBarChanged() {
_widget.setMinimumWidth(_widget.computeMinWidth()); _widget.recountGeometryConstraints();
_widget.updateControlsGeometry();
_widget.fixOrder();
} }
void Controller::activate() { void Controller::activate() {

View file

@ -48,6 +48,8 @@ public:
void showSettings(); void showSettings();
[[nodiscard]] int verticalShadowTop() const;
template <typename BoxType> template <typename BoxType>
QPointer<BoxType> show( QPointer<BoxType> show(
object_ptr<BoxType> content, object_ptr<BoxType> content,

View file

@ -10,11 +10,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h" #include "ui/widgets/shadow.h"
#include "styles/style_window.h" #include "styles/style_window.h"
#include "base/call_delayed.h"
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <QtGui/QWindow> #include <QtGui/QWindow>
namespace Window { namespace Window {
namespace {
// If we toggle frameless window hint in maximized window, and
// show it back too quickly, the mouse position inside the window
// won't be correct (from Qt-s point of view) until we Alt-Tab from
// that window. If we show the window back with this delay it works.
constexpr auto kShowAfterFramelessToggleDelay = crl::time(1000);
} // namespace
TitleWidgetQt::TitleWidgetQt(QWidget *parent) TitleWidgetQt::TitleWidgetQt(QWidget *parent)
: TitleWidget(parent) : TitleWidget(parent)
@ -45,11 +55,35 @@ TitleWidgetQt::TitleWidgetQt(QWidget *parent)
QCoreApplication::instance()->installEventFilter(this); QCoreApplication::instance()->installEventFilter(this);
window()->setWindowFlag(Qt::FramelessWindowHint, true); _windowWasFrameless = (window()->windowFlags() & Qt::FramelessWindowHint) != 0;
if (!_windowWasFrameless) {
toggleFramelessWindow(true);
}
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
resize(width(), _st.height); resize(width(), _st.height);
} }
TitleWidgetQt::~TitleWidgetQt() {
restoreCursor();
if (!_windowWasFrameless) {
toggleFramelessWindow(false);
}
}
void TitleWidgetQt::toggleFramelessWindow(bool enabled) {
// setWindowFlag calls setParent(parentWidget(), newFlags), which
// always calls hide() explicitly, we have to show() the window back.
const auto top = window();
const auto hidden = top->isHidden();
top->setWindowFlag(Qt::FramelessWindowHint, enabled);
if (!hidden) {
base::call_delayed(
kShowAfterFramelessToggleDelay,
top,
[=] { top->show(); });
}
}
void TitleWidgetQt::init() { void TitleWidgetQt::init() {
connect( connect(
window()->windowHandle(), window()->windowHandle(),
@ -103,7 +137,7 @@ void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) { bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
if (e->type() == QEvent::MouseMove if (e->type() == QEvent::MouseMove
|| e->type() == QEvent::MouseButtonPress) { || e->type() == QEvent::MouseButtonPress) {
if(window()->isAncestorOf(static_cast<QWidget*>(obj))) { if (window()->isAncestorOf(static_cast<QWidget*>(obj))) {
const auto mouseEvent = static_cast<QMouseEvent*>(e); const auto mouseEvent = static_cast<QMouseEvent*>(e);
const auto edges = edgesFromPos(mouseEvent->windowPos().toPoint()); const auto edges = edgesFromPos(mouseEvent->windowPos().toPoint());
@ -111,7 +145,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
updateCursor(edges); updateCursor(edges);
} }
if(e->type() == QEvent::MouseButtonPress if (e->type() == QEvent::MouseButtonPress
&& mouseEvent->button() == Qt::LeftButton && mouseEvent->button() == Qt::LeftButton
&& window()->windowState() != Qt::WindowMaximized) { && window()->windowState() != Qt::WindowMaximized) {
return startResize(edges); return startResize(edges);
@ -119,9 +153,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
} }
} else if (e->type() == QEvent::Leave) { } else if (e->type() == QEvent::Leave) {
if (window() == static_cast<QWidget*>(obj)) { if (window() == static_cast<QWidget*>(obj)) {
while (QGuiApplication::overrideCursor()) { restoreCursor();
QGuiApplication::restoreOverrideCursor();
}
} }
} }
@ -196,14 +228,22 @@ Qt::Edges TitleWidgetQt::edgesFromPos(const QPoint &pos) {
} }
} }
void TitleWidgetQt::restoreCursor() {
if (_cursorOverriden) {
_cursorOverriden = false;
QGuiApplication::restoreOverrideCursor();
}
}
void TitleWidgetQt::updateCursor(Qt::Edges edges) { void TitleWidgetQt::updateCursor(Qt::Edges edges) {
if (!edges || window()->windowState() == Qt::WindowMaximized) { if (!edges || window()->windowState() == Qt::WindowMaximized) {
while (QGuiApplication::overrideCursor()) { restoreCursor();
QGuiApplication::restoreOverrideCursor();
}
return; return;
} else if (!QGuiApplication::overrideCursor()) { } else if (!QGuiApplication::overrideCursor()) {
_cursorOverriden = false;
}
if (!_cursorOverriden) {
_cursorOverriden = true;
QGuiApplication::setOverrideCursor(QCursor()); QGuiApplication::setOverrideCursor(QCursor());
} }

View file

@ -24,6 +24,7 @@ namespace Window {
class TitleWidgetQt : public TitleWidget { class TitleWidgetQt : public TitleWidget {
public: public:
TitleWidgetQt(QWidget *parent); TitleWidgetQt(QWidget *parent);
~TitleWidgetQt();
void init() override; void init() override;
@ -40,8 +41,10 @@ private:
void updateButtonsState(); void updateButtonsState();
void updateControlsPosition(); void updateControlsPosition();
void toggleFramelessWindow(bool enabled);
Qt::Edges edgesFromPos(const QPoint &pos); Qt::Edges edgesFromPos(const QPoint &pos);
void updateCursor(Qt::Edges edges); void updateCursor(Qt::Edges edges);
void restoreCursor();
bool startResize(Qt::Edges edges); bool startResize(Qt::Edges edges);
const style::WindowTitle &_st; const style::WindowTitle &_st;
@ -52,6 +55,8 @@ private:
bool _maximizedState = false; bool _maximizedState = false;
bool _activeState = false; bool _activeState = false;
bool _windowWasFrameless = false;
bool _cursorOverriden = false;
}; };

View file

@ -1,7 +1,7 @@
AppVersion 2001017 AppVersion 2001018
AppVersionStrMajor 2.1 AppVersionStrMajor 2.1
AppVersionStrSmall 2.1.17 AppVersionStrSmall 2.1.18
AppVersionStr 2.1.17 AppVersionStr 2.1.18
BetaChannel 1 BetaChannel 1
AlphaVersion 0 AlphaVersion 0
AppVersionOriginal 2.1.17.beta AppVersionOriginal 2.1.18.beta

@ -1 +1 @@
Subproject commit 11a39d9d941e4cd1c60a0c97352cbf89700f42fc Subproject commit c262a0931e4b32ff156aa12cb2657c8cdd444c69

View file

@ -1,3 +1,10 @@
2.1.18 beta (08.07.20)
- Fix a possible crash in Picture-in-Picture video player.
- Fix copying links from message texts.
- Raise file size limit to 2000 MB.
- Allow using system window frame in Windows and Linux.
2.1.17 beta (02.07.20) 2.1.17 beta (02.07.20)
- Fix messages editing in a non-active account. - Fix messages editing in a non-active account.