From 3b327d93976075d77d4b0fa8f555b33b0e5021b1 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 26 Feb 2020 20:12:51 +0400 Subject: [PATCH 01/43] Fix launching with data in ~/.TelegramDesktop Regression was introduced in 60612635ef. Fixes #7289. --- Telegram/SourceFiles/platform/linux/specific_linux.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 609c3d7e5..47a3bc170 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -400,7 +400,9 @@ QString psAppDataPath() { if (!home.isEmpty()) { auto oldPath = home + qsl(".TelegramDesktop/"); auto oldSettingsBase = oldPath + qsl("tdata/settings"); - if (QFile(oldSettingsBase + '0').exists() || QFile(oldSettingsBase + '1').exists()) { + if (QFile(oldSettingsBase + '0').exists() + || QFile(oldSettingsBase + '1').exists() + || QFile(oldSettingsBase + 's').exists()) { return oldPath; } } From 872e063501bf5fe0d0e7cfb4a7536ef01f2a19da Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 26 Feb 2020 20:17:13 +0400 Subject: [PATCH 02/43] Fix docs. --- docs/building-msvc.md | 1 - docs/building-xcode.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/building-msvc.md b/docs/building-msvc.md index e23677577..60b47713f 100644 --- a/docs/building-msvc.md +++ b/docs/building-msvc.md @@ -18,7 +18,6 @@ You will require **api_id** and **api_hash** to access the Telegram API servers. ## Install third party software -Strawberry * Download **Strawberry Perl** installer from [http://strawberryperl.com/](http://strawberryperl.com/) and install to ***BuildPath*\\ThirdParty\\Strawberry** * Download **NASM** installer from [http://www.nasm.us](http://www.nasm.us) and install to ***BuildPath*\\ThirdParty\\NASM** * Download **Yasm** executable from [http://yasm.tortall.net/Download.html](http://yasm.tortall.net/Download.html), rename to *yasm.exe* and put to ***BuildPath*\\ThirdParty\\yasm** diff --git a/docs/building-xcode.md b/docs/building-xcode.md index d4f374265..1bb348427 100644 --- a/docs/building-xcode.md +++ b/docs/building-xcode.md @@ -51,7 +51,7 @@ Go to ***BuildPath*** and run git clone https://github.com/desktop-app/patches.git cd patches git checkout 4f1cffb - cd ../ + cd .. git clone --branch 0.10.0 https://github.com/ericniebler/range-v3 cd xz-5.0.5 From 8b704f9bd7897511b5207082a912938ccfa11bcf Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 25 Feb 2020 06:39:14 +0400 Subject: [PATCH 03/43] Fix escaping in linux launcher creating --- .../platform/linux/specific_linux.cpp | 65 ++++++++++++------- .../SourceFiles/platform/mac/specific_mac.mm | 2 +- .../SourceFiles/platform/platform_specific.h | 2 +- .../SourceFiles/platform/win/specific_win.cpp | 2 +- .../SourceFiles/settings/settings_codes.cpp | 4 +- 5 files changed, 47 insertions(+), 28 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 47a3bc170..0bacb65d4 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -46,7 +46,7 @@ constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs; constexpr auto kSnapLauncherDir = "/var/lib/snapd/desktop/applications/"_cs; #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION -void SandboxAutostart(bool autostart) { +void SandboxAutostart(bool autostart, bool silent = false) { QVariantMap options; options["reason"] = tr::lng_settings_auto_start(tr::now); options["autostart"] = autostart; @@ -62,11 +62,14 @@ void SandboxAutostart(bool autostart) { qsl("org.freedesktop.portal.Background") ).call(qsl("RequestBackground"), QString(), options); - if (requestBackgroundReply.type() == QDBusMessage::ErrorMessage) { - LOG(("Flatpak autostart error: %1") - .arg(requestBackgroundReply.errorMessage())); - } else if (requestBackgroundReply.type() != QDBusMessage::ReplyMessage) { - LOG(("Flatpak autostart error: invalid reply")); + if (!silent) { + if (requestBackgroundReply.type() == QDBusMessage::ErrorMessage) { + LOG(("Flatpak autostart error: %1") + .arg(requestBackgroundReply.errorMessage())); + } else if (requestBackgroundReply.type() + != QDBusMessage::ReplyMessage) { + LOG(("Flatpak autostart error: invalid reply")); + } } } #endif @@ -120,7 +123,10 @@ void FallbackFontConfig() { #endif // TDESKTOP_USE_FONT_CONFIG_FALLBACK } -bool GenerateDesktopFile(const QString &targetPath, const QString &args) { +bool GenerateDesktopFile( + const QString &targetPath, + const QString &args, + bool silent = false) { DEBUG_LOG(("App Info: placing .desktop file to %1").arg(targetPath)); if (!QDir(targetPath).exists()) QDir().mkpath(targetPath); @@ -142,7 +148,9 @@ bool GenerateDesktopFile(const QString &targetPath, const QString &args) { fileText = s.readAll(); source.close(); } else { - LOG(("App Error: Could not open '%1' for read").arg(sourceFile)); + if (!silent) { + LOG(("App Error: Could not open '%1' for read").arg(sourceFile)); + } return false; } @@ -150,21 +158,26 @@ bool GenerateDesktopFile(const QString &targetPath, const QString &args) { if (target.open(QIODevice::WriteOnly)) { #ifdef DESKTOP_APP_USE_PACKAGED fileText = fileText.replace( - QRegularExpression(qsl("^Exec=(.*) -- %u$"), + QRegularExpression( + qsl("^Exec=(.*) -- %u$"), QRegularExpression::MultilineOption), qsl("Exec=\\1") + (args.isEmpty() ? QString() : ' ' + args)); #else fileText = fileText.replace( - QRegularExpression(qsl("^TryExec=.*$"), + QRegularExpression( + qsl("^TryExec=.*$"), QRegularExpression::MultilineOption), qsl("TryExec=") - + EscapeShell(QFile::encodeName(cExeDir() + cExeName()))); + + QFile::encodeName(cExeDir() + cExeName()) + .replace('\\', qsl("\\\\"))); fileText = fileText.replace( - QRegularExpression(qsl("^Exec=.*$"), + QRegularExpression( + qsl("^Exec=.*$"), QRegularExpression::MultilineOption), qsl("Exec=") + EscapeShell(QFile::encodeName(cExeDir() + cExeName())) + .replace('\\', qsl("\\\\")) + (args.isEmpty() ? QString() : ' ' + args)); #endif target.write(fileText.toUtf8()); @@ -175,7 +188,9 @@ bool GenerateDesktopFile(const QString &targetPath, const QString &args) { return true; } else { - LOG(("App Error: Could not open '%1' for write").arg(targetFile)); + if (!silent) { + LOG(("App Error: Could not open '%1' for write").arg(targetFile)); + } return false; } } @@ -309,7 +324,6 @@ QString GetLauncherBasename() { return possibleBasenames[0]; }(); - LOG(("Launcher filename is %1.desktop").arg(LauncherBasename)); return LauncherBasename; } @@ -434,6 +448,7 @@ int psFixPrevious() { namespace Platform { void start() { + LOG(("Launcher filename: %1").arg(GetLauncherFilename())); FallbackFontConfig(); #ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG @@ -456,12 +471,14 @@ void start() { void finish() { } -void RegisterCustomScheme() { +void RegisterCustomScheme(bool force) { #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME auto home = getHomeDir(); - if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty()) - return; // don't update desktop file for alpha version - if (Core::UpdaterDisabled()) + if (home.isEmpty() || cExeName().isEmpty()) + return; + + // don't update desktop file for alpha version or if updater is disabled + if ((cAlphaVersion() || Core::UpdaterDisabled()) && !force) return; const auto applicationsPath = QStandardPaths::writableLocation( @@ -473,7 +490,7 @@ void RegisterCustomScheme() { const auto icons = QStandardPaths::writableLocation( QStandardPaths::GenericDataLocation) - + qsl("/icons/"); + + qsl("/icons/"); if (!QDir(icons).exists()) QDir().mkpath(icons); @@ -487,7 +504,7 @@ void RegisterCustomScheme() { } if (!iconExists) { if (QFile(qsl(":/gui/art/logo_256.png")).copy(icon)) { - DEBUG_LOG(("App Info: Icon copied to 'tdata'")); + DEBUG_LOG(("App Info: Icon copied to '%1'").arg(icon)); } } #endif // !TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION @@ -562,12 +579,12 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) { void psAutoStart(bool start, bool silent) { auto home = getHomeDir(); - if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty()) + if (home.isEmpty() || cExeName().isEmpty()) return; if (InSandbox()) { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - SandboxAutostart(start); + SandboxAutostart(start, silent); #endif } else { const auto autostart = [&] { @@ -580,12 +597,12 @@ void psAutoStart(bool start, bool silent) { } else { return QStandardPaths::writableLocation( QStandardPaths::GenericConfigLocation) - + qsl("/autostart/"); + + qsl("/autostart/"); } }(); if (start) { - GenerateDesktopFile(autostart, qsl("-autostart")); + GenerateDesktopFile(autostart, qsl("-autostart"), silent); } else { QFile::remove(autostart + GetLauncherFilename()); } diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.mm b/Telegram/SourceFiles/platform/mac/specific_mac.mm index c8490da50..8b31672f2 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac.mm @@ -136,7 +136,7 @@ void RemoveQuarantine(const QString &path) { removexattr(local.data(), kQuarantineAttribute, 0); } -void RegisterCustomScheme() { +void RegisterCustomScheme(bool force) { #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME OSStatus result = LSSetDefaultHandlerForURLScheme(CFSTR("tg"), (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); DEBUG_LOG(("App Info: set default handler for 'tg' scheme result: %1").arg(result)); diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index f5650f969..18ebd6c0c 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -28,7 +28,7 @@ enum class SystemSettingsType { void SetWatchingMediaKeys(bool watching); void SetApplicationIcon(const QIcon &icon); -void RegisterCustomScheme(); +void RegisterCustomScheme(bool force = false); PermissionStatus GetPermissionStatus(PermissionType type); void RequestPermission(PermissionType type, Fn resultCallback); void OpenSystemSettingsForPermission(PermissionType type); diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp index 88af1e066..356505422 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.cpp +++ b/Telegram/SourceFiles/platform/win/specific_win.cpp @@ -404,7 +404,7 @@ namespace { namespace Platform { -void RegisterCustomScheme() { +void RegisterCustomScheme(bool force) { if (cExeName().isEmpty()) { return; } diff --git a/Telegram/SourceFiles/settings/settings_codes.cpp b/Telegram/SourceFiles/settings/settings_codes.cpp index 505146b57..e50471fa8 100644 --- a/Telegram/SourceFiles/settings/settings_codes.cpp +++ b/Telegram/SourceFiles/settings/settings_codes.cpp @@ -112,10 +112,12 @@ auto GenerateCodes() { } }); }); +#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME codes.emplace(qsl("registertg"), [](::Main::Session *session) { - Platform::RegisterCustomScheme(); + Platform::RegisterCustomScheme(true); Ui::Toast::Show("Forced custom scheme register."); }); +#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME codes.emplace(qsl("export"), [](::Main::Session *session) { session->data().startExport(); }); From 3a5c0976bb121f79efba30e05ce5645715ef13e8 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 25 Feb 2020 16:56:11 +0300 Subject: [PATCH 04/43] Updated docs. - Removed libenchant-dev. - Removed installing OpenSSL shared docs for Linux. - Updated xz and libiconv for Xcode. --- .github/workflows/linux.yml | 11 ++++---- .github/workflows/mac.yml | 4 +-- README.md | 4 +-- docs/building-cmake.md | 6 ++-- docs/building-qtcreator.md | 2 +- docs/building-xcode.md | 55 ++++++++++++++++++++++++------------- 6 files changed, 50 insertions(+), 32 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index a083df13a..f659e9e22 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -71,7 +71,7 @@ jobs: libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \ autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \ libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \ - libvorbis-dev libenchant-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ + libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \ libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \ libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \ @@ -342,14 +342,15 @@ jobs: run: | cd $LibrariesPath + opensslDir=openssl_${OPENSSL_VER} git clone -b OpenSSL_${OPENSSL_VER}-stable --depth=1 \ - $GIT/openssl/openssl openssl_${OPENSSL_VER} - cd openssl_${OPENSSL_VER} + $GIT/openssl/openssl $opensslDir + cd $opensslDir ./config --prefix=$LibrariesPath/openssl-cache make -j$(nproc) - sudo make install + sudo make install_sw cd .. - rm -rf openssl_${OPENSSL_VER} + rm -rf $opensslDir - name: OpenSSL install. run: | cd $LibrariesPath diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 9e29fb255..7713139ed 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -26,11 +26,11 @@ jobs: GIT: "https://github.com" PREFIX: "/usr/local/macos" MACOSX_DEPLOYMENT_TARGET: "10.12" - XZ: "xz-5.0.5" + XZ: "xz-5.2.4" QT: "5_12_5" OPENSSL_VER: "1_1_1" QT_PREFIX: "/usr/local/desktop-app/Qt-5.12.5" - LIBICONV_VER: "libiconv-1.15" + LIBICONV_VER: "libiconv-1.16" UPLOAD_ARTIFACT: "false" ONLY_CACHE: "false" MANUAL_CACHING: "2" diff --git a/README.md b/README.md index 2918db6ee..b474bd8b2 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,8 @@ The source code is published under GPLv3 with OpenSSL exception, the license is ## Build instructions * [Visual Studio 2019][msvc] -* [Xcode 10][xcode] -* [GYP/CMake on GNU/Linux][cmake] +* [Xcode 11][xcode] +* [CMake on GNU/Linux][cmake] [//]: # (LINKS) [telegram]: https://telegram.org diff --git a/docs/building-cmake.md b/docs/building-cmake.md index af59c2d30..65ede9bfc 100644 --- a/docs/building-cmake.md +++ b/docs/building-cmake.md @@ -1,4 +1,4 @@ -## Build instructions for GYP/CMake under Ubuntu 14.04 +## Build instructions for CMake under Ubuntu 14.04 ### Prepare folder @@ -17,7 +17,7 @@ You will need GCC 8 installed. To install them and all the required dependencies libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \ autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \ libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \ - libvorbis-dev libenchant-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ + libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \ libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \ libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \ @@ -214,7 +214,7 @@ Go to ***BuildPath*** and run git checkout OpenSSL_1_1_1-stable ./config --prefix=/usr/local/desktop-app/openssl-1.1.1 make $MAKE_THREADS_CNT - sudo make install + sudo make install_sw cd .. git clone https://github.com/xkbcommon/libxkbcommon.git diff --git a/docs/building-qtcreator.md b/docs/building-qtcreator.md index aa592148f..71fe151e1 100644 --- a/docs/building-qtcreator.md +++ b/docs/building-qtcreator.md @@ -30,7 +30,7 @@ By git – in Terminal go to **/home/user/TBuild** and run Install dev libraries - sudo apt-get install libexif-dev liblzma-dev libz-dev libssl-dev libappindicator-dev libunity-dev libenchant-dev + sudo apt-get install libexif-dev liblzma-dev libz-dev libssl-dev libappindicator-dev libunity-dev #### zlib 1.2.8 diff --git a/docs/building-xcode.md b/docs/building-xcode.md index 1bb348427..fba6b3064 100644 --- a/docs/building-xcode.md +++ b/docs/building-xcode.md @@ -1,4 +1,4 @@ -## Build instructions for Xcode 10.1 +## Build instructions for Xcode 11 ### Prepare folder @@ -8,18 +8,14 @@ Choose a folder for the future build, for example **/Users/user/TBuild**. It wil You will require **api_id** and **api_hash** to access the Telegram API servers. To learn how to obtain them [click here][api_credentials]. -### Download libraries - -Download [**xz-5.0.5**](http://tukaani.org/xz/xz-5.0.5.tar.gz) and unpack to ***BuildPath*/Libraries/macos/xz-5.0.5** - -Download [**libiconv-1.15**](http://www.gnu.org/software/libiconv/#downloading) and unpack to ***BuildPath*/Libraries/macos/libiconv-1.15** - ### Clone source code and prepare libraries Go to ***BuildPath*** and run MAKE_THREADS_CNT=-j8 MACOSX_DEPLOYMENT_TARGET=10.12 + UNGUARDED="-Werror=unguarded-availability-new" + MIN_VER="-mmacosx-version-min=10.12" ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" brew install automake cmake fdk-aac git lame libass libtool libvorbis libvpx ninja opus sdl shtool texi2html theora wget x264 xvid yasm pkg-config gnu-tar @@ -45,6 +41,7 @@ Go to ***BuildPath*** and run sudo ./setup.py install cd ../.. + mkdir -p Libraries/macos cd Libraries/macos LibrariesPath=`pwd` @@ -54,15 +51,19 @@ Go to ***BuildPath*** and run cd .. git clone --branch 0.10.0 https://github.com/ericniebler/range-v3 - cd xz-5.0.5 - CFLAGS="-mmacosx-version-min=10.12" LDFLAGS="-mmacosx-version-min=10.12" ./configure --prefix=/usr/local/macos + xz_ver=5.2.4 + wget https://tukaani.org/xz/xz-$xz_ver.tar.gz + tar -xvzf xz-$xz_ver.tar.gz + rm xz-$xz_ver.tar.gz + cd xz-$xz_ver + CFLAGS="$MIN_VER" LDFLAGS="$MIN_VER" ./configure --prefix=/usr/local/macos make $MAKE_THREADS_CNT sudo make install cd .. git clone https://github.com/desktop-app/zlib.git cd zlib - CFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" LDFLAGS="-mmacosx-version-min=10.12" ./configure --prefix=/usr/local/macos + CFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure --prefix=/usr/local/macos make $MAKE_THREADS_CNT sudo make install cd .. @@ -70,7 +71,7 @@ Go to ***BuildPath*** and run git clone https://github.com/openssl/openssl openssl_1_1_1 cd openssl_1_1_1 git checkout OpenSSL_1_1_1-stable - ./Configure --prefix=/usr/local/macos darwin64-x86_64-cc -static -mmacosx-version-min=10.12 + ./Configure --prefix=/usr/local/macos darwin64-x86_64-cc -static $MIN_VER make build_libs $MAKE_THREADS_CNT cd .. @@ -78,13 +79,17 @@ Go to ***BuildPath*** and run cd opus git checkout v1.3 ./autogen.sh - CFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" CPPFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" LDFLAGS="-mmacosx-version-min=10.12" ./configure --prefix=/usr/local/macos + CFLAGS="$MIN_VER $UNGUARDED" CPPFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure --prefix=/usr/local/macos make $MAKE_THREADS_CNT sudo make install cd .. - cd libiconv-1.15 - CFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" CPPFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" LDFLAGS="-mmacosx-version-min=10.12" ./configure --enable-static --prefix=/usr/local/macos + libiconv_ver=1.16 + wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$libiconv_ver.tar.gz + tar -xvzf libiconv-$libiconv_ver.tar.gz + rm libiconv-$libiconv_ver.tar.gz + cd libiconv-$libiconv_ver + CFLAGS="$MIN_VER $UNGUARDED" CPPFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure --enable-static --prefix=/usr/local/macos make $MAKE_THREADS_CNT sudo make install cd .. @@ -97,9 +102,9 @@ Go to ***BuildPath*** and run PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/X11/lib/pkgconfig ./configure --prefix=/usr/local/macos \ - --extra-cflags="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" \ - --extra-cxxflags="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" \ - --extra-ldflags="-mmacosx-version-min=10.12" \ + --extra-cflags="$MIN_VER $UNGUARDED" \ + --extra-cxxflags="$MIN_VER $UNGUARDED" \ + --extra-ldflags="$MIN_VER" \ --enable-protocol=file --enable-libopus \ --disable-programs \ --disable-doc \ @@ -205,7 +210,7 @@ Go to ***BuildPath*** and run cd openal-soft git checkout v1.19 cd build - CFLAGS='-Werror=unguarded-availability-new' CPPFLAGS='-Werror=unguarded-availability-new' cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/local/macos -D ALSOFT_EXAMPLES=OFF -D LIBTYPE:STRING=STATIC -D CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.12 .. + CFLAGS=$UNGUARDED CPPFLAGS=$UNGUARDED cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/local/macos -D ALSOFT_EXAMPLES=OFF -D LIBTYPE:STRING=STATIC -D CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.12 .. make $MAKE_THREADS_CNT sudo make install cd ../.. @@ -241,7 +246,19 @@ Go to ***BuildPath*** and run git apply ../../patches/qtbase_5_12_5.diff cd .. - ./configure -prefix "/usr/local/desktop-app/Qt-5.12.5" -debug-and-release -force-debug-info -opensource -confirm-license -static -opengl desktop -no-openssl -securetransport -nomake examples -nomake tests -platform macx-clang + ./configure -prefix "/usr/local/desktop-app/Qt-5.12.5" \ + -debug-and-release \ + -force-debug-info \ + -opensource \ + -confirm-license \ + -static \ + -opengl desktop \ + -no-openssl \ + -securetransport \ + -nomake examples \ + -nomake tests \ + -platform macx-clang + make $MAKE_THREADS_CNT sudo make install cd .. From 3b300f23e16e496ea451a6a9fdf149d406972b86 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 25 Feb 2020 03:45:46 +0400 Subject: [PATCH 05/43] Independent check for image in Linux native notifications --- .../linux/notifications_manager_linux.cpp | 86 ++++++++++--------- .../linux/notifications_manager_linux.h | 3 +- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 7f77c0235..00803863b 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -83,6 +83,31 @@ QVersionNumber ParseSpecificationVersion( return QVersionNumber(); } +QString GetImageKey( + const std::shared_ptr ¬ificationInterface) { + const auto specificationVersion = ParseSpecificationVersion( + GetServerInformation(notificationInterface)); + + if (!specificationVersion.isNull()) { + const auto majorVersion = specificationVersion.majorVersion(); + const auto minorVersion = specificationVersion.minorVersion(); + + if ((majorVersion == 1 && minorVersion >= 2) || majorVersion > 1) { + return qsl("image-data"); + } else if (majorVersion == 1 && minorVersion == 1) { + return qsl("image_data"); + } else if ((majorVersion == 1 && minorVersion < 1) + || majorVersion < 1) { + return qsl("icon_data"); + } else { + LOG(("Native notification error: unknown specification version")); + } + } else { + LOG(("Native notification error: specification version is null")); + } + return QString(); +} + } NotificationData::NotificationData( @@ -97,6 +122,7 @@ NotificationData::NotificationData( : _notificationInterface(notificationInterface) , _manager(manager) , _title(title) +, _imageKey(GetImageKey(_notificationInterface)) , _peerId(peerId) , _msgId(msgId) { const auto capabilities = GetCapabilities(_notificationInterface); @@ -161,7 +187,6 @@ NotificationData::NotificationData( } _hints["category"] = qsl("im.received"); - _hints["desktop-entry"] = GetLauncherBasename(); _notificationInterface->connection().connect( @@ -173,14 +198,16 @@ NotificationData::NotificationData( SLOT(notificationClosed(uint))); } -bool NotificationData::show(bool hideNameAndPhoto) { +bool NotificationData::show() { + const auto iconName = _imageKey.isEmpty() || !_hints.contains(_imageKey) + ? qsl("telegram") + : QString(); + const QDBusReply notifyReply = _notificationInterface->call( qsl("Notify"), AppName.utf16(), uint(0), - hideNameAndPhoto - ? qsl("telegram") - : QString(), + iconName, _title, _body, _actions, @@ -198,8 +225,9 @@ bool NotificationData::show(bool hideNameAndPhoto) { } bool NotificationData::close() { - const QDBusReply closeReply = _notificationInterface - ->call(qsl("CloseNotification"), _notificationId); + const QDBusReply closeReply = _notificationInterface->call( + qsl("CloseNotification"), + _notificationId); if (!closeReply.isValid()) { LOG(("Native notification error: %1") @@ -210,28 +238,7 @@ bool NotificationData::close() { } void NotificationData::setImage(const QString &imagePath) { - const auto specificationVersion = ParseSpecificationVersion( - GetServerInformation(_notificationInterface)); - - QString imageKey; - - if (!specificationVersion.isNull()) { - const auto majorVersion = specificationVersion.majorVersion(); - const auto minorVersion = specificationVersion.minorVersion(); - - if ((majorVersion == 1 && minorVersion >= 2) || majorVersion > 1) { - imageKey = qsl("image-data"); - } else if (majorVersion == 1 && minorVersion == 1) { - imageKey = qsl("image_data"); - } else if ((majorVersion == 1 && minorVersion < 1) - || majorVersion < 1) { - imageKey = qsl("icon_data"); - } else { - LOG(("Native notification error: unknown specification version")); - return; - } - } else { - LOG(("Native notification error: specification version is null")); + if (_imageKey.isEmpty()) { return; } @@ -246,16 +253,17 @@ void NotificationData::setImage(const QString &imagePath) { image.sizeInBytes()); #endif - ImageData imageData; - imageData.width = image.width(); - imageData.height = image.height(); - imageData.rowStride = image.bytesPerLine(); - imageData.hasAlpha = true; - imageData.bitsPerSample = 8; - imageData.channels = 4; - imageData.data = imageBytes; + const auto imageData = ImageData{ + image.width(), + image.height(), + image.bytesPerLine(), + true, + 8, + 4, + imageBytes + }; - _hints[imageKey] = QVariant::fromValue(imageData); + _hints[_imageKey] = QVariant::fromValue(imageData); } void NotificationData::notificationClosed(uint id) { @@ -410,7 +418,7 @@ void Manager::Private::showNotification( i = _notifications.insert(peer->id, QMap()); } _notifications[peer->id].insert(msgId, notification); - if (!notification->show(hideNameAndPhoto)) { + if (!notification->show()) { i = _notifications.find(peer->id); if (i != _notifications.cend()) { i->remove(msgId); diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index ef641b4a9..c9428fbbb 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -50,7 +50,7 @@ public: NotificationData(NotificationData &&other) = delete; NotificationData &operator=(NotificationData &&other) = delete; - bool show(bool hideNameAndPhoto); + bool show(); bool close(); void setImage(const QString &imagePath); @@ -69,6 +69,7 @@ private: QString _body; QStringList _actions; QVariantMap _hints; + QString _imageKey; uint _notificationId; PeerId _peerId; From 7bd05985551aa1be634f9e2027e3b9b72c776efb Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 26 Feb 2020 15:38:31 +0400 Subject: [PATCH 06/43] Unified function to detect icon name on Linux --- .../SourceFiles/platform/linux/main_window_linux.cpp | 12 +++--------- .../platform/linux/notifications_manager_linux.cpp | 2 +- .../SourceFiles/platform/linux/specific_linux.cpp | 8 ++++++++ Telegram/SourceFiles/platform/linux/specific_linux.h | 2 ++ Telegram/SourceFiles/window/main_window.cpp | 6 +++--- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index bd3f656ff..da77c191a 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -31,7 +31,6 @@ namespace Platform { namespace { constexpr auto kDisableTrayCounter = "TDESKTOP_DISABLE_TRAY_COUNTER"_cs; -constexpr auto kTrayIconName = "telegram"_cs; constexpr auto kPanelTrayIconName = "telegram-panel"_cs; constexpr auto kMutePanelTrayIconName = "telegram-mute-panel"_cs; constexpr auto kAttentionPanelTrayIconName = "telegram-attention-panel"_cs; @@ -56,18 +55,13 @@ QString GetPanelIconName() { } QString GetTrayIconName() { + const auto iconName = GetIconName(); const auto panelIconName = GetPanelIconName(); if (QIcon::hasThemeIcon(panelIconName)) { return panelIconName; - } else if (InSandbox()) { - const auto launcherBasename = GetLauncherBasename(); - - if (QIcon::hasThemeIcon(launcherBasename)) { - return launcherBasename; - } - } else if (QIcon::hasThemeIcon(kTrayIconName.utf16())) { - return kTrayIconName.utf16(); + } else if (QIcon::hasThemeIcon(iconName)) { + return iconName; } return QString(); diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 00803863b..71e785d59 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -200,7 +200,7 @@ NotificationData::NotificationData( bool NotificationData::show() { const auto iconName = _imageKey.isEmpty() || !_hints.contains(_imageKey) - ? qsl("telegram") + ? GetIconName() : QString(); const QDBusReply notifyReply = _notificationInterface->call( diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 0bacb65d4..4e6ee35c8 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -44,6 +44,7 @@ namespace { constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs; constexpr auto kSnapLauncherDir = "/var/lib/snapd/desktop/applications/"_cs; +constexpr auto kIconName = "telegram"_cs; #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION void SandboxAutostart(bool autostart, bool silent = false) { @@ -333,6 +334,13 @@ QString GetLauncherFilename() { return LauncherFilename; } +QString GetIconName() { + static const auto IconName = InSandbox() + ? GetLauncherBasename() + : kIconName.utf16(); + return IconName; +} + } // namespace Platform namespace { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index f878dac71..526a2aec5 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -35,6 +35,8 @@ QString SingleInstanceLocalServerName(const QString &hash); QString GetLauncherBasename(); QString GetLauncherFilename(); +QString GetIconName(); + inline std::optional LastUserInputTime() { return std::nullopt; } diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 50b956497..a220b0369 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -117,9 +117,9 @@ QIcon CreateOfficialIcon(Main::Account *account) { QIcon CreateIcon(Main::Account *account) { auto result = CreateOfficialIcon(account); - if (Platform::IsLinux()) { - return QIcon::fromTheme("telegram", result); - } +#ifdef Q_OS_LINUX + return QIcon::fromTheme(Platform::GetIconName(), result); +#endif return result; } From a0584ea7a19b377cd0a578bee2c2610aa8533cd3 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 26 Feb 2020 12:38:24 +0300 Subject: [PATCH 07/43] Moved all destruction calls of DictLoader to main thread. --- .../chat_helpers/spellchecker_common.cpp | 28 ++++++++----------- .../chat_helpers/spellchecker_common.h | 1 + 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp index ee4b0d7c6..881a495dc 100644 --- a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp +++ b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp @@ -133,27 +133,22 @@ void DownloadDictionaryInBackground( const auto id = langs[counter]; counter++; const auto destroyer = [=] { - // This is a temporary workaround. - const auto copyId = id; - const auto copyLangs = langs; - const auto copySession = session; - const auto copyCounter = counter; BackgroundLoader = nullptr; BackgroundLoaderChanged.fire(0); - if (DictionaryExists(copyId)) { - auto dicts = copySession->settings().dictionariesEnabled(); - if (!ranges::contains(dicts, copyId)) { - dicts.push_back(copyId); - copySession->settings().setDictionariesEnabled(std::move(dicts)); - copySession->saveSettingsDelayed(); + if (DictionaryExists(id)) { + auto dicts = session->settings().dictionariesEnabled(); + if (!ranges::contains(dicts, id)) { + dicts.push_back(id); + session->settings().setDictionariesEnabled(std::move(dicts)); + session->saveSettingsDelayed(); } } - if (copyCounter >= copyLangs.size()) { + if (counter >= langs.size()) { return; } - DownloadDictionaryInBackground(copySession, copyCounter, copyLangs); + DownloadDictionaryInBackground(session, counter, langs); }; if (DictionaryExists(id)) { destroyer(); @@ -194,20 +189,21 @@ DictLoader::DictLoader( } void DictLoader::unpack(const QString &path) { - Expects(_destroyCallback); crl::async([=] { const auto success = Spellchecker::UnpackDictionary(path, id()); if (success) { QFile(path).remove(); + destroy(); + return; } - crl::on_main(success ? _destroyCallback : [=] { fail(); }); + crl::on_main([=] { fail(); }); }); } void DictLoader::destroy() { Expects(_destroyCallback); - _destroyCallback(); + crl::on_main(_destroyCallback); } void DictLoader::fail() { diff --git a/Telegram/SourceFiles/chat_helpers/spellchecker_common.h b/Telegram/SourceFiles/chat_helpers/spellchecker_common.h index 203c4e047..f806ceb08 100644 --- a/Telegram/SourceFiles/chat_helpers/spellchecker_common.h +++ b/Telegram/SourceFiles/chat_helpers/spellchecker_common.h @@ -60,6 +60,7 @@ private: void unpack(const QString &path) override; void fail() override; + // Be sure to always call it in the main thread. Fn _destroyCallback; rpl::lifetime _lifetime; From 4e345ac6881a89c060aeccf7753ab5be974a35ba Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 26 Feb 2020 14:25:51 +0300 Subject: [PATCH 08/43] Returned display of message status for self and last messages. --- .../SourceFiles/history/view/history_view_element.cpp | 10 ++++++++++ .../SourceFiles/history/view/history_view_element.h | 2 ++ .../history/view/media/history_view_gif.cpp | 3 ++- .../history/view/media/history_view_media_grouped.cpp | 4 +++- .../view/media/history_view_media_unwrapped.cpp | 1 + .../history/view/media/history_view_photo.cpp | 4 +++- 6 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 4a287222d..6921d7aa8 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -280,6 +280,16 @@ bool Element::isUnderCursor() const { return _delegate->elementUnderCursor(this); } +bool Element::isLastAndSelfMessage() const { + if (!hasOutLayout()) { + return false; + } + if (const auto last = data()->_history->lastMessage()) { + return last == data(); + } + return false; +} + void Element::setPendingResize() { _flags |= Flag::NeedsResize; if (_context == Context::History) { diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 734ba8a79..d23b08f17 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -158,6 +158,8 @@ public: bool pendingResize() const; bool isUnderCursor() const; + bool isLastAndSelfMessage() const; + bool isAttachedToPrevious() const; bool isAttachedToNext() const; diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 3b584aba2..6c3c3bdd8 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -1444,7 +1444,8 @@ bool Gif::dataLoaded() const { bool Gif::needInfoDisplay() const { return _parent->data()->isSending() || _data->uploading() - || _parent->isUnderCursor(); + || _parent->isUnderCursor() + || _parent->isLastAndSelfMessage(); } bool Gif::needCornerStatusDisplay() const { diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp index 0b742bbe2..13ab8e046 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_grouped.cpp @@ -453,7 +453,9 @@ bool GroupedMedia::computeNeedBubble() const { } bool GroupedMedia::needInfoDisplay() const { - return (_parent->data()->id < 0 || _parent->isUnderCursor()); + return (_parent->data()->id < 0 + || _parent->isUnderCursor() + || _parent->isLastAndSelfMessage()); } } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp index 3f989962a..7b49cd2b1 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp @@ -367,6 +367,7 @@ bool UnwrappedMedia::needInfoDisplay() const { return (_parent->data()->id < 0) || (_parent->isUnderCursor()) || (_parent->displayRightAction()) + || (_parent->isLastAndSelfMessage()) || (_parent->hasOutLayout() && !Adaptive::ChatWide() && _content->alwaysShowOutTimestamp()); diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index 2b326315b..2d5cb756e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -480,7 +480,9 @@ bool Photo::dataLoaded() const { } bool Photo::needInfoDisplay() const { - return (_parent->data()->id < 0 || _parent->isUnderCursor()); + return (_parent->data()->id < 0 + || _parent->isUnderCursor() + || _parent->isLastAndSelfMessage()); } void Photo::validateGroupedCache( From 57b76e3f0021aedda940b18902bf57a5cb92c333 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 29 Feb 2020 07:42:24 +0400 Subject: [PATCH 09/43] Remove usage of QDBusInterface from non-class methods in Linux native notifications --- .../linux/notifications_manager_linux.cpp | 118 +++++++++--------- .../linux/notifications_manager_linux.h | 14 +-- 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 71e785d59..b8a86f0b6 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -7,16 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "platform/linux/notifications_manager_linux.h" +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include "platform/linux/specific_linux.h" #include "history/history.h" #include "lang/lang_keys.h" #include "facades.h" -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include +#include #include #include -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION namespace Platform { namespace Notifications { @@ -28,44 +29,47 @@ constexpr auto kService = "org.freedesktop.Notifications"_cs; constexpr auto kObjectPath = "/org/freedesktop/Notifications"_cs; constexpr auto kInterface = kService; -std::vector GetServerInformation( - const std::shared_ptr ¬ificationInterface) { +std::vector GetServerInformation() { std::vector serverInformation; - const auto serverInformationReply = notificationInterface - ->call(qsl("GetServerInformation")); - if (serverInformationReply.type() == QDBusMessage::ReplyMessage) { - for (const auto &arg : serverInformationReply.arguments()) { - if (static_cast(arg.type()) - == QMetaType::QString) { - serverInformation.push_back(arg.toString()); - } else { - LOG(("Native notification error: " - "all elements in GetServerInformation " - "should be strings")); - } - } - } else if (serverInformationReply.type() == QDBusMessage::ErrorMessage) { - LOG(("Native notification error: %1") - .arg(serverInformationReply.errorMessage())); + const auto message = QDBusMessage::createMethodCall( + kService.utf16(), + kObjectPath.utf16(), + kInterface.utf16(), + qsl("GetServerInformation")); + + const auto reply = QDBusConnection::sessionBus().call(message); + + if (reply.type() == QDBusMessage::ReplyMessage) { + ranges::transform( + reply.arguments(), + ranges::back_inserter(serverInformation), + &QVariant::toString + ); + } else if (reply.type() == QDBusMessage::ErrorMessage) { + LOG(("Native notification error: %1").arg(reply.errorMessage())); } else { LOG(("Native notification error: " - "error while getting information about notification daemon")); + "invalid reply from GetServerInformation")); } return serverInformation; } -QStringList GetCapabilities( - const std::shared_ptr ¬ificationInterface) { - const QDBusReply capabilitiesReply = notificationInterface - ->call(qsl("GetCapabilities")); +QStringList GetCapabilities() { + const auto message = QDBusMessage::createMethodCall( + kService.utf16(), + kObjectPath.utf16(), + kInterface.utf16(), + qsl("GetCapabilities")); - if (capabilitiesReply.isValid()) { - return capabilitiesReply.value(); + const QDBusReply reply = QDBusConnection::sessionBus().call( + message); + + if (reply.isValid()) { + return reply.value(); } else { - LOG(("Native notification error: %1") - .arg(capabilitiesReply.error().message())); + LOG(("Native notification error: %1").arg(reply.error().message())); } return {}; @@ -83,10 +87,9 @@ QVersionNumber ParseSpecificationVersion( return QVersionNumber(); } -QString GetImageKey( - const std::shared_ptr ¬ificationInterface) { +QString GetImageKey() { const auto specificationVersion = ParseSpecificationVersion( - GetServerInformation(notificationInterface)); + GetServerInformation()); if (!specificationVersion.isNull()) { const auto majorVersion = specificationVersion.majorVersion(); @@ -105,13 +108,14 @@ QString GetImageKey( } else { LOG(("Native notification error: specification version is null")); } + return QString(); } } NotificationData::NotificationData( - const std::shared_ptr ¬ificationInterface, + not_null notificationInterface, const base::weak_ptr &manager, const QString &title, const QString &subtitle, @@ -122,10 +126,10 @@ NotificationData::NotificationData( : _notificationInterface(notificationInterface) , _manager(manager) , _title(title) -, _imageKey(GetImageKey(_notificationInterface)) +, _imageKey(GetImageKey()) , _peerId(peerId) , _msgId(msgId) { - const auto capabilities = GetCapabilities(_notificationInterface); + const auto capabilities = GetCapabilities(); if (capabilities.contains(qsl("body-markup"))) { _body = subtitle.isEmpty() @@ -203,7 +207,7 @@ bool NotificationData::show() { ? GetIconName() : QString(); - const QDBusReply notifyReply = _notificationInterface->call( + const QDBusReply reply = _notificationInterface->call( qsl("Notify"), AppName.utf16(), uint(0), @@ -214,27 +218,25 @@ bool NotificationData::show() { _hints, -1); - if (notifyReply.isValid()) { - _notificationId = notifyReply.value(); + if (reply.isValid()) { + _notificationId = reply.value(); } else { - LOG(("Native notification error: %1") - .arg(notifyReply.error().message())); + LOG(("Native notification error: %1").arg(reply.error().message())); } - return notifyReply.isValid(); + return reply.isValid(); } bool NotificationData::close() { - const QDBusReply closeReply = _notificationInterface->call( + const QDBusReply reply = _notificationInterface->call( qsl("CloseNotification"), _notificationId); - if (!closeReply.isValid()) { - LOG(("Native notification error: %1") - .arg(closeReply.error().message())); + if (!reply.isValid()) { + LOG(("Native notification error: %1").arg(reply.error().message())); } - return closeReply.isValid(); + return reply.isValid(); } void NotificationData::setImage(const QString &imagePath) { @@ -249,9 +251,9 @@ void NotificationData::setImage(const QString &imagePath) { (const char*)image.constBits(), #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) image.byteCount()); -#else +#else // Qt < 5.10.0 image.sizeInBytes()); -#endif +#endif // Qt >= 5.10.0 const auto imageData = ImageData{ image.width(), @@ -328,7 +330,7 @@ const QDBusArgument &operator>>( argument.endStructure(); return argument; } -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION bool Supported() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -339,9 +341,9 @@ bool Supported() { ).isValid(); return Available; -#else +#else // !TDESKTOP_DISABLE_DBUS_INTEGRATION return false; -#endif +#endif // TDESKTOP_DISABLE_DBUS_INTEGRATION } std::unique_ptr Create( @@ -350,12 +352,12 @@ std::unique_ptr Create( if (Global::NativeNotifications() && Supported()) { return std::make_unique(system); } -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION return nullptr; } #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION -Manager::Private::Private(Manager *manager, Type type) +Manager::Private::Private(not_null manager, Type type) : _cachedUserpics(type) , _manager(manager) , _notificationInterface( @@ -366,9 +368,9 @@ Manager::Private::Private(Manager *manager, Type type) qDBusRegisterMetaType(); const auto specificationVersion = ParseSpecificationVersion( - GetServerInformation(_notificationInterface)); + GetServerInformation()); - const auto capabilities = GetCapabilities(_notificationInterface); + const auto capabilities = GetCapabilities(); if (!specificationVersion.isNull()) { LOG(("Notification daemon specification version: %1") @@ -390,7 +392,7 @@ void Manager::Private::showNotification( bool hideNameAndPhoto, bool hideReplyButton) { auto notification = std::make_shared( - _notificationInterface, + _notificationInterface.get(), _manager, title, subtitle, @@ -462,7 +464,7 @@ Manager::Private::~Private() { clearAll(); } -Manager::Manager(Window::Notifications::System *system) +Manager::Manager(not_null system) : NativeManager(system) , _private(std::make_unique(this, Private::Type::Rounded)) { } @@ -498,7 +500,7 @@ void Manager::doClearAllFast() { void Manager::doClearFromHistory(not_null history) { _private->clearFromHistory(history); } -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } // namespace Notifications } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index c9428fbbb..82c74d26d 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include #include -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION namespace Platform { namespace Notifications { @@ -36,7 +36,7 @@ class NotificationData : public QObject { public: NotificationData( - const std::shared_ptr ¬ificationInterface, + not_null notificationInterface, const base::weak_ptr &manager, const QString &title, const QString &subtitle, @@ -62,7 +62,7 @@ public: }; private: - std::shared_ptr _notificationInterface; + const not_null _notificationInterface; base::weak_ptr _manager; QString _title; @@ -95,7 +95,7 @@ class Manager : public Window::Notifications::NativeManager , public base::has_weak_ptr { public: - Manager(Window::Notifications::System *system); + Manager(not_null system); void clearNotification(PeerId peerId, MsgId msgId); ~Manager(); @@ -120,7 +120,7 @@ private: class Manager::Private { public: using Type = Window::Notifications::CachedUserpics::Type; - explicit Private(Manager *manager, Type type); + explicit Private(not_null manager, Type type); void showNotification( not_null peer, @@ -144,11 +144,11 @@ private: base::weak_ptr _manager; std::shared_ptr _notificationInterface; }; -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } // namespace Notifications } // namespace Platform #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION Q_DECLARE_METATYPE(Platform::Notifications::NotificationData::ImageData) -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION From 5c89dfad85a05fda6aeabe2b98017fcc8b01c624 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 2 Mar 2020 11:44:56 +0400 Subject: [PATCH 10/43] Implement LastUserInputTime on Linux This is a dbus implementation, ideally a X11 implementation should be added as a fallback to get it work on non-mainstream DEs (and WMs) --- .../platform/linux/specific_linux.cpp | 29 +++++++++++++++++++ .../platform/linux/specific_linux.h | 4 --- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 4e6ee35c8..895529b11 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -26,6 +26,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include +#include +#include +#include +#include #endif #include @@ -341,6 +345,31 @@ QString GetIconName() { return IconName; } +std::optional LastUserInputTime() { + // TODO: a fallback pure-X11 implementation, this one covers only major DEs on X11 and Wayland + // an example: https://stackoverflow.com/q/9049087 +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + static const auto message = QDBusMessage::createMethodCall( + qsl("org.freedesktop.ScreenSaver"), + qsl("/org/freedesktop/ScreenSaver"), + qsl("org.freedesktop.ScreenSaver"), + qsl("GetSessionIdleTime")); + + const QDBusReply reply = QDBusConnection::sessionBus().call( + message); + + if (reply.isValid()) { + return (crl::now() - static_cast(reply.value())); + } else if (reply.error().type() != QDBusError::ServiceUnknown) { + LOG(("Unable to get last user input time: %1: %2") + .arg(reply.error().name()) + .arg(reply.error().message())); + } +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + + return std::nullopt; +} + } // namespace Platform namespace { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index 526a2aec5..7f18032cb 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -37,10 +37,6 @@ QString GetLauncherFilename(); QString GetIconName(); -inline std::optional LastUserInputTime() { - return std::nullopt; -} - inline void IgnoreApplicationActivationRightNow() { } From 7202ffca7631be7cfe5843195edb66915737bd45 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 3 Mar 2020 05:24:13 +0400 Subject: [PATCH 11/43] Remove unneeded TrayIconFileTemplate function Use /.flatpak-info instead of deprecated /run/user/$UID/flatpak-info Improve indentation in UseXDGDesktopPortal and IsAppIndicator Remove unneeded NeedTrayIconFile and rename IsAppIndicator to IsIndicatorApplication Include only needed part of QtDBus in main_window_linux.cpp Remove usage of QDBusInterface from SandboxAutostart and IsSNIAvailable Don't check dbus activatable services in IsIndicatorApplication Move XEmbed menu initialization to initTrayMenuHook, tray availability check to initHook Don't create unneeded file for tooltip icon, since indicator-application doesn't support tooltips Passthrough counter from updateIconCounters Suppress log errors for LastUserInputTime on GNOME Set applcation name and icon name for pulseaudio --- .../platform/linux/main_window_linux.cpp | 151 ++++++++++-------- .../platform/linux/main_window_linux.h | 4 +- .../platform/linux/specific_linux.cpp | 56 ++++--- 3 files changed, 118 insertions(+), 93 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index da77c191a..818946e0b 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -24,7 +24,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION -#include +#include +#include +#include +#include +#include +#include +#include #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION namespace Platform { @@ -35,6 +41,7 @@ constexpr auto kPanelTrayIconName = "telegram-panel"_cs; constexpr auto kMutePanelTrayIconName = "telegram-mute-panel"_cs; constexpr auto kAttentionPanelTrayIconName = "telegram-attention-panel"_cs; constexpr auto kSNIWatcherService = "org.kde.StatusNotifierWatcher"_cs; +constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; constexpr auto kTrayIconFilename = "tdesktop-trayicon-XXXXXX.png"_cs; bool TrayIconMuted = true; @@ -43,10 +50,7 @@ base::flat_map TrayIconImageBack; QIcon TrayIcon; QString TrayIconThemeName, TrayIconName; -QString GetPanelIconName() { - const auto counter = Core::App().unreadBadge(); - const auto muted = Core::App().unreadBadgeMuted(); - +QString GetPanelIconName(int counter, bool muted) { return (counter > 0) ? (muted ? kMutePanelTrayIconName.utf16() @@ -54,9 +58,9 @@ QString GetPanelIconName() { : kPanelTrayIconName.utf16(); } -QString GetTrayIconName() { +QString GetTrayIconName(int counter, bool muted) { const auto iconName = GetIconName(); - const auto panelIconName = GetPanelIconName(); + const auto panelIconName = GetPanelIconName(counter, muted); if (QIcon::hasThemeIcon(panelIconName)) { return panelIconName; @@ -67,9 +71,9 @@ QString GetTrayIconName() { return QString(); } -QIcon TrayIconGen() { +QIcon TrayIconGen(int counter, bool muted) { const auto iconThemeName = QIcon::themeName(); - const auto iconName = GetTrayIconName(); + const auto iconName = GetTrayIconName(counter, muted); if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) && !iconName.isEmpty()) { @@ -84,8 +88,6 @@ QIcon TrayIconGen() { return TrayIcon; } - const auto counter = Core::App().unreadBadge(); - const auto muted = Core::App().unreadBadgeMuted(); const auto counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; @@ -196,47 +198,40 @@ QIcon TrayIconGen() { return TrayIcon; } -bool IsAppIndicator() { -#ifdef TDESKTOP_DISABLE_DBUS_INTEGRATION - static const auto AppIndicator = false; -#else // TDESKTOP_DISABLE_DBUS_INTEGRATION - static const auto AppIndicator = QDBusInterface( - qsl("com.canonical.indicator.application"), - qsl("/com/canonical/indicator/application/service"), - qsl("com.canonical.indicator.application.service")).isValid() - || QDBusInterface( - qsl("org.ayatana.indicator.application"), - qsl("/org/ayatana/indicator/application/service"), - qsl("org.ayatana.indicator.application.service")).isValid(); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION - - return AppIndicator; -} - #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION -static bool NeedTrayIconFile() { +bool IsIndicatorApplication() { // Hack for indicator-application, which doesn't handle icons sent across D-Bus: // save the icon to a temp file and set the icon name to that filename. - static const auto TrayIconFileNeeded = IsAppIndicator(); - return TrayIconFileNeeded; -} + static const auto IndicatorApplication = [&] { + const auto interface = QDBusConnection::sessionBus().interface(); -static inline QString TrayIconFileTemplate() { - static const auto TempFileTemplate = AppRuntimeDirectory() - + kTrayIconFilename.utf16(); - return TempFileTemplate; + const auto ubuntuIndicator = interface->isServiceRegistered( + qsl("com.canonical.indicator.application")); + + const auto ayatanaIndicator = interface->isServiceRegistered( + qsl("org.ayatana.indicator.application")); + + return ubuntuIndicator || ayatanaIndicator; + }(); + + return IndicatorApplication; } std::unique_ptr TrayIconFile( const QIcon &icon, int size, QObject *parent) { + static const auto templateName = AppRuntimeDirectory() + + kTrayIconFilename.utf16(); + auto ret = std::make_unique( - TrayIconFileTemplate(), + templateName, parent); + ret->open(); icon.pixmap(size).save(ret.get()); ret->close(); + return ret; } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -244,15 +239,25 @@ std::unique_ptr TrayIconFile( bool IsSNIAvailable() { static const auto SNIAvailable = [&] { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - QDBusInterface systrayHost( + auto message = QDBusMessage::createMethodCall( kSNIWatcherService.utf16(), qsl("/StatusNotifierWatcher"), - kSNIWatcherService.utf16()); + kPropertiesInterface.utf16(), + qsl("Get")); - return systrayHost.isValid() - && systrayHost - .property("IsStatusNotifierHostRegistered") - .toBool(); + message.setArguments({ + kSNIWatcherService.utf16(), + qsl("IsStatusNotifierHostRegistered") + }); + + const QDBusReply reply = QDBusConnection::sessionBus().call( + message); + + if (reply.isValid()) { + return reply.value().toBool(); + } else if (reply.error().type() != QDBusError::ServiceUnknown) { + LOG(("SNI Error: %1").arg(reply.error().message())); + } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION return false; @@ -288,6 +293,20 @@ MainWindow::MainWindow(not_null controller) : Window::MainWindow(controller) { } +void MainWindow::initHook() { + const auto trayAvailable = IsSNIAvailable() + || QSystemTrayIcon::isSystemTrayAvailable(); + + LOG(("System tray available: %1").arg(Logs::b(trayAvailable))); + cSetSupportTray(trayAvailable); + + if (UseUnityCounter()) { + LOG(("Using Unity launcher counter.")); + } else { + LOG(("Not using Unity launcher counter.")); + } +} + bool MainWindow::hasTrayIcon() const { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION return trayIcon || _sniTrayIcon; @@ -313,23 +332,23 @@ void MainWindow::psTrayMenuUpdated() { } #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION -void MainWindow::setSNITrayIcon(const QIcon &icon) { - const auto iconName = GetTrayIconName(); +void MainWindow::setSNITrayIcon(int counter, bool muted) { + const auto iconName = GetTrayIconName(counter, muted); if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) && !iconName.isEmpty()) { _sniTrayIcon->setIconByName(iconName); _sniTrayIcon->setToolTipIconByName(iconName); - } else if (NeedTrayIconFile()) { + } else if (IsIndicatorApplication()) { + const auto icon = TrayIconGen(counter, muted); _trayIconFile = TrayIconFile(icon, 22, this); - _trayToolTipIconFile = TrayIconFile(icon, 48, this); if (_trayIconFile) { + // indicator-application doesn't support tooltips _sniTrayIcon->setIconByName(_trayIconFile->fileName()); - _sniTrayIcon->setToolTipIconByName( - _trayToolTipIconFile->fileName()); } } else { + const auto icon = TrayIconGen(counter, muted); _sniTrayIcon->setIconByPixmap(icon); _sniTrayIcon->setToolTipIconByPixmap(icon); } @@ -358,6 +377,9 @@ void MainWindow::attachToSNITrayIcon() { #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION void MainWindow::psSetupTrayIcon() { + const auto counter = Core::App().unreadBadge(); + const auto muted = Core::App().unreadBadgeMuted(); + if (IsSNIAvailable()) { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION LOG(("Using SNI tray icon.")); @@ -367,7 +389,7 @@ void MainWindow::psSetupTrayIcon() { this); _sniTrayIcon->setTitle(AppName.utf16()); - setSNITrayIcon(TrayIconGen()); + setSNITrayIcon(counter, muted); attachToSNITrayIcon(); } @@ -375,15 +397,9 @@ void MainWindow::psSetupTrayIcon() { #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } else { LOG(("Using Qt tray icon.")); - - if (!_trayIconMenuXEmbed) { - _trayIconMenuXEmbed = new Ui::PopupMenu(nullptr, trayIconMenu); - _trayIconMenuXEmbed->deleteOnHide(false); - } - if (!trayIcon) { trayIcon = new QSystemTrayIcon(this); - trayIcon->setIcon(TrayIconGen()); + trayIcon->setIcon(TrayIconGen(counter, muted)); attachToTrayIcon(trayIcon); } @@ -423,11 +439,13 @@ void MainWindow::unreadCounterChangedHook() { } void MainWindow::updateIconCounters() { + const auto counter = Core::App().unreadBadge(); + const auto muted = Core::App().unreadBadgeMuted(); + updateWindowIcon(); #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION if (UseUnityCounter()) { - const auto counter = Core::App().unreadBadge(); const auto launcherUrl = "application://" + GetLauncherFilename(); QVariantMap dbusUnityProperties; if (counter > 0) { @@ -455,11 +473,11 @@ void MainWindow::updateIconCounters() { if (IsSNIAvailable()) { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION if (_sniTrayIcon) { - setSNITrayIcon(TrayIconGen()); + setSNITrayIcon(counter, muted); } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } else if (trayIcon) { - trayIcon->setIcon(TrayIconGen()); + trayIcon->setIcon(TrayIconGen(counter, muted)); } } @@ -472,16 +490,9 @@ void MainWindow::LibsLoaded() { } void MainWindow::initTrayMenuHook() { - const auto trayAvailable = IsSNIAvailable() - || QSystemTrayIcon::isSystemTrayAvailable(); - - LOG(("System tray available: %1").arg(Logs::b(trayAvailable))); - cSetSupportTray(trayAvailable); - - if (UseUnityCounter()) { - LOG(("Using Unity launcher counter.")); - } else { - LOG(("Not using Unity launcher counter.")); + if (!IsSNIAvailable()) { + _trayIconMenuXEmbed = new Ui::PopupMenu(nullptr, trayIconMenu); + _trayIconMenuXEmbed->deleteOnHide(false); } } diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index f6eadc5d1..392520947 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -39,6 +39,7 @@ public slots: void psShowTrayMenu(); protected: + void initHook() override; void unreadCounterChangedHook() override; void initTrayMenuHook() override; @@ -68,9 +69,8 @@ private: #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION StatusNotifierItem *_sniTrayIcon = nullptr; std::unique_ptr _trayIconFile = nullptr; - std::unique_ptr _trayToolTipIconFile = nullptr; - void setSNITrayIcon(const QIcon &icon); + void setSNITrayIcon(int counter, bool muted); void attachToSNITrayIcon(); #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 895529b11..4b715d0ee 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -30,7 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION #include #include @@ -61,23 +61,29 @@ void SandboxAutostart(bool autostart, bool silent = false) { }); options["dbus-activatable"] = false; - const auto requestBackgroundReply = QDBusInterface( + auto message = QDBusMessage::createMethodCall( qsl("org.freedesktop.portal.Desktop"), qsl("/org/freedesktop/portal/desktop"), - qsl("org.freedesktop.portal.Background") - ).call(qsl("RequestBackground"), QString(), options); + qsl("org.freedesktop.portal.Background"), + qsl("RequestBackground")); - if (!silent) { - if (requestBackgroundReply.type() == QDBusMessage::ErrorMessage) { - LOG(("Flatpak autostart error: %1") - .arg(requestBackgroundReply.errorMessage())); - } else if (requestBackgroundReply.type() - != QDBusMessage::ReplyMessage) { - LOG(("Flatpak autostart error: invalid reply")); + message.setArguments({ + QString(), + options + }); + + if (silent) { + QDBusConnection::sessionBus().send(message); + } else { + const QDBusReply reply = QDBusConnection::sessionBus().call( + message); + + if (!reply.isValid()) { + LOG(("Flatpak autostart error: %1").arg(reply.error().message())); } } } -#endif +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION bool RunShellCommand(const QByteArray &command) { auto result = system(command.constData()); @@ -168,7 +174,7 @@ bool GenerateDesktopFile( QRegularExpression::MultilineOption), qsl("Exec=\\1") + (args.isEmpty() ? QString() : ' ' + args)); -#else +#else // DESKTOP_APP_USE_PACKAGED fileText = fileText.replace( QRegularExpression( qsl("^TryExec=.*$"), @@ -184,7 +190,7 @@ bool GenerateDesktopFile( + EscapeShell(QFile::encodeName(cExeDir() + cExeName())) .replace('\\', qsl("\\\\")) + (args.isEmpty() ? QString() : ' ' + args)); -#endif +#endif // !DESKTOP_APP_USE_PACKAGED target.write(fileText.toUtf8()); target.close(); @@ -209,9 +215,7 @@ void SetApplicationIcon(const QIcon &icon) { } bool InSandbox() { - static const auto Sandbox = QFileInfo::exists( - QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) - + qsl("/flatpak-info")); + static const auto Sandbox = QFileInfo::exists(qsl("/.flatpak-info")); return Sandbox; } @@ -228,12 +232,18 @@ bool IsXDGDesktopPortalPresent() { "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop").isValid(); #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + return XDGDesktopPortalPresent; } bool UseXDGDesktopPortal() { - static const auto UsePortal = qEnvironmentVariableIsSet("TDESKTOP_USE_PORTAL") - && IsXDGDesktopPortalPresent(); + static const auto UsePortal = [&] { + const auto envVar = qEnvironmentVariableIsSet("TDESKTOP_USE_PORTAL"); + const auto portalPresent = IsXDGDesktopPortalPresent(); + + return envVar && portalPresent; + }(); + return UsePortal; } @@ -360,7 +370,8 @@ std::optional LastUserInputTime() { if (reply.isValid()) { return (crl::now() - static_cast(reply.value())); - } else if (reply.error().type() != QDBusError::ServiceUnknown) { + } else if (reply.error().type() != QDBusError::ServiceUnknown + && reply.error().type() != QDBusError::NotSupported) { LOG(("Unable to get last user input time: %1: %2") .arg(reply.error().name()) .arg(reply.error().message())); @@ -488,6 +499,9 @@ void start() { LOG(("Launcher filename: %1").arg(GetLauncherFilename())); FallbackFontConfig(); + qputenv("PULSE_PROP_application.name", AppName.utf8()); + qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1()); + #ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG LOG(("Checking for XDG Desktop Portal...")); // this can give us a chance to use a proper file dialog for current session @@ -622,7 +636,7 @@ void psAutoStart(bool start, bool silent) { if (InSandbox()) { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION SandboxAutostart(start, silent); -#endif +#endif // !DESKTOP_APP_USE_PACKAGED } else { const auto autostart = [&] { if (InSnap()) { From 3fb6bbeae4d258d72720c8ddbb962551b50410ac Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 5 Mar 2020 23:46:46 +0400 Subject: [PATCH 12/43] Optimize icon regeneration --- .../platform/linux/main_window_linux.cpp | 250 ++++++++++-------- .../platform/linux/main_window_linux.h | 2 +- 2 files changed, 142 insertions(+), 110 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 818946e0b..8e7e9051b 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -71,131 +71,151 @@ QString GetTrayIconName(int counter, bool muted) { return QString(); } +int GetCounterSlice(int counter) { + return (counter >= 1000) + ? (1000 + (counter % 100)) + : counter; +} + +bool IsIconRegenerationNeeded( + int counter, + bool muted, + const QString &iconThemeName = QIcon::themeName()) { + const auto iconName = GetTrayIconName(counter, muted); + const auto counterSlice = GetCounterSlice(counter); + + return TrayIcon.isNull() + || iconThemeName != TrayIconThemeName + || iconName != TrayIconName + || muted != TrayIconMuted + || counterSlice != TrayIconCount; +} + +void UpdateIconRegenerationNeeded( + const QIcon &icon, + int counter, + bool muted, + const QString &iconThemeName) { + const auto iconName = GetTrayIconName(counter, muted); + const auto counterSlice = GetCounterSlice(counter); + + TrayIcon = icon; + TrayIconMuted = muted; + TrayIconCount = counterSlice; + TrayIconThemeName = iconThemeName; + TrayIconName = iconName; +} + QIcon TrayIconGen(int counter, bool muted) { const auto iconThemeName = QIcon::themeName(); + + if (!IsIconRegenerationNeeded(counter, muted, iconThemeName)) { + return TrayIcon; + } + const auto iconName = GetTrayIconName(counter, muted); if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) && !iconName.isEmpty()) { - if (TrayIcon.isNull() + const auto result = QIcon::fromTheme(iconName); + UpdateIconRegenerationNeeded(result, counter, muted, iconThemeName); + return result; + } + + QIcon result; + QIcon systemIcon; + + const auto iconSizes = { + 16, + 22, + 24, + 32, + 48, + 64 + }; + + for (const auto iconSize : iconSizes) { + auto ¤tImageBack = TrayIconImageBack[iconSize]; + const auto desiredSize = QSize(iconSize, iconSize); + + if (currentImageBack.isNull() || iconThemeName != TrayIconThemeName || iconName != TrayIconName) { - TrayIcon = QIcon::fromTheme(iconName); - TrayIconThemeName = iconThemeName; - TrayIconName = iconName; - } + if (!iconName.isEmpty()) { + if(systemIcon.isNull()) { + systemIcon = QIcon::fromTheme(iconName); + } - return TrayIcon; - } - - const auto counterSlice = (counter >= 1000) - ? (1000 + (counter % 100)) - : counter; - - if (TrayIcon.isNull() - || iconThemeName != TrayIconThemeName - || iconName != TrayIconName - || muted != TrayIconMuted - || counterSlice != TrayIconCount) { - QIcon result; - QIcon systemIcon; - - const auto iconSizes = { - 16, - 22, - 24, - 32, - 48, - 64 - }; - - for (const auto iconSize : iconSizes) { - auto ¤tImageBack = TrayIconImageBack[iconSize]; - const auto desiredSize = QSize(iconSize, iconSize); - - if (currentImageBack.isNull() - || iconThemeName != TrayIconThemeName - || iconName != TrayIconName) { - if (!iconName.isEmpty()) { - if(systemIcon.isNull()) { - systemIcon = QIcon::fromTheme(iconName); - } - - if (systemIcon.actualSize(desiredSize) == desiredSize) { - currentImageBack = systemIcon - .pixmap(desiredSize) - .toImage(); - } else { - const auto availableSizes = systemIcon - .availableSizes(); - - const auto biggestSize = ranges::max_element( - availableSizes, - std::less<>(), - &QSize::width); - - currentImageBack = systemIcon - .pixmap(*biggestSize) - .toImage(); - } + if (systemIcon.actualSize(desiredSize) == desiredSize) { + currentImageBack = systemIcon + .pixmap(desiredSize) + .toImage(); } else { - currentImageBack = Core::App().logo(); - } + const auto availableSizes = systemIcon + .availableSizes(); - if (currentImageBack.size() != desiredSize) { - currentImageBack = currentImageBack.scaled( - desiredSize, - Qt::IgnoreAspectRatio, - Qt::SmoothTransformation); + const auto biggestSize = ranges::max_element( + availableSizes, + std::less<>(), + &QSize::width); + + currentImageBack = systemIcon + .pixmap(*biggestSize) + .toImage(); } + } else { + currentImageBack = Core::App().logo(); } - auto iconImage = currentImageBack; - TrayIconMuted = muted; - TrayIconCount = counterSlice; - TrayIconThemeName = iconThemeName; - TrayIconName = iconName; - - if (!qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) - && counter > 0) { - QPainter p(&iconImage); - int32 layerSize = -16; - - if (iconSize >= 48) { - layerSize = -32; - } else if (iconSize >= 36) { - layerSize = -24; - } else if (iconSize >= 32) { - layerSize = -20; - } - - auto &bg = muted - ? st::trayCounterBgMute - : st::trayCounterBg; - - auto &fg = st::trayCounterFg; - - auto layer = App::wnd()->iconWithCounter( - layerSize, - counter, - bg, - fg, - false); - - p.drawImage( - iconImage.width() - layer.width() - 1, - iconImage.height() - layer.height() - 1, - layer); + if (currentImageBack.size() != desiredSize) { + currentImageBack = currentImageBack.scaled( + desiredSize, + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); } - - result.addPixmap(App::pixmapFromImageInPlace( - std::move(iconImage))); } - TrayIcon = result; + auto iconImage = currentImageBack; + + if (!qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) + && counter > 0) { + QPainter p(&iconImage); + int32 layerSize = -16; + + if (iconSize >= 48) { + layerSize = -32; + } else if (iconSize >= 36) { + layerSize = -24; + } else if (iconSize >= 32) { + layerSize = -20; + } + + auto &bg = muted + ? st::trayCounterBgMute + : st::trayCounterBg; + + auto &fg = st::trayCounterFg; + + auto layer = App::wnd()->iconWithCounter( + layerSize, + counter, + bg, + fg, + false); + + p.drawImage( + iconImage.width() - layer.width() - 1, + iconImage.height() - layer.height() - 1, + layer); + } + + result.addPixmap(App::pixmapFromImageInPlace( + std::move(iconImage))); } - return TrayIcon; + UpdateIconRegenerationNeeded(result, counter, muted, iconThemeName); + + return result; } #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -332,14 +352,22 @@ void MainWindow::psTrayMenuUpdated() { } #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION -void MainWindow::setSNITrayIcon(int counter, bool muted) { +void MainWindow::setSNITrayIcon(int counter, bool muted, bool firstShow) { const auto iconName = GetTrayIconName(counter, muted); if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) && !iconName.isEmpty()) { + if (_sniTrayIcon->iconName() == iconName) { + return; + } + _sniTrayIcon->setIconByName(iconName); _sniTrayIcon->setToolTipIconByName(iconName); } else if (IsIndicatorApplication()) { + if(!IsIconRegenerationNeeded(counter, muted) && !firstShow) { + return; + } + const auto icon = TrayIconGen(counter, muted); _trayIconFile = TrayIconFile(icon, 22, this); @@ -348,6 +376,10 @@ void MainWindow::setSNITrayIcon(int counter, bool muted) { _sniTrayIcon->setIconByName(_trayIconFile->fileName()); } } else { + if(!IsIconRegenerationNeeded(counter, muted) && !firstShow) { + return; + } + const auto icon = TrayIconGen(counter, muted); _sniTrayIcon->setIconByPixmap(icon); _sniTrayIcon->setToolTipIconByPixmap(icon); @@ -389,7 +421,7 @@ void MainWindow::psSetupTrayIcon() { this); _sniTrayIcon->setTitle(AppName.utf16()); - setSNITrayIcon(counter, muted); + setSNITrayIcon(counter, muted, true); attachToSNITrayIcon(); } @@ -476,7 +508,7 @@ void MainWindow::updateIconCounters() { setSNITrayIcon(counter, muted); } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION - } else if (trayIcon) { + } else if (trayIcon && IsIconRegenerationNeeded(counter, muted)) { trayIcon->setIcon(TrayIconGen(counter, muted)); } } diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 392520947..297ec1d62 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -70,7 +70,7 @@ private: StatusNotifierItem *_sniTrayIcon = nullptr; std::unique_ptr _trayIconFile = nullptr; - void setSNITrayIcon(int counter, bool muted); + void setSNITrayIcon(int counter, bool muted, bool firstShow = false); void attachToSNITrayIcon(); #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION From 7aadaca62e90ebd1a5a27d0d61edc13f337adcd8 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 3 Mar 2020 12:52:05 +0400 Subject: [PATCH 13/43] Implement SkipAudio and SkipToast on Linux --- .../linux/notifications_manager_linux.cpp | 46 +++++++++++++++++++ .../linux/notifications_manager_linux.h | 8 ---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index b8a86f0b6..4f094e591 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include #include #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -28,6 +29,7 @@ namespace { constexpr auto kService = "org.freedesktop.Notifications"_cs; constexpr auto kObjectPath = "/org/freedesktop/Notifications"_cs; constexpr auto kInterface = kService; +constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; std::vector GetServerInformation() { std::vector serverInformation; @@ -75,6 +77,30 @@ QStringList GetCapabilities() { return {}; } +bool Inhibited() { + auto message = QDBusMessage::createMethodCall( + kService.utf16(), + kObjectPath.utf16(), + kPropertiesInterface.utf16(), + qsl("Get")); + + message.setArguments({ + qsl("org.freedesktop.Notifications"), + qsl("Inhibited") + }); + + const QDBusReply reply = QDBusConnection::sessionBus().call( + message); + + if (reply.isValid()) { + return reply.value().toBool(); + } else if (reply.error().type() != QDBusError::InvalidArgs) { + LOG(("Native notification error: %1").arg(reply.error().message())); + } + + return false; +} + QVersionNumber ParseSpecificationVersion( const std::vector &serverInformation) { if (serverInformation.size() >= 4) { @@ -332,6 +358,26 @@ const QDBusArgument &operator>>( } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +bool SkipAudio() { +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + if (Supported()) { + return Inhibited(); + } +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + + return false; +} + +bool SkipToast() { +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + if (Supported()) { + return Inhibited(); + } +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + + return false; +} + bool Supported() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION static const auto Available = QDBusInterface( diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index 82c74d26d..2cd5ba953 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -19,14 +19,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Platform { namespace Notifications { -inline bool SkipAudio() { - return false; -} - -inline bool SkipToast() { - return false; -} - inline void FlashBounce() { } From fdf16d0aea614e585d8618883191b840feded4ff Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 2 Mar 2020 19:55:29 +0400 Subject: [PATCH 14/43] Fix notification daemon detection on KDE Minimize usage of QDBusInterface Log the whole notification daemon information --- .../linux/notifications_manager_linux.cpp | 96 +++++++++---------- .../linux/notifications_manager_linux.h | 8 +- 2 files changed, 51 insertions(+), 53 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 4f094e591..0a50d2c2c 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "facades.h" #include -#include +#include #include #include #include @@ -113,10 +113,7 @@ QVersionNumber ParseSpecificationVersion( return QVersionNumber(); } -QString GetImageKey() { - const auto specificationVersion = ParseSpecificationVersion( - GetServerInformation()); - +QString GetImageKey(const QVersionNumber &specificationVersion) { if (!specificationVersion.isNull()) { const auto majorVersion = specificationVersion.majorVersion(); const auto minorVersion = specificationVersion.minorVersion(); @@ -141,7 +138,6 @@ QString GetImageKey() { } NotificationData::NotificationData( - not_null notificationInterface, const base::weak_ptr &manager, const QString &title, const QString &subtitle, @@ -149,10 +145,11 @@ NotificationData::NotificationData( PeerId peerId, MsgId msgId, bool hideReplyButton) -: _notificationInterface(notificationInterface) +: _dbusConnection(QDBusConnection::sessionBus()) , _manager(manager) , _title(title) -, _imageKey(GetImageKey()) +, _imageKey(GetImageKey(ParseSpecificationVersion( + GetServerInformation()))) , _peerId(peerId) , _msgId(msgId) { const auto capabilities = GetCapabilities(); @@ -172,7 +169,7 @@ NotificationData::NotificationData( if (capabilities.contains(qsl("actions"))) { _actions << qsl("default") << QString(); - _notificationInterface->connection().connect( + _dbusConnection.connect( kService.utf16(), kObjectPath.utf16(), kInterface.utf16(), @@ -181,10 +178,11 @@ NotificationData::NotificationData( SLOT(notificationClicked(uint,QString))); if (capabilities.contains(qsl("inline-reply")) && !hideReplyButton) { - _actions << qsl("inline-reply") + _actions + << qsl("inline-reply") << tr::lng_notification_reply(tr::now); - _notificationInterface->connection().connect( + _dbusConnection.connect( kService.utf16(), kObjectPath.utf16(), kInterface.utf16(), @@ -193,7 +191,8 @@ NotificationData::NotificationData( SLOT(notificationReplied(uint,QString))); } else { // icon name according to https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html - _actions << qsl("mail-reply-sender") + _actions + << qsl("mail-reply-sender") << tr::lng_notification_reply(tr::now); } } @@ -219,7 +218,7 @@ NotificationData::NotificationData( _hints["category"] = qsl("im.received"); _hints["desktop-entry"] = GetLauncherBasename(); - _notificationInterface->connection().connect( + _dbusConnection.connect( kService.utf16(), kObjectPath.utf16(), kInterface.utf16(), @@ -233,8 +232,13 @@ bool NotificationData::show() { ? GetIconName() : QString(); - const QDBusReply reply = _notificationInterface->call( - qsl("Notify"), + auto message = QDBusMessage::createMethodCall( + kService.utf16(), + kObjectPath.utf16(), + kInterface.utf16(), + qsl("Notify")); + + message.setArguments({ AppName.utf16(), uint(0), iconName, @@ -242,7 +246,11 @@ bool NotificationData::show() { _body, _actions, _hints, - -1); + -1 + }); + + const QDBusReply reply = _dbusConnection.call( + message); if (reply.isValid()) { _notificationId = reply.value(); @@ -253,16 +261,18 @@ bool NotificationData::show() { return reply.isValid(); } -bool NotificationData::close() { - const QDBusReply reply = _notificationInterface->call( - qsl("CloseNotification"), - _notificationId); +void NotificationData::close() { + auto message = QDBusMessage::createMethodCall( + kService.utf16(), + kObjectPath.utf16(), + kInterface.utf16(), + qsl("CloseNotification")); - if (!reply.isValid()) { - LOG(("Native notification error: %1").arg(reply.error().message())); - } + message.setArguments({ + _notificationId + }); - return reply.isValid(); + _dbusConnection.send(message); } void NotificationData::setImage(const QString &imagePath) { @@ -331,7 +341,8 @@ QDBusArgument &operator<<( QDBusArgument &argument, const NotificationData::ImageData &imageData) { argument.beginStructure(); - argument << imageData.width + argument + << imageData.width << imageData.height << imageData.rowStride << imageData.hasAlpha @@ -346,7 +357,8 @@ const QDBusArgument &operator>>( const QDBusArgument &argument, NotificationData::ImageData &imageData) { argument.beginStructure(); - argument >> imageData.width + argument + >> imageData.width >> imageData.height >> imageData.rowStride >> imageData.hasAlpha @@ -380,12 +392,7 @@ bool SkipToast() { bool Supported() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - static const auto Available = QDBusInterface( - kService.utf16(), - kObjectPath.utf16(), - kInterface.utf16() - ).isValid(); - + static const auto Available = !GetServerInformation().empty(); return Available; #else // !TDESKTOP_DISABLE_DBUS_INTEGRATION return false; @@ -405,27 +412,21 @@ std::unique_ptr Create( #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION Manager::Private::Private(not_null manager, Type type) : _cachedUserpics(type) -, _manager(manager) -, _notificationInterface( - std::make_shared( - kService.utf16(), - kObjectPath.utf16(), - kInterface.utf16())) { +, _manager(manager) { qDBusRegisterMetaType(); - const auto specificationVersion = ParseSpecificationVersion( - GetServerInformation()); - + const auto serverInformation = GetServerInformation(); const auto capabilities = GetCapabilities(); - if (!specificationVersion.isNull()) { - LOG(("Notification daemon specification version: %1") - .arg(specificationVersion.toString())); + if (!serverInformation.empty()) { + LOG(("Notification daemon product name: %1").arg(serverInformation[0])); + LOG(("Notification daemon vendor name: %1").arg(serverInformation[1])); + LOG(("Notification daemon version: %1").arg(serverInformation[2])); + LOG(("Notification daemon specification version: %1").arg(serverInformation[3])); } - if (!capabilities.empty()) { - const auto capabilitiesString = capabilities.join(", "); - LOG(("Notification daemon capabilities: %1").arg(capabilitiesString)); + if (!capabilities.isEmpty()) { + LOG(("Notification daemon capabilities: %1").arg(capabilities.join(", "))); } } @@ -438,7 +439,6 @@ void Manager::Private::showNotification( bool hideNameAndPhoto, bool hideReplyButton) { auto notification = std::make_shared( - _notificationInterface.get(), _manager, title, subtitle, diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index 2cd5ba953..d22a02f11 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/weak_ptr.h" #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION -#include +#include #include #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -28,7 +28,6 @@ class NotificationData : public QObject { public: NotificationData( - not_null notificationInterface, const base::weak_ptr &manager, const QString &title, const QString &subtitle, @@ -43,7 +42,7 @@ public: NotificationData &operator=(NotificationData &&other) = delete; bool show(); - bool close(); + void close(); void setImage(const QString &imagePath); struct ImageData { @@ -54,7 +53,7 @@ public: }; private: - const not_null _notificationInterface; + QDBusConnection _dbusConnection; base::weak_ptr _manager; QString _title; @@ -134,7 +133,6 @@ private: Window::Notifications::CachedUserpics _cachedUserpics; base::weak_ptr _manager; - std::shared_ptr _notificationInterface; }; #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION From 7ac4c6e479e0582a950c7e32663d6b2021b81444 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 6 Mar 2020 09:55:22 +0400 Subject: [PATCH 15/43] Add mark as read feature to linux native notifications --- .../linux/notifications_manager_linux.cpp | 38 +++++++++++-------- .../linux/notifications_manager_linux.h | 2 +- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 0a50d2c2c..8a34da6fe 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -169,13 +169,9 @@ NotificationData::NotificationData( if (capabilities.contains(qsl("actions"))) { _actions << qsl("default") << QString(); - _dbusConnection.connect( - kService.utf16(), - kObjectPath.utf16(), - kInterface.utf16(), - qsl("ActionInvoked"), - this, - SLOT(notificationClicked(uint,QString))); + _actions + << qsl("mail-mark-read") + << tr::lng_context_mark_read(tr::now); if (capabilities.contains(qsl("inline-reply")) && !hideReplyButton) { _actions @@ -195,6 +191,14 @@ NotificationData::NotificationData( << qsl("mail-reply-sender") << tr::lng_notification_reply(tr::now); } + + _dbusConnection.connect( + kService.utf16(), + kObjectPath.utf16(), + kInterface.utf16(), + qsl("ActionInvoked"), + this, + SLOT(actionInvoked(uint,QString))); } if (capabilities.contains(qsl("action-icons"))) { @@ -313,19 +317,23 @@ void NotificationData::notificationClosed(uint id) { } } -void NotificationData::notificationClicked(uint id, const QString &actionId) { +void NotificationData::actionInvoked(uint id, const QString &actionName) { if (id != _notificationId) { return; } - if (actionId != qsl("default") && actionId != qsl("mail-reply-sender")) { - return; + if (actionName == qsl("default") + || actionName == qsl("mail-reply-sender")) { + const auto manager = _manager; + crl::on_main(manager, [=] { + manager->notificationActivated(_peerId, _msgId); + }); + } else if (actionName == qsl("mail-mark-read")) { + const auto manager = _manager; + crl::on_main(manager, [=] { + manager->notificationReplied(_peerId, _msgId, {}); + }); } - - const auto manager = _manager; - crl::on_main(manager, [=] { - manager->notificationActivated(_peerId, _msgId); - }); } void NotificationData::notificationReplied(uint id, const QString &text) { diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index d22a02f11..ba6bcc88f 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -68,7 +68,7 @@ private: private slots: void notificationClosed(uint id); - void notificationClicked(uint id, const QString &actionId); + void actionInvoked(uint id, const QString &actionName); void notificationReplied(uint id, const QString &text); }; From fdd431dce94439f788161a4bb8f6c44aa135d528 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 4 Mar 2020 22:21:09 +0400 Subject: [PATCH 16/43] Human-readable error for single instance logging --- Telegram/SourceFiles/core/sandbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/core/sandbox.cpp b/Telegram/SourceFiles/core/sandbox.cpp index bd43415c7..46c967b4f 100644 --- a/Telegram/SourceFiles/core/sandbox.cpp +++ b/Telegram/SourceFiles/core/sandbox.cpp @@ -274,7 +274,7 @@ void Sandbox::socketError(QLocalSocket::LocalSocketError e) { psCheckLocalSocket(_localServerName); if (!_localServer.listen(_localServerName)) { - LOG(("Failed to start listening to %1 server, error %2").arg(_localServerName).arg(int(_localServer.serverError()))); + LOG(("Failed to start listening to %1 server: %2").arg(_localServerName).arg(_localServer.errorString())); return App::quit(); } #endif // !Q_OS_WINRT From 1dc6d942cfe7681510b2df34a9123a1b078598b0 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 7 Mar 2020 02:52:12 +0400 Subject: [PATCH 17/43] Add new snap permission and layout for alsa Add audio-playback and audio-record interfaces since pulseaudio interface is deprecated --- snap/snapcraft.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 62a4f41c6..74de50313 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -14,9 +14,12 @@ apps: environment: # Use GTK3 cursor theme, icon theme and open/save file dialogs. QT_QPA_PLATFORMTHEME: gtk3 - # Wayland support is still too bad. + # The blocker is https://github.com/ubuntu/snapcraft-desktop-helpers/issues/172 DISABLE_WAYLAND: 1 plugs: + - alsa + - audio-playback + - audio-record - desktop - desktop-legacy - home @@ -44,6 +47,10 @@ plugs: target: $SNAP/data-dir/sounds default-provider: gtk-common-themes +layout: + /usr/share/alsa: + bind: $SNAP/usr/share/alsa + parts: telegram: plugin: cmake From 5927e8272c8a3ea756fb4439d1a6afa49298b823 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 7 Mar 2020 09:54:47 +0400 Subject: [PATCH 18/43] Convert TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION to runtime environment variable --- .../SourceFiles/platform/linux/specific_linux.cpp | 12 +++++++----- Telegram/cmake/telegram_options.cmake | 5 ----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 4b715d0ee..7f3e22615 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -524,18 +524,21 @@ void finish() { void RegisterCustomScheme(bool force) { #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME - auto home = getHomeDir(); + const auto home = getHomeDir(); if (home.isEmpty() || cExeName().isEmpty()) return; + static const auto disabledByEnv = qEnvironmentVariableIsSet( + "TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION"); + // don't update desktop file for alpha version or if updater is disabled - if ((cAlphaVersion() || Core::UpdaterDisabled()) && !force) + if ((cAlphaVersion() || Core::UpdaterDisabled() || disabledByEnv) + && !force) return; const auto applicationsPath = QStandardPaths::writableLocation( QStandardPaths::ApplicationsLocation) + '/'; -#ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION GenerateDesktopFile(applicationsPath, qsl("-- %u")); const auto icons = @@ -558,7 +561,6 @@ void RegisterCustomScheme(bool force) { DEBUG_LOG(("App Info: Icon copied to '%1'").arg(icon)); } } -#endif // !TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION RunShellCommand("update-desktop-database " + EscapeShell(QFile::encodeName(applicationsPath))); @@ -629,7 +631,7 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) { } void psAutoStart(bool start, bool silent) { - auto home = getHomeDir(); + const auto home = getHomeDir(); if (home.isEmpty() || cExeName().isEmpty()) return; diff --git a/Telegram/cmake/telegram_options.cmake b/Telegram/cmake/telegram_options.cmake index 9bc19e5ae..bb63d3730 100644 --- a/Telegram/cmake/telegram_options.cmake +++ b/Telegram/cmake/telegram_options.cmake @@ -7,7 +7,6 @@ option(TDESKTOP_FORCE_GTK_FILE_DIALOG "Force using GTK file dialog (Linux only)." OFF) option(TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME "Disable automatic 'tg://' URL scheme handler registration." ${DESKTOP_APP_USE_PACKAGED}) option(TDESKTOP_DISABLE_NETWORK_PROXY "Disable all code for working through Socks5 or MTProxy." OFF) -option(TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION "Disable automatic '.desktop' file generation (Linux only)." ${DESKTOP_APP_USE_PACKAGED}) option(TDESKTOP_DISABLE_GTK_INTEGRATION "Disable all code for GTK integration (Linux only)." ON) option(TDESKTOP_USE_PACKAGED_TGVOIP "Find libtgvoip using CMake instead of bundled one." ${DESKTOP_APP_USE_PACKAGED}) option(TDESKTOP_API_TEST "Use test API credentials." OFF) @@ -77,10 +76,6 @@ if (TDESKTOP_DISABLE_NETWORK_PROXY) target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_NETWORK_PROXY) endif() -if (TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION) - target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION) -endif() - if (TDESKTOP_DISABLE_GTK_INTEGRATION) target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_GTK_INTEGRATION) endif() From b66acdd0dc0edb24bcd43ec6dd2d36d642d3cac8 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 9 Mar 2020 11:11:12 +0400 Subject: [PATCH 19/43] Use ffmpeg 4.x in snap --- .github/workflows/snap.yml | 19 +++++- snap/snapcraft.yaml | 115 +++++++++++++++++++++++++++++++++---- 2 files changed, 122 insertions(+), 12 deletions(-) diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml index 53ff92d93..8a5767e58 100644 --- a/.github/workflows/snap.yml +++ b/.github/workflows/snap.yml @@ -47,6 +47,10 @@ jobs: md5cache=$(md5sum CMAKE_CACHE_KEY.txt | cut -c -32) echo ::set-env name=CMAKE_CACHE_KEY::$md5cache + awk -v RS="" -v ORS="\n\n" '/^ ffmpeg:/' snap/snapcraft.yaml > FFMPEG_CACHE_KEY.txt + md5cache=$(md5sum FFMPEG_CACHE_KEY.txt | cut -c -32) + echo ::set-env name=FFMPEG_CACHE_KEY::$md5cache + - name: CMake cache. id: cache-cmake uses: actions/cache@v1 @@ -58,6 +62,17 @@ jobs: if: steps.cache-cmake.outputs.cache-hit != 'true' run: snapcraft build --destructive-mode cmake + - name: FFmpeg cache. + id: cache-ffmpeg + uses: actions/cache@v1 + with: + path: parts/ffmpeg + key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}-${{ env.FFMPEG_CACHE_KEY }} + + - name: FFmpeg build. + if: steps.cache-ffmpeg.outputs.cache-hit != 'true' + run: snapcraft build --destructive-mode ffmpeg + - name: Telegram Desktop snap build. if: env.ONLY_CACHE == 'false' run: snapcraft --destructive-mode @@ -80,5 +95,5 @@ jobs: - name: Remove unneeded directories for cache. run: | - rm -rf parts/cmake/{build,src,ubuntu} - rm -rf parts/cmake/state/{stage,prime} + rm -rf parts/{cmake,ffmpeg}/{build,src,ubuntu} + rm -rf parts/{cmake,ffmpeg}/state/{stage,prime} diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 74de50313..51feca617 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -63,11 +63,6 @@ parts: - qtbase5-private-dev - libmapbox-variant-dev - libasound2-dev - - libavcodec-dev - - libavformat-dev - - libavutil-dev - - libswscale-dev - - libswresample-dev - libdbusmenu-qt5-dev - libhunspell-dev - liblz4-dev @@ -81,11 +76,6 @@ parts: stage-packages: - qt5-image-formats-plugins - libasound2 - - libavcodec57 - - libavformat57 - - libavutil55 - - libswscale4 - - libswresample2 - libdbusmenu-qt5-2 - libhunspell-1.6-0 - liblz4-1 @@ -126,6 +116,7 @@ parts: after: - cmake - desktop-qt5 + - ffmpeg - range-v3 - xxhash @@ -183,6 +174,110 @@ parts: - libtinfo5 prime: [-./*] + ffmpeg: + source: https://github.com/FFmpeg/FFmpeg.git + source-depth: 1 + source-branch: release/4.2 + plugin: autotools + build-packages: + - libtool + - pkg-config + - texi2html + - yasm + - libass-dev + - libfreetype6-dev + - libgpac-dev + - liblzma-dev + - libopus-dev + - libsdl1.2-dev + - libtheora-dev + - libva-dev + - libvdpau-dev + - libvorbis-dev + - libxcb1-dev + - libxcb-shm0-dev + - libxcb-xfixes0-dev + - zlib1g-dev + stage-packages: + - freeglut3 + - libass9 + - libfreetype6 + - libgpac4 + - liblzma5 + - libopus0 + - libslang2 + - libsdl1.2debian + - libtheora0 + - libva2 + - libva-drm2 + - libvdpau1 + - libvorbis0a + - libxcb1 + - libxcb-shm0 + - libxcb-xfixes0 + - zlib1g + configflags: + - --prefix=/usr + - --disable-debug + - --disable-programs + - --disable-doc + - --disable-everything + - --enable-gpl + - --enable-version3 + - --enable-libopus + - --enable-decoder=aac + - --enable-decoder=aac_latm + - --enable-decoder=aasc + - --enable-decoder=flac + - --enable-decoder=gif + - --enable-decoder=h264 + - --enable-decoder=h264_vdpau + - --enable-decoder=mp1 + - --enable-decoder=mp1float + - --enable-decoder=mp2 + - --enable-decoder=mp2float + - --enable-decoder=mp3 + - --enable-decoder=mp3adu + - --enable-decoder=mp3adufloat + - --enable-decoder=mp3float + - --enable-decoder=mp3on4 + - --enable-decoder=mp3on4float + - --enable-decoder=mpeg4 + - --enable-decoder=mpeg4_vdpau + - --enable-decoder=msmpeg4v2 + - --enable-decoder=msmpeg4v3 + - --enable-decoder=opus + - --enable-decoder=vorbis + - --enable-decoder=wavpack + - --enable-decoder=wmalossless + - --enable-decoder=wmapro + - --enable-decoder=wmav1 + - --enable-decoder=wmav2 + - --enable-decoder=wmavoice + - --enable-encoder=libopus + - --enable-hwaccel=h264_vaapi + - --enable-hwaccel=h264_vdpau + - --enable-hwaccel=mpeg4_vaapi + - --enable-hwaccel=mpeg4_vdpau + - --enable-parser=aac + - --enable-parser=aac_latm + - --enable-parser=flac + - --enable-parser=h264 + - --enable-parser=mpeg4video + - --enable-parser=mpegaudio + - --enable-parser=opus + - --enable-parser=vorbis + - --enable-demuxer=aac + - --enable-demuxer=flac + - --enable-demuxer=gif + - --enable-demuxer=h264 + - --enable-demuxer=mov + - --enable-demuxer=mp3 + - --enable-demuxer=ogg + - --enable-demuxer=wav + - --enable-muxer=ogg + - --enable-muxer=opus + range-v3: source: https://github.com/ericniebler/range-v3.git source-depth: 1 From 32169fa7bd3f845173b5bffee46f31163aa1a22e Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 7 Mar 2020 09:28:28 +0400 Subject: [PATCH 20/43] Remove separate switch for GTK integration and fix condition for GTK file dialog Since it is used only for GTK file dialog and to get it by default on any static builds --- Telegram/cmake/telegram_options.cmake | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Telegram/cmake/telegram_options.cmake b/Telegram/cmake/telegram_options.cmake index bb63d3730..50b57c9c1 100644 --- a/Telegram/cmake/telegram_options.cmake +++ b/Telegram/cmake/telegram_options.cmake @@ -7,7 +7,6 @@ option(TDESKTOP_FORCE_GTK_FILE_DIALOG "Force using GTK file dialog (Linux only)." OFF) option(TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME "Disable automatic 'tg://' URL scheme handler registration." ${DESKTOP_APP_USE_PACKAGED}) option(TDESKTOP_DISABLE_NETWORK_PROXY "Disable all code for working through Socks5 or MTProxy." OFF) -option(TDESKTOP_DISABLE_GTK_INTEGRATION "Disable all code for GTK integration (Linux only)." ON) option(TDESKTOP_USE_PACKAGED_TGVOIP "Find libtgvoip using CMake instead of bundled one." ${DESKTOP_APP_USE_PACKAGED}) option(TDESKTOP_API_TEST "Use test API credentials." OFF) set(TDESKTOP_API_ID "0" CACHE STRING "Provide 'api_id' for the Telegram API access.") @@ -42,12 +41,12 @@ if (TDESKTOP_API_ID STREQUAL "0" OR TDESKTOP_API_HASH STREQUAL "") " ") endif() -if (NOT DESKTOP_APP_SPECIAL_TARGET STREQUAL "") +if (NOT DESKTOP_APP_USE_PACKAGED) set(TDESKTOP_FORCE_GTK_FILE_DIALOG ON) endif() -if (TDESKTOP_FORCE_GTK_FILE_DIALOG) - set(TDESKTOP_DISABLE_GTK_INTEGRATION OFF) +if (NOT TDESKTOP_FORCE_GTK_FILE_DIALOG) + set(TDESKTOP_DISABLE_GTK_INTEGRATION ON) endif() if (DESKTOP_APP_DISABLE_SPELLCHECK) From fdd841e5c4308f845123c066d996fe62c9be51a3 Mon Sep 17 00:00:00 2001 From: Av Date: Tue, 3 Mar 2020 11:47:49 -0800 Subject: [PATCH 21/43] Increase media cache memory size to solve flicker issue When displaying large numbers of GIFs, Telegram's Media Cache runs out of size and unloads items that are still being displayed. --- Telegram/SourceFiles/data/data_document.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index 56b6d5ff6..9603ba960 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -42,7 +42,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace { -constexpr auto kMemoryForCache = 32 * 1024 * 1024; +// Updated Mar 3, 2020: Increase the size of the memory cache for media, to prevent items still being displayed from being unloaded. +constexpr auto kMemoryForCache = 128 * 1024 * 1024; // was 32, updated to 128 const auto kAnimatedStickerDimensions = QSize(512, 512); using FilePathResolve = DocumentData::FilePathResolve; From afc902a5cb4eb95ee6e436cde6aa8d3e3c8f8916 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 2 Mar 2020 11:31:04 +0400 Subject: [PATCH 22/43] Don't set device explicitly when capturing Also update openal to 1.20.1 since it has pulseaudio.allow-moves by default Fix playback devices enumerating --- .github/workflows/linux.yml | 2 +- .../SourceFiles/media/audio/media_audio.cpp | 4 ++-- .../media/audio/media_audio_capture.cpp | 18 ++++++------------ docs/building-cmake.md | 2 +- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index f659e9e22..c9e9878ee 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -323,7 +323,7 @@ jobs: run: | cd $LibrariesPath - git clone -b openal-soft-1.19.1 --depth=1 $GIT/kcat/openal-soft.git + git clone -b openal-soft-1.20.1 --depth=1 $GIT/kcat/openal-soft.git cd openal-soft/build cmake -D LIBTYPE:STRING=STATIC .. make -j$(nproc) diff --git a/Telegram/SourceFiles/media/audio/media_audio.cpp b/Telegram/SourceFiles/media/audio/media_audio.cpp index c1234c4da..2ff60a1be 100644 --- a/Telegram/SourceFiles/media/audio/media_audio.cpp +++ b/Telegram/SourceFiles/media/audio/media_audio.cpp @@ -82,7 +82,7 @@ bool PlaybackErrorHappened() { void EnumeratePlaybackDevices() { auto deviceNames = QStringList(); - auto devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER); + auto devices = alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER); Assert(devices != nullptr); while (*devices != 0) { auto deviceName8Bit = QByteArray(devices); @@ -92,7 +92,7 @@ void EnumeratePlaybackDevices() { } LOG(("Audio Playback Devices: %1").arg(deviceNames.join(';'))); - if (auto device = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER)) { + if (auto device = alcGetString(nullptr, ALC_DEFAULT_ALL_DEVICES_SPECIFIER)) { LOG(("Audio Playback Default Device: %1").arg(QString::fromLocal8Bit(device))); } else { LOG(("Audio Playback Default Device: (null)")); diff --git a/Telegram/SourceFiles/media/audio/media_audio_capture.cpp b/Telegram/SourceFiles/media/audio/media_audio_capture.cpp index c3b0dbd68..06b4ae259 100644 --- a/Telegram/SourceFiles/media/audio/media_audio_capture.cpp +++ b/Telegram/SourceFiles/media/audio/media_audio_capture.cpp @@ -62,16 +62,12 @@ Instance::Instance() : _inner(new Inner(&_thread)) { void Instance::check() { _available = false; - if (auto defaultDevice = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)) { - if (auto device = alcCaptureOpenDevice(defaultDevice, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5)) { - auto error = ErrorHappened(device); - alcCaptureCloseDevice(device); - _available = !error; - } else { - LOG(("Audio Error: Could not open capture device!")); - } + if (auto device = alcCaptureOpenDevice(nullptr, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5)) { + auto error = ErrorHappened(device); + alcCaptureCloseDevice(device); + _available = !error; } else { - LOG(("Audio Error: No capture device found!")); + LOG(("Audio Error: Could not open capture device!")); } } @@ -177,9 +173,7 @@ void Instance::Inner::onInit() { void Instance::Inner::onStart() { // Start OpenAL Capture - const ALCchar *dName = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); - DEBUG_LOG(("Audio Info: Capture device name '%1'").arg(dName)); - d->device = alcCaptureOpenDevice(dName, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5); + d->device = alcCaptureOpenDevice(nullptr, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5); if (!d->device) { LOG(("Audio Error: capture device not present!")); emit error(); diff --git a/docs/building-cmake.md b/docs/building-cmake.md index 65ede9bfc..0583ae4f3 100644 --- a/docs/building-cmake.md +++ b/docs/building-cmake.md @@ -198,7 +198,7 @@ Go to ***BuildPath*** and run git clone git://repo.or.cz/openal-soft.git cd openal-soft - git checkout openal-soft-1.19.1 + git checkout openal-soft-1.20.1 cd build if [ `uname -p` == "i686" ]; then cmake -D LIBTYPE:STRING=STATIC -D ALSOFT_UTILS:BOOL=OFF .. From ba5d9eda2d5e28227a15eb4b41deae91e8f5bbf9 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 10 Mar 2020 12:36:06 +0400 Subject: [PATCH 23/43] Minimize dbus requests --- .../linux/notifications_manager_linux.cpp | 55 +++++++++++++++---- .../platform/linux/specific_linux.cpp | 20 ++++++- 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 8a34da6fe..6b9057437 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -31,7 +31,9 @@ constexpr auto kObjectPath = "/org/freedesktop/Notifications"_cs; constexpr auto kInterface = kService; constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; -std::vector GetServerInformation() { +bool InhibitedNotSupported = false; + +std::vector ComputeServerInformation() { std::vector serverInformation; const auto message = QDBusMessage::createMethodCall( @@ -58,7 +60,12 @@ std::vector GetServerInformation() { return serverInformation; } -QStringList GetCapabilities() { +std::vector GetServerInformation() { + static const auto ServerInformation = ComputeServerInformation(); + return ServerInformation; +} + +QStringList ComputeCapabilities() { const auto message = QDBusMessage::createMethodCall( kService.utf16(), kObjectPath.utf16(), @@ -77,6 +84,11 @@ QStringList GetCapabilities() { return {}; } +QStringList GetCapabilities() { + static const auto Capabilities = ComputeCapabilities(); + return Capabilities; +} + bool Inhibited() { auto message = QDBusMessage::createMethodCall( kService.utf16(), @@ -92,9 +104,20 @@ bool Inhibited() { const QDBusReply reply = QDBusConnection::sessionBus().call( message); + constexpr auto notSupportedErrors = { + QDBusError::ServiceUnknown, + QDBusError::InvalidArgs, + }; + if (reply.isValid()) { return reply.value().toBool(); - } else if (reply.error().type() != QDBusError::InvalidArgs) { + } else if (ranges::contains(notSupportedErrors, reply.error().type())) { + InhibitedNotSupported = true; + } else { + if (reply.error().type() == QDBusError::AccessDenied) { + InhibitedNotSupported = true; + } + LOG(("Native notification error: %1").arg(reply.error().message())); } @@ -380,7 +403,9 @@ const QDBusArgument &operator>>( bool SkipAudio() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - if (Supported()) { + if (Supported() + && GetCapabilities().contains(qsl("inhibitions")) + && !InhibitedNotSupported) { return Inhibited(); } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -390,7 +415,9 @@ bool SkipAudio() { bool SkipToast() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - if (Supported()) { + if (Supported() + && GetCapabilities().contains(qsl("inhibitions")) + && !InhibitedNotSupported) { return Inhibited(); } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION @@ -427,14 +454,22 @@ Manager::Private::Private(not_null manager, Type type) const auto capabilities = GetCapabilities(); if (!serverInformation.empty()) { - LOG(("Notification daemon product name: %1").arg(serverInformation[0])); - LOG(("Notification daemon vendor name: %1").arg(serverInformation[1])); - LOG(("Notification daemon version: %1").arg(serverInformation[2])); - LOG(("Notification daemon specification version: %1").arg(serverInformation[3])); + LOG(("Notification daemon product name: %1") + .arg(serverInformation[0])); + + LOG(("Notification daemon vendor name: %1") + .arg(serverInformation[1])); + + LOG(("Notification daemon version: %1") + .arg(serverInformation[2])); + + LOG(("Notification daemon specification version: %1") + .arg(serverInformation[3])); } if (!capabilities.isEmpty()) { - LOG(("Notification daemon capabilities: %1").arg(capabilities.join(", "))); + LOG(("Notification daemon capabilities: %1") + .arg(capabilities.join(", "))); } } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 7f3e22615..b9c5d3f0b 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -359,6 +359,12 @@ std::optional LastUserInputTime() { // TODO: a fallback pure-X11 implementation, this one covers only major DEs on X11 and Wayland // an example: https://stackoverflow.com/q/9049087 #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + static auto NotSupported = false; + + if (NotSupported) { + return std::nullopt; + } + static const auto message = QDBusMessage::createMethodCall( qsl("org.freedesktop.ScreenSaver"), qsl("/org/freedesktop/ScreenSaver"), @@ -368,10 +374,20 @@ std::optional LastUserInputTime() { const QDBusReply reply = QDBusConnection::sessionBus().call( message); + constexpr auto notSupportedErrors = { + QDBusError::ServiceUnknown, + QDBusError::NotSupported, + }; + if (reply.isValid()) { return (crl::now() - static_cast(reply.value())); - } else if (reply.error().type() != QDBusError::ServiceUnknown - && reply.error().type() != QDBusError::NotSupported) { + } else if (ranges::contains(notSupportedErrors, reply.error().type())) { + NotSupported = true; + } else { + if (reply.error().type() == QDBusError::AccessDenied) { + NotSupported = true; + } + LOG(("Unable to get last user input time: %1: %2") .arg(reply.error().name()) .arg(reply.error().message())); From 75d54adfceb81ce8ee83417dff253b145abe4edd Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 12 Mar 2020 16:49:04 +0400 Subject: [PATCH 24/43] Add TDESKTOP_FORCE_PANEL_ICON environment variable for possibility to use system icon even if it is not detected --- Telegram/SourceFiles/platform/linux/main_window_linux.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 8e7e9051b..35d3a6e8a 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -37,6 +37,7 @@ namespace Platform { namespace { constexpr auto kDisableTrayCounter = "TDESKTOP_DISABLE_TRAY_COUNTER"_cs; +constexpr auto kForcePanelIcon = "TDESKTOP_FORCE_PANEL_ICON"_cs; constexpr auto kPanelTrayIconName = "telegram-panel"_cs; constexpr auto kMutePanelTrayIconName = "telegram-mute-panel"_cs; constexpr auto kAttentionPanelTrayIconName = "telegram-attention-panel"_cs; @@ -356,7 +357,8 @@ void MainWindow::setSNITrayIcon(int counter, bool muted, bool firstShow) { const auto iconName = GetTrayIconName(counter, muted); if (qEnvironmentVariableIsSet(kDisableTrayCounter.utf8()) - && !iconName.isEmpty()) { + && (!iconName.isEmpty() + || qEnvironmentVariableIsSet(kForcePanelIcon.utf8()))) { if (_sniTrayIcon->iconName() == iconName) { return; } From aedb6206a5972aba31df19c4f2137bdaa82fd0f3 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 12 Mar 2020 09:52:29 +0400 Subject: [PATCH 25/43] Set a list of architectures that snap package runs on --- snap/snapcraft.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 51feca617..442476f9c 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -6,6 +6,13 @@ base: core18 grade: stable confinement: strict +architectures: + - build-on: amd64 + - build-on: i386 + - build-on: arm64 + - build-on: armhf + - build-on: ppc64el + apps: telegram-desktop: command: bin/desktop-launch telegram-desktop From 229d15c4921046f9596ee3f71148c401eef8c39c Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 12 Mar 2020 13:14:26 +0400 Subject: [PATCH 26/43] Add tag `launchable` into linux appdata --- Telegram/CMakeLists.txt | 3 ++- ...egramdesktop.appdata.xml => telegramdesktop.appdata.xml.in} | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) rename lib/xdg/{telegramdesktop.appdata.xml => telegramdesktop.appdata.xml.in} (97%) diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index a760408dd..1a3e0bc15 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1211,6 +1211,7 @@ endif() if (LINUX AND DESKTOP_APP_USE_PACKAGED) include(GNUInstallDirs) + configure_file("../lib/xdg/telegramdesktop.appdata.xml.in" "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.appdata.xml" @ONLY) install(TARGETS Telegram RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}") install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "telegram.png") install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "telegram.png") @@ -1220,5 +1221,5 @@ if (LINUX AND DESKTOP_APP_USE_PACKAGED) install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "telegram.png") install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "telegram.png") install(FILES "../lib/xdg/telegramdesktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.desktop") - install(FILES "../lib/xdg/telegramdesktop.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.appdata.xml") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.appdata.xml") endif() diff --git a/lib/xdg/telegramdesktop.appdata.xml b/lib/xdg/telegramdesktop.appdata.xml.in similarity index 97% rename from lib/xdg/telegramdesktop.appdata.xml rename to lib/xdg/telegramdesktop.appdata.xml.in index 9eedae55c..bd5bf53e3 100644 --- a/lib/xdg/telegramdesktop.appdata.xml +++ b/lib/xdg/telegramdesktop.appdata.xml.in @@ -62,6 +62,7 @@ none none + @TDESKTOP_LAUNCHER_BASENAME@.desktop telegram-desktop From fda8a38bfc16aecd8721b5e560ef60c8447b157b Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 12 Mar 2020 14:33:01 +0400 Subject: [PATCH 27/43] Set application display name --- Telegram/SourceFiles/core/launcher.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Telegram/SourceFiles/core/launcher.cpp b/Telegram/SourceFiles/core/launcher.cpp index 19d9c3bbf..dceee3429 100644 --- a/Telegram/SourceFiles/core/launcher.cpp +++ b/Telegram/SourceFiles/core/launcher.cpp @@ -247,6 +247,7 @@ void Launcher::init() { prepareSettings(); QApplication::setApplicationName(qsl("TelegramDesktop")); + QApplication::setApplicationDisplayName(AppName.utf16()); #if defined(Q_OS_LINUX) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) QApplication::setDesktopFileName(Platform::GetLauncherFilename()); From fb99b9b547dadaab76a42f082987233e93a31319 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 11 Mar 2020 20:09:37 +0400 Subject: [PATCH 28/43] Disable neon in ffmpeg to fix videos and animated stickers on arm architectures --- Telegram/Patches/ffmpeg.diff | 225 +++++++++++++++++++++++++++++++++++ snap/snapcraft.yaml | 11 ++ 2 files changed, 236 insertions(+) create mode 100644 Telegram/Patches/ffmpeg.diff diff --git a/Telegram/Patches/ffmpeg.diff b/Telegram/Patches/ffmpeg.diff new file mode 100644 index 000000000..b5ab619fe --- /dev/null +++ b/Telegram/Patches/ffmpeg.diff @@ -0,0 +1,225 @@ +diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile +index 00f93bf59f..52da7036f3 100644 +--- a/libavcodec/aarch64/Makefile ++++ b/libavcodec/aarch64/Makefile +@@ -6,6 +6,7 @@ OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o + OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o + OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o + OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.o ++OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o + OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_init.o + OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o + OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp_init.o +@@ -21,6 +22,7 @@ OBJS-$(CONFIG_VC1DSP) += aarch64/vc1dsp_init_aarch64.o + OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_init.o + OBJS-$(CONFIG_VP9_DECODER) += aarch64/vp9dsp_init_10bpp_aarch64.o \ + aarch64/vp9dsp_init_12bpp_aarch64.o \ ++ aarch64/vp9mc_aarch64.o \ + aarch64/vp9dsp_init_aarch64.o + + # ARMv8 optimizations +@@ -41,8 +43,7 @@ NEON-OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_neon.o + NEON-OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_neon.o \ + aarch64/hpeldsp_neon.o + NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o +-NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o \ +- aarch64/simple_idct_neon.o ++NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/simple_idct_neon.o + NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o + NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o + NEON-OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_neon.o +diff --git a/libavcodec/aarch64/idctdsp_init_aarch64.c b/libavcodec/aarch64/idctdsp_init_aarch64.c +index 0406e60830..742a3372e3 100644 +--- a/libavcodec/aarch64/idctdsp_init_aarch64.c ++++ b/libavcodec/aarch64/idctdsp_init_aarch64.c +@@ -21,6 +21,8 @@ + */ + + #include "libavutil/attributes.h" ++#include "libavutil/cpu.h" ++#include "libavutil/arm/cpu.h" + #include "libavcodec/avcodec.h" + #include "libavcodec/idctdsp.h" + #include "idct.h" +@@ -28,7 +30,9 @@ + av_cold void ff_idctdsp_init_aarch64(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) + { +- if (!avctx->lowres && !high_bit_depth) { ++ int cpu_flags = av_get_cpu_flags(); ++ ++ if (have_neon(cpu_flags) && !avctx->lowres && !high_bit_depth) { + if (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEAUTO || + avctx->idct_algo == FF_IDCT_SIMPLENEON) { +diff --git a/libavcodec/aarch64/vp9mc_16bpp_neon.S b/libavcodec/aarch64/vp9mc_16bpp_neon.S +index cac6428709..53b372c262 100644 +--- a/libavcodec/aarch64/vp9mc_16bpp_neon.S ++++ b/libavcodec/aarch64/vp9mc_16bpp_neon.S +@@ -25,31 +25,6 @@ + // const uint8_t *ref, ptrdiff_t ref_stride, + // int h, int mx, int my); + +-function ff_vp9_copy128_aarch64, export=1 +-1: +- ldp x5, x6, [x2] +- ldp x7, x8, [x2, #16] +- stp x5, x6, [x0] +- ldp x9, x10, [x2, #32] +- stp x7, x8, [x0, #16] +- subs w4, w4, #1 +- ldp x11, x12, [x2, #48] +- stp x9, x10, [x0, #32] +- stp x11, x12, [x0, #48] +- ldp x5, x6, [x2, #64] +- ldp x7, x8, [x2, #80] +- stp x5, x6, [x0, #64] +- ldp x9, x10, [x2, #96] +- stp x7, x8, [x0, #80] +- ldp x11, x12, [x2, #112] +- stp x9, x10, [x0, #96] +- stp x11, x12, [x0, #112] +- add x2, x2, x3 +- add x0, x0, x1 +- b.ne 1b +- ret +-endfunc +- + function ff_vp9_avg64_16_neon, export=1 + mov x5, x0 + sub x1, x1, #64 +diff --git a/libavcodec/aarch64/vp9mc_aarch64.S b/libavcodec/aarch64/vp9mc_aarch64.S +new file mode 100644 +index 0000000000..f17a8cf04a +--- /dev/null ++++ b/libavcodec/aarch64/vp9mc_aarch64.S +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (c) 2016 Google Inc. ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "libavutil/aarch64/asm.S" ++ ++// All public functions in this file have the following signature: ++// typedef void (*vp9_mc_func)(uint8_t *dst, ptrdiff_t dst_stride, ++// const uint8_t *ref, ptrdiff_t ref_stride, ++// int h, int mx, int my); ++ ++function ff_vp9_copy128_aarch64, export=1 ++1: ++ ldp x5, x6, [x2] ++ ldp x7, x8, [x2, #16] ++ stp x5, x6, [x0] ++ ldp x9, x10, [x2, #32] ++ stp x7, x8, [x0, #16] ++ subs w4, w4, #1 ++ ldp x11, x12, [x2, #48] ++ stp x9, x10, [x0, #32] ++ stp x11, x12, [x0, #48] ++ ldp x5, x6, [x2, #64] ++ ldp x7, x8, [x2, #80] ++ stp x5, x6, [x0, #64] ++ ldp x9, x10, [x2, #96] ++ stp x7, x8, [x0, #80] ++ ldp x11, x12, [x2, #112] ++ stp x9, x10, [x0, #96] ++ stp x11, x12, [x0, #112] ++ add x2, x2, x3 ++ add x0, x0, x1 ++ b.ne 1b ++ ret ++endfunc ++ ++function ff_vp9_copy64_aarch64, export=1 ++1: ++ ldp x5, x6, [x2] ++ ldp x7, x8, [x2, #16] ++ stp x5, x6, [x0] ++ ldp x9, x10, [x2, #32] ++ stp x7, x8, [x0, #16] ++ subs w4, w4, #1 ++ ldp x11, x12, [x2, #48] ++ stp x9, x10, [x0, #32] ++ stp x11, x12, [x0, #48] ++ add x2, x2, x3 ++ add x0, x0, x1 ++ b.ne 1b ++ ret ++endfunc ++ ++function ff_vp9_copy32_aarch64, export=1 ++1: ++ ldp x5, x6, [x2] ++ ldp x7, x8, [x2, #16] ++ stp x5, x6, [x0] ++ subs w4, w4, #1 ++ stp x7, x8, [x0, #16] ++ add x2, x2, x3 ++ add x0, x0, x1 ++ b.ne 1b ++ ret ++endfunc +diff --git a/libavcodec/aarch64/vp9mc_neon.S b/libavcodec/aarch64/vp9mc_neon.S +index f67624ca04..abf2bae9db 100644 +--- a/libavcodec/aarch64/vp9mc_neon.S ++++ b/libavcodec/aarch64/vp9mc_neon.S +@@ -25,23 +25,6 @@ + // const uint8_t *ref, ptrdiff_t ref_stride, + // int h, int mx, int my); + +-function ff_vp9_copy64_aarch64, export=1 +-1: +- ldp x5, x6, [x2] +- ldp x7, x8, [x2, #16] +- stp x5, x6, [x0] +- ldp x9, x10, [x2, #32] +- stp x7, x8, [x0, #16] +- subs w4, w4, #1 +- ldp x11, x12, [x2, #48] +- stp x9, x10, [x0, #32] +- stp x11, x12, [x0, #48] +- add x2, x2, x3 +- add x0, x0, x1 +- b.ne 1b +- ret +-endfunc +- + function ff_vp9_avg64_neon, export=1 + mov x5, x0 + 1: +@@ -64,19 +47,6 @@ function ff_vp9_avg64_neon, export=1 + ret + endfunc + +-function ff_vp9_copy32_aarch64, export=1 +-1: +- ldp x5, x6, [x2] +- ldp x7, x8, [x2, #16] +- stp x5, x6, [x0] +- subs w4, w4, #1 +- stp x7, x8, [x0, #16] +- add x2, x2, x3 +- add x0, x0, x1 +- b.ne 1b +- ret +-endfunc +- + function ff_vp9_avg32_neon, export=1 + 1: + ld1 {v2.16b, v3.16b}, [x2], x3 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 442476f9c..a15b99cb0 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -127,6 +127,11 @@ parts: - range-v3 - xxhash + patches: + plugin: dump + source: Telegram/Patches + prime: [-./*] + desktop-qt5: source: https://github.com/ubuntu/snapcraft-desktop-helpers.git source-subdir: qt @@ -229,6 +234,7 @@ parts: - --disable-programs - --disable-doc - --disable-everything + - --disable-neon - --enable-gpl - --enable-version3 - --enable-libopus @@ -284,6 +290,11 @@ parts: - --enable-demuxer=wav - --enable-muxer=ogg - --enable-muxer=opus + override-pull: | + snapcraftctl pull + patch -p1 < "$SNAPCRAFT_STAGE/ffmpeg.diff" + after: + - patches range-v3: source: https://github.com/ericniebler/range-v3.git From cd33d855a474f881783ee114f08d1759a371810f Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Fri, 13 Mar 2020 17:54:54 +0400 Subject: [PATCH 29/43] Update openal to fix 2x sound speed in snap --- snap/snapcraft.yaml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index a15b99cb0..1c8fb4824 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -75,7 +75,6 @@ parts: - liblz4-dev - liblzma-dev - libminizip-dev - - libopenal-dev - libopus-dev - libpulse-dev - libssl-dev @@ -88,7 +87,6 @@ parts: - liblz4-1 - liblzma5 - libminizip1 - - libopenal1 - libopus0 - libpulse0 - libssl1.1 @@ -124,6 +122,7 @@ parts: - cmake - desktop-qt5 - ffmpeg + - openal - range-v3 - xxhash @@ -296,6 +295,28 @@ parts: after: - patches + openal: + source: https://github.com/kcat/openal-soft.git + source-depth: 1 + source-tag: openal-soft-1.20.1 + plugin: cmake + build-packages: + - libasound2-dev + - libpulse-dev + - libsndio-dev + - portaudio19-dev + stage-packages: + - libasound2 + - libpulse0 + - libportaudio2 + - libsndio6.1 + configflags: + - -DCMAKE_BUILD_TYPE=Release + - -DALSOFT_EXAMPLES=OFF + - -DALSOFT_TESTS=OFF + - -DALSOFT_UTILS=OFF + - -DALSOFT_CONFIG=OFF + range-v3: source: https://github.com/ericniebler/range-v3.git source-depth: 1 From 854bc9f84a822fd1edfaffee34f8e6913e0cdf9a Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 3 Mar 2020 11:21:08 +0400 Subject: [PATCH 30/43] Fix blurred thumbnails in albums. Regression was introduced in dc146cb1fe. Once again fixes #6332. --- Telegram/SourceFiles/history/view/media/history_view_gif.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 6c3c3bdd8..db3296bc1 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -1130,7 +1130,7 @@ void Gif::validateGroupedCache( const auto height = geometry.height(); const auto options = Option::Smooth | Option::RoundedLarge - | (blur ? Option(0) : Option::Blurred) + | (blur ? Option::Blurred : Option(0)) | ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None) | ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None) | ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None) From 1df1b9fb53783b559af4961d7f25dcc1ac79c1e3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 4 Mar 2020 13:19:57 +0400 Subject: [PATCH 31/43] Fix build with external minizip. --- CMakeLists.txt | 3 +++ Telegram/CMakeLists.txt | 1 + Telegram/SourceFiles/mtproto/details/mtproto_dump_to_text.cpp | 3 ++- cmake | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d427ad059..645d886a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,9 @@ project(Telegram ) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Telegram) +get_filename_component(third_party_loc "Telegram/ThirdParty" REALPATH) +get_filename_component(submodules_loc "Telegram" REALPATH) + include(cmake/variables.cmake) include(cmake/nice_target_sources.cmake) include(cmake/target_link_static_libraries.cmake) diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 1a3e0bc15..b7be40f6b 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -94,6 +94,7 @@ PRIVATE desktop-app::external_lz4 desktop-app::external_rlottie desktop-app::external_zlib + desktop-app::external_minizip desktop-app::external_qt desktop-app::external_qr_code_generator desktop-app::external_crash_reports diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_dump_to_text.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_dump_to_text.cpp index 2ec424f6c..088fc015a 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_dump_to_text.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_dump_to_text.cpp @@ -7,10 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/details/mtproto_dump_to_text.h" -#include "base/zlib_help.h" #include "scheme-dump_to_text.h" #include "scheme.h" +#include "zlib.h" + namespace MTP::details { bool DumpToTextCore(DumpToTextBuffer &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons) { diff --git a/cmake b/cmake index 81e27ccc0..ce1b017f3 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 81e27ccc0e7bf27405569ce98582860dfc9ea9bb +Subproject commit ce1b017f3527c3bfc8283eaf2439ed0eb72ecd8b From 14aa45516412a70c9a7b487872b5c0a96936cd49 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 6 Mar 2020 13:49:39 +0400 Subject: [PATCH 32/43] Fix freeze in complex file location saving. Fixes #6986. --- Telegram/SourceFiles/storage/localstorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index cac8a7bb3..16dc9627e 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -3158,7 +3158,7 @@ void writeFileLocation(MediaKey location, const FileLocation &local) { return; } if (i.value().first != location) { - for (FileLocations::iterator j = _fileLocations.find(i.value().first), e = _fileLocations.end(); (j != e) && (j.key() == i.value().first);) { + for (FileLocations::iterator j = _fileLocations.find(i.value().first), e = _fileLocations.end(); (j != e) && (j.key() == i.value().first); ++j) { if (j.value() == i.value().second) { _fileLocations.erase(j); break; From 07eab8555a0abbd62f615fa291f1d79e848f060e Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 6 Mar 2020 15:07:24 +0400 Subject: [PATCH 33/43] Fix crash in lottie animation destroy-on-init. --- Telegram/SourceFiles/history/history_widget.cpp | 4 +++- Telegram/lib_lottie | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 0abfd9ddd..7514da8b3 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -5106,6 +5106,8 @@ int HistoryWidget::countInitialScrollTop() { } void HistoryWidget::createUnreadBarIfBelowVisibleArea(int withScrollTop) { + Expects(_history != nullptr); + if (_history->unreadBar()) { return; } @@ -5227,7 +5229,7 @@ void HistoryWidget::updateHistoryGeometry( newScrollTop = countInitialScrollTop(); _historyInited = true; _scrollToAnimation.stop(); - } else if (wasAtBottom && !loadedDown) { + } else if (wasAtBottom && !loadedDown && !_history->unreadBar()) { newScrollTop = countAutomaticScrollTop(); } else { newScrollTop = std::min( diff --git a/Telegram/lib_lottie b/Telegram/lib_lottie index 17b6a6d53..0f6c9f4ac 160000 --- a/Telegram/lib_lottie +++ b/Telegram/lib_lottie @@ -1 +1 @@ -Subproject commit 17b6a6d53252b3e3ff02b113e352c152bd697896 +Subproject commit 0f6c9f4acbdc2412a1a941b4ee96b150589b8369 From 6bf3dd10c11d737481d134954361c0dd433917ba Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 13 Mar 2020 12:07:05 +0400 Subject: [PATCH 34/43] Make checked read of sticker sets order. In case local data is corrupted previously it lead to OOM crash. --- Telegram/SourceFiles/storage/localstorage.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 16dc9627e..d44fc2d25 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -3673,7 +3673,23 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, // Read orders of installed and featured stickers. if (outOrder) { - stickers.stream >> *outOrder; + auto outOrderCount = quint32(); + stickers.stream >> outOrderCount; + if (!_checkStreamStatus(stickers.stream) + || outOrderCount < 0 + || outOrderCount > 1000) { + return failed(); + } + outOrder->reserve(outOrderCount); + for (auto i = 0; i != outOrderCount; ++i) { + auto value = uint64(); + stickers.stream >> value; + if (!_checkStreamStatus(stickers.stream)) { + outOrder->clear(); + return failed(); + } + outOrder->push_back(value); + } } if (!_checkStreamStatus(stickers.stream)) { return failed(); From 95d8bb01ac3867bc6f19b59dc47d1b2cd729bf6e Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 12 Mar 2020 12:12:03 +0300 Subject: [PATCH 35/43] Guarded paletteChanged handling in touchbar's PinnedDialogButton. --- Telegram/SourceFiles/platform/mac/mac_touchbar.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm index 4758605c4..e4b5f70ce 100644 --- a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm +++ b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm @@ -481,6 +481,8 @@ void AppendEmojiPacks(std::vector &to) { @implementation PinnedDialogButton { rpl::lifetime _lifetime; rpl::lifetime _peerChangedLifetime; + base::has_weak_ptr _guard; + bool isWaitingUserpicLoad; } @@ -518,7 +520,7 @@ void AppendEmojiPacks(std::vector &to) { ) | rpl::filter([](const Window::Theme::BackgroundUpdate &update) { return update.paletteChanged(); }) | rpl::start_with_next([=] { - crl::on_main([=] { + crl::on_main(&_guard, [=] { if (_number <= kSavedMessagesId || UseEmptyUserpic(_peer)) { [self updateUserpic]; } else if (_peer From 084b9ce4ded11533384823f902511cd3f609434d Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 13 Mar 2020 22:56:50 +0400 Subject: [PATCH 36/43] Update lib_spellcheck. --- Telegram/lib_spellcheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Telegram/lib_spellcheck b/Telegram/lib_spellcheck index dbb92ddbe..25f44d999 160000 --- a/Telegram/lib_spellcheck +++ b/Telegram/lib_spellcheck @@ -1 +1 @@ -Subproject commit dbb92ddbef82988d426ef7a0ffa40a698cdc3fd3 +Subproject commit 25f44d99915101e7a832cb38bd9b2cee47508c94 From 1492571232596c55544203f3183ae094aefa0485 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 13 Mar 2020 23:14:23 +0400 Subject: [PATCH 37/43] Fix members dropdown and mention autocomplete. Fixes #7345. --- Telegram/SourceFiles/apiwrap.cpp | 3 ++- .../chat_helpers/field_autocomplete.cpp | 5 ++--- Telegram/SourceFiles/data/data_channel.cpp | 14 ++++++++++++++ Telegram/SourceFiles/data/data_channel.h | 16 ++-------------- .../history/view/history_view_top_bar_widget.cpp | 2 +- .../profile/profile_block_group_members.cpp | 2 +- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index a0feaa15b..5dbea9760 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1503,7 +1503,8 @@ void ApiWrap::applyLastParticipantsList( channel->mgInfo->lastAdmins.clear(); channel->mgInfo->lastRestricted.clear(); channel->mgInfo->lastParticipants.clear(); - channel->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate; + channel->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate + | MegagroupInfo::LastParticipantsOnceReceived; auto botStatus = channel->mgInfo->botStatus; const auto emptyAdminRights = MTP_chatAdminRights(MTP_flags(0)); diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index 3f4186ddf..b000c917a 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -206,8 +206,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) { if (_chat) { maxListSize += (_chat->participants.empty() ? _chat->lastAuthors.size() : _chat->participants.size()); } else if (_channel && _channel->isMegagroup()) { - if (_channel->mgInfo->lastParticipants.empty() || _channel->lastParticipantsCountOutdated()) { - } else { + if (!_channel->lastParticipantsRequestNeeded()) { maxListSize += _channel->mgInfo->lastParticipants.size(); } } @@ -274,7 +273,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) { } } else if (_channel && _channel->isMegagroup()) { QMultiMap ordered; - if (_channel->mgInfo->lastParticipants.empty() || _channel->lastParticipantsCountOutdated()) { + if (_channel->lastParticipantsRequestNeeded()) { Auth().api().requestLastParticipants(_channel); } else { mrows.reserve(mrows.size() + _channel->mgInfo->lastParticipants.size()); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index f81a767cc..7c8755f69 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -340,6 +340,20 @@ bool ChannelData::isGroupAdmin(not_null user) const { return false; } +bool ChannelData::lastParticipantsRequestNeeded() const { + if (!mgInfo) { + return false; + } else if (mgInfo->lastParticipantsCount == membersCount()) { + mgInfo->lastParticipantsStatus + &= ~MegagroupInfo::LastParticipantsCountOutdated; + } + return mgInfo->lastParticipants.empty() + || !(mgInfo->lastParticipantsStatus + & MegagroupInfo::LastParticipantsOnceReceived) + || (mgInfo->lastParticipantsStatus + & MegagroupInfo::LastParticipantsCountOutdated); +} + auto ChannelData::unavailableReasons() const -> const std::vector & { return _unavailableReasons; diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index df583c286..78c360f17 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -73,6 +73,7 @@ public: enum LastParticipantsStatus { LastParticipantsUpToDate = 0x00, + LastParticipantsOnceReceived = 0x01, LastParticipantsCountOutdated = 0x02, }; mutable int lastParticipantsStatus = LastParticipantsUpToDate; @@ -219,20 +220,7 @@ public: void markForbidden(); [[nodiscard]] bool isGroupAdmin(not_null user) const; - - [[nodiscard]] bool lastParticipantsCountOutdated() const { - if (!mgInfo - || !(mgInfo->lastParticipantsStatus - & MegagroupInfo::LastParticipantsCountOutdated)) { - return false; - } - if (mgInfo->lastParticipantsCount == membersCount()) { - mgInfo->lastParticipantsStatus - &= ~MegagroupInfo::LastParticipantsCountOutdated; - return false; - } - return true; - } + [[nodiscard]] bool lastParticipantsRequestNeeded() const; [[nodiscard]] bool isMegagroup() const { return flags() & MTPDchannel::Flag::f_megagroup; } diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 92af82f9b..412f90afd 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -848,7 +848,7 @@ void TopBarWidget::updateOnlineDisplay() { } } else if (const auto channel = _activeChat.peer()->asChannel()) { if (channel->isMegagroup() && channel->membersCount() > 0 && channel->membersCount() <= Global::ChatSizeMax()) { - if (channel->mgInfo->lastParticipants.empty() || channel->lastParticipantsCountOutdated()) { + if (channel->lastParticipantsRequestNeeded()) { session().api().requestLastParticipants(channel); } const auto self = session().user(); diff --git a/Telegram/SourceFiles/profile/profile_block_group_members.cpp b/Telegram/SourceFiles/profile/profile_block_group_members.cpp index 15199b13c..3b6c1608a 100644 --- a/Telegram/SourceFiles/profile/profile_block_group_members.cpp +++ b/Telegram/SourceFiles/profile/profile_block_group_members.cpp @@ -192,7 +192,7 @@ void GroupMembersWidget::refreshMembers() { fillChatMembers(chat); } else if (const auto megagroup = peer()->asMegagroup()) { auto &megagroupInfo = megagroup->mgInfo; - if (megagroupInfo->lastParticipants.empty() || megagroup->lastParticipantsCountOutdated()) { + if (megagroup->lastParticipantsRequestNeeded()) { Auth().api().requestLastParticipants(megagroup); } fillMegagroupMembers(megagroup); From f5b103cb8942add726611a25581ea26e5cef177f Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 14 Mar 2020 13:04:15 +0400 Subject: [PATCH 38/43] Return neon optimizations in rlottie. --- cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake b/cmake index ce1b017f3..9280064cc 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit ce1b017f3527c3bfc8283eaf2439ed0eb72ecd8b +Subproject commit 9280064cc8a5e8f8acc4cdda3a6a905379d3df0d From 3a3207f15a9b8110eae557401353dc565da3e91f Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 14 Mar 2020 13:45:49 +0400 Subject: [PATCH 39/43] Beta version 1.9.20. - Fix crash in shared links search. - Fix blurred thumbnails in albums with video files. - Fix a possible crash in animated stickers rendering. --- Telegram/Resources/uwp/AppX/AppxManifest.xml | 2 +- Telegram/Resources/winrc/Telegram.rc | 8 ++--- Telegram/Resources/winrc/Updater.rc | 8 ++--- Telegram/SourceFiles/core/changelogs.cpp | 36 +++++--------------- Telegram/SourceFiles/core/version.h | 4 +-- Telegram/build/version | 8 ++--- changelog.txt | 6 ++++ 7 files changed, 29 insertions(+), 43 deletions(-) diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index 474eae12b..00a57955b 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -9,7 +9,7 @@ + Version="1.9.20.0" /> Telegram Desktop Telegram FZ-LLC diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index c33e6deb8..979b17b0b 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -33,8 +33,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,9,19,0 - PRODUCTVERSION 1,9,19,0 + FILEVERSION 1,9,20,0 + PRODUCTVERSION 1,9,20,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -51,10 +51,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop" - VALUE "FileVersion", "1.9.19.0" + VALUE "FileVersion", "1.9.20.0" VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "1.9.19.0" + VALUE "ProductVersion", "1.9.20.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 7cc7ae53e..45eda8e21 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -24,8 +24,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,9,19,0 - PRODUCTVERSION 1,9,19,0 + FILEVERSION 1,9,20,0 + PRODUCTVERSION 1,9,20,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -42,10 +42,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop Updater" - VALUE "FileVersion", "1.9.19.0" + VALUE "FileVersion", "1.9.20.0" VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "1.9.19.0" + VALUE "ProductVersion", "1.9.20.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/core/changelogs.cpp b/Telegram/SourceFiles/core/changelogs.cpp index 1ea716f18..dcda47479 100644 --- a/Telegram/SourceFiles/core/changelogs.cpp +++ b/Telegram/SourceFiles/core/changelogs.cpp @@ -18,33 +18,6 @@ namespace { std::map BetaLogs() { return { - { - 1008005, - "\xE2\x80\xA2 Create new themes based on your color " - "and wallpaper choices.\n" - - "\xE2\x80\xA2 Share your themes with other users via links.\n" - - "\xE2\x80\xA2 Update your theme for all its users " - "when you change something.\n" - }, - { - 1009000, - "\xE2\x80\xA2 System spell checker on Windows 8+ and macOS 10.12+.\n" - }, - { - 1009002, - "\xE2\x80\xA2 Videos in chats start playing automatically.\n" - - "\xE2\x80\xA2 Resume playback from where you left off " - "when watching long videos.\n" - - "\xE2\x80\xA2 Control videos, GIFs and round video messages " - "automatic playback in " - "Settings > Advanced > Automatic media download.\n" - - "\xE2\x80\xA2 Spell checker on Linux using Enchant.\n" - }, { 1009010, "\xE2\x80\xA2 Switch to the Picture-in-Picture mode " @@ -63,12 +36,19 @@ std::map BetaLogs() { "\xE2\x80\xA2 Bug fixes and other minor improvements." }, - { 1009017, "\xE2\x80\xA2 Spell checker on Windows 7.\n" "\xE2\x80\xA2 Bug fixes and other minor improvements." + }, + { + 1009020, + "\xE2\x80\xA2 Fix crash in shared links search.\n" + + "\xE2\x80\xA2 Fix blurred thumbnails in albums with video files.\n" + + "\xE2\x80\xA2 Fix a possible crash in animated stickers rendering." } }; }; diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index fedd6ea8f..2387991aa 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs; constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs; constexpr auto AppName = "Telegram Desktop"_cs; constexpr auto AppFile = "Telegram"_cs; -constexpr auto AppVersion = 1009019; -constexpr auto AppVersionStr = "1.9.19"; +constexpr auto AppVersion = 1009020; +constexpr auto AppVersionStr = "1.9.20"; constexpr auto AppBetaVersion = true; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; diff --git a/Telegram/build/version b/Telegram/build/version index 37dc9a595..02fc021df 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,7 +1,7 @@ -AppVersion 1009019 +AppVersion 1009020 AppVersionStrMajor 1.9 -AppVersionStrSmall 1.9.19 -AppVersionStr 1.9.19 +AppVersionStrSmall 1.9.20 +AppVersionStr 1.9.20 BetaChannel 1 AlphaVersion 0 -AppVersionOriginal 1.9.19.beta +AppVersionOriginal 1.9.20.beta diff --git a/changelog.txt b/changelog.txt index 990ae6a71..4ac9906fc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,9 @@ +1.9.20 beta (14.03.20) + +- Fix crash in shared links search. +- Fix blurred thumbnails in albums with video files. +- Fix a possible crash in animated stickers rendering. + 1.9.19 beta (25.02.20) - Bug fixes and other minor improvements. From 6777b204534dd577025b7c913af3bc8e02d40a64 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 14 Mar 2020 14:11:41 +0400 Subject: [PATCH 40/43] Beta version 1.9.20: Fix build on GCC. --- Telegram/SourceFiles/storage/localstorage.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index d44fc2d25..0418ce73a 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -3675,9 +3675,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, if (outOrder) { auto outOrderCount = quint32(); stickers.stream >> outOrderCount; - if (!_checkStreamStatus(stickers.stream) - || outOrderCount < 0 - || outOrderCount > 1000) { + if (!_checkStreamStatus(stickers.stream) || outOrderCount > 1000) { return failed(); } outOrder->reserve(outOrderCount); From 5f33abd391eee9a02bb52263b7592858d565c4ca Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 10 Mar 2020 14:17:19 +0400 Subject: [PATCH 41/43] Change tray implementation on demand --- .../platform/linux/main_window_linux.cpp | 149 ++++++++++++------ .../platform/linux/main_window_linux.h | 7 + 2 files changed, 104 insertions(+), 52 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 35d3a6e8a..1df10783c 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include #include #include #include @@ -51,6 +52,8 @@ base::flat_map TrayIconImageBack; QIcon TrayIcon; QString TrayIconThemeName, TrayIconName; +bool SNIAvailable = false; + QString GetPanelIconName(int counter, bool muted) { return (counter > 0) ? (muted @@ -258,33 +261,29 @@ std::unique_ptr TrayIconFile( #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION bool IsSNIAvailable() { - static const auto SNIAvailable = [&] { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - auto message = QDBusMessage::createMethodCall( - kSNIWatcherService.utf16(), - qsl("/StatusNotifierWatcher"), - kPropertiesInterface.utf16(), - qsl("Get")); + auto message = QDBusMessage::createMethodCall( + kSNIWatcherService.utf16(), + qsl("/StatusNotifierWatcher"), + kPropertiesInterface.utf16(), + qsl("Get")); - message.setArguments({ - kSNIWatcherService.utf16(), - qsl("IsStatusNotifierHostRegistered") - }); + message.setArguments({ + kSNIWatcherService.utf16(), + qsl("IsStatusNotifierHostRegistered") + }); - const QDBusReply reply = QDBusConnection::sessionBus().call( - message); + const QDBusReply reply = QDBusConnection::sessionBus().call( + message); - if (reply.isValid()) { - return reply.value().toBool(); - } else if (reply.error().type() != QDBusError::ServiceUnknown) { - LOG(("SNI Error: %1").arg(reply.error().message())); - } + if (reply.isValid()) { + return reply.value().toBool(); + } else if (reply.error().type() != QDBusError::ServiceUnknown) { + LOG(("SNI Error: %1").arg(reply.error().message())); + } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION - return false; - }(); - - return SNIAvailable; + return false; } bool UseUnityCounter() { @@ -315,12 +314,28 @@ MainWindow::MainWindow(not_null controller) } void MainWindow::initHook() { - const auto trayAvailable = IsSNIAvailable() + SNIAvailable = IsSNIAvailable(); + + const auto trayAvailable = SNIAvailable || QSystemTrayIcon::isSystemTrayAvailable(); LOG(("System tray available: %1").arg(Logs::b(trayAvailable))); cSetSupportTray(trayAvailable); +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + auto sniWatcher = new QDBusServiceWatcher( + kSNIWatcherService.utf16(), + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForOwnerChange, + this); + + connect( + sniWatcher, + &QDBusServiceWatcher::serviceOwnerChanged, + this, + &MainWindow::onSNIOwnerChanged); +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + if (UseUnityCounter()) { LOG(("Using Unity launcher counter.")); } else { @@ -337,17 +352,13 @@ bool MainWindow::hasTrayIcon() const { } void MainWindow::psShowTrayMenu() { - if (!IsSNIAvailable()) { - _trayIconMenuXEmbed->popup(QCursor::pos()); - } + _trayIconMenuXEmbed->popup(QCursor::pos()); } void MainWindow::psTrayMenuUpdated() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - if (IsSNIAvailable()) { - if (_sniTrayIcon && trayIconMenu) { - _sniTrayIcon->setContextMenu(trayIconMenu); - } + if (_sniTrayIcon && trayIconMenu) { + _sniTrayIcon->setContextMenu(trayIconMenu); } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } @@ -408,13 +419,51 @@ void MainWindow::attachToSNITrayIcon() { }); updateTrayMenu(); } + +void MainWindow::onSNIOwnerChanged( + const QString &service, + const QString &oldOwner, + const QString &newOwner) { + if (oldOwner.isEmpty() && !newOwner.isEmpty()) { + LOG(("Switching to SNI tray icon...")); + } else if (!oldOwner.isEmpty() && newOwner.isEmpty()) { + LOG(("Switching to Qt tray icon...")); + } else { + return; + } + + if (_sniTrayIcon) { + _sniTrayIcon->setContextMenu(0); + _sniTrayIcon->deleteLater(); + } + _sniTrayIcon = nullptr; + + if (trayIcon) { + trayIcon->setContextMenu(0); + trayIcon->deleteLater(); + } + trayIcon = nullptr; + + SNIAvailable = IsSNIAvailable(); + + const auto trayAvailable = SNIAvailable + || QSystemTrayIcon::isSystemTrayAvailable(); + + cSetSupportTray(trayAvailable); + + if(cSupportTray()) { + psSetupTrayIcon(); + } else { + LOG(("System tray is not available.")); + } +} #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION void MainWindow::psSetupTrayIcon() { const auto counter = Core::App().unreadBadge(); const auto muted = Core::App().unreadBadgeMuted(); - if (IsSNIAvailable()) { + if (SNIAvailable) { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION LOG(("Using SNI tray icon.")); if (!_sniTrayIcon) { @@ -447,21 +496,19 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { if (!cSupportTray()) return; if (mode == dbiwmWindowOnly) { - if (IsSNIAvailable()) { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - if (_sniTrayIcon) { - _sniTrayIcon->setContextMenu(0); - _sniTrayIcon->deleteLater(); - } - _sniTrayIcon = 0; -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION - } else { - if (trayIcon) { - trayIcon->setContextMenu(0); - trayIcon->deleteLater(); - } - trayIcon = 0; + if (_sniTrayIcon) { + _sniTrayIcon->setContextMenu(0); + _sniTrayIcon->deleteLater(); } + _sniTrayIcon = nullptr; +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + + if (trayIcon) { + trayIcon->setContextMenu(0); + trayIcon->deleteLater(); + } + trayIcon = nullptr; } else { psSetupTrayIcon(); } @@ -504,13 +551,13 @@ void MainWindow::updateIconCounters() { } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION - if (IsSNIAvailable()) { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION - if (_sniTrayIcon) { - setSNITrayIcon(counter, muted); - } + if (_sniTrayIcon) { + setSNITrayIcon(counter, muted); + } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION - } else if (trayIcon && IsIconRegenerationNeeded(counter, muted)) { + + if (trayIcon && IsIconRegenerationNeeded(counter, muted)) { trayIcon->setIcon(TrayIconGen(counter, muted)); } } @@ -524,10 +571,8 @@ void MainWindow::LibsLoaded() { } void MainWindow::initTrayMenuHook() { - if (!IsSNIAvailable()) { - _trayIconMenuXEmbed = new Ui::PopupMenu(nullptr, trayIconMenu); - _trayIconMenuXEmbed->deleteOnHide(false); - } + _trayIconMenuXEmbed = new Ui::PopupMenu(nullptr, trayIconMenu); + _trayIconMenuXEmbed->deleteOnHide(false); } MainWindow::~MainWindow() { diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 297ec1d62..5a4466645 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -38,6 +38,13 @@ public: public slots: void psShowTrayMenu(); +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + void onSNIOwnerChanged( + const QString &service, + const QString &oldOwner, + const QString &newOwner); +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + protected: void initHook() override; void unreadCounterChangedHook() override; From 46445e0542f0104d8a06938076f7140c6d4a5d84 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 4 Mar 2020 09:45:44 +0400 Subject: [PATCH 42/43] Implement global menu on Linux --- Telegram/Resources/langs/lang.strings | 2 + .../platform/linux/main_window_linux.cpp | 405 ++++++++++++++++++ .../platform/linux/main_window_linux.h | 45 ++ 3 files changed, 452 insertions(+) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 02c23cbb8..849fbcb02 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2239,6 +2239,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_linux_menu_undo" = "Undo"; "lng_linux_menu_redo" = "Redo"; +"lng_linux_menu_tools" = "Tools"; +"lng_linux_menu_help" = "Help"; "lng_linux_no_audio_prefs" = "You don't have any audio configuration applications installed."; diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 1df10783c..af339231c 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -13,15 +13,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/linux_desktop_environment.h" #include "platform/platform_notifications_manager.h" #include "history/history.h" +#include "history/history_widget.h" +#include "history/history_inner_widget.h" +#include "main/main_account.h" // Account::sessionChanges. #include "mainwindow.h" #include "core/application.h" #include "core/sandbox.h" +#include "boxes/peer_list_controllers.h" +#include "boxes/about_box.h" #include "lang/lang_keys.h" #include "storage/localstorage.h" +#include "window/window_session_controller.h" +#include "ui/widgets/input_fields.h" #include "facades.h" #include "app.h" #include +#include #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include @@ -46,6 +54,10 @@ constexpr auto kSNIWatcherService = "org.kde.StatusNotifierWatcher"_cs; constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; constexpr auto kTrayIconFilename = "tdesktop-trayicon-XXXXXX.png"_cs; +constexpr auto kAppMenuService = "com.canonical.AppMenu.Registrar"_cs; +constexpr auto kAppMenuObjectPath = "/com/canonical/AppMenu/Registrar"_cs; +constexpr auto kAppMenuInterface = kAppMenuService; + bool TrayIconMuted = true; int32 TrayIconCount = 0; base::flat_map TrayIconImageBack; @@ -307,6 +319,71 @@ quint32 djbStringHash(QString string) { return hash; } +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +bool AppMenuSupported() { + static const auto Available = QDBusInterface( + kAppMenuService.utf16(), + kAppMenuObjectPath.utf16(), + kAppMenuInterface.utf16()).isValid(); + + return Available; +} + +void RegisterAppMenu(uint winId, const QDBusObjectPath &menuPath) { + auto message = QDBusMessage::createMethodCall( + kAppMenuService.utf16(), + kAppMenuObjectPath.utf16(), + kAppMenuInterface.utf16(), + qsl("RegisterWindow")); + + message.setArguments({ + winId, + QVariant::fromValue(menuPath) + }); + + QDBusConnection::sessionBus().send(message); +} + +void UnregisterAppMenu(uint winId) { + auto message = QDBusMessage::createMethodCall( + kAppMenuService.utf16(), + kAppMenuObjectPath.utf16(), + kAppMenuInterface.utf16(), + qsl("UnregisterWindow")); + + message.setArguments({ + winId + }); + + QDBusConnection::sessionBus().send(message); +} + +void SendKeySequence( + Qt::Key key, + Qt::KeyboardModifiers modifiers = Qt::NoModifier) { + const auto focused = QApplication::focusWidget(); + if (qobject_cast(focused) + || qobject_cast(focused) + || qobject_cast(focused)) { + QApplication::postEvent( + focused, + new QKeyEvent(QEvent::KeyPress, key, modifiers)); + + QApplication::postEvent( + focused, + new QKeyEvent(QEvent::KeyRelease, key, modifiers)); + } +} + +void ForceDisabled(QAction *action, bool disabled) { + if (action->isEnabled()) { + if (disabled) action->setDisabled(true); + } else if (!disabled) { + action->setDisabled(false); + } +} +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + } // namespace MainWindow::MainWindow(not_null controller) @@ -341,6 +418,12 @@ void MainWindow::initHook() { } else { LOG(("Not using Unity launcher counter.")); } + + connect( + windowHandle(), + &QWindow::visibleChanged, + this, + &MainWindow::onVisibleChanged); } bool MainWindow::hasTrayIcon() const { @@ -575,9 +658,331 @@ void MainWindow::initTrayMenuHook() { _trayIconMenuXEmbed->deleteOnHide(false); } +void MainWindow::createGlobalMenu() { +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + if (!AppMenuSupported()) return; + + psMainMenu = new QMenu(this); + + auto file = psMainMenu->addMenu(tr::lng_mac_menu_file(tr::now)); + + psLogout = file->addAction( + tr::lng_mac_menu_logout(tr::now), + App::wnd(), + SLOT(onLogout())); + + auto quit = file->addAction( + tr::lng_mac_menu_quit_telegram(tr::now, lt_telegram, qsl("Telegram")), + App::wnd(), + SLOT(quitFromTray()), + QKeySequence::Quit); + + quit->setMenuRole(QAction::QuitRole); + + auto edit = psMainMenu->addMenu(tr::lng_mac_menu_edit(tr::now)); + + psUndo = edit->addAction( + tr::lng_linux_menu_undo(tr::now), + this, + SLOT(psLinuxUndo()), + QKeySequence::Undo); + + psRedo = edit->addAction( + tr::lng_linux_menu_redo(tr::now), + this, + SLOT(psLinuxRedo()), + QKeySequence::Redo); + + edit->addSeparator(); + + psCut = edit->addAction( + tr::lng_mac_menu_cut(tr::now), + this, + SLOT(psLinuxCut()), + QKeySequence::Cut); + psCopy = edit->addAction( + tr::lng_mac_menu_copy(tr::now), + this, + SLOT(psLinuxCopy()), + QKeySequence::Copy); + + psPaste = edit->addAction( + tr::lng_mac_menu_paste(tr::now), + this, + SLOT(psLinuxPaste()), + QKeySequence::Paste); + + psDelete = edit->addAction( + tr::lng_mac_menu_delete(tr::now), + this, + SLOT(psLinuxDelete()), + QKeySequence(Qt::ControlModifier | Qt::Key_Backspace)); + + edit->addSeparator(); + + psBold = edit->addAction( + tr::lng_menu_formatting_bold(tr::now), + this, + SLOT(psLinuxBold()), + QKeySequence::Bold); + + psItalic = edit->addAction( + tr::lng_menu_formatting_italic(tr::now), + this, + SLOT(psLinuxItalic()), + QKeySequence::Italic); + + psUnderline = edit->addAction( + tr::lng_menu_formatting_underline(tr::now), + this, + SLOT(psLinuxUnderline()), + QKeySequence::Underline); + + psStrikeOut = edit->addAction( + tr::lng_menu_formatting_strike_out(tr::now), + this, + SLOT(psLinuxStrikeOut()), + Ui::kStrikeOutSequence); + + psMonospace = edit->addAction( + tr::lng_menu_formatting_monospace(tr::now), + this, + SLOT(psLinuxMonospace()), + Ui::kMonospaceSequence); + + psClearFormat = edit->addAction( + tr::lng_menu_formatting_clear(tr::now), + this, + SLOT(psLinuxClearFormat()), + Ui::kClearFormatSequence); + + edit->addSeparator(); + + psSelectAll = edit->addAction( + tr::lng_mac_menu_select_all(tr::now), + this, SLOT(psLinuxSelectAll()), + QKeySequence::SelectAll); + + edit->addSeparator(); + + auto prefs = edit->addAction( + tr::lng_mac_menu_preferences(tr::now), + App::wnd(), + SLOT(showSettings()), + QKeySequence(Qt::ControlModifier | Qt::Key_Comma)); + + prefs->setMenuRole(QAction::PreferencesRole); + + auto tools = psMainMenu->addMenu(tr::lng_linux_menu_tools(tr::now)); + + psContacts = tools->addAction( + tr::lng_mac_menu_contacts(tr::now), + crl::guard(this, [=] { + if (isHidden()) { + App::wnd()->showFromTray(); + } + + if (!account().sessionExists()) { + return; + } + + Ui::show( + Box(std::make_unique( + sessionController()), + [](not_null box) { + box->addButton(tr::lng_close(), [box] { + box->closeBox(); + }); + + box->addLeftButton(tr::lng_profile_add_contact(), [] { + App::wnd()->onShowAddContact(); + }); + })); + })); + + psAddContact = tools->addAction( + tr::lng_mac_menu_add_contact(tr::now), + App::wnd(), + SLOT(onShowAddContact())); + + tools->addSeparator(); + + psNewGroup = tools->addAction( + tr::lng_mac_menu_new_group(tr::now), + App::wnd(), + SLOT(onShowNewGroup())); + + psNewChannel = tools->addAction( + tr::lng_mac_menu_new_channel(tr::now), + App::wnd(), + SLOT(onShowNewChannel())); + + auto help = psMainMenu->addMenu(tr::lng_linux_menu_help(tr::now)); + + auto about = help->addAction( + tr::lng_mac_menu_about_telegram( + tr::now, + lt_telegram, + qsl("Telegram")), + [] { + if (App::wnd() && App::wnd()->isHidden()) { + App::wnd()->showFromTray(); + } + + Ui::show(Box()); + }); + + about->setMenuRole(QAction::AboutQtRole); + + _mainMenuPath.setPath(qsl("/MenuBar")); + + _mainMenuExporter = new DBusMenuExporter( + _mainMenuPath.path(), + psMainMenu); + + RegisterAppMenu(winId(), _mainMenuPath); + + updateGlobalMenu(); +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +} + +void MainWindow::psLinuxUndo() { + SendKeySequence(Qt::Key_Z, Qt::ControlModifier); +} + +void MainWindow::psLinuxRedo() { + SendKeySequence(Qt::Key_Z, Qt::ControlModifier | Qt::ShiftModifier); +} + +void MainWindow::psLinuxCut() { + SendKeySequence(Qt::Key_X, Qt::ControlModifier); +} + +void MainWindow::psLinuxCopy() { + SendKeySequence(Qt::Key_C, Qt::ControlModifier); +} + +void MainWindow::psLinuxPaste() { + SendKeySequence(Qt::Key_V, Qt::ControlModifier); +} + +void MainWindow::psLinuxDelete() { + SendKeySequence(Qt::Key_Delete); +} + +void MainWindow::psLinuxSelectAll() { + SendKeySequence(Qt::Key_A, Qt::ControlModifier); +} + +void MainWindow::psLinuxBold() { + SendKeySequence(Qt::Key_B, Qt::ControlModifier); +} + +void MainWindow::psLinuxItalic() { + SendKeySequence(Qt::Key_I, Qt::ControlModifier); +} + +void MainWindow::psLinuxUnderline() { + SendKeySequence(Qt::Key_U, Qt::ControlModifier); +} + +void MainWindow::psLinuxStrikeOut() { + SendKeySequence(Qt::Key_X, Qt::ControlModifier | Qt::ShiftModifier); +} + +void MainWindow::psLinuxMonospace() { + SendKeySequence(Qt::Key_M, Qt::ControlModifier | Qt::ShiftModifier); +} + +void MainWindow::psLinuxClearFormat() { + SendKeySequence(Qt::Key_N, Qt::ControlModifier | Qt::ShiftModifier); +} + +void MainWindow::updateGlobalMenuHook() { +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + if (!AppMenuSupported() || !App::wnd() || !positionInited()) return; + + const auto focused = QApplication::focusWidget(); + auto canUndo = false; + auto canRedo = false; + auto canCut = false; + auto canCopy = false; + auto canPaste = false; + auto canDelete = false; + auto canSelectAll = false; + const auto clipboardHasText = QGuiApplication::clipboard() + ->ownsClipboard(); + auto markdownEnabled = false; + if (const auto edit = qobject_cast(focused)) { + canCut = canCopy = canDelete = edit->hasSelectedText(); + canSelectAll = !edit->text().isEmpty(); + canUndo = edit->isUndoAvailable(); + canRedo = edit->isRedoAvailable(); + canPaste = clipboardHasText; + } else if (const auto edit = qobject_cast(focused)) { + canCut = canCopy = canDelete = edit->textCursor().hasSelection(); + canSelectAll = !edit->document()->isEmpty(); + canUndo = edit->document()->isUndoAvailable(); + canRedo = edit->document()->isRedoAvailable(); + canPaste = clipboardHasText; + if (canCopy) { + if (const auto inputField = qobject_cast( + focused->parentWidget())) { + markdownEnabled = inputField->isMarkdownEnabled(); + } + } + } else if (const auto list = qobject_cast(focused)) { + canCopy = list->canCopySelected(); + canDelete = list->canDeleteSelected(); + } + App::wnd()->updateIsActive(0); + const auto logged = account().sessionExists(); + const auto locked = Core::App().locked(); + const auto inactive = !logged || locked; + const auto support = logged && account().session().supportMode(); + ForceDisabled(psLogout, !logged && !locked); + ForceDisabled(psUndo, !canUndo); + ForceDisabled(psRedo, !canRedo); + ForceDisabled(psCut, !canCut); + ForceDisabled(psCopy, !canCopy); + ForceDisabled(psPaste, !canPaste); + ForceDisabled(psDelete, !canDelete); + ForceDisabled(psSelectAll, !canSelectAll); + ForceDisabled(psContacts, inactive || support); + ForceDisabled(psAddContact, inactive); + ForceDisabled(psNewGroup, inactive || support); + ForceDisabled(psNewChannel, inactive || support); + + ForceDisabled(psBold, !markdownEnabled); + ForceDisabled(psItalic, !markdownEnabled); + ForceDisabled(psUnderline, !markdownEnabled); + ForceDisabled(psStrikeOut, !markdownEnabled); + ForceDisabled(psMonospace, !markdownEnabled); + ForceDisabled(psClearFormat, !markdownEnabled); +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +} + +void MainWindow::onVisibleChanged(bool visible) { +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION + if (AppMenuSupported() && !_mainMenuPath.path().isEmpty()) { + if (visible) { + RegisterAppMenu(winId(), _mainMenuPath); + } else { + UnregisterAppMenu(winId()); + } + } +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +} + MainWindow::~MainWindow() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION delete _sniTrayIcon; + + if (AppMenuSupported()) { + UnregisterAppMenu(winId()); + delete _mainMenuExporter; + delete psMainMenu; + } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION delete _trayIconMenuXEmbed; diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 5a4466645..d870bc74c 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include "statusnotifieritem.h" #include +#include +#include #endif namespace Platform { @@ -45,14 +47,33 @@ public slots: const QString &newOwner); #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + void psLinuxUndo(); + void psLinuxRedo(); + void psLinuxCut(); + void psLinuxCopy(); + void psLinuxPaste(); + void psLinuxDelete(); + void psLinuxSelectAll(); + + void psLinuxBold(); + void psLinuxItalic(); + void psLinuxUnderline(); + void psLinuxStrikeOut(); + void psLinuxMonospace(); + void psLinuxClearFormat(); + + void onVisibleChanged(bool visible); + protected: void initHook() override; void unreadCounterChangedHook() override; + void updateGlobalMenuHook() override; void initTrayMenuHook() override; bool hasTrayIcon() const override; void workmodeUpdated(DBIWorkMode mode) override; + void createGlobalMenu() override; QSystemTrayIcon *trayIcon = nullptr; QMenu *trayIconMenu = nullptr; @@ -77,6 +98,30 @@ private: StatusNotifierItem *_sniTrayIcon = nullptr; std::unique_ptr _trayIconFile = nullptr; + DBusMenuExporter *_mainMenuExporter = nullptr; + QDBusObjectPath _mainMenuPath; + + QMenu *psMainMenu = nullptr; + QAction *psLogout = nullptr; + QAction *psUndo = nullptr; + QAction *psRedo = nullptr; + QAction *psCut = nullptr; + QAction *psCopy = nullptr; + QAction *psPaste = nullptr; + QAction *psDelete = nullptr; + QAction *psSelectAll = nullptr; + QAction *psContacts = nullptr; + QAction *psAddContact = nullptr; + QAction *psNewGroup = nullptr; + QAction *psNewChannel = nullptr; + + QAction *psBold = nullptr; + QAction *psItalic = nullptr; + QAction *psUnderline = nullptr; + QAction *psStrikeOut = nullptr; + QAction *psMonospace = nullptr; + QAction *psClearFormat = nullptr; + void setSNITrayIcon(int counter, bool muted, bool firstShow = false); void attachToSNITrayIcon(); #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION From fec6a8dd962bb0cc4f96521149733f658f9488b2 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 14 Mar 2020 16:13:33 +0400 Subject: [PATCH 43/43] Beta version 1.9.20: Fix build without dbus. --- .../platform/linux/main_window_linux.cpp | 32 +++++++++++-------- .../platform/linux/main_window_linux.h | 3 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index af339231c..d4abdcf7c 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -411,6 +411,12 @@ void MainWindow::initHook() { &QDBusServiceWatcher::serviceOwnerChanged, this, &MainWindow::onSNIOwnerChanged); + + connect( + windowHandle(), + &QWindow::visibleChanged, + this, + &MainWindow::onVisibleChanged); #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION if (UseUnityCounter()) { @@ -418,12 +424,6 @@ void MainWindow::initHook() { } else { LOG(("Not using Unity launcher counter.")); } - - connect( - windowHandle(), - &QWindow::visibleChanged, - this, - &MainWindow::onVisibleChanged); } bool MainWindow::hasTrayIcon() const { @@ -632,9 +632,7 @@ void MainWindow::updateIconCounters() { signal << dbusUnityProperties; QDBusConnection::sessionBus().send(signal); } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION if (_sniTrayIcon) { setSNITrayIcon(counter, muted); } @@ -658,8 +656,17 @@ void MainWindow::initTrayMenuHook() { _trayIconMenuXEmbed->deleteOnHide(false); } +#ifdef TDESKTOP_DISABLE_DBUS_INTEGRATION + +void MainWindow::createGlobalMenu() { +} + +void MainWindow::updateGlobalMenuHook() { +} + +#else // TDESKTOP_DISABLE_DBUS_INTEGRATION + void MainWindow::createGlobalMenu() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION if (!AppMenuSupported()) return; psMainMenu = new QMenu(this); @@ -843,7 +850,6 @@ void MainWindow::createGlobalMenu() { RegisterAppMenu(winId(), _mainMenuPath); updateGlobalMenu(); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } void MainWindow::psLinuxUndo() { @@ -899,7 +905,6 @@ void MainWindow::psLinuxClearFormat() { } void MainWindow::updateGlobalMenuHook() { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION if (!AppMenuSupported() || !App::wnd() || !positionInited()) return; const auto focused = QApplication::focusWidget(); @@ -959,11 +964,9 @@ void MainWindow::updateGlobalMenuHook() { ForceDisabled(psStrikeOut, !markdownEnabled); ForceDisabled(psMonospace, !markdownEnabled); ForceDisabled(psClearFormat, !markdownEnabled); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } void MainWindow::onVisibleChanged(bool visible) { -#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION if (AppMenuSupported() && !_mainMenuPath.path().isEmpty()) { if (visible) { RegisterAppMenu(winId(), _mainMenuPath); @@ -971,9 +974,10 @@ void MainWindow::onVisibleChanged(bool visible) { UnregisterAppMenu(winId()); } } -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION } +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + MainWindow::~MainWindow() { #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION delete _sniTrayIcon; diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index d870bc74c..8602c5380 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -45,7 +45,6 @@ public slots: const QString &service, const QString &oldOwner, const QString &newOwner); -#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION void psLinuxUndo(); void psLinuxRedo(); @@ -64,6 +63,8 @@ public slots: void onVisibleChanged(bool visible); +#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION + protected: void initHook() override; void unreadCounterChangedHook() override;