Updated TDesktop sources to 2.7.1+df73bda

This commit is contained in:
Eric Kotato 2021-04-07 00:16:52 +03:00
commit d6614eb9cc
19 changed files with 235 additions and 191 deletions

View file

@ -253,7 +253,6 @@ std::unique_ptr<PeerListRow> InviteContactsController::createRow(
Panel::Panel(not_null<GroupCall*> call) Panel::Panel(not_null<GroupCall*> call)
: _call(call) : _call(call)
, _peer(call->peer()) , _peer(call->peer())
, _window(std::make_unique<Ui::Window>(Core::App().getModalParent()))
, _layerBg(std::make_unique<Ui::LayerManager>(_window->body())) , _layerBg(std::make_unique<Ui::LayerManager>(_window->body()))
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
, _controls(std::make_unique<Ui::Platform::TitleControls>( , _controls(std::make_unique<Ui::Platform::TitleControls>(

View file

@ -33,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/empty_userpic.h" #include "ui/empty_userpic.h"
#include "ui/emoji_config.h" #include "ui/emoji_config.h"
#include "core/application.h" #include "core/application.h"
#include "mainwindow.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -185,7 +184,6 @@ void Panel::Incoming::fillBottomShadow(QPainter &p) {
Panel::Panel(not_null<Call*> call) Panel::Panel(not_null<Call*> call)
: _call(call) : _call(call)
, _user(call->user()) , _user(call->user())
, _window(std::make_unique<Ui::Window>(Core::App().getModalParent()))
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
, _controls(std::make_unique<Ui::Platform::TitleControls>( , _controls(std::make_unique<Ui::Platform::TitleControls>(
_window->body(), _window->body(),

View file

@ -23,7 +23,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/ui_integration.h" #include "core/ui_integration.h"
#include "chat_helpers/emoji_keywords.h" #include "chat_helpers/emoji_keywords.h"
#include "chat_helpers/stickers_emoji_image_loader.h" #include "chat_helpers/stickers_emoji_image_loader.h"
#include "base/platform/base_platform_info.h"
#include "base/platform/base_platform_last_input.h" #include "base/platform/base_platform_last_input.h"
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -1002,13 +1001,6 @@ void Application::notifyFileDialogShown(bool shown) {
} }
} }
QWidget *Application::getModalParent() {
return (Platform::IsWayland() && activeWindow())
? activeWindow()->widget().get()
: nullptr;
}
void Application::checkMediaViewActivation() { void Application::checkMediaViewActivation() {
if (_mediaView && !_mediaView->isHidden()) { if (_mediaView && !_mediaView->isHidden()) {
_mediaView->activateWindow(); _mediaView->activateWindow();

View file

@ -139,7 +139,6 @@ public:
bool minimizeActiveWindow(); bool minimizeActiveWindow();
[[nodiscard]] QWidget *getFileDialogParent(); [[nodiscard]] QWidget *getFileDialogParent();
void notifyFileDialogShown(bool shown); void notifyFileDialogShown(bool shown);
[[nodiscard]] QWidget *getModalParent();
void checkSystemDarkMode(); void checkSystemDarkMode();
// Media view interface. // Media view interface.

View file

@ -213,7 +213,7 @@ bool gForwardChatOnClick = false;
#if defined TDESKTOP_API_ID && defined TDESKTOP_API_HASH #if defined TDESKTOP_API_ID && defined TDESKTOP_API_HASH
int gApiId = TDESKTOP_API_ID; int gApiId = TDESKTOP_API_ID;
QString gApiHash = MACRO_TO_STRING(TDESKTOP_API_HASH); QString gApiHash = QT_STRINGIFY(TDESKTOP_API_HASH);
#else // TDESKTOP_API_ID && TDESKTOP_API_HASH #else // TDESKTOP_API_ID && TDESKTOP_API_HASH

View file

@ -132,11 +132,11 @@ private:
auto to = std::make_unique<QFile>(_logsFilePath(type, postfix)); auto to = std::make_unique<QFile>(_logsFilePath(type, postfix));
if (to->exists() && !to->remove()) { if (to->exists() && !to->remove()) {
LOG(("Could not delete '%1' file to start new logging!").arg(to->fileName())); LOG(("Could not delete '%1' file to start new logging: %2").arg(to->fileName(), to->errorString()));
return false; return false;
} }
if (!QFile(files[type]->fileName()).copy(to->fileName())) { // don't close files[type] yet if (!QFile(files[type]->fileName()).copy(to->fileName())) { // don't close files[type] yet
LOG(("Could not copy '%1' to '%2' to start new logging!").arg(files[type]->fileName(), to->fileName())); LOG(("Could not copy '%1' to '%2' to start new logging: %3").arg(files[type]->fileName(), to->fileName(), to->errorString()));
return false; return false;
} }
if (to->open(mode | QIODevice::Append)) { if (to->open(mode | QIODevice::Append)) {
@ -158,7 +158,7 @@ private:
return true; return true;
} }
LOG(("Could not open '%1' file to start new logging!").arg(to->fileName())); LOG(("Could not open '%1' file to start new logging: %2").arg(to->fileName(), to->errorString()));
return false; return false;
} else { } else {
bool found = false; bool found = false;
@ -209,7 +209,7 @@ NEW LOGGING INSTANCE STARTED!!!\n\
return true; return true;
} else if (type != LogDataMain) { } else if (type != LogDataMain) {
LOG(("Could not open debug log '%1'!").arg(files[type]->fileName())); LOG(("Could not open debug log '%1': %2").arg(files[type]->fileName(), files[type]->errorString()));
} }
return false; return false;
} }

View file

@ -373,8 +373,7 @@ QImage RotateFrameImage(QImage image, int rotation) {
PipPanel::PipPanel( PipPanel::PipPanel(
QWidget *parent, QWidget *parent,
Fn<void(QPainter&, FrameRequest)> paint) Fn<void(QPainter&, FrameRequest)> paint)
: PipParent(Core::App().getModalParent()) : _parent(parent)
, _parent(parent)
, _paint(std::move(paint)) { , _paint(std::move(paint)) {
setWindowFlags(Qt::Tool setWindowFlags(Qt::Tool
| Qt::WindowStaysOnTopHint | Qt::WindowStaysOnTopHint
@ -388,7 +387,17 @@ PipPanel::PipPanel(
Ui::Platform::InitOnTopPanel(this); Ui::Platform::InitOnTopPanel(this);
setMouseTracking(true); setMouseTracking(true);
resize(0, 0); resize(0, 0);
show(); hide();
createWinId();
}
void PipPanel::setVisibleHook(bool visible) {
PipParent::setVisibleHook(visible);
// workaround Qt's forced transient parent
if (visible) {
Ui::Platform::ClearTransientParent(this);
}
} }
void PipPanel::setAspectRatio(QSize ratio) { void PipPanel::setAspectRatio(QSize ratio) {

View file

@ -78,6 +78,8 @@ protected:
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void setVisibleHook(bool visible) override;
private: private:
void setPositionDefault(); void setPositionDefault();
void setPositionOnScreen(Position position, QRect available); void setPositionOnScreen(Position position, QRect available);

View file

@ -65,7 +65,7 @@ QByteArray DnsUserAgent() {
static const auto kResult = QByteArray( static const auto kResult = QByteArray(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) " "AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/88.0.4324.182 Safari/537.36"); "Chrome/89.0.4389.90 Safari/537.36");
return kResult; return kResult;
} }

View file

@ -66,7 +66,7 @@ void Launcher::initHook() {
AppName.utf16().replace(' ', '_')); AppName.utf16().replace(' ', '_'));
} }
return qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME) ".desktop"); return qsl(QT_STRINGIFY(TDESKTOP_LAUNCHER_BASENAME) ".desktop");
}()); }());
} }

