mirror of
https://github.com/telegramdesktop/tdesktop
synced 2024-12-28 01:23:09 +00:00
Add Ui::PostponeCall() on return to event loop.
This commit is contained in:
parent
a167a8587b
commit
89cf733d24
@ -102,6 +102,7 @@ Application::Application(
|
||||
int &argc,
|
||||
char **argv)
|
||||
: QApplication(argc, argv)
|
||||
, _mainThreadId(QThread::currentThreadId())
|
||||
, _launcher(launcher)
|
||||
, _updateChecker(Core::UpdaterDisabled()
|
||||
? nullptr
|
||||
@ -356,6 +357,12 @@ void Application::createMessenger() {
|
||||
Expects(!App::quitting());
|
||||
|
||||
_messengerInstance = std::make_unique<Messenger>(_launcher);
|
||||
|
||||
// Ideally this should go to constructor.
|
||||
// But we want to catch all native events and Messenger installs
|
||||
// its own filter that can filter out some of them. So we install
|
||||
// our filter after the Messenger constructor installs his.
|
||||
installNativeEventFilter(this);
|
||||
}
|
||||
|
||||
void Application::refreshGlobalProxy() {
|
||||
@ -381,6 +388,53 @@ void Application::refreshGlobalProxy() {
|
||||
#endif // TDESKTOP_DISABLE_NETWORK_PROXY
|
||||
}
|
||||
|
||||
void Application::postponeCall(FnMut<void()> &&callable) {
|
||||
Expects(callable != nullptr);
|
||||
Expects(_eventNestingLevel > _loopNestingLevel);
|
||||
|
||||
_postponedCalls.push_back({
|
||||
_loopNestingLevel,
|
||||
std::move(callable)
|
||||
});
|
||||
}
|
||||
|
||||
bool Application::notify(QObject *receiver, QEvent *e) {
|
||||
if (QThread::currentThreadId() != _mainThreadId) {
|
||||
return QApplication::notify(receiver, e);
|
||||
}
|
||||
++_eventNestingLevel;
|
||||
const auto result = QApplication::notify(receiver, e);
|
||||
if (_eventNestingLevel == _loopNestingLevel) {
|
||||
_loopNestingLevel = _previousLoopNestingLevels.back();
|
||||
_previousLoopNestingLevels.pop_back();
|
||||
}
|
||||
processPostponedCalls(--_eventNestingLevel);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Application::processPostponedCalls(int level) {
|
||||
while (!_postponedCalls.empty()) {
|
||||
auto &last = _postponedCalls.back();
|
||||
if (last.loopNestingLevel != level) {
|
||||
break;
|
||||
}
|
||||
auto taken = std::move(last);
|
||||
_postponedCalls.pop_back();
|
||||
taken.callable();
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::nativeEventFilter(
|
||||
const QByteArray &eventType,
|
||||
void *message,
|
||||
long *result) {
|
||||
if (_eventNestingLevel > _loopNestingLevel) {
|
||||
_previousLoopNestingLevels.push_back(_loopNestingLevel);
|
||||
_loopNestingLevel = _eventNestingLevel;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Application::closeApplication() {
|
||||
if (App::launchState() == App::QuitProcessed) return;
|
||||
App::setLaunchState(App::QuitProcessed);
|
||||
|
@ -15,7 +15,7 @@ class UpdateChecker;
|
||||
bool InternalPassportLink(const QString &url);
|
||||
bool StartUrlRequiresActivate(const QString &url);
|
||||
|
||||
class Application : public QApplication {
|
||||
class Application : public QApplication, private QAbstractNativeEventFilter {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -26,6 +26,9 @@ public:
|
||||
void createMessenger();
|
||||
void refreshGlobalProxy();
|
||||
|
||||
void postponeCall(FnMut<void()> &&callable);
|
||||
bool notify(QObject *receiver, QEvent *e) override;
|
||||
|
||||
~Application();
|
||||
|
||||
signals:
|
||||
@ -50,6 +53,23 @@ private:
|
||||
typedef QPair<QLocalSocket*, QByteArray> LocalClient;
|
||||
typedef QList<LocalClient> LocalClients;
|
||||
|
||||
struct PostponedCall {
|
||||
int loopNestingLevel = 0;
|
||||
FnMut<void()> callable;
|
||||
};
|
||||
|
||||
bool nativeEventFilter(
|
||||
const QByteArray &eventType,
|
||||
void *message,
|
||||
long *result) override;
|
||||
void processPostponedCalls(int level);
|
||||
|
||||
const Qt::HANDLE _mainThreadId = nullptr;
|
||||
int _eventNestingLevel = 0;
|
||||
int _loopNestingLevel = 0;
|
||||
std::vector<int> _previousLoopNestingLevels;
|
||||
std::vector<PostponedCall> _postponedCalls;
|
||||
|
||||
not_null<Core::Launcher*> _launcher;
|
||||
std::unique_ptr<Messenger> _messengerInstance;
|
||||
|
||||
|
@ -233,6 +233,11 @@ void ForceFullRepaint(not_null<QWidget*> widget) {
|
||||
refresher->show();
|
||||
}
|
||||
|
||||
void PostponeCall(FnMut<void()> &&callable) {
|
||||
const auto app = static_cast<Application*>(qApp);
|
||||
app->postponeCall(std::move(callable));
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
||||
void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button, const QPoint &globalPoint) {
|
||||
|
@ -59,6 +59,20 @@ QImage GrabWidgetToImage(
|
||||
|
||||
void ForceFullRepaint(not_null<QWidget*> widget);
|
||||
|
||||
void PostponeCall(FnMut<void()> &&callable);
|
||||
|
||||
template <
|
||||
typename Guard,
|
||||
typename Callable,
|
||||
typename GuardTraits = crl::guard_traits<std::decay_t<Guard>>,
|
||||
typename = std::enable_if_t<
|
||||
sizeof(GuardTraits) != crl::details::dependent_zero<GuardTraits>>>
|
||||
inline void PostponeCall(Guard &&object, Callable &&callable) {
|
||||
return PostponeCall(crl::guard(
|
||||
std::forward<Guard>(object),
|
||||
std::forward<Callable>(callable)));
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
||||
enum class RectPart {
|
||||
|
@ -375,7 +375,7 @@ void LayerStackWidget::keyPressEvent(QKeyEvent *e) {
|
||||
}
|
||||
|
||||
void LayerStackWidget::mousePressEvent(QMouseEvent *e) {
|
||||
crl::on_main(this, [=] { backgroundClicked(); });
|
||||
Ui::PostponeCall(this, [=] { backgroundClicked(); });
|
||||
}
|
||||
|
||||
void LayerStackWidget::backgroundClicked() {
|
||||
|
Loading…
Reference in New Issue
Block a user