Updated TDesktop sources to 2.1.18 beta
This commit is contained in:
commit
d920a689e3
45 changed files with 465 additions and 758 deletions
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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 бота",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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 бота",
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -598,6 +598,7 @@ void PipPanel::mousePressEvent(QMouseEvent *e) {
|
|||
if (e->button() != Qt::LeftButton) {
|
||||
return;
|
||||
}
|
||||
updateOverState(e->pos());
|
||||
_pressState = _overState;
|
||||
_pressPoint = e->globalPos();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ public:
|
|||
|
||||
void showSettings();
|
||||
|
||||
[[nodiscard]] int verticalShadowTop() const;
|
||||
|
||||
template <typename BoxType>
|
||||
QPointer<BoxType> show(
|
||||
object_ptr<BoxType> content,
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue