forked from quickshell/quickshell
		
	root: recreate the qml engine on reload instead of clearing it
This causes singletons to be recreated instead of kept alive.
This commit is contained in:
		
							parent
							
								
									9f6ef37f61
								
							
						
					
					
						commit
						463f9a297f
					
				
					 9 changed files with 109 additions and 78 deletions
				
			
		| 
						 | 
				
			
			@ -70,21 +70,26 @@ file(GENERATE
 | 
			
		|||
	CONTENT ""
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_library(qt-pch ${CMAKE_CURRENT_BINARY_DIR}/pchstub.cpp)
 | 
			
		||||
target_link_libraries(qt-pch PRIVATE ${QT_DEPS})
 | 
			
		||||
target_precompile_headers(qt-pch PUBLIC
 | 
			
		||||
	<memory>
 | 
			
		||||
	<qobject.h>
 | 
			
		||||
	<qqmlengine.h>
 | 
			
		||||
	<qlist.h>
 | 
			
		||||
	<qcolor.h>
 | 
			
		||||
	<qquickitem.h>
 | 
			
		||||
	<qevent.h>
 | 
			
		||||
)
 | 
			
		||||
# pch breaks clang-tidy..... somehow
 | 
			
		||||
if (NOT NO_PCH)
 | 
			
		||||
	add_library(qt-pch ${CMAKE_CURRENT_BINARY_DIR}/pchstub.cpp)
 | 
			
		||||
	target_link_libraries(qt-pch PRIVATE ${QT_DEPS})
 | 
			
		||||
	target_precompile_headers(qt-pch PUBLIC
 | 
			
		||||
		<memory>
 | 
			
		||||
		<qobject.h>
 | 
			
		||||
		<qqmlengine.h>
 | 
			
		||||
		<qlist.h>
 | 
			
		||||
		<qcolor.h>
 | 
			
		||||
		<qquickitem.h>
 | 
			
		||||
		<qevent.h>
 | 
			
		||||
	)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
function (qs_pch target)
 | 
			
		||||
	target_precompile_headers(${target} REUSE_FROM qt-pch)
 | 
			
		||||
	target_link_libraries(${target} PRIVATE ${QT_DEPS}) # required for gcc to accept the pch on plugin targets
 | 
			
		||||
	if (NOT NO_PCH)
 | 
			
		||||
		target_precompile_headers(${target} REUSE_FROM qt-pch)
 | 
			
		||||
		target_link_libraries(${target} PRIVATE ${QT_DEPS}) # required for gcc to accept the pch on plugin targets
 | 
			
		||||
  endif()
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
add_subdirectory(src)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
#include "main.hpp"
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include <qcommandlineoption.h>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,38 +57,81 @@ void QuickshellSettings::setWatchFiles(bool watchFiles) {
 | 
			
		|||
	emit this->watchFilesChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QuickshellGlobal::QuickshellGlobal(QObject* parent): QObject(parent) {
 | 
			
		||||
	// clang-format off
 | 
			
		||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::workingDirectoryChanged, this, &QuickshellGlobal::workingDirectoryChanged);
 | 
			
		||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::watchFilesChanged, this, &QuickshellGlobal::watchFilesChanged);
 | 
			
		||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::lastWindowClosed, this, &QuickshellGlobal::lastWindowClosed);
 | 
			
		||||
	// clang-format on
 | 
			
		||||
 | 
			
		||||
