mirror of https://github.com/procxx/kepka.git
				
				
				
			Fix postponed calls from crl::on_main() on macOS.
In libdispatch crl::on_main() implementation we bypass Application::notify() frame. So we handle event loop nesting control manually by wrapping all invokations done through crl::on_main() with the same methods we do from Application::notify().
This commit is contained in:
		
							parent
							
								
									d17c985bcb
								
							
						
					
					
						commit
						d539d9b5d2
					
				|  | @ -416,12 +416,11 @@ void Application::postponeCall(FnMut<void()> &&callable) { | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Application::notify(QObject *receiver, QEvent *e) { | void Application::incrementEventNestingLevel() { | ||||||
| 	if (QThread::currentThreadId() != _mainThreadId) { |  | ||||||
| 		return QApplication::notify(receiver, e); |  | ||||||
| 	} |  | ||||||
| 	++_eventNestingLevel; | 	++_eventNestingLevel; | ||||||
| 	const auto result = QApplication::notify(receiver, e); | } | ||||||
|  | 
 | ||||||
|  | void Application::decrementEventNestingLevel() { | ||||||
| 	if (_eventNestingLevel == _loopNestingLevel) { | 	if (_eventNestingLevel == _loopNestingLevel) { | ||||||
| 		_loopNestingLevel = _previousLoopNestingLevels.back(); | 		_loopNestingLevel = _previousLoopNestingLevels.back(); | ||||||
| 		_previousLoopNestingLevels.pop_back(); | 		_previousLoopNestingLevels.pop_back(); | ||||||
|  | @ -429,7 +428,22 @@ bool Application::notify(QObject *receiver, QEvent *e) { | ||||||
| 	const auto processTillLevel = _eventNestingLevel - 1; | 	const auto processTillLevel = _eventNestingLevel - 1; | ||||||
| 	processPostponedCalls(processTillLevel); | 	processPostponedCalls(processTillLevel); | ||||||
| 	_eventNestingLevel = processTillLevel; | 	_eventNestingLevel = processTillLevel; | ||||||
| 	return result; | } | ||||||
|  | 
 | ||||||
|  | void Application::registerEnterFromEventLoop() { | ||||||
|  | 	if (_eventNestingLevel > _loopNestingLevel) { | ||||||
|  | 		_previousLoopNestingLevels.push_back(_loopNestingLevel); | ||||||
|  | 		_loopNestingLevel = _eventNestingLevel; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Application::notify(QObject *receiver, QEvent *e) { | ||||||
|  | 	if (QThread::currentThreadId() != _mainThreadId) { | ||||||
|  | 		return QApplication::notify(receiver, e); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const auto wrap = createEventNestingLevel(); | ||||||
|  | 	return QApplication::notify(receiver, e); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Application::processPostponedCalls(int level) { | void Application::processPostponedCalls(int level) { | ||||||
|  | @ -448,10 +462,7 @@ bool Application::nativeEventFilter( | ||||||
| 		const QByteArray &eventType, | 		const QByteArray &eventType, | ||||||
| 		void *message, | 		void *message, | ||||||
| 		long *result) { | 		long *result) { | ||||||
| 	if (_eventNestingLevel > _loopNestingLevel) { | 	registerEnterFromEventLoop(); | ||||||
| 		_previousLoopNestingLevels.push_back(_loopNestingLevel); |  | ||||||
| 		_loopNestingLevel = _eventNestingLevel; |  | ||||||
| 	} |  | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,6 +28,11 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void postponeCall(FnMut<void()> &&callable); | 	void postponeCall(FnMut<void()> &&callable); | ||||||
| 	bool notify(QObject *receiver, QEvent *e) override; | 	bool notify(QObject *receiver, QEvent *e) override; | ||||||
|  | 	void registerEnterFromEventLoop(); | ||||||
|  | 	auto createEventNestingLevel() { | ||||||
|  | 		incrementEventNestingLevel(); | ||||||
|  | 		return gsl::finally([=] { decrementEventNestingLevel(); }); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	void activateWindowDelayed(not_null<QWidget*> widget); | 	void activateWindowDelayed(not_null<QWidget*> widget); | ||||||
| 	void pauseDelayedWindowActivations(); | 	void pauseDelayedWindowActivations(); | ||||||
|  | @ -65,6 +70,8 @@ private: | ||||||
| 		FnMut<void()> callable; | 		FnMut<void()> callable; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	void incrementEventNestingLevel(); | ||||||
|  | 	void decrementEventNestingLevel(); | ||||||
| 	bool nativeEventFilter( | 	bool nativeEventFilter( | ||||||
| 		const QByteArray &eventType, | 		const QByteArray &eventType, | ||||||
| 		void *message, | 		void *message, | ||||||
|  |  | ||||||
|  | @ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||||||
| */ | */ | ||||||
| #include "core/main_queue_processor.h" | #include "core/main_queue_processor.h" | ||||||
| 
 | 
 | ||||||
|  | #include "application.h" | ||||||
|  | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
|  | @ -38,15 +40,6 @@ void ProcessorEvent::process() { | ||||||
| 	_callable(_argument); | 	_callable(_argument); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ProcessMainQueue(void (*callable)(void*), void *argument) { |  | ||||||
| 	QMutexLocker lock(&ProcessorMutex); |  | ||||||
| 
 |  | ||||||
| 	if (ProcessorInstance) { |  | ||||||
| 		const auto event = new ProcessorEvent(callable, argument); |  | ||||||
| 		QCoreApplication::postEvent(ProcessorInstance, event); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessObservables() { | void ProcessObservables() { | ||||||
| 	Global::RefHandleObservables().call(); | 	Global::RefHandleObservables().call(); | ||||||
| } | } | ||||||
|  | @ -55,7 +48,20 @@ void ProcessObservables() { | ||||||
| 
 | 
 | ||||||
| MainQueueProcessor::MainQueueProcessor() { | MainQueueProcessor::MainQueueProcessor() { | ||||||
| 	acquire(); | 	acquire(); | ||||||
| 	crl::init_main_queue(ProcessMainQueue); | 
 | ||||||
|  | 	crl::init_main_queue([](void (*callable)(void*), void *argument) { | ||||||
|  | 		QMutexLocker lock(&ProcessorMutex); | ||||||
|  | 
 | ||||||
|  | 		if (ProcessorInstance) { | ||||||
|  | 			const auto event = new ProcessorEvent(callable, argument); | ||||||
|  | 			QCoreApplication::postEvent(ProcessorInstance, event); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	crl::wrap_main_queue([](void (*callable)(void*), void *argument) { | ||||||
|  | 		App().registerEnterFromEventLoop(); | ||||||
|  | 		const auto wrap = App().createEventNestingLevel(); | ||||||
|  | 		callable(argument); | ||||||
|  | 	}); | ||||||
| 
 | 
 | ||||||
| 	base::InitObservables(ProcessObservables); | 	base::InitObservables(ProcessObservables); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit 4291015efab76bda5886a56b5007f4531be17d46 | Subproject commit 9b7c6b5d9f1b59d2160bf6e9c4e74510f955efe1 | ||||||
		Loading…
	
		Reference in New Issue