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_workmode_tray" = "Show tray 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_start_min" = "Launch minimized";
"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_settings_system" = "System";
"ktg_settings_use_native_decorations" = "Native window decorations";
"ktg_settings_other" = "Other";
"ktg_profile_copy_id" = "Copy ID";

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -85,7 +85,6 @@ namespace App {
void setLaunchState(LaunchState state);
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
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);

View file

@ -61,7 +61,17 @@ std::map<int, const char*> BetaLogs() {
"- Fix high definition GIF animations opening in media viewer.\n"
"- 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))
<< qint32(_thirdColumnWidth.current())
<< qint32(_thirdSectionExtendedBy)
<< qint32(_notifyFromAll ? 1 : 0);
<< qint32(_notifyFromAll ? 1 : 0)
<< qint32(_nativeWindowFrame.current() ? 1 : 0);
}
return result;
}
@ -169,6 +170,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 thirdColumnWidth = _thirdColumnWidth.current();
qint32 thirdSectionExtendedBy = _thirdSectionExtendedBy;
qint32 notifyFromAll = _notifyFromAll ? 1 : 0;
qint32 nativeWindowFrame = _nativeWindowFrame.current() ? 1 : 0;
stream >> themesAccentColors;
if (!stream.atEnd()) {
@ -243,6 +245,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
>> notifyFromAll;
dialogsWidthRatio = snap(dialogsWidthRatioInt / 1000000., 0., 1.);
}
if (!stream.atEnd()) {
stream >> nativeWindowFrame;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
@ -335,6 +340,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
_tabbedSelectorSectionEnabled = false;
}
_notifyFromAll = (notifyFromAll == 1);
_nativeWindowFrame = (nativeWindowFrame == 1);
}
bool Settings::chatWide() const {

View file

@ -407,6 +407,15 @@ public:
[[nodiscard]] bool notifyFromAll() const {
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]] float64 DefaultDialogsWidthRatio();
@ -474,6 +483,7 @@ private:
rpl::variable<float64> _dialogsWidthRatio; // per-window
rpl::variable<int> _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w
bool _notifyFromAll = true;
rpl::variable<bool> _nativeWindowFrame = false;
bool _tabbedReplacedWithInfo = false; // 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 AppName = "Kotatogram Desktop"_cs;
constexpr auto AppFile = "Kotatogram"_cs;
constexpr auto AppVersion = 2001017;
constexpr auto AppVersionStr = "2.1.17";
constexpr auto AppVersion = 2001018;
constexpr auto AppVersionStr = "2.1.18";
constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -437,12 +437,12 @@ void SetupKotatoSystem(
AddSkip(container);
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>>(
container.get());
AddButton(
container,
tr::ktg_settings_use_native_decorations(),
tr::lng_settings_native_frame(),
st::settingsButton
)->toggleOn(
useNativeDecorationsToggled->events_starting_with_copy(cUseNativeDecorations())
@ -464,7 +464,7 @@ void SetupKotatoSystem(
confirmed,
cancelled));
}, container->lifetime());
#endif // Q_OS_WIN || Q_OS_MAC || Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
#endif // Q_OS_MAC
AddButton(
container,

View file

@ -2185,13 +2185,19 @@ void MainWidget::updateControlsGeometry() {
auto mainSectionWidth = width() - dialogsWidth - thirdSectionWidth;
_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) {
_thirdShadow->setGeometryToLeft(
width() - thirdSectionWidth - st::lineWidth,
0,
shadowTop,
st::lineWidth,
height());
shadowHeight);
}
if (_callTopBar) {
_callTopBar->resizeToWidth(mainSectionWidth);

View file

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

View file

@ -16,7 +16,7 @@ namespace Streaming {
namespace {
// 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) {
return (size > 0 && size <= kMaxFileSize) ? int(size) : 0;

View file

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

View file

@ -22,14 +22,22 @@ void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palet
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 (!DesktopEnvironment::IsUnity()) {
return object_ptr<Window::TitleWidgetQt>(parent);
}
return !DesktopEnvironment::IsUnity();
#else // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
return false;
#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() {

View file

@ -32,8 +32,16 @@ private:
};
inline bool AllowNativeWindowFrameToggle() {
return false;
}
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent);
inline bool NativeTitleRequiresShadow() {
return false;
}
int PreviewTitleHeight();
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 {
bool AllowNativeWindowFrameToggle();
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent);
bool NativeTitleRequiresShadow();
int PreviewTitleHeight();
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 {
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
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
}
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() {

View file

@ -38,28 +38,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <Windowsx.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 &);
using namespace Microsoft::WRL;
@ -112,515 +90,6 @@ HWND createTaskbarHider() {
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;
bool handleSessionNotification = false;
@ -638,13 +107,17 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
if (!_taskbarCreatedMsgId) {
_taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated");
}
if (!UseNativeDecorations()) {
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
if (update.paletteChanged()) {
_psShadowWindows.setColor(st::windowShadowFg->c);
}
});
}
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
if (_shadow && update.paletteChanged()) {
_shadow->setColor(st::windowShadowFg->c);
}
});
Core::App().settings().nativeWindowFrameChanges(
) | rpl::start_with_next([=] {
initShadows();
validateWindowTheme();
fixMaximizedWindow();
}, lifetime());
}
void MainWindow::TaskbarCreated() {
@ -654,23 +127,21 @@ void MainWindow::TaskbarCreated() {
}
}
void MainWindow::shadowsUpdate(ShadowsChanges changes, WINDOWPOS *position) {
if (!UseNativeDecorations()) {
_psShadowWindows.update(changes, position);
void MainWindow::shadowsUpdate(
Ui::Platform::WindowShadow::Changes changes,
WINDOWPOS *position) {
if (_shadow) {
_shadow->update(changes, position);
}
}
void MainWindow::shadowsActivate() {
if (!UseNativeDecorations()) {
// _psShadowWindows.setColor(_shActive);
shadowsUpdate(ShadowsChange::Activate);
}
// _shadow->setColor(_shActive);
shadowsUpdate(Ui::Platform::WindowShadow::Change::Activate);
}
void MainWindow::shadowsDeactivate() {
// if (!UseNativeDecorations()) {
// _psShadowWindows.setColor(_shInactive);
// }
// _shadow->setColor(_shInactive);
}
void MainWindow::psShowTrayMenu() {
@ -768,6 +239,10 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
}
}
void MainWindow::updateWindowIcon() {
updateIconCounters();
}
void MainWindow::unreadCounterChangedHook() {
setWindowTitle(titleText());
updateIconCounters();
@ -840,17 +315,22 @@ void MainWindow::initHook() {
}
void MainWindow::initShadows() {
if (!UseNativeDecorations()) {
_psShadowWindows.init(this, st::windowShadowFg->c);
_shadowsWorking = true;
psUpdateMargins();
shadowsUpdate(ShadowsChange::Hidden);
if (Core::App().settings().nativeWindowFrame()) {
_shadow.reset();
} else {
_shadow.emplace(this, st::windowShadowFg->c);
}
updateCustomMargins();
firstShadowsUpdate();
}
void MainWindow::firstShadowsUpdate() {
if (!UseNativeDecorations() && !(windowState() & Qt::WindowMinimized) && !isHidden()) {
shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized | ShadowsChange::Shown);
using Change = Ui::Platform::WindowShadow::Change;
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() {
if (!ps_hWnd || _inUpdateMargins) return;
void MainWindow::updateCustomMargins() {
if (!ps_hWnd || _inUpdateMargins) {
return;
}
_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);
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);
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) {
RECT w, m;
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);
_deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0;
}
return margins;
}
if (const auto native = QGuiApplication::platformNativeInterface()) {
native->setWindowProperty(
windowHandle()->handle(),
qsl("WindowsCustomMargins"),
QVariant::fromValue<QMargins>(margins));
void MainWindow::validateWindowTheme() {
if (IsWindows8OrGreater()) {
return;
} else if (Dlls::SetWindowTheme != nullptr) {
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()) {
if (Dlls::SetWindowTheme != nullptr) {
Dlls::SetWindowTheme(ps_hWnd, L" ", L" ");
QApplication::setStyle(QStyleFactory::create(qsl("Windows")));
}
}
void MainWindow::fixMaximizedWindow() {
auto r = RECT();
GetClientRect(ps_hWnd, &r);
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 {
@ -1000,10 +517,6 @@ MainWindow::~MainWindow() {
if (ps_menu) DestroyMenu(ps_menu);
psDestroyIcons();
if (!UseNativeDecorations()) {
_shadowsWorking = false;
_psShadowWindows.destroy();
}
if (ps_tbHider_hWnd) DestroyWindow(ps_tbHider_hWnd);
EventFilter::Destroy();

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#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/flags.h"
@ -30,7 +31,9 @@ public:
void psInitSysMenu();
void updateSystemMenu(Qt::WindowState state);
void psUpdateMargins();
void updateCustomMargins();
void updateWindowIcon() override;
void psRefreshTaskbarIcon();
@ -42,22 +45,11 @@ public:
static void TaskbarCreated();
// 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 shadowsDeactivate();
void shadowsUpdate(ShadowsChanges changes, WINDOWPOS *position = nullptr);
void shadowsUpdate(
Ui::Platform::WindowShadow::Changes changes,
WINDOWPOS *position = nullptr);
int deltaLeft() const {
return _deltaLeft;
@ -99,12 +91,15 @@ protected:
private:
void updateIconCounters();
QMargins computeCustomMargins();
void validateWindowTheme();
void psDestroyIcons();
void fixMaximizedWindow();
static UINT _taskbarCreatedMsgId;
bool _shadowsWorking = false;
std::optional<Ui::Platform::WindowShadow> _shadow;
bool _themeInited = false;
bool _inUpdateMargins = false;

View file

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

View file

@ -78,56 +78,13 @@ bool EventFilter::nativeEventFilter(
});
}
bool EventFilter::mainWindowEvent(
bool EventFilter::customWindowFrameEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
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) {
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: {
if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false;
if (result) *result = 0;
@ -162,47 +119,6 @@ bool EventFilter::mainWindowEvent(
}
} 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: {
if (!result) return false;
@ -230,6 +146,103 @@ bool EventFilter::mainWindowEvent(
case WM_NCRBUTTONUP: {
SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
} 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: {
if (wParam == SC_MOUSEMENU) {

View file

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

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/about_box.h"
#include "boxes/confirm_box.h"
#include "platform/platform_specific.h"
#include "platform/platform_window_title.h"
#include "base/platform/base_platform_info.h"
#include "window/window_session_controller.h"
#include "lang/lang_keys.h"
@ -407,6 +408,20 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
}, 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()) {
const auto minimizedToggled = [] {
return cStartMinimized() && !Global::LocalPasscode();

View file

@ -776,7 +776,7 @@ void FileLoadTask::process() {
}
_result->filesize = (int32)qMin(filesize, qint64(INT_MAX));
if (!filesize || filesize > App::kFileSizeLimit) {
if (!filesize || filesize > kFileSizeLimit) {
return;
}
@ -963,7 +963,7 @@ void FileLoadTask::finish() {
tr::lng_send_image_empty(tr::now, lt_name, _filepath)),
Ui::LayerOption::KeepOther);
removeFromAlbum();
} else if (_result->filesize > App::kFileSizeLimit) {
} else if (_result->filesize > kFileSizeLimit) {
Ui::show(
Box<InformBox>(
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 "api/api_common.h"
constexpr auto kFileSizeLimit = 2000 * 1024 * 1024; // Load files up to 1500mb
enum class CompressConfirm {
Auto,
Yes,

View file

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

View file

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/crc32hash.h"
#include "base/call_delayed.h"
#include "ui/toast/toast.h"
#include "ui/widgets/shadow.h"
#include "ui/ui_utility.h"
#include "apiwrap.h"
#include "mainwindow.h"
@ -265,9 +266,14 @@ void MainWindow::init() {
updatePalette();
if (!UseNativeDecorations() && (_title = Platform::CreateTitleWidget(this))) {
_title->init();
if (Platform::AllowNativeWindowFrameToggle()) {
Core::App().settings().nativeWindowFrameChanges(
) | rpl::start_with_next([=](bool native) {
refreshTitleWidget();
recountGeometryConstraints();
}, lifetime());
}
refreshTitleWidget();
initSize();
updateUnreadCounter();
@ -340,9 +346,34 @@ int MainWindow::computeMinHeight() const {
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());
setMinimumHeight(computeMinHeight());
}
void MainWindow::recountGeometryConstraints() {
updateMinimumSize();
updateControlsGeometry();
fixOrder();
}
void MainWindow::initSize() {
updateMinimumSize();
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)));
@ -455,6 +486,9 @@ void MainWindow::updateControlsGeometry() {
_title->setGeometry(0, bodyTop, width(), _title->height());
bodyTop += _title->height();
}
if (_titleShadow) {
_titleShadow->setGeometry(0, bodyTop, width(), st::lineWidth);
}
if (_outdated) {
Ui::SendPendingMoveResizeEvents(_outdated.data());
_outdated->resizeToWidth(width());
@ -637,6 +671,8 @@ void MainWindow::launchDrag(std::unique_ptr<QMimeData> data) {
}
}
MainWindow::~MainWindow() = default;
MainWindow::~MainWindow() {
_title.destroy();
}
} // namespace Window

View file

@ -21,6 +21,7 @@ class Account;
namespace Ui {
class BoxContent;
class PlainShadow;
} // namespace Ui
namespace Window {
@ -81,6 +82,8 @@ public:
virtual void updateTrayMenu(bool force = false) {
}
virtual void fixOrder() {
}
virtual ~MainWindow();
@ -102,6 +105,7 @@ public:
int computeMinWidth() const;
int computeMinHeight() const;
void recountGeometryConstraints();
virtual void updateControlsGeometry();
public slots:
@ -174,6 +178,8 @@ protected:
void updateUnreadCounter();
private:
void refreshTitleWidget();
void updateMinimumSize();
void updatePalette();
void initSize();
@ -185,6 +191,7 @@ private:
bool _positionInited = false;
object_ptr<TitleWidget> _title = { nullptr };
object_ptr<Ui::PlainShadow> _titleShadow = { nullptr };
object_ptr<Ui::RpWidget> _outdated;
object_ptr<Ui::RpWidget> _body;
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 "core/application.h"
#include "core/click_handler_types.h"
#include "platform/platform_window_title.h"
#include "main/main_account.h"
#include "main/main_domain.h"
#include "main/main_session.h"
@ -241,6 +242,13 @@ void Controller::showSettings() {
_widget.showSettings();
}
int Controller::verticalShadowTop() const {
return (Platform::NativeTitleRequiresShadow()
&& Core::App().settings().nativeWindowFrame())
? st::lineWidth
: 0;
}
void Controller::showToast(const QString &text) {
Ui::Toast::Show(_widget.bodyWidget(), text);
}
@ -257,9 +265,7 @@ void Controller::showRightColumn(object_ptr<TWidget> widget) {
}
void Controller::sideBarChanged() {
_widget.setMinimumWidth(_widget.computeMinWidth());
_widget.updateControlsGeometry();
_widget.fixOrder();
_widget.recountGeometryConstraints();
}
void Controller::activate() {

View file

@ -48,6 +48,8 @@ public:
void showSettings();
[[nodiscard]] int verticalShadowTop() const;
template <typename BoxType>
QPointer<BoxType> show(
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/shadow.h"
#include "styles/style_window.h"
#include "base/call_delayed.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
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)
: TitleWidget(parent)
@ -45,11 +55,35 @@ TitleWidgetQt::TitleWidgetQt(QWidget *parent)
QCoreApplication::instance()->installEventFilter(this);
window()->setWindowFlag(Qt::FramelessWindowHint, true);
_windowWasFrameless = (window()->windowFlags() & Qt::FramelessWindowHint) != 0;
if (!_windowWasFrameless) {
toggleFramelessWindow(true);
}
setAttribute(Qt::WA_OpaquePaintEvent);
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() {
connect(
window()->windowHandle(),
@ -103,7 +137,7 @@ void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
if (e->type() == QEvent::MouseMove
|| 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 edges = edgesFromPos(mouseEvent->windowPos().toPoint());
@ -111,7 +145,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
updateCursor(edges);
}
if(e->type() == QEvent::MouseButtonPress
if (e->type() == QEvent::MouseButtonPress
&& mouseEvent->button() == Qt::LeftButton
&& window()->windowState() != Qt::WindowMaximized) {
return startResize(edges);
@ -119,9 +153,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
}
} else if (e->type() == QEvent::Leave) {
if (window() == static_cast<QWidget*>(obj)) {
while (QGuiApplication::overrideCursor()) {
QGuiApplication::restoreOverrideCursor();
}
restoreCursor();
}
}
@ -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) {
if (!edges || window()->windowState() == Qt::WindowMaximized) {
while (QGuiApplication::overrideCursor()) {
QGuiApplication::restoreOverrideCursor();
}
restoreCursor();
return;
} else if (!QGuiApplication::overrideCursor()) {
_cursorOverriden = false;
}
if (!_cursorOverriden) {
_cursorOverriden = true;
QGuiApplication::setOverrideCursor(QCursor());
}

View file

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

View file

@ -1,7 +1,7 @@
AppVersion 2001017
AppVersion 2001018
AppVersionStrMajor 2.1
AppVersionStrSmall 2.1.17
AppVersionStr 2.1.17
AppVersionStrSmall 2.1.18
AppVersionStr 2.1.18
BetaChannel 1
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)
- Fix messages editing in a non-active account.