View file

@ -21,7 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "app.h" #include "mainwidget.h"
#include <QtCore/QBuffer> #include <QtCore/QBuffer>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
@ -33,13 +33,12 @@ namespace Platform {
namespace internal { namespace internal {
namespace { namespace {
constexpr auto kService = "org.mpris.MediaPlayer2.Kotatogram"_cs; constexpr auto kService = "org.mpris.MediaPlayer2.tdesktop"_cs;
constexpr auto kObjectPath = "/org/mpris/MediaPlayer2"_cs; constexpr auto kObjectPath = "/org/mpris/MediaPlayer2"_cs;
constexpr auto kFakeTrackPath = "/org/telegram/desktop/track/0"_cs; constexpr auto kFakeTrackPath = "/org/telegram/desktop/track/0"_cs;
constexpr auto kInterface = "org.mpris.MediaPlayer2"_cs; constexpr auto kInterface = "org.mpris.MediaPlayer2"_cs;
constexpr auto kPlayerInterface = "org.mpris.MediaPlayer2.Player"_cs; constexpr auto kPlayerInterface = "org.mpris.MediaPlayer2.Player"_cs;
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
constexpr auto kSongType = AudioMsgId::Type::Song;
constexpr auto kIntrospectionXML = R"INTROSPECTION(<node> constexpr auto kIntrospectionXML = R"INTROSPECTION(<node>
<interface name='org.mpris.MediaPlayer2'> <interface name='org.mpris.MediaPlayer2'>
@ -101,50 +100,56 @@ auto CreateMetadata(
Data::DocumentMedia *trackView) { Data::DocumentMedia *trackView) {
std::map<Glib::ustring, Glib::VariantBase> result; std::map<Glib::ustring, Glib::VariantBase> result;
if (!Media::Player::IsStoppedOrStopping(state.state)) { if (Media::Player::IsStoppedOrStopping(state.state)) {
result["mpris:trackid"] = Glib::wrap(g_variant_new_object_path( return result;
kFakeTrackPath.utf8().constData())); }
result["mpris:length"] = Glib::Variant<gint64>::create(
state.length * 1000);
const auto audioData = state.id.audio(); result["mpris:trackid"] = Glib::wrap(g_variant_new_object_path(
if (audioData) { kFakeTrackPath.utf8().constData()));
result["mpris:length"] = Glib::Variant<gint64>::create(
state.length * 1000);
result["xesam:title"] = Glib::Variant<Glib::ustring>::create(
"Unknown Track");
const auto audioData = state.id.audio();
if (audioData) {
if (!audioData->filename().isEmpty()) {
result["xesam:title"] = Glib::Variant< result["xesam:title"] = Glib::Variant<
Glib::ustring Glib::ustring
>::create(audioData->filename().toStdString()); >::create(audioData->filename().toStdString());
if (audioData->isSong()) {
const auto songData = audioData->song();
if (!songData->performer.isEmpty()) {
result["xesam:artist"] = Glib::Variant<
std::vector<Glib::ustring>
>::create({ songData->performer.toStdString() });
}
if (!songData->performer.isEmpty()) {
result["xesam:title"] = Glib::Variant<
Glib::ustring
>::create(songData->title.toStdString());
}
}
} }
if (trackView) { if (audioData->isSong()) {
trackView->thumbnailWanted(Data::FileOrigin()); const auto songData = audioData->song();
if (trackView->thumbnail()) { if (!songData->performer.isEmpty()) {
QByteArray thumbnailData; result["xesam:artist"] = Glib::Variant<
QBuffer thumbnailBuffer(&thumbnailData); std::vector<Glib::ustring>
trackView->thumbnail()->original().save( >::create({ songData->performer.toStdString() });
&thumbnailBuffer,
"JPG",
87);
result["mpris:artUrl"] = Glib::Variant<
Glib::ustring
>::create("data:image/jpeg;base64,"
+ thumbnailData
.toBase64()
.toStdString());
} }
if (!songData->title.isEmpty()) {
result["xesam:title"] = Glib::Variant<
Glib::ustring
>::create(songData->title.toStdString());
}
}
}
if (trackView) {
trackView->thumbnailWanted(Data::FileOrigin());
if (trackView->thumbnail()) {
QByteArray thumbnailData;
QBuffer thumbnailBuffer(&thumbnailData);
trackView->thumbnail()->original().save(
&thumbnailBuffer,
"JPG",
87);
result["mpris:artUrl"] = Glib::Variant<
Glib::ustring
>::create("data:image/jpeg;base64,"
+ thumbnailData
.toBase64()
.toStdString());
} }
} }
@ -172,9 +177,13 @@ void HandleMethodCall(
auto parametersCopy = parameters; auto parametersCopy = parameters;
if (method_name == "Quit") { if (method_name == "Quit") {
App::quit(); if (const auto main = App::main()) {
main->closeBothPlayers();
}
} else if (method_name == "Raise") { } else if (method_name == "Raise") {
App::wnd()->showFromTray(); if (const auto window = App::wnd()) {
window->showFromTray();
}
} else if (method_name == "Next") { } else if (method_name == "Next") {
Media::Player::instance()->next(); Media::Player::instance()->next();
} else if (method_name == "Pause") { } else if (method_name == "Pause") {
@ -190,10 +199,10 @@ void HandleMethodCall(
parametersCopy.get_child(0)); parametersCopy.get_child(0));
const auto state = Media::Player::instance()->getState( const auto state = Media::Player::instance()->getState(
kSongType); Media::Player::instance()->getActiveType());
Media::Player::instance()->finishSeeking( Media::Player::instance()->finishSeeking(
kSongType, Media::Player::instance()->getActiveType(),
float64(state.position * 1000 + offset) float64(state.position * 1000 + offset)
/ (state.length * 1000)); / (state.length * 1000));
} else if (method_name == "SetPosition") { } else if (method_name == "SetPosition") {
@ -201,10 +210,10 @@ void HandleMethodCall(
parametersCopy.get_child(1)); parametersCopy.get_child(1));
const auto state = Media::Player::instance()->getState( const auto state = Media::Player::instance()->getState(
kSongType); Media::Player::instance()->getActiveType());
Media::Player::instance()->finishSeeking( Media::Player::instance()->finishSeeking(
kSongType, Media::Player::instance()->getActiveType(),
float64(position) / (state.length * 1000)); float64(position) / (state.length * 1000));
} else if (method_name == "Stop") { } else if (method_name == "Stop") {
Media::Player::instance()->stop(); Media::Player::instance()->stop();
@ -262,7 +271,7 @@ void HandleGetProperty(
property = Glib::Variant<float64>::create(1.0); property = Glib::Variant<float64>::create(1.0);
} else if (property_name == "Metadata") { } else if (property_name == "Metadata") {
const auto state = Media::Player::instance()->getState( const auto state = Media::Player::instance()->getState(
kSongType); Media::Player::instance()->getActiveType());
const auto trackView = [&]() -> std::shared_ptr<Data::DocumentMedia> { const auto trackView = [&]() -> std::shared_ptr<Data::DocumentMedia> {
const auto audioData = state.id.audio(); const auto audioData = state.id.audio();
@ -278,13 +287,13 @@ void HandleGetProperty(
property = Glib::Variant<float64>::create(1.0); property = Glib::Variant<float64>::create(1.0);
} else if (property_name == "PlaybackStatus") { } else if (property_name == "PlaybackStatus") {
const auto state = Media::Player::instance()->getState( const auto state = Media::Player::instance()->getState(
kSongType); Media::Player::instance()->getActiveType());
property = Glib::Variant<Glib::ustring>::create( property = Glib::Variant<Glib::ustring>::create(
PlaybackStatus(state.state)); PlaybackStatus(state.state));
} else if (property_name == "Position") { } else if (property_name == "Position") {
const auto state = Media::Player::instance()->getState( const auto state = Media::Player::instance()->getState(
kSongType); Media::Player::instance()->getActiveType());
property = Glib::Variant<gint64>::create(state.position * 1000); property = Glib::Variant<gint64>::create(state.position * 1000);
} else if (property_name == "Rate") { } else if (property_name == "Rate") {
@ -381,46 +390,46 @@ public:
uint registerId = 0; uint registerId = 0;
uint playerRegisterId = 0; uint playerRegisterId = 0;
std::map<Glib::ustring, Glib::VariantBase> metadata;
Glib::ustring playbackStatus; Glib::ustring playbackStatus;
gint64 position = 0; gint64 position = 0;
DocumentData *audioData = nullptr;
std::shared_ptr<Data::DocumentMedia> trackView; std::shared_ptr<Data::DocumentMedia> trackView;
Image *thumbnail = nullptr;
rpl::lifetime lifetime; rpl::lifetime lifetime;
}; };
void MPRISSupport::Private::updateTrackState( void MPRISSupport::Private::updateTrackState(
const Media::Player::TrackState &state) { const Media::Player::TrackState &state) {
if (state.id.type() != kSongType) { const auto currentAudioData = state.id.audio();
return;
}
const auto audioData = state.id.audio();
if (audioData && audioData->isSongWithCover()) {
const auto view = audioData->createMediaView();
if (!trackView || trackView->owner() != view->owner()) {
trackView = view;
}
} else {
trackView = nullptr;
}
const auto currentMetadata = CreateMetadata(state, trackView.get());
const auto currentPosition = state.position * 1000; const auto currentPosition = state.position * 1000;
const auto currentPlaybackStatus = PlaybackStatus(state.state); const auto currentPlaybackStatus = PlaybackStatus(state.state);
if (!ranges::equal(currentMetadata, metadata, [&]( if (currentAudioData != audioData) {
const auto &item1, audioData = currentAudioData;
const auto &item2) { if (audioData && audioData->isSongWithCover()) {
return item1.first == item2.first trackView = audioData->createMediaView();
&& item1.second.equal(item2.second); thumbnail = trackView->thumbnail();
})) { } else {
metadata = currentMetadata; trackView = nullptr;
thumbnail = nullptr;
}
PlayerPropertyChanged( PlayerPropertyChanged(
"Metadata", "Metadata",
Glib::Variant< Glib::Variant<
std::map<Glib::ustring, Glib::VariantBase> std::map<Glib::ustring, Glib::VariantBase>
>::create(metadata)); >::create(CreateMetadata(state, trackView.get())));
}
if (trackView && (trackView->thumbnail() != thumbnail)) {
thumbnail = trackView->thumbnail();
PlayerPropertyChanged(
"Metadata",
Glib::Variant<
std::map<Glib::ustring, Glib::VariantBase>
>::create(CreateMetadata(state, trackView.get())));
} }
if (currentPlaybackStatus != playbackStatus) { if (currentPlaybackStatus != playbackStatus) {
@ -467,16 +476,20 @@ MPRISSupport::MPRISSupport()
InterfaceVTable); InterfaceVTable);
_private->updateTrackState( _private->updateTrackState(
Media::Player::instance()->getState(kSongType)); Media::Player::instance()->getState(
Media::Player::instance()->getActiveType()));
Core::App().domain().active().session().downloaderTaskFinished( Core::App().domain().active().session().downloaderTaskFinished(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
_private->updateTrackState( _private->updateTrackState(
Media::Player::instance()->getState(kSongType)); Media::Player::instance()->getState(
Media::Player::instance()->getActiveType()));
}, _private->lifetime); }, _private->lifetime);
Media::Player::instance()->updatedNotifier( Media::Player::instance()->updatedNotifier(
) | rpl::start_with_next([=]( ) | rpl::filter([=](const Media::Player::TrackState &state) {
return state.id.type() == Media::Player::instance()->getActiveType();
}) | rpl::start_with_next([=](
const Media::Player::TrackState &state) { const Media::Player::TrackState &state) {
_private->updateTrackState(state); _private->updateTrackState(state);
}, _private->lifetime); }, _private->lifetime);

View file

@ -20,21 +20,21 @@ namespace Platform {
namespace internal { namespace internal {
namespace { namespace {
constexpr auto kNotificationService = "org.freedesktop.Notifications"_cs; constexpr auto kService = "org.freedesktop.Notifications"_cs;
bool IsNotificationServiceActivatable() { auto Activatable() {
static const auto Result = [] { static const auto Result = []() -> std::optional<bool> {
try { try {
const auto connection = Gio::DBus::Connection::get_sync( const auto connection = Gio::DBus::Connection::get_sync(
Gio::DBus::BusType::BUS_TYPE_SESSION); Gio::DBus::BusType::BUS_TYPE_SESSION);
return ranges::contains( return ranges::contains(
base::Platform::DBus::ListActivatableNames(connection), base::Platform::DBus::ListActivatableNames(connection),
Glib::ustring(std::string(kNotificationService))); Glib::ustring(std::string(kService)));
} catch (...) { } catch (...) {
} }
return false; return std::nullopt;
}(); }();
return Result; return Result;
@ -56,14 +56,13 @@ NotificationServiceWatcher::NotificationServiceWatcher()
_private->signalId = base::Platform::DBus::RegisterServiceWatcher( _private->signalId = base::Platform::DBus::RegisterServiceWatcher(
_private->dbusConnection, _private->dbusConnection,
std::string(kNotificationService), std::string(kService),
[]( [](
const Glib::ustring &service, const Glib::ustring &service,
const Glib::ustring &oldOwner, const Glib::ustring &oldOwner,
const Glib::ustring &newOwner) { const Glib::ustring &newOwner) {
if (!Core::App().domain().started() if (!Core::App().domain().started()
|| (IsNotificationServiceActivatable() || (Activatable().value_or(true) && newOwner.empty())) {
&& newOwner.empty())) {
return; return;
} }

View file

@ -16,8 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/openssl_help.h" #include "base/openssl_help.h"
#include "base/qt_adapters.h" #include "base/qt_adapters.h"
#include <QtCore/QMimeType>
#include <QtCore/QMimeDatabase>
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <QtWidgets/QFileDialog> #include <QtWidgets/QFileDialog>
@ -282,7 +280,7 @@ void XDPFileDialog::openPortal() {
if (_acceptMode == QFileDialog::AcceptSave) { if (_acceptMode == QFileDialog::AcceptSave) {
if (!_directory.empty()) { if (!_directory.empty()) {
options["current_folder"] = Glib::Variant<std::string>::create( options["current_folder"] = Glib::Variant<std::string>::create(
_directory +'\0'); _directory + '\0');
} }
if (!_selectedFiles.empty()) { if (!_selectedFiles.empty()) {
@ -302,8 +300,12 @@ void XDPFileDialog::openPortal() {
if (!_mimeTypesFilters.empty()) { if (!_mimeTypesFilters.empty()) {
for (const auto &mimeTypeFilter : _mimeTypesFilters) { for (const auto &mimeTypeFilter : _mimeTypesFilters) {
const auto mimeType = QMimeDatabase().mimeTypeForName( auto mimeTypeUncertain = false;
QString::fromStdString(mimeTypeFilter)); const auto mimeType = Gio::content_type_guess(
mimeTypeFilter,
nullptr,
0,
mimeTypeUncertain);
// Creates e.g. (1, "image/png") // Creates e.g. (1, "image/png")
const auto filterCondition = FilterCondition{ const auto filterCondition = FilterCondition{
@ -313,7 +315,7 @@ void XDPFileDialog::openPortal() {
// Creates e.g. [("Images", [((1, "image/png"))])] // Creates e.g. [("Images", [((1, "image/png"))])]
filterList.push_back({ filterList.push_back({
mimeType.comment().toStdString(), Gio::content_type_get_description(mimeType),
FilterConditionList{filterCondition}, FilterConditionList{filterCondition},
}); });
@ -326,18 +328,16 @@ void XDPFileDialog::openPortal() {
for (const auto &nameFilter : _nameFilters) { for (const auto &nameFilter : _nameFilters) {
// Do parsing: // Do parsing:
// Supported format is ("Images (*.png *.jpg)") // Supported format is ("Images (*.png *.jpg)")
const QRegularExpression regexp( const auto regexp = Glib::Regex::create(filterRegExp);
QString::fromLatin1(filterRegExp));
const QRegularExpressionMatch match = regexp.match( Glib::MatchInfo match;
QString::fromStdString(nameFilter)); regexp->match(nameFilter, match);
if (match.hasMatch()) { if (match.matches()) {
const auto userVisibleName = match.captured(1).toStdString(); const auto userVisibleName = match.fetch(1);
const auto filterStrings = QStringListToStd( const auto filterStrings = Glib::Regex::create(" ")->split(
match.captured(2).split( match.fetch(2),
QLatin1Char(' '), Glib::RegexMatchFlags::REGEX_MATCH_NOTEMPTY);
base::QStringSkipEmptyParts));
if (filterStrings.empty()) { if (filterStrings.empty()) {
LOG(( LOG((

View file

@ -46,6 +46,40 @@ bool InhibitionSupported = false;
std::optional<ServerInformation> CurrentServerInformation; std::optional<ServerInformation> CurrentServerInformation;
QStringList CurrentCapabilities; QStringList CurrentCapabilities;
void StartServiceAsync(
Fn<void()> callback,
const Glib::RefPtr<Gio::Cancellable> &cancellable = Glib::RefPtr<Gio::Cancellable>()) {
try {
const auto connection = Gio::DBus::Connection::get_sync(
Gio::DBus::BusType::BUS_TYPE_SESSION);
base::Platform::DBus::StartServiceByNameAsync(
connection,
std::string(kService),
[=](Fn<base::Platform::DBus::StartReply()> result) {
try {
result(); // get the error if any
} catch (const Glib::Error &e) {
LOG(("Native Notification Error: %1").arg(
QString::fromStdString(e.what())));
} catch (const std::exception &e) {
LOG(("Native Notification Error: %1").arg(
QString::fromStdString(e.what())));
}
crl::on_main([=] { callback(); });
},
cancellable);
return;
} catch (const Glib::Error &e) {
LOG(("Native Notification Error: %1").arg(
QString::fromStdString(e.what())));
}
crl::on_main([=] { callback(); });
}
bool GetServiceRegistered() { bool GetServiceRegistered() {
try { try {
const auto connection = Gio::DBus::Connection::get_sync( const auto connection = Gio::DBus::Connection::get_sync(
@ -125,7 +159,7 @@ void GetServerInformation(
QString::fromStdString(e.what()))); QString::fromStdString(e.what())));
} }
crl::on_main([=] { callback({}); }); crl::on_main([=] { callback(std::nullopt); });
}, },
std::string(kService)); std::string(kService));
@ -244,6 +278,11 @@ bool Inhibited() {
const auto connection = Gio::DBus::Connection::get_sync( const auto connection = Gio::DBus::Connection::get_sync(
Gio::DBus::BusType::BUS_TYPE_SESSION); Gio::DBus::BusType::BUS_TYPE_SESSION);
// a hack for snap's activation restriction
base::Platform::DBus::StartServiceByName(
connection,
std::string(kService));
auto reply = connection->call_sync( auto reply = connection->call_sync(
std::string(kObjectPath), std::string(kObjectPath),
std::string(kPropertiesInterface), std::string(kPropertiesInterface),
@ -336,6 +375,7 @@ public:
private: private:
Glib::RefPtr<Gio::DBus::Connection> _dbusConnection; Glib::RefPtr<Gio::DBus::Connection> _dbusConnection;
Glib::RefPtr<Gio::Cancellable> _cancellable;
base::weak_ptr<Manager> _manager; base::weak_ptr<Manager> _manager;
Glib::ustring _title; Glib::ustring _title;
@ -350,13 +390,13 @@ private:
uint _notificationClosedSignalId = 0; uint _notificationClosedSignalId = 0;
NotificationId _id; NotificationId _id;
void notificationShown(
const Glib::RefPtr<Gio::AsyncResult> &result);
void notificationClosed(uint id, uint reason); void notificationClosed(uint id, uint reason);
void actionInvoked(uint id, const Glib::ustring &actionName); void actionInvoked(uint id, const Glib::ustring &actionName);
void notificationReplied(uint id, const Glib::ustring &text); void notificationReplied(uint id, const Glib::ustring &text);
void notificationShown(
const Glib::RefPtr<Gio::AsyncResult> &result);
void signalEmitted( void signalEmitted(
const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &sender_name, const Glib::ustring &sender_name,
@ -376,7 +416,8 @@ NotificationData::NotificationData(
const QString &msg, const QString &msg,
NotificationId id, NotificationId id,
bool hideReplyButton) bool hideReplyButton)
: _manager(manager) : _cancellable(Gio::Cancellable::create())
, _manager(manager)
, _title(title.toStdString()) , _title(title.toStdString())
, _imageKey(GetImageKey(CurrentServerInformationValue().specVersion)) , _imageKey(GetImageKey(CurrentServerInformationValue().specVersion))
, _id(id) { , _id(id) {
@ -475,6 +516,10 @@ NotificationData::NotificationData(
} }
NotificationData::~NotificationData() { NotificationData::~NotificationData() {
if (_cancellable) {
_cancellable->cancel();
}
if (_dbusConnection) { if (_dbusConnection) {
if (_actionInvokedSignalId != 0) { if (_actionInvokedSignalId != 0) {
_dbusConnection->signal_unsubscribe(_actionInvokedSignalId); _dbusConnection->signal_unsubscribe(_actionInvokedSignalId);
@ -491,7 +536,8 @@ NotificationData::~NotificationData() {
} }
void NotificationData::show() { void NotificationData::show() {
try { // a hack for snap's activation restriction
StartServiceAsync([=] {
const auto iconName = _imageKey.empty() const auto iconName = _imageKey.empty()
|| _hints.find(_imageKey) == end(_hints) || _hints.find(_imageKey) == end(_hints)
? Glib::ustring(GetIconName().toStdString()) ? Glib::ustring(GetIconName().toStdString())
@ -513,16 +559,7 @@ void NotificationData::show() {
}), }),
sigc::mem_fun(this, &NotificationData::notificationShown), sigc::mem_fun(this, &NotificationData::notificationShown),
std::string(kService)); std::string(kService));
} catch (const Glib::Error &e) { }, _cancellable);
LOG(("Native Notification Error: %1").arg(
QString::fromStdString(e.what())));
const auto manager = _manager;
const auto my = _id;
crl::on_main(manager, [=] {
manager->clearNotification(my);
});
}
} }
void NotificationData::notificationShown( void NotificationData::notificationShown(
@ -549,20 +586,15 @@ void NotificationData::notificationShown(
} }
void NotificationData::close() { void NotificationData::close() {
try { _dbusConnection->call(
_dbusConnection->call( std::string(kObjectPath),
std::string(kObjectPath), std::string(kInterface),
std::string(kInterface), "CloseNotification",
"CloseNotification", base::Platform::MakeGlibVariant(std::tuple{
base::Platform::MakeGlibVariant(std::tuple{ _notificationId,
_notificationId, }),
}), {},
{}, std::string(kService));
std::string(kService));
} catch (const Glib::Error &e) {
LOG(("Native Notification Error: %1").arg(
QString::fromStdString(e.what())));
}
} }
void NotificationData::setImage(const QString &imagePath) { void NotificationData::setImage(const QString &imagePath) {
@ -710,8 +742,6 @@ bool ByDefault() {
} }
void Create(Window::Notifications::System *system) { void Create(Window::Notifications::System *system) {
ServiceRegistered = GetServiceRegistered();
const auto managerSetter = [=] { const auto managerSetter = [=] {
using ManagerType = Window::Notifications::ManagerType; using ManagerType = Window::Notifications::ManagerType;
if ((Core::App().settings().nativeNotifications() && Supported()) if ((Core::App().settings().nativeNotifications() && Supported())
@ -726,13 +756,39 @@ void Create(Window::Notifications::System *system) {
} }
}; };
if (!ServiceRegistered) { const auto counter = std::make_shared<int>(3);
CurrentServerInformation = std::nullopt; const auto oneReady = [=] {
CurrentCapabilities = QStringList{}; if (!--*counter) {
InhibitionSupported = false; managerSetter();
managerSetter(); }
return; };
}
const auto serviceActivated = [=] {
ServiceRegistered = GetServiceRegistered();
if (!ServiceRegistered) {
CurrentServerInformation = std::nullopt;
CurrentCapabilities = QStringList{};
InhibitionSupported = false;
managerSetter();
return;
}
GetServerInformation([=](const std::optional<ServerInformation> &result) {
CurrentServerInformation = result;
oneReady();
});
GetCapabilities([=](const QStringList &result) {
CurrentCapabilities = result;
oneReady();
});
GetInhibitionSupported([=](bool result) {
InhibitionSupported = result;
oneReady();
});
};
// There are some asserts that manager is not nullptr, // There are some asserts that manager is not nullptr,
// avoid crashes until some real manager is created // avoid crashes until some real manager is created
@ -741,27 +797,8 @@ void Create(Window::Notifications::System *system) {
system->setManager(std::make_unique<DummyManager>(system)); system->setManager(std::make_unique<DummyManager>(system));
} }
const auto counter = std::make_shared<int>(3); // snap doesn't allow access when the daemon is not running :(
const auto oneReady = [=] { StartServiceAsync(serviceActivated);
if (!--*counter) {
managerSetter();
}
};
GetServerInformation([=](const std::optional<ServerInformation> &result) {
CurrentServerInformation = result;
oneReady();
});
GetCapabilities([=](const QStringList &result) {
CurrentCapabilities = result;
oneReady();
});
GetInhibitionSupported([=](bool result) {
InhibitionSupported = result;
oneReady();
});
} }
class Manager::Private { class Manager::Private {

View file

@ -438,8 +438,7 @@ NotificationsCount::~NotificationsCount() {
NotificationsCount::SampleWidget::SampleWidget( NotificationsCount::SampleWidget::SampleWidget(
NotificationsCount *owner, NotificationsCount *owner,
const QPixmap &cache) const QPixmap &cache)
: QWidget(Core::App().getModalParent()) : _owner(owner)
, _owner(owner)
, _cache(cache) { , _cache(cache) {
const QSize size( const QSize size(
cache.width() / cache.devicePixelRatio(), cache.width() / cache.devicePixelRatio(),

View file

@ -31,8 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui { namespace Ui {
SeparatePanel::SeparatePanel() SeparatePanel::SeparatePanel()
: RpWidget(Core::App().getModalParent()) : _close(this, st::separatePanelClose)
, _close(this, st::separatePanelClose)
, _back(this, object_ptr<Ui::IconButton>(this, st::separatePanelBack)) , _back(this, object_ptr<Ui::IconButton>(this, st::separatePanelBack))
, _body(this) { , _body(this) {
setMouseTracking(true); setMouseTracking(true);

View file

@ -30,7 +30,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "facades.h" #include "facades.h"
#include "app.h" #include "app.h"
#include "mainwindow.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_window.h" #include "styles/style_window.h"
@ -422,8 +421,7 @@ Widget::Widget(
QPoint startPosition, QPoint startPosition,
int shift, int shift,
Direction shiftDirection) Direction shiftDirection)
: RpWidget(Core::App().getModalParent()) : _manager(manager)
, _manager(manager)
, _startPosition(startPosition) , _startPosition(startPosition)
, _direction(shiftDirection) , _direction(shiftDirection)
, _shift(shift) , _shift(shift)

@ -1 +1 @@
Subproject commit c227e5d5ee3bb07b6edaf128fbec665b54050387 Subproject commit abb86932a6215f5df72941e466d22a760efa39de

@ -1 +1 @@
Subproject commit 84a46ce77304eb38380ba76e7b418976008e3d02 Subproject commit 50415733c8c4f6fccc8a9340102abb6a74209b6c