QuickshellTracked::QuickshellTracked() {
 | 
			
		||||
	auto* app = QCoreApplication::instance();
 | 
			
		||||
	auto* guiApp = qobject_cast<QGuiApplication*>(app);
 | 
			
		||||
 | 
			
		||||
	if (guiApp != nullptr) {
 | 
			
		||||
		// clang-format off
 | 
			
		||||
		QObject::connect(guiApp, &QGuiApplication::primaryScreenChanged, this, &QuickshellGlobal::updateScreens);
 | 
			
		||||
		QObject::connect(guiApp, &QGuiApplication::screenAdded, this, &QuickshellGlobal::updateScreens);
 | 
			
		||||
		QObject::connect(guiApp, &QGuiApplication::screenRemoved, this, &QuickshellGlobal::updateScreens);
 | 
			
		||||
		QObject::connect(guiApp, &QGuiApplication::primaryScreenChanged, this, &QuickshellTracked::updateScreens);
 | 
			
		||||
		QObject::connect(guiApp, &QGuiApplication::screenAdded, this, &QuickshellTracked::updateScreens);
 | 
			
		||||
		QObject::connect(guiApp, &QGuiApplication::screenRemoved, this, &QuickshellTracked::updateScreens);
 | 
			
		||||
		// clang-format on
 | 
			
		||||
 | 
			
		||||
		this->updateScreens();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QuickshellTracked* QuickshellTracked::instance() {
 | 
			
		||||
	static QuickshellTracked* instance = nullptr; // NOLINT
 | 
			
		||||
	if (instance == nullptr) {
 | 
			
		||||
		QJSEngine::setObjectOwnership(instance, QJSEngine::CppOwnership);
 | 
			
		||||
		instance = new QuickshellTracked();
 | 
			
		||||
	}
 | 
			
		||||
	return instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QuickshellTracked::updateScreens() {
 | 
			
		||||
	auto screens = QGuiApplication::screens();
 | 
			
		||||
	auto newScreens = QList<QuickshellScreenInfo*>();
 | 
			
		||||
 | 
			
		||||
	for (auto* newScreen: screens) {
 | 
			
		||||
		for (auto i = 0; i < this->screens.length(); i++) {
 | 
			
		||||
			auto* oldScreen = this->screens[i];
 | 
			
		||||
			if (newScreen == oldScreen->screen) {
 | 
			
		||||
				newScreens.push_back(oldScreen);
 | 
			
		||||
				this->screens.remove(i);
 | 
			
		||||
				goto next;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			auto* si = new QuickshellScreenInfo(this, newScreen);
 | 
			
		||||
			QQmlEngine::setObjectOwnership(si, QQmlEngine::CppOwnership);
 | 
			
		||||
			newScreens.push_back(si);
 | 
			
		||||
		}
 | 
			
		||||
	next:;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (auto* oldScreen: this->screens) {
 | 
			
		||||
		oldScreen->deleteLater();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->screens = newScreens;
 | 
			
		||||
	emit this->screensChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QuickshellGlobal::QuickshellGlobal(QObject* parent): QObject(parent) {
 | 
			
		||||
	// clang-format off
 | 
			
		||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::workingDirectoryChanged, this, &QuickshellGlobal::workingDirectoryChanged);
 | 
			
		||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::watchFilesChanged, this, &QuickshellGlobal::watchFilesChanged);
 | 
			
		||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::lastWindowClosed, this, &QuickshellGlobal::lastWindowClosed);
 | 
			
		||||
 | 
			
		||||
	QObject::connect(QuickshellTracked::instance(), &QuickshellTracked::screensChanged, this, &QuickshellGlobal::screensChanged);
 | 
			
		||||
	// clang-format on
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qint32 QuickshellGlobal::processId() const { // NOLINT
 | 
			
		||||
	return getpid();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qsizetype QuickshellGlobal::screensCount(QQmlListProperty<QuickshellScreenInfo>* prop) {
 | 
			
		||||
	return static_cast<QuickshellGlobal*>(prop->object)->mScreens.size(); // NOLINT
 | 
			
		||||
qsizetype QuickshellGlobal::screensCount(QQmlListProperty<QuickshellScreenInfo>* /*unused*/) {
 | 
			
		||||
	return QuickshellTracked::instance()->screens.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QuickshellScreenInfo*
 | 
			
		||||
QuickshellGlobal::screenAt(QQmlListProperty<QuickshellScreenInfo>* prop, qsizetype i) {
 | 
			
		||||
	return static_cast<QuickshellGlobal*>(prop->object)->mScreens.at(i); // NOLINT
 | 
			
		||||
QuickshellGlobal::screenAt(QQmlListProperty<QuickshellScreenInfo>* /*unused*/, qsizetype i) {
 | 
			
		||||
	return QuickshellTracked::instance()->screens.at(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QQmlListProperty<QuickshellScreenInfo> QuickshellGlobal::screens() {
 | 
			
		||||
| 
						 | 
				
			
			@ -128,36 +171,6 @@ void QuickshellGlobal::setWatchFiles(bool watchFiles) { // NOLINT
 | 
			
		|||
	QuickshellSettings::instance()->setWatchFiles(watchFiles);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QuickshellGlobal::updateScreens() {
 | 
			
		||||
	auto screens = QGuiApplication::screens();
 | 
			
		||||
	auto newScreens = QList<QuickshellScreenInfo*>();
 | 
			
		||||
 | 
			
		||||
	for (auto* newScreen: screens) {
 | 
			
		||||
		for (auto i = 0; i < this->mScreens.length(); i++) {
 | 
			
		||||
			auto* oldScreen = this->mScreens[i];
 | 
			
		||||
			if (newScreen == oldScreen->screen) {
 | 
			
		||||
				newScreens.push_back(oldScreen);
 | 
			
		||||
				this->mScreens.remove(i);
 | 
			
		||||
				goto next;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			auto* si = new QuickshellScreenInfo(this, newScreen);
 | 
			
		||||
			QQmlEngine::setObjectOwnership(si, QQmlEngine::CppOwnership);
 | 
			
		||||
			newScreens.push_back(si);
 | 
			
		||||
		}
 | 
			
		||||
	next:;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (auto* oldScreen: this->mScreens) {
 | 
			
		||||
		oldScreen->deleteLater();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->mScreens = newScreens;
 | 
			
		||||
	emit this->screensChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant QuickshellGlobal::env(const QString& variable) { // NOLINT
 | 
			
		||||
	auto vstr = variable.toStdString();
 | 
			
		||||
	if (!qEnvironmentVariableIsSet(vstr.data())) return QVariant::fromValue(nullptr);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,6 +53,23 @@ private:
 | 
			
		|||
	bool mWatchFiles = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QuickshellTracked: public QObject {
 | 
			
		||||
	Q_OBJECT;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	QuickshellTracked();
 | 
			
		||||
 | 
			
		||||
	QVector<QuickshellScreenInfo*> screens;
 | 
			
		||||
 | 
			
		||||
	static QuickshellTracked* instance();
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
	void updateScreens();
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	void screensChanged();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QuickshellGlobal: public QObject {
 | 
			
		||||
	Q_OBJECT;
 | 
			
		||||
	// clang-format off
 | 
			
		||||
| 
						 | 
				
			
			@ -124,12 +141,7 @@ signals:
 | 
			
		|||
	void workingDirectoryChanged();
 | 
			
		||||
	void watchFilesChanged();
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
	void updateScreens();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	static qsizetype screensCount(QQmlListProperty<QuickshellScreenInfo>* prop);
 | 
			
		||||
	static QuickshellScreenInfo* screenAt(QQmlListProperty<QuickshellScreenInfo>* prop, qsizetype i);
 | 
			
		||||
 | 
			
		||||
	QVector<QuickshellScreenInfo*> mScreens;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,12 +21,7 @@
 | 
			
		|||
RootWrapper::RootWrapper(QString rootPath)
 | 
			
		||||
    : QObject(nullptr)
 | 
			
		||||
    , rootPath(std::move(rootPath))
 | 
			
		||||
    , engine(this)
 | 
			
		||||
    , originalWorkingDirectory(QDir::current().absolutePath()) {
 | 
			
		||||
	auto* app = QCoreApplication::instance();
 | 
			
		||||
	QObject::connect(&this->engine, &QQmlEngine::quit, app, &QCoreApplication::quit);
 | 
			
		||||
	QObject::connect(&this->engine, &QQmlEngine::exit, app, &QCoreApplication::exit);
 | 
			
		||||
 | 
			
		||||
	// clang-format off
 | 
			
		||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::watchFilesChanged, this, &RootWrapper::onWatchFilesChanged);
 | 
			
		||||
	// clang-format on
 | 
			
		||||
| 
						 | 
				
			
			@ -45,16 +40,22 @@ RootWrapper::~RootWrapper() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void RootWrapper::reloadGraph(bool hard) {
 | 
			
		||||
	auto* oldEngine = this->engine;
 | 
			
		||||
	this->engine = new QQmlEngine(this);
 | 
			
		||||
 | 
			
		||||
	auto* app = QCoreApplication::instance();
 | 
			
		||||
	QObject::connect(this->engine, &QQmlEngine::quit, app, &QCoreApplication::quit);
 | 
			
		||||
	QObject::connect(this->engine, &QQmlEngine::exit, app, &QCoreApplication::exit);
 | 
			
		||||
 | 
			
		||||
	if (this->root != nullptr) {
 | 
			
		||||
		QuickshellSettings::reset();
 | 
			
		||||
		this->engine.clearComponentCache();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	QDir::setCurrent(this->originalWorkingDirectory);
 | 
			
		||||
 | 
			
		||||
	auto component = QQmlComponent(&this->engine, QUrl::fromLocalFile(this->rootPath));
 | 
			
		||||
	auto component = QQmlComponent(this->engine, QUrl::fromLocalFile(this->rootPath));
 | 
			
		||||
 | 
			
		||||
	auto* obj = component.beginCreate(this->engine.rootContext());
 | 
			
		||||
	auto* obj = component.beginCreate(this->engine->rootContext());
 | 
			
		||||
 | 
			
		||||
	if (obj == nullptr) {
 | 
			
		||||
		qWarning() << component.errorString().toStdString().c_str();
 | 
			
		||||
| 
						 | 
				
			
			@ -90,6 +91,8 @@ void RootWrapper::reloadGraph(bool hard) {
 | 
			
		|||
		QuickshellPlugin::runOnReload();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	delete oldEngine;
 | 
			
		||||
 | 
			
		||||
	this->onWatchFilesChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ private slots:
 | 
			
		|||
 | 
			
		||||
private:
 | 
			
		||||
	QString rootPath;
 | 
			
		||||
	QQmlEngine engine;
 | 
			
		||||
	QQmlEngine* engine = nullptr;
 | 
			
		||||
	ShellRoot* root = nullptr;
 | 
			
		||||
	FiletreeWatcher* configWatcher = nullptr;
 | 
			
		||||
	QString originalWorkingDirectory;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
#include "core/main.hpp"
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv) {
 | 
			
		||||
	return qs_main(argc, argv);
 | 
			
		||||
}
 | 
			
		||||
int main(int argc, char** argv) { return qs_main(argc, argv); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,7 +78,8 @@ void WlSessionLock::updateSurfaces(WlSessionLock* old) {
 | 
			
		|||
				auto* instance = qobject_cast<WlSessionLockSurface*>(instanceObj);
 | 
			
		||||
 | 
			
		||||
				if (instance == nullptr) {
 | 
			
		||||
					qWarning() << "WlSessionLock.surface does not create a WlSessionLockSurface. Aborting lock.";
 | 
			
		||||
					qWarning(
 | 
			
		||||
					) << "WlSessionLock.surface does not create a WlSessionLockSurface. Aborting lock.";
 | 
			
		||||
					if (instanceObj != nullptr) instanceObj->deleteLater();
 | 
			
		||||
					this->unlock();
 | 
			
		||||
					return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ enum Enum {
 | 
			
		|||
};
 | 
			
		||||
Q_ENUM_NS(Enum);
 | 
			
		||||
 | 
			
		||||
} // namespace Layer
 | 
			
		||||
} // namespace WlrLayer
 | 
			
		||||
 | 
			
		||||
///! WlrLayershell keyboard focus mode
 | 
			
		||||
namespace WlrKeyboardFocus { // NOLINT
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ enum Enum {
 | 
			
		|||
};
 | 
			
		||||
Q_ENUM_NS(Enum);
 | 
			
		||||
 | 
			
		||||
} // namespace KeyboardFocus
 | 
			
		||||
} // namespace WlrKeyboardFocus
 | 
			
		||||
 | 
			
		||||
class QSWaylandLayerSurface;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue