forked from quickshell/quickshell
		
	all: optimize build
This commit is contained in:
		
							parent
							
								
									1168879d6d
								
							
						
					
					
						commit
						7ffce72b31
					
				
					 51 changed files with 1526 additions and 1277 deletions
				
			
		| 
						 | 
					@ -65,6 +65,7 @@ boption(SERVICE_UPOWER "UPower" ON)
 | 
				
			||||||
boption(SERVICE_NOTIFICATIONS "Notifications" ON)
 | 
					boption(SERVICE_NOTIFICATIONS "Notifications" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include(cmake/install-qml-module.cmake)
 | 
					include(cmake/install-qml-module.cmake)
 | 
				
			||||||
 | 
					include(cmake/util.cmake)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_compile_options(-Wall -Wextra)
 | 
					add_compile_options(-Wall -Wextra)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,9 +88,10 @@ if (NOT CMAKE_BUILD_TYPE)
 | 
				
			||||||
	set(CMAKE_BUILD_TYPE Debug)
 | 
						set(CMAKE_BUILD_TYPE Debug)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(QT_DEPS Qt6::Gui Qt6::Qml Qt6::Quick Qt6::QuickControls2 Qt6::Widgets)
 | 
					 | 
				
			||||||
set(QT_FPDEPS Gui Qml Quick QuickControls2 Widgets)
 | 
					set(QT_FPDEPS Gui Qml Quick QuickControls2 Widgets)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(cmake/pch.cmake)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (BUILD_TESTING)
 | 
					if (BUILD_TESTING)
 | 
				
			||||||
	enable_testing()
 | 
						enable_testing()
 | 
				
			||||||
	add_definitions(-DQS_TEST)
 | 
						add_definitions(-DQS_TEST)
 | 
				
			||||||
| 
						 | 
					@ -97,56 +99,27 @@ if (BUILD_TESTING)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (SOCKETS)
 | 
					if (SOCKETS)
 | 
				
			||||||
	list(APPEND QT_DEPS Qt6::Network)
 | 
					 | 
				
			||||||
	list(APPEND QT_FPDEPS Network)
 | 
						list(APPEND QT_FPDEPS Network)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (WAYLAND)
 | 
					if (WAYLAND)
 | 
				
			||||||
	list(APPEND QT_DEPS Qt6::WaylandClient Qt6::WaylandClientPrivate)
 | 
					 | 
				
			||||||
	list(APPEND QT_FPDEPS WaylandClient)
 | 
						list(APPEND QT_FPDEPS WaylandClient)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (SERVICE_STATUS_NOTIFIER OR SERVICE_MPRIS)
 | 
					if (SERVICE_STATUS_NOTIFIER OR SERVICE_MPRIS OR SERVICE_UPOWER OR SERVICE_NOTIFICATIONS)
 | 
				
			||||||
	set(DBUS ON)
 | 
						set(DBUS ON)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (DBUS)
 | 
					if (DBUS)
 | 
				
			||||||
	list(APPEND QT_DEPS Qt6::DBus)
 | 
					 | 
				
			||||||
	list(APPEND QT_FPDEPS DBus)
 | 
						list(APPEND QT_FPDEPS DBus)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
find_package(Qt6 REQUIRED COMPONENTS ${QT_FPDEPS})
 | 
					find_package(Qt6 REQUIRED COMPONENTS ${QT_FPDEPS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_AUTOUIC OFF)
 | 
				
			||||||
qt_standard_project_setup(REQUIRES 6.6)
 | 
					qt_standard_project_setup(REQUIRES 6.6)
 | 
				
			||||||
set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml_modules)
 | 
					set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml_modules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# pch breaks clang-tidy..... somehow
 | 
					 | 
				
			||||||
if (NOT NO_PCH)
 | 
					 | 
				
			||||||
	file(GENERATE
 | 
					 | 
				
			||||||
		OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pchstub.cpp
 | 
					 | 
				
			||||||
		CONTENT "// intentionally empty"
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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)
 | 
					 | 
				
			||||||
	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)
 | 
					add_subdirectory(src)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (USE_JEMALLOC)
 | 
					if (USE_JEMALLOC)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										85
									
								
								cmake/pch.cmake
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								cmake/pch.cmake
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,85 @@
 | 
				
			||||||
 | 
					# pch breaks clang-tidy..... somehow
 | 
				
			||||||
 | 
					if (NOT NO_PCH)
 | 
				
			||||||
 | 
						file(GENERATE
 | 
				
			||||||
 | 
							OUTPUT ${CMAKE_BINARY_DIR}/pchstub.cpp
 | 
				
			||||||
 | 
							CONTENT "// intentionally empty"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function (qs_pch target)
 | 
				
			||||||
 | 
						if (NO_PCH)
 | 
				
			||||||
 | 
							return()
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmake_parse_arguments(PARSE_ARGV 1 arg "" "SET" "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ("${arg_SET}" STREQUAL "")
 | 
				
			||||||
 | 
							set(arg_SET "common")
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						target_precompile_headers(${target} REUSE_FROM "qs-pchset-${arg_SET}")
 | 
				
			||||||
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function (qs_module_pch target)
 | 
				
			||||||
 | 
						qs_pch(${target} ${ARGN})
 | 
				
			||||||
 | 
						qs_pch("${target}plugin" SET plugin)
 | 
				
			||||||
 | 
						qs_pch("${target}plugin_init" SET plugin)
 | 
				
			||||||
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function (qs_add_pchset SETNAME)
 | 
				
			||||||
 | 
						if (NO_PCH)
 | 
				
			||||||
 | 
							return()
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "HEADERS;DEPENDENCIES")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set(LIBNAME "qs-pchset-${SETNAME}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						add_library(${LIBNAME} ${CMAKE_BINARY_DIR}/pchstub.cpp)
 | 
				
			||||||
 | 
						target_link_libraries(${LIBNAME} ${arg_DEPENDENCIES})
 | 
				
			||||||
 | 
						target_precompile_headers(${LIBNAME} PUBLIC ${arg_HEADERS})
 | 
				
			||||||
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(COMMON_PCH_SET
 | 
				
			||||||
 | 
						<chrono>
 | 
				
			||||||
 | 
						<memory>
 | 
				
			||||||
 | 
						<vector>
 | 
				
			||||||
 | 
						<qdebug.h>
 | 
				
			||||||
 | 
						<qobject.h>
 | 
				
			||||||
 | 
						<qmetatype.h>
 | 
				
			||||||
 | 
						<qstring.h>
 | 
				
			||||||
 | 
						<qchar.h>
 | 
				
			||||||
 | 
						<qlist.h>
 | 
				
			||||||
 | 
						<qabstractitemmodel.h>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_pchset(common
 | 
				
			||||||
 | 
						DEPENDENCIES Qt::Quick
 | 
				
			||||||
 | 
						HEADERS ${COMMON_PCH_SET}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_pchset(large
 | 
				
			||||||
 | 
						DEPENDENCIES Qt::Quick
 | 
				
			||||||
 | 
						HEADERS
 | 
				
			||||||
 | 
							${COMMON_PCH_SET}
 | 
				
			||||||
 | 
							<qiodevice.h>
 | 
				
			||||||
 | 
							<qevent.h>
 | 
				
			||||||
 | 
							<qcoreapplication.h>
 | 
				
			||||||
 | 
							<qqmlengine.h>
 | 
				
			||||||
 | 
							<qquickitem.h>
 | 
				
			||||||
 | 
							<qquickwindow.h>
 | 
				
			||||||
 | 
							<qcolor.h>
 | 
				
			||||||
 | 
							<qdir.h>
 | 
				
			||||||
 | 
							<qtimer.h>
 | 
				
			||||||
 | 
							<qabstractitemmodel.h>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# including qplugin.h directly will cause required symbols to disappear
 | 
				
			||||||
 | 
					qs_add_pchset(plugin
 | 
				
			||||||
 | 
						DEPENDENCIES Qt::Qml
 | 
				
			||||||
 | 
						HEADERS
 | 
				
			||||||
 | 
							<qobject.h>
 | 
				
			||||||
 | 
							<qjsonobject.h>
 | 
				
			||||||
 | 
							<qpointer.h>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										20
									
								
								cmake/util.cmake
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								cmake/util.cmake
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					function (qs_append_qmldir target text)
 | 
				
			||||||
 | 
						get_property(qmldir_content TARGET ${target} PROPERTY _qt_internal_qmldir_content)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ("${qmldir_content}" STREQUAL "")
 | 
				
			||||||
 | 
							message(WARNING "qs_append_qmldir depends on private Qt cmake code, which has broken.")
 | 
				
			||||||
 | 
							return()
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set_property(TARGET ${target} APPEND_STRING PROPERTY _qt_internal_qmldir_content ${text})
 | 
				
			||||||
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# DEPENDENCIES introduces a cmake dependency which we don't need with static modules.
 | 
				
			||||||
 | 
					# This greatly improves comp speed by not introducing those dependencies.
 | 
				
			||||||
 | 
					function (qs_add_module_deps_light target)
 | 
				
			||||||
 | 
						foreach (dep IN LISTS ARGN)
 | 
				
			||||||
 | 
							string(APPEND qmldir_extra "depends ${dep}\n")
 | 
				
			||||||
 | 
						endforeach()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qs_append_qmldir(${target} "${qmldir_extra}")
 | 
				
			||||||
 | 
					endfunction()
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,8 @@
 | 
				
			||||||
qt_add_executable(quickshell main.cpp)
 | 
					qt_add_executable(quickshell main.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE ${QT_DEPS} quickshell-build)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
install(TARGETS quickshell RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
 | 
					install(TARGETS quickshell RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_subdirectory(launch)
 | 
				
			||||||
add_subdirectory(build)
 | 
					add_subdirectory(build)
 | 
				
			||||||
add_subdirectory(core)
 | 
					add_subdirectory(core)
 | 
				
			||||||
add_subdirectory(ipc)
 | 
					add_subdirectory(ipc)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,3 @@
 | 
				
			||||||
find_package(CLI11 CONFIG REQUIRED)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
qt_add_library(quickshell-core STATIC
 | 
					qt_add_library(quickshell-core STATIC
 | 
				
			||||||
	plugin.cpp
 | 
						plugin.cpp
 | 
				
			||||||
	shell.cpp
 | 
						shell.cpp
 | 
				
			||||||
| 
						 | 
					@ -37,10 +35,9 @@ qt_add_library(quickshell-core STATIC
 | 
				
			||||||
	paths.cpp
 | 
						paths.cpp
 | 
				
			||||||
	instanceinfo.cpp
 | 
						instanceinfo.cpp
 | 
				
			||||||
	common.cpp
 | 
						common.cpp
 | 
				
			||||||
 | 
						iconprovider.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-core PRIVATE quickshell-build)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
qt_add_qml_module(quickshell-core
 | 
					qt_add_qml_module(quickshell-core
 | 
				
			||||||
	URI Quickshell
 | 
						URI Quickshell
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
| 
						 | 
					@ -51,10 +48,9 @@ qt_add_qml_module(quickshell-core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-core)
 | 
					install_qml_module(quickshell-core)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-core PRIVATE ${QT_DEPS} CLI11::CLI11)
 | 
					target_link_libraries(quickshell-core PRIVATE Qt::Quick Qt::Widgets)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-core)
 | 
					qs_module_pch(quickshell-core SET large)
 | 
				
			||||||
qs_pch(quickshell-coreplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-coreplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-coreplugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qtimer.h>
 | 
					#include <qtimer.h>
 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "util.hpp"
 | 
					#include "util.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,17 +8,12 @@
 | 
				
			||||||
#include <qfileinfo.h>
 | 
					#include <qfileinfo.h>
 | 
				
			||||||
#include <qfilesystemwatcher.h>
 | 
					#include <qfilesystemwatcher.h>
 | 
				
			||||||
#include <qhash.h>
 | 
					#include <qhash.h>
 | 
				
			||||||
#include <qicon.h>
 | 
					 | 
				
			||||||
#include <qiconengine.h>
 | 
					 | 
				
			||||||
#include <qlogging.h>
 | 
					#include <qlogging.h>
 | 
				
			||||||
#include <qloggingcategory.h>
 | 
					#include <qloggingcategory.h>
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qpixmap.h>
 | 
					 | 
				
			||||||
#include <qqmlcontext.h>
 | 
					#include <qqmlcontext.h>
 | 
				
			||||||
#include <qqmlengine.h>
 | 
					#include <qqmlengine.h>
 | 
				
			||||||
#include <qqmlincubator.h>
 | 
					#include <qqmlincubator.h>
 | 
				
			||||||
#include <qquickimageprovider.h>
 | 
					 | 
				
			||||||
#include <qsize.h>
 | 
					 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "iconimageprovider.hpp"
 | 
					#include "iconimageprovider.hpp"
 | 
				
			||||||
| 
						 | 
					@ -331,90 +326,6 @@ EngineGeneration* EngineGeneration::currentGeneration() {
 | 
				
			||||||
	} else return nullptr;
 | 
						} else return nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// QMenu re-calls pixmap() every time the mouse moves so its important to cache it.
 | 
					 | 
				
			||||||
class PixmapCacheIconEngine: public QIconEngine {
 | 
					 | 
				
			||||||
	void paint(
 | 
					 | 
				
			||||||
	    QPainter* /*unused*/,
 | 
					 | 
				
			||||||
	    const QRect& /*unused*/,
 | 
					 | 
				
			||||||
	    QIcon::Mode /*unused*/,
 | 
					 | 
				
			||||||
	    QIcon::State /*unused*/
 | 
					 | 
				
			||||||
	) override {
 | 
					 | 
				
			||||||
		qFatal(
 | 
					 | 
				
			||||||
		) << "Unexpected icon paint request bypassed pixmap method. Please report this as a bug.";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	QPixmap pixmap(const QSize& size, QIcon::Mode /*unused*/, QIcon::State /*unused*/) override {
 | 
					 | 
				
			||||||
		if (this->lastPixmap.isNull() || size != this->lastSize) {
 | 
					 | 
				
			||||||
			this->lastPixmap = this->createPixmap(size);
 | 
					 | 
				
			||||||
			this->lastSize = size;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return this->lastPixmap;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	virtual QPixmap createPixmap(const QSize& size) = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
	QSize lastSize;
 | 
					 | 
				
			||||||
	QPixmap lastPixmap;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ImageProviderIconEngine: public PixmapCacheIconEngine {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	explicit ImageProviderIconEngine(QQuickImageProvider* provider, QString id)
 | 
					 | 
				
			||||||
	    : provider(provider)
 | 
					 | 
				
			||||||
	    , id(std::move(id)) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	QPixmap createPixmap(const QSize& size) override {
 | 
					 | 
				
			||||||
		if (this->provider->imageType() == QQmlImageProviderBase::Pixmap) {
 | 
					 | 
				
			||||||
			return this->provider->requestPixmap(this->id, nullptr, size);
 | 
					 | 
				
			||||||
		} else if (this->provider->imageType() == QQmlImageProviderBase::Image) {
 | 
					 | 
				
			||||||
			auto image = this->provider->requestImage(this->id, nullptr, size);
 | 
					 | 
				
			||||||
			return QPixmap::fromImage(image);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			qFatal() << "Unexpected ImageProviderIconEngine image type" << this->provider->imageType();
 | 
					 | 
				
			||||||
			return QPixmap(); // never reached, satisfies lint
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	[[nodiscard]] QIconEngine* clone() const override {
 | 
					 | 
				
			||||||
		return new ImageProviderIconEngine(this->provider, this->id);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
	QQuickImageProvider* provider;
 | 
					 | 
				
			||||||
	QString id;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
QIcon EngineGeneration::iconByUrl(const QUrl& url) const {
 | 
					 | 
				
			||||||
	if (url.isEmpty()) return QIcon();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto scheme = url.scheme();
 | 
					 | 
				
			||||||
	if (scheme == "image") {
 | 
					 | 
				
			||||||
		auto providerName = url.authority();
 | 
					 | 
				
			||||||
		auto path = url.path();
 | 
					 | 
				
			||||||
		if (!path.isEmpty()) path = path.sliced(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto* provider = qobject_cast<QQuickImageProvider*>(this->engine->imageProvider(providerName));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (provider == nullptr) {
 | 
					 | 
				
			||||||
			qWarning() << "iconByUrl failed: no provider found for" << url;
 | 
					 | 
				
			||||||
			return QIcon();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (provider->imageType() == QQmlImageProviderBase::Pixmap
 | 
					 | 
				
			||||||
		    || provider->imageType() == QQmlImageProviderBase::Image)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			return QIcon(new ImageProviderIconEngine(provider, path));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		qWarning() << "iconByUrl failed: unsupported scheme" << scheme << "in path" << url;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return QIcon();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EngineGeneration* EngineGeneration::findEngineGeneration(QQmlEngine* engine) {
 | 
					EngineGeneration* EngineGeneration::findEngineGeneration(QQmlEngine* engine) {
 | 
				
			||||||
	return g_generations.value(engine);
 | 
						return g_generations.value(engine);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,13 +4,11 @@
 | 
				
			||||||
#include <qdir.h>
 | 
					#include <qdir.h>
 | 
				
			||||||
#include <qfilesystemwatcher.h>
 | 
					#include <qfilesystemwatcher.h>
 | 
				
			||||||
#include <qhash.h>
 | 
					#include <qhash.h>
 | 
				
			||||||
#include <qicon.h>
 | 
					 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qpair.h>
 | 
					#include <qpair.h>
 | 
				
			||||||
#include <qqmlengine.h>
 | 
					#include <qqmlengine.h>
 | 
				
			||||||
#include <qqmlincubator.h>
 | 
					#include <qqmlincubator.h>
 | 
				
			||||||
#include <qtclasshelpermacros.h>
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
#include <qurl.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "incubator.hpp"
 | 
					#include "incubator.hpp"
 | 
				
			||||||
#include "qsintercept.hpp"
 | 
					#include "qsintercept.hpp"
 | 
				
			||||||
| 
						 | 
					@ -54,8 +52,6 @@ public:
 | 
				
			||||||
	// otherwise null.
 | 
						// otherwise null.
 | 
				
			||||||
	static EngineGeneration* currentGeneration();
 | 
						static EngineGeneration* currentGeneration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] QIcon iconByUrl(const QUrl& url) const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	RootWrapper* wrapper = nullptr;
 | 
						RootWrapper* wrapper = nullptr;
 | 
				
			||||||
	QDir rootPath;
 | 
						QDir rootPath;
 | 
				
			||||||
	QmlScanner scanner;
 | 
						QmlScanner scanner;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										105
									
								
								src/core/iconprovider.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/core/iconprovider.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,105 @@
 | 
				
			||||||
 | 
					#include "iconprovider.hpp"
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qicon.h>
 | 
				
			||||||
 | 
					#include <qiconengine.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qpixmap.h>
 | 
				
			||||||
 | 
					#include <qqmlengine.h>
 | 
				
			||||||
 | 
					#include <qquickimageprovider.h>
 | 
				
			||||||
 | 
					#include <qrect.h>
 | 
				
			||||||
 | 
					#include <qsize.h>
 | 
				
			||||||
 | 
					#include <qstring.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "generation.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// QMenu re-calls pixmap() every time the mouse moves so its important to cache it.
 | 
				
			||||||
 | 
					class PixmapCacheIconEngine: public QIconEngine {
 | 
				
			||||||
 | 
						void paint(
 | 
				
			||||||
 | 
						    QPainter* /*unused*/,
 | 
				
			||||||
 | 
						    const QRect& /*unused*/,
 | 
				
			||||||
 | 
						    QIcon::Mode /*unused*/,
 | 
				
			||||||
 | 
						    QIcon::State /*unused*/
 | 
				
			||||||
 | 
						) override {
 | 
				
			||||||
 | 
							qFatal(
 | 
				
			||||||
 | 
							) << "Unexpected icon paint request bypassed pixmap method. Please report this as a bug.";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QPixmap pixmap(const QSize& size, QIcon::Mode /*unused*/, QIcon::State /*unused*/) override {
 | 
				
			||||||
 | 
							if (this->lastPixmap.isNull() || size != this->lastSize) {
 | 
				
			||||||
 | 
								this->lastPixmap = this->createPixmap(size);
 | 
				
			||||||
 | 
								this->lastSize = size;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return this->lastPixmap;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						virtual QPixmap createPixmap(const QSize& size) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						QSize lastSize;
 | 
				
			||||||
 | 
						QPixmap lastPixmap;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ImageProviderIconEngine: public PixmapCacheIconEngine {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit ImageProviderIconEngine(QQuickImageProvider* provider, QString id)
 | 
				
			||||||
 | 
						    : provider(provider)
 | 
				
			||||||
 | 
						    , id(std::move(id)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QPixmap createPixmap(const QSize& size) override {
 | 
				
			||||||
 | 
							if (this->provider->imageType() == QQmlImageProviderBase::Pixmap) {
 | 
				
			||||||
 | 
								return this->provider->requestPixmap(this->id, nullptr, size);
 | 
				
			||||||
 | 
							} else if (this->provider->imageType() == QQmlImageProviderBase::Image) {
 | 
				
			||||||
 | 
								auto image = this->provider->requestImage(this->id, nullptr, size);
 | 
				
			||||||
 | 
								return QPixmap::fromImage(image);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								qFatal() << "Unexpected ImageProviderIconEngine image type" << this->provider->imageType();
 | 
				
			||||||
 | 
								return QPixmap(); // never reached, satisfies lint
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QIconEngine* clone() const override {
 | 
				
			||||||
 | 
							return new ImageProviderIconEngine(this->provider, this->id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						QQuickImageProvider* provider;
 | 
				
			||||||
 | 
						QString id;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QIcon getEngineImageAsIcon(QQmlEngine* engine, const QUrl& url) {
 | 
				
			||||||
 | 
						if (!engine || url.isEmpty()) return QIcon();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto scheme = url.scheme();
 | 
				
			||||||
 | 
						if (scheme == "image") {
 | 
				
			||||||
 | 
							auto providerName = url.authority();
 | 
				
			||||||
 | 
							auto path = url.path();
 | 
				
			||||||
 | 
							if (!path.isEmpty()) path = path.sliced(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* provider = qobject_cast<QQuickImageProvider*>(engine->imageProvider(providerName));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (provider == nullptr) {
 | 
				
			||||||
 | 
								qWarning() << "iconByUrl failed: no provider found for" << url;
 | 
				
			||||||
 | 
								return QIcon();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (provider->imageType() == QQmlImageProviderBase::Pixmap
 | 
				
			||||||
 | 
							    || provider->imageType() == QQmlImageProviderBase::Image)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return QIcon(new ImageProviderIconEngine(provider, path));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							qWarning() << "iconByUrl failed: unsupported scheme" << scheme << "in path" << url;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return QIcon();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QIcon getCurrentEngineImageAsIcon(const QUrl& url) {
 | 
				
			||||||
 | 
						auto* generation = EngineGeneration::currentGeneration();
 | 
				
			||||||
 | 
						if (!generation) return QIcon();
 | 
				
			||||||
 | 
						return getEngineImageAsIcon(generation->engine, url);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								src/core/iconprovider.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/core/iconprovider.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qicon.h>
 | 
				
			||||||
 | 
					#include <qqmlengine.h>
 | 
				
			||||||
 | 
					#include <qurl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QIcon getEngineImageAsIcon(QQmlEngine* engine, const QUrl& url);
 | 
				
			||||||
 | 
					QIcon getCurrentEngineImageAsIcon(const QUrl& url);
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../window/proxywindow.hpp"
 | 
					#include "../window/proxywindow.hpp"
 | 
				
			||||||
#include "../window/windowinterface.hpp"
 | 
					#include "../window/windowinterface.hpp"
 | 
				
			||||||
#include "generation.hpp"
 | 
					#include "iconprovider.hpp"
 | 
				
			||||||
 | 
					#include "platformmenu_p.hpp"
 | 
				
			||||||
#include "popupanchor.hpp"
 | 
					#include "popupanchor.hpp"
 | 
				
			||||||
#include "qsmenu.hpp"
 | 
					#include "qsmenu.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -174,8 +175,7 @@ void PlatformMenuEntry::relayout() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto icon = this->menu->icon();
 | 
							auto icon = this->menu->icon();
 | 
				
			||||||
		if (!icon.isEmpty()) {
 | 
							if (!icon.isEmpty()) {
 | 
				
			||||||
			auto* generation = EngineGeneration::currentGeneration();
 | 
								this->qmenu->setIcon(getCurrentEngineImageAsIcon(icon));
 | 
				
			||||||
			this->qmenu->setIcon(generation->iconByUrl(this->menu->icon()));
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto children = this->menu->children();
 | 
							auto children = this->menu->children();
 | 
				
			||||||
| 
						 | 
					@ -216,8 +216,7 @@ void PlatformMenuEntry::relayout() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto icon = this->menu->icon();
 | 
							auto icon = this->menu->icon();
 | 
				
			||||||
		if (!icon.isEmpty()) {
 | 
							if (!icon.isEmpty()) {
 | 
				
			||||||
			auto* generation = EngineGeneration::currentGeneration();
 | 
								this->qaction->setIcon(getCurrentEngineImageAsIcon(icon));
 | 
				
			||||||
			this->qaction->setIcon(generation->iconByUrl(this->menu->icon()));
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this->qaction->setEnabled(this->menu->enabled());
 | 
							this->qaction->setEnabled(this->menu->enabled());
 | 
				
			||||||
| 
						 | 
					@ -272,8 +271,7 @@ void PlatformMenuEntry::onIconChanged() {
 | 
				
			||||||
	QIcon icon;
 | 
						QIcon icon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!iconName.isEmpty()) {
 | 
						if (!iconName.isEmpty()) {
 | 
				
			||||||
		auto* generation = EngineGeneration::currentGeneration();
 | 
							icon = getCurrentEngineImageAsIcon(iconName);
 | 
				
			||||||
		icon = generation->iconByUrl(iconName);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->qmenu != nullptr) {
 | 
						if (this->qmenu != nullptr) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,9 +5,7 @@
 | 
				
			||||||
#include <qaction.h>
 | 
					#include <qaction.h>
 | 
				
			||||||
#include <qactiongroup.h>
 | 
					#include <qactiongroup.h>
 | 
				
			||||||
#include <qcontainerfwd.h>
 | 
					#include <qcontainerfwd.h>
 | 
				
			||||||
#include <qmenu.h>
 | 
					 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qpoint.h>
 | 
					 | 
				
			||||||
#include <qqmlintegration.h>
 | 
					#include <qqmlintegration.h>
 | 
				
			||||||
#include <qqmllist.h>
 | 
					#include <qqmllist.h>
 | 
				
			||||||
#include <qtclasshelpermacros.h>
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
| 
						 | 
					@ -18,17 +16,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace qs::menu::platform {
 | 
					namespace qs::menu::platform {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PlatformMenuQMenu: public QMenu {
 | 
					class PlatformMenuQMenu;
 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	explicit PlatformMenuQMenu() = default;
 | 
					 | 
				
			||||||
	~PlatformMenuQMenu() override;
 | 
					 | 
				
			||||||
	Q_DISABLE_COPY_MOVE(PlatformMenuQMenu);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void setVisible(bool visible) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	PlatformMenuQMenu* containingMenu = nullptr;
 | 
					 | 
				
			||||||
	QPoint targetPosition;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PlatformMenuEntry: public QObject {
 | 
					class PlatformMenuEntry: public QObject {
 | 
				
			||||||
	Q_OBJECT;
 | 
						Q_OBJECT;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/core/platformmenu_p.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/core/platformmenu_p.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <qmenu.h>
 | 
				
			||||||
 | 
					#include <qpoint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::menu::platform {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PlatformMenuQMenu: public QMenu {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit PlatformMenuQMenu() = default;
 | 
				
			||||||
 | 
						~PlatformMenuQMenu() override;
 | 
				
			||||||
 | 
						Q_DISABLE_COPY_MOVE(PlatformMenuQMenu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void setVisible(bool visible) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PlatformMenuQMenu* containingMenu = nullptr;
 | 
				
			||||||
 | 
						QPoint targetPosition;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::menu::platform
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <optional>
 | 
					#include <optional>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QtQmlIntegration/qqmlintegration.h>
 | 
					 | 
				
			||||||
#include <qflags.h>
 | 
					#include <qflags.h>
 | 
				
			||||||
#include <qnamespace.h>
 | 
					#include <qnamespace.h>
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
function (qs_test name)
 | 
					function (qs_test name)
 | 
				
			||||||
	add_executable(${name} ${ARGN})
 | 
						add_executable(${name} ${ARGN})
 | 
				
			||||||
	target_link_libraries(${name} PRIVATE ${QT_DEPS} Qt6::Test quickshell-core quickshell-window)
 | 
						target_link_libraries(${name} PRIVATE Qt::Quick Qt::Test quickshell-core quickshell-window)
 | 
				
			||||||
	add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
 | 
						add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
 | 
				
			||||||
endfunction()
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,8 +16,18 @@ qt_add_library(quickshell-dbus STATIC
 | 
				
			||||||
# dbus headers
 | 
					# dbus headers
 | 
				
			||||||
target_include_directories(quickshell-dbus PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 | 
					target_include_directories(quickshell-dbus PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-dbus PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-dbus PRIVATE Qt::Core Qt::DBus)
 | 
				
			||||||
 | 
					# todo: link dbus to quickshell here instead of in modules that use it directly
 | 
				
			||||||
 | 
					# linker does not like this as is
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-dbus)
 | 
					qs_add_pchset(dbus
 | 
				
			||||||
 | 
						DEPENDENCIES Qt::DBus
 | 
				
			||||||
 | 
						HEADERS
 | 
				
			||||||
 | 
							<QtDBus>
 | 
				
			||||||
 | 
							<qdebug.h>
 | 
				
			||||||
 | 
							<qdbusargument.h>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_pch(quickshell-dbus SET dbus)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(dbusmenu)
 | 
					add_subdirectory(dbusmenu)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,15 +17,18 @@ qt_add_library(quickshell-dbusmenu STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-dbusmenu
 | 
					qt_add_qml_module(quickshell-dbusmenu
 | 
				
			||||||
	URI Quickshell.DBusMenu
 | 
						URI Quickshell.DBusMenu
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell
 | 
						DEPENDENCIES QtQml
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-dbusmenu Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-dbusmenu)
 | 
					install_qml_module(quickshell-dbusmenu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# dbus headers
 | 
					# dbus headers
 | 
				
			||||||
target_include_directories(quickshell-dbusmenu PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 | 
					target_include_directories(quickshell-dbusmenu PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-dbusmenu PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-dbusmenu PRIVATE Qt::Quick Qt::DBus quickshell-dbus)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-dbusmenu)
 | 
					qs_module_pch(quickshell-dbusmenu SET dbus)
 | 
				
			||||||
qs_pch(quickshell-dbusmenuplugin)
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell PRIVATE quickshell-dbusmenuplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,6 @@
 | 
				
			||||||
#include <qloggingcategory.h>
 | 
					#include <qloggingcategory.h>
 | 
				
			||||||
#include <qmetatype.h>
 | 
					#include <qmetatype.h>
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qpolygon.h>
 | 
					 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
#include <qvariant.h>
 | 
					#include <qvariant.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,14 +23,12 @@ qt_add_qml_module(quickshell-io
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-io)
 | 
					install_qml_module(quickshell-io)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-io PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-io PRIVATE Qt::Quick)
 | 
				
			||||||
target_link_libraries(quickshell-io-init PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-io-init PRIVATE Qt::Qml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-ioplugin quickshell-io-init)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-ioplugin quickshell-io-init)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-io)
 | 
					qs_module_pch(quickshell-io)
 | 
				
			||||||
qs_pch(quickshell-ioplugin)
 | 
					 | 
				
			||||||
qs_pch(quickshell-io-init)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (BUILD_TESTING)
 | 
					if (BUILD_TESTING)
 | 
				
			||||||
	add_subdirectory(test)
 | 
						add_subdirectory(test)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
function (qs_test name)
 | 
					function (qs_test name)
 | 
				
			||||||
	add_executable(${name} ${ARGN})
 | 
						add_executable(${name} ${ARGN})
 | 
				
			||||||
	target_link_libraries(${name} PRIVATE ${QT_DEPS} Qt6::Test)
 | 
						target_link_libraries(${name} PRIVATE Qt::Quick Qt::Network Qt::Test)
 | 
				
			||||||
	add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
 | 
						add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
 | 
				
			||||||
endfunction()
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,8 @@ qt_add_library(quickshell-ipc STATIC
 | 
				
			||||||
	ipc.cpp
 | 
						ipc.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-ipc PRIVATE ${QT_DEPS})
 | 
					qs_pch(quickshell-ipc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell-ipc PRIVATE Qt::Quick Qt::Network)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-ipc)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-ipc)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/launch/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/launch/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					find_package(CLI11 CONFIG REQUIRED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qt_add_library(quickshell-launch STATIC
 | 
				
			||||||
 | 
						parsecommand.cpp
 | 
				
			||||||
 | 
						command.cpp
 | 
				
			||||||
 | 
						launch.cpp
 | 
				
			||||||
 | 
						main.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell-launch PRIVATE
 | 
				
			||||||
 | 
						Qt::Quick Qt::Widgets CLI11::CLI11 quickshell-build
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_pchset(launch
 | 
				
			||||||
 | 
						DEPENDENCIES Qt::Core CLI11::CLI11
 | 
				
			||||||
 | 
						HEADERS
 | 
				
			||||||
 | 
							<CLI/App.hpp>
 | 
				
			||||||
 | 
							<qcoreapplication.h>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_pch(quickshell-launch SET launch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell PRIVATE quickshell-launch)
 | 
				
			||||||
							
								
								
									
										448
									
								
								src/launch/command.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										448
									
								
								src/launch/command.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,448 @@
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <cerrno>
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qconfig.h>
 | 
				
			||||||
 | 
					#include <qcontainerfwd.h>
 | 
				
			||||||
 | 
					#include <qcoreapplication.h>
 | 
				
			||||||
 | 
					#include <qcryptographichash.h>
 | 
				
			||||||
 | 
					#include <qdatetime.h>
 | 
				
			||||||
 | 
					#include <qdebug.h>
 | 
				
			||||||
 | 
					#include <qdir.h>
 | 
				
			||||||
 | 
					#include <qfileinfo.h>
 | 
				
			||||||
 | 
					#include <qjsonarray.h>
 | 
				
			||||||
 | 
					#include <qjsondocument.h>
 | 
				
			||||||
 | 
					#include <qjsonobject.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qloggingcategory.h>
 | 
				
			||||||
 | 
					#include <qnamespace.h>
 | 
				
			||||||
 | 
					#include <qstandardpaths.h>
 | 
				
			||||||
 | 
					#include <qtversion.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../core/instanceinfo.hpp"
 | 
				
			||||||
 | 
					#include "../core/logging.hpp"
 | 
				
			||||||
 | 
					#include "../core/paths.hpp"
 | 
				
			||||||
 | 
					#include "../io/ipccomm.hpp"
 | 
				
			||||||
 | 
					#include "../ipc/ipc.hpp"
 | 
				
			||||||
 | 
					#include "build.hpp"
 | 
				
			||||||
 | 
					#include "launch_p.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::launch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using qs::ipc::IpcClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int readLogFile(CommandState& cmd);
 | 
				
			||||||
 | 
					int listInstances(CommandState& cmd);
 | 
				
			||||||
 | 
					int killInstances(CommandState& cmd);
 | 
				
			||||||
 | 
					int msgInstance(CommandState& cmd);
 | 
				
			||||||
 | 
					int launchFromCommand(CommandState& cmd, QCoreApplication* coreApplication);
 | 
				
			||||||
 | 
					int locateConfigFile(CommandState& cmd, QString& path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int runCommand(int argc, char** argv, QCoreApplication* coreApplication) {
 | 
				
			||||||
 | 
						auto state = CommandState();
 | 
				
			||||||
 | 
						if (auto ret = parseCommand(argc, argv, state); ret != 0) return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state.misc.checkCompat) {
 | 
				
			||||||
 | 
							if (strcmp(qVersion(), QT_VERSION_STR) != 0) {
 | 
				
			||||||
 | 
								QTextStream(stdout) << "\033[31mCOMPATIBILITY WARNING: Quickshell was built against Qt "
 | 
				
			||||||
 | 
								                    << QT_VERSION_STR << " but the system has updated to Qt " << qVersion()
 | 
				
			||||||
 | 
								                    << " without rebuilding the package. This is likely to cause crashes, so "
 | 
				
			||||||
 | 
								                       "you must rebuild the quickshell package.\n";
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Has to happen before extra threads are spawned.
 | 
				
			||||||
 | 
						if (state.misc.daemonize) {
 | 
				
			||||||
 | 
							auto closepipes = std::array<int, 2>();
 | 
				
			||||||
 | 
							if (pipe(closepipes.data()) == -1) {
 | 
				
			||||||
 | 
								qFatal().nospace() << "Failed to create messaging pipes for daemon with error " << errno
 | 
				
			||||||
 | 
								                   << ": " << qt_error_string();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							DAEMON_PIPE = closepipes[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pid_t pid = fork(); // NOLINT (include)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (pid == -1) {
 | 
				
			||||||
 | 
								qFatal().nospace() << "Failed to fork daemon with error " << errno << ": "
 | 
				
			||||||
 | 
								                   << qt_error_string();
 | 
				
			||||||
 | 
							} else if (pid == 0) {
 | 
				
			||||||
 | 
								close(closepipes[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (setsid() == -1) {
 | 
				
			||||||
 | 
									qFatal().nospace() << "Failed to setsid with error " << errno << ": " << qt_error_string();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								close(closepipes[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int ret = 0;
 | 
				
			||||||
 | 
								if (read(closepipes[0], &ret, sizeof(int)) == -1) {
 | 
				
			||||||
 | 
									qFatal() << "Failed to wait for daemon launch (it may have crashed)";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto level = state.log.verbosity == 0 ? QtWarningMsg
 | 
				
			||||||
 | 
							           : state.log.verbosity == 1 ? QtInfoMsg
 | 
				
			||||||
 | 
							                                      : QtDebugMsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							LogManager::init(
 | 
				
			||||||
 | 
							    !state.log.noColor,
 | 
				
			||||||
 | 
							    state.log.timestamp,
 | 
				
			||||||
 | 
							    state.log.sparse,
 | 
				
			||||||
 | 
							    level,
 | 
				
			||||||
 | 
							    *state.log.rules,
 | 
				
			||||||
 | 
							    *state.subcommand.log ? "READER" : ""
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state.misc.printVersion) {
 | 
				
			||||||
 | 
							qCInfo(logBare).noquote().nospace() << "quickshell pre-release, revision " << GIT_REVISION
 | 
				
			||||||
 | 
							                                    << ", distributed by: " << DISTRIBUTOR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (state.log.verbosity > 1) {
 | 
				
			||||||
 | 
								qCInfo(logBare).noquote() << "\nBuildtime Qt Version:" << QT_VERSION_STR;
 | 
				
			||||||
 | 
								qCInfo(logBare).noquote() << "Runtime Qt Version:" << qVersion();
 | 
				
			||||||
 | 
								qCInfo(logBare).noquote() << "Compiler:" << COMPILER;
 | 
				
			||||||
 | 
								qCInfo(logBare).noquote() << "Compile Flags:" << COMPILE_FLAGS;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (state.log.verbosity > 0) {
 | 
				
			||||||
 | 
								qCInfo(logBare).noquote() << "\nBuild Type:" << BUILD_TYPE;
 | 
				
			||||||
 | 
								qCInfo(logBare).noquote() << "Build configuration:";
 | 
				
			||||||
 | 
								qCInfo(logBare).noquote().nospace() << BUILD_CONFIGURATION;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (*state.subcommand.log) {
 | 
				
			||||||
 | 
							return readLogFile(state);
 | 
				
			||||||
 | 
						} else if (*state.subcommand.list) {
 | 
				
			||||||
 | 
							return listInstances(state);
 | 
				
			||||||
 | 
						} else if (*state.subcommand.kill) {
 | 
				
			||||||
 | 
							return killInstances(state);
 | 
				
			||||||
 | 
						} else if (*state.subcommand.msg) {
 | 
				
			||||||
 | 
							return msgInstance(state);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (strcmp(qVersion(), QT_VERSION_STR) != 0) {
 | 
				
			||||||
 | 
								qWarning() << "\033[31mQuickshell was built against Qt" << QT_VERSION_STR
 | 
				
			||||||
 | 
								           << "but the system has updated to Qt" << qVersion()
 | 
				
			||||||
 | 
								           << "without rebuilding the package. This is likely to cause crashes, so "
 | 
				
			||||||
 | 
								              "the quickshell package must be rebuilt.\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return launchFromCommand(state, coreApplication);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int locateConfigFile(CommandState& cmd, QString& path) {
 | 
				
			||||||
 | 
						if (!cmd.config.path->isEmpty()) {
 | 
				
			||||||
 | 
							path = *cmd.config.path;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							auto manifestPath = *cmd.config.manifest;
 | 
				
			||||||
 | 
							if (manifestPath.isEmpty()) {
 | 
				
			||||||
 | 
								auto configDir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation));
 | 
				
			||||||
 | 
								auto path = configDir.filePath("manifest.conf");
 | 
				
			||||||
 | 
								if (QFileInfo(path).isFile()) manifestPath = path;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!manifestPath.isEmpty()) {
 | 
				
			||||||
 | 
								auto file = QFile(manifestPath);
 | 
				
			||||||
 | 
								if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
 | 
				
			||||||
 | 
									auto stream = QTextStream(&file);
 | 
				
			||||||
 | 
									while (!stream.atEnd()) {
 | 
				
			||||||
 | 
										auto line = stream.readLine();
 | 
				
			||||||
 | 
										if (line.trimmed().startsWith("#")) continue;
 | 
				
			||||||
 | 
										if (line.trimmed().isEmpty()) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										auto split = line.split('=');
 | 
				
			||||||
 | 
										if (split.length() != 2) {
 | 
				
			||||||
 | 
											qCritical() << "Manifest line not in expected format 'name = relativepath':" << line;
 | 
				
			||||||
 | 
											return -1;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (split[0].trimmed() == *cmd.config.name) {
 | 
				
			||||||
 | 
											path = QDir(QFileInfo(file).canonicalPath()).filePath(split[1].trimmed());
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (path.isEmpty()) {
 | 
				
			||||||
 | 
										qCCritical(logBare) << "Configuration" << *cmd.config.name
 | 
				
			||||||
 | 
										                    << "not found when searching manifest" << manifestPath;
 | 
				
			||||||
 | 
										return -1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									qCCritical(logBare) << "Could not open maifest at path" << *cmd.config.manifest;
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								auto configDir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (cmd.config.name->isEmpty()) {
 | 
				
			||||||
 | 
									path = configDir.path();
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									path = configDir.filePath(*cmd.config.name);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (QFileInfo(path).isDir()) {
 | 
				
			||||||
 | 
							path = QDir(path).filePath("shell.qml");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!QFileInfo(path).isFile()) {
 | 
				
			||||||
 | 
							qCCritical(logBare) << "Could not open config file at" << path;
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						path = QFileInfo(path).canonicalFilePath();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sortInstances(QVector<InstanceLockInfo>& list) {
 | 
				
			||||||
 | 
						std::sort(list.begin(), list.end(), [](const InstanceLockInfo& a, const InstanceLockInfo& b) {
 | 
				
			||||||
 | 
							return a.instance.launchTime < b.instance.launchTime;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int selectInstance(CommandState& cmd, InstanceLockInfo* instance) {
 | 
				
			||||||
 | 
						auto* basePath = QsPaths::instance()->baseRunDir();
 | 
				
			||||||
 | 
						if (!basePath) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QString path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cmd.instance.pid != -1) {
 | 
				
			||||||
 | 
							path = QDir(basePath->filePath("by-pid")).filePath(QString::number(cmd.instance.pid));
 | 
				
			||||||
 | 
							if (!QsPaths::checkLock(path, instance)) {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "No instance found for pid" << cmd.instance.pid;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (!cmd.instance.id->isEmpty()) {
 | 
				
			||||||
 | 
							path = basePath->filePath("by-pid");
 | 
				
			||||||
 | 
							auto instances = QsPaths::collectInstances(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto itr =
 | 
				
			||||||
 | 
							    std::remove_if(instances.begin(), instances.end(), [&](const InstanceLockInfo& info) {
 | 
				
			||||||
 | 
								    return !info.instance.instanceId.startsWith(*cmd.instance.id);
 | 
				
			||||||
 | 
							    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							instances.erase(itr, instances.end());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (instances.isEmpty()) {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "No running instances start with" << *cmd.instance.id;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							} else if (instances.length() != 1) {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "More than one instance starts with" << *cmd.instance.id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (auto& instance: instances) {
 | 
				
			||||||
 | 
									qCInfo(logBare).noquote() << " -" << instance.instance.instanceId;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								*instance = instances.value(0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							QString configFilePath;
 | 
				
			||||||
 | 
							auto r = locateConfigFile(cmd, configFilePath);
 | 
				
			||||||
 | 
							if (r != 0) return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto pathId =
 | 
				
			||||||
 | 
							    QCryptographicHash::hash(configFilePath.toUtf8(), QCryptographicHash::Md5).toHex();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							path = QDir(basePath->filePath("by-path")).filePath(pathId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto instances = QsPaths::collectInstances(path);
 | 
				
			||||||
 | 
							sortInstances(instances);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (instances.isEmpty()) {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "No running instances for" << configFilePath;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*instance = instances.value(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int readLogFile(CommandState& cmd) {
 | 
				
			||||||
 | 
						auto path = *cmd.log.file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (path.isEmpty()) {
 | 
				
			||||||
 | 
							InstanceLockInfo instance;
 | 
				
			||||||
 | 
							auto r = selectInstance(cmd, &instance);
 | 
				
			||||||
 | 
							if (r != 0) return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							path = QDir(QsPaths::basePath(instance.instance.instanceId)).filePath("log.qslog");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto file = QFile(path);
 | 
				
			||||||
 | 
						if (!file.open(QFile::ReadOnly)) {
 | 
				
			||||||
 | 
							qCCritical(logBare) << "Failed to open log file" << path;
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return qs::log::readEncodedLogs(
 | 
				
			||||||
 | 
						           &file,
 | 
				
			||||||
 | 
						           path,
 | 
				
			||||||
 | 
						           cmd.log.timestamp,
 | 
				
			||||||
 | 
						           cmd.log.tail,
 | 
				
			||||||
 | 
						           cmd.log.follow,
 | 
				
			||||||
 | 
						           *cmd.log.readoutRules
 | 
				
			||||||
 | 
						       )
 | 
				
			||||||
 | 
						         ? 0
 | 
				
			||||||
 | 
						         : -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int listInstances(CommandState& cmd) {
 | 
				
			||||||
 | 
						auto* basePath = QsPaths::instance()->baseRunDir();
 | 
				
			||||||
 | 
						if (!basePath) return -1; // NOLINT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QString path;
 | 
				
			||||||
 | 
						QString configFilePath;
 | 
				
			||||||
 | 
						if (cmd.instance.all) {
 | 
				
			||||||
 | 
							path = basePath->filePath("by-pid");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							auto r = locateConfigFile(cmd, configFilePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (r != 0) {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "Use --all to list all instances.";
 | 
				
			||||||
 | 
								return r;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto pathId =
 | 
				
			||||||
 | 
							    QCryptographicHash::hash(configFilePath.toUtf8(), QCryptographicHash::Md5).toHex();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							path = QDir(basePath->filePath("by-path")).filePath(pathId);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto instances = QsPaths::collectInstances(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (instances.isEmpty()) {
 | 
				
			||||||
 | 
							if (cmd.instance.all) {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "No running instances.";
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "No running instances for" << configFilePath;
 | 
				
			||||||
 | 
								qCInfo(logBare) << "Use --all to list all instances.";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							sortInstances(instances);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (cmd.output.json) {
 | 
				
			||||||
 | 
								auto array = QJsonArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (auto& instance: instances) {
 | 
				
			||||||
 | 
									auto json = QJsonObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									json["id"] = instance.instance.instanceId;
 | 
				
			||||||
 | 
									json["pid"] = instance.pid;
 | 
				
			||||||
 | 
									json["shell_id"] = instance.instance.shellId;
 | 
				
			||||||
 | 
									json["config_path"] = instance.instance.configPath;
 | 
				
			||||||
 | 
									json["launch_time"] = instance.instance.launchTime.toString(Qt::ISODate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									array.push_back(json);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto document = QJsonDocument(array);
 | 
				
			||||||
 | 
								QTextStream(stdout) << document.toJson(QJsonDocument::Indented);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								for (auto& instance: instances) {
 | 
				
			||||||
 | 
									auto launchTimeStr = instance.instance.launchTime.toString("yyyy-MM-dd hh:mm:ss");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									auto runSeconds = instance.instance.launchTime.secsTo(QDateTime::currentDateTime());
 | 
				
			||||||
 | 
									auto remSeconds = runSeconds % 60;
 | 
				
			||||||
 | 
									auto runMinutes = (runSeconds - remSeconds) / 60;
 | 
				
			||||||
 | 
									auto remMinutes = runMinutes % 60;
 | 
				
			||||||
 | 
									auto runHours = (runMinutes - remMinutes) / 60;
 | 
				
			||||||
 | 
									auto runtimeStr = QString("%1 hours, %2 minutes, %3 seconds")
 | 
				
			||||||
 | 
									                      .arg(runHours)
 | 
				
			||||||
 | 
									                      .arg(remMinutes)
 | 
				
			||||||
 | 
									                      .arg(remSeconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									qCInfo(logBare).noquote().nospace()
 | 
				
			||||||
 | 
									    << "Instance " << instance.instance.instanceId << ":\n"
 | 
				
			||||||
 | 
									    << "  Process ID: " << instance.pid << '\n'
 | 
				
			||||||
 | 
									    << "  Shell ID: " << instance.instance.shellId << '\n'
 | 
				
			||||||
 | 
									    << "  Config path: " << instance.instance.configPath << '\n'
 | 
				
			||||||
 | 
									    << "  Launch time: " << launchTimeStr << " (running for " << runtimeStr << ")\n";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int killInstances(CommandState& cmd) {
 | 
				
			||||||
 | 
						InstanceLockInfo instance;
 | 
				
			||||||
 | 
						auto r = selectInstance(cmd, &instance);
 | 
				
			||||||
 | 
						if (r != 0) return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return IpcClient::connect(instance.instance.instanceId, [&](IpcClient& client) {
 | 
				
			||||||
 | 
							client.kill();
 | 
				
			||||||
 | 
							qCInfo(logBare).noquote() << "Killed" << instance.instance.instanceId;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int msgInstance(CommandState& cmd) {
 | 
				
			||||||
 | 
						InstanceLockInfo instance;
 | 
				
			||||||
 | 
						auto r = selectInstance(cmd, &instance);
 | 
				
			||||||
 | 
						if (r != 0) return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return IpcClient::connect(instance.instance.instanceId, [&](IpcClient& client) {
 | 
				
			||||||
 | 
							if (cmd.ipc.info) {
 | 
				
			||||||
 | 
								return qs::io::ipc::comm::queryMetadata(&client, *cmd.ipc.target, *cmd.ipc.function);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								QVector<QString> arguments;
 | 
				
			||||||
 | 
								for (auto& arg: cmd.ipc.arguments) {
 | 
				
			||||||
 | 
									arguments += *arg;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return qs::io::ipc::comm::callFunction(
 | 
				
			||||||
 | 
								    &client,
 | 
				
			||||||
 | 
								    *cmd.ipc.target,
 | 
				
			||||||
 | 
								    *cmd.ipc.function,
 | 
				
			||||||
 | 
								    arguments
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int launchFromCommand(CommandState& cmd, QCoreApplication* coreApplication) {
 | 
				
			||||||
 | 
						QString configPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto r = locateConfigFile(cmd, configPath);
 | 
				
			||||||
 | 
						if (r != 0) return r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							InstanceLockInfo info;
 | 
				
			||||||
 | 
							if (cmd.misc.noDuplicate && selectInstance(cmd, &info) == 0) {
 | 
				
			||||||
 | 
								qCInfo(logBare) << "An instance of this configuration is already running.";
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return launch(
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						        .configPath = configPath,
 | 
				
			||||||
 | 
						        .debugPort = cmd.debug.port,
 | 
				
			||||||
 | 
						        .waitForDebug = cmd.debug.wait,
 | 
				
			||||||
 | 
						    },
 | 
				
			||||||
 | 
						    cmd.exec.argv,
 | 
				
			||||||
 | 
						    coreApplication
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::launch
 | 
				
			||||||
							
								
								
									
										238
									
								
								src/launch/launch.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								src/launch/launch.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,238 @@
 | 
				
			||||||
 | 
					#include <qapplication.h>
 | 
				
			||||||
 | 
					#include <qcoreapplication.h>
 | 
				
			||||||
 | 
					#include <qcryptographichash.h>
 | 
				
			||||||
 | 
					#include <qdebug.h>
 | 
				
			||||||
 | 
					#include <qdir.h>
 | 
				
			||||||
 | 
					#include <qfile.h>
 | 
				
			||||||
 | 
					#include <qguiapplication.h>
 | 
				
			||||||
 | 
					#include <qhash.h>
 | 
				
			||||||
 | 
					#include <qlist.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qnamespace.h>
 | 
				
			||||||
 | 
					#include <qqmldebug.h>
 | 
				
			||||||
 | 
					#include <qquickwindow.h>
 | 
				
			||||||
 | 
					#include <qstring.h>
 | 
				
			||||||
 | 
					#include <qtenvironmentvariables.h>
 | 
				
			||||||
 | 
					#include <qtextstream.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../core/common.hpp"
 | 
				
			||||||
 | 
					#include "../core/instanceinfo.hpp"
 | 
				
			||||||
 | 
					#include "../core/logging.hpp"
 | 
				
			||||||
 | 
					#include "../core/paths.hpp"
 | 
				
			||||||
 | 
					#include "../core/plugin.hpp"
 | 
				
			||||||
 | 
					#include "../core/rootwrapper.hpp"
 | 
				
			||||||
 | 
					#include "../ipc/ipc.hpp"
 | 
				
			||||||
 | 
					#include "build.hpp"
 | 
				
			||||||
 | 
					#include "launch_p.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if CRASH_REPORTER
 | 
				
			||||||
 | 
					#include "../crash/handler.hpp"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::launch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					QString base36Encode(T number) {
 | 
				
			||||||
 | 
						const QString digits = "0123456789abcdefghijklmnopqrstuvwxyz";
 | 
				
			||||||
 | 
						QString result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							result.prepend(digits[number % 36]);
 | 
				
			||||||
 | 
							number /= 36;
 | 
				
			||||||
 | 
						} while (number > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto i = 0; i < result.length() / 2; i++) {
 | 
				
			||||||
 | 
							auto opposite = result.length() - i - 1;
 | 
				
			||||||
 | 
							auto c = result.at(i);
 | 
				
			||||||
 | 
							result[i] = result.at(opposite);
 | 
				
			||||||
 | 
							result[opposite] = c;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplication) {
 | 
				
			||||||
 | 
						auto pathId = QCryptographicHash::hash(args.configPath.toUtf8(), QCryptographicHash::Md5).toHex();
 | 
				
			||||||
 | 
						auto shellId = QString(pathId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qInfo() << "Launching config:" << args.configPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto file = QFile(args.configPath);
 | 
				
			||||||
 | 
						if (!file.open(QFile::ReadOnly | QFile::Text)) {
 | 
				
			||||||
 | 
							qCritical() << "Could not open config file" << args.configPath;
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							bool useQApplication = false;
 | 
				
			||||||
 | 
							bool nativeTextRendering = false;
 | 
				
			||||||
 | 
							bool desktopSettingsAware = true;
 | 
				
			||||||
 | 
							QString iconTheme = qEnvironmentVariable("QS_ICON_THEME");
 | 
				
			||||||
 | 
							QHash<QString, QString> envOverrides;
 | 
				
			||||||
 | 
						} pragmas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto stream = QTextStream(&file);
 | 
				
			||||||
 | 
						while (!stream.atEnd()) {
 | 
				
			||||||
 | 
							auto line = stream.readLine().trimmed();
 | 
				
			||||||
 | 
							if (line.startsWith("//@ pragma ")) {
 | 
				
			||||||
 | 
								auto pragma = line.sliced(11).trimmed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (pragma == "UseQApplication") pragmas.useQApplication = true;
 | 
				
			||||||
 | 
								else if (pragma == "NativeTextRendering") pragmas.nativeTextRendering = true;
 | 
				
			||||||
 | 
								else if (pragma == "IgnoreSystemSettings") pragmas.desktopSettingsAware = false;
 | 
				
			||||||
 | 
								else if (pragma.startsWith("IconTheme ")) pragmas.iconTheme = pragma.sliced(10);
 | 
				
			||||||
 | 
								else if (pragma.startsWith("Env ")) {
 | 
				
			||||||
 | 
									auto envPragma = pragma.sliced(4);
 | 
				
			||||||
 | 
									auto splitIdx = envPragma.indexOf('=');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (splitIdx == -1) {
 | 
				
			||||||
 | 
										qCritical() << "Env pragma" << pragma << "not in the form 'VAR = VALUE'";
 | 
				
			||||||
 | 
										return -1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									auto var = envPragma.sliced(0, splitIdx).trimmed();
 | 
				
			||||||
 | 
									auto val = envPragma.sliced(splitIdx + 1).trimmed();
 | 
				
			||||||
 | 
									pragmas.envOverrides.insert(var, val);
 | 
				
			||||||
 | 
								} else if (pragma.startsWith("ShellId ")) {
 | 
				
			||||||
 | 
									shellId = pragma.sliced(8).trimmed();
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									qCritical() << "Unrecognized pragma" << pragma;
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (line.startsWith("import")) break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pragmas.iconTheme.isEmpty()) {
 | 
				
			||||||
 | 
							QIcon::setThemeName(pragmas.iconTheme);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qInfo() << "Shell ID:" << shellId << "Path ID" << pathId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto launchTime = qs::Common::LAUNCH_TIME.toSecsSinceEpoch();
 | 
				
			||||||
 | 
						InstanceInfo::CURRENT = InstanceInfo {
 | 
				
			||||||
 | 
						    .instanceId = base36Encode(getpid()) + base36Encode(launchTime),
 | 
				
			||||||
 | 
						    .configPath = args.configPath,
 | 
				
			||||||
 | 
						    .shellId = shellId,
 | 
				
			||||||
 | 
						    .launchTime = qs::Common::LAUNCH_TIME,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if CRASH_REPORTER
 | 
				
			||||||
 | 
						auto crashHandler = crash::CrashHandler();
 | 
				
			||||||
 | 
						crashHandler.init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto* log = LogManager::instance();
 | 
				
			||||||
 | 
							crashHandler.setRelaunchInfo({
 | 
				
			||||||
 | 
							    .instance = InstanceInfo::CURRENT,
 | 
				
			||||||
 | 
							    .noColor = !log->colorLogs,
 | 
				
			||||||
 | 
							    .timestamp = log->timestampLogs,
 | 
				
			||||||
 | 
							    .sparseLogsOnly = log->isSparse(),
 | 
				
			||||||
 | 
							    .defaultLogLevel = log->defaultLevel(),
 | 
				
			||||||
 | 
							    .logRules = log->rulesString(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QsPaths::init(shellId, pathId);
 | 
				
			||||||
 | 
						QsPaths::instance()->linkRunDir();
 | 
				
			||||||
 | 
						QsPaths::instance()->linkPathDir();
 | 
				
			||||||
 | 
						LogManager::initFs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto [var, val]: pragmas.envOverrides.asKeyValueRange()) {
 | 
				
			||||||
 | 
							qputenv(var.toUtf8(), val.toUtf8());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The qml engine currently refuses to cache non file (qsintercept) paths.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// if (auto* cacheDir = QsPaths::instance()->cacheDir()) {
 | 
				
			||||||
 | 
						// 	auto qmlCacheDir = cacheDir->filePath("qml-engine-cache");
 | 
				
			||||||
 | 
						// 	qputenv("QML_DISK_CACHE_PATH", qmlCacheDir.toLocal8Bit());
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 	if (!qEnvironmentVariableIsSet("QML_DISK_CACHE")) {
 | 
				
			||||||
 | 
						// 		qputenv("QML_DISK_CACHE", "aot,qmlc");
 | 
				
			||||||
 | 
						// 	}
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// While the simple animation driver can lead to better animations in some cases,
 | 
				
			||||||
 | 
						// it also can cause excessive repainting at excessively high framerates which can
 | 
				
			||||||
 | 
						// lead to noticeable amounts of gpu usage, including overheating on some systems.
 | 
				
			||||||
 | 
						// This gets worse the more windows are open, as repaints trigger on all of them for
 | 
				
			||||||
 | 
						// some reason. See QTBUG-126099 for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// if (!qEnvironmentVariableIsSet("QSG_USE_SIMPLE_ANIMATION_DRIVER")) {
 | 
				
			||||||
 | 
						// 	qputenv("QSG_USE_SIMPLE_ANIMATION_DRIVER", "1");
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Some programs place icons in the pixmaps folder instead of the icons folder.
 | 
				
			||||||
 | 
						// This seems to be controlled by the QPA and qt6ct does not provide it.
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							QList<QString> dataPaths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (qEnvironmentVariableIsSet("XDG_DATA_DIRS")) {
 | 
				
			||||||
 | 
								auto var = qEnvironmentVariable("XDG_DATA_DIRS");
 | 
				
			||||||
 | 
								dataPaths = var.split(u':', Qt::SkipEmptyParts);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								dataPaths.push_back("/usr/local/share");
 | 
				
			||||||
 | 
								dataPaths.push_back("/usr/share");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto fallbackPaths = QIcon::fallbackSearchPaths();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (auto& path: dataPaths) {
 | 
				
			||||||
 | 
								auto newPath = QDir(path).filePath("pixmaps");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!fallbackPaths.contains(newPath)) {
 | 
				
			||||||
 | 
									fallbackPaths.push_back(newPath);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							QIcon::setFallbackSearchPaths(fallbackPaths);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QGuiApplication::setDesktopSettingsAware(pragmas.desktopSettingsAware);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delete coreApplication;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QGuiApplication* app = nullptr;
 | 
				
			||||||
 | 
						auto qArgC = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pragmas.useQApplication) {
 | 
				
			||||||
 | 
							app = new QApplication(qArgC, argv);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							app = new QGuiApplication(qArgC, argv);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (args.debugPort != -1) {
 | 
				
			||||||
 | 
							QQmlDebuggingEnabler::enableDebugging(true);
 | 
				
			||||||
 | 
							auto wait = args.waitForDebug ? QQmlDebuggingEnabler::WaitForClient
 | 
				
			||||||
 | 
							                              : QQmlDebuggingEnabler::DoNotWaitForClient;
 | 
				
			||||||
 | 
							QQmlDebuggingEnabler::startTcpDebugServer(args.debugPort, wait);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QuickshellPlugin::initPlugins();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Base window transparency appears to be additive.
 | 
				
			||||||
 | 
						// Use a fully transparent window with a colored rect.
 | 
				
			||||||
 | 
						QQuickWindow::setDefaultAlphaBuffer(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pragmas.nativeTextRendering) {
 | 
				
			||||||
 | 
							QQuickWindow::setTextRenderType(QQuickWindow::NativeTextRendering);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qs::ipc::IpcServer::start();
 | 
				
			||||||
 | 
						QsPaths::instance()->createLock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto root = RootWrapper(args.configPath, shellId);
 | 
				
			||||||
 | 
						QGuiApplication::setQuitOnLastWindowClosed(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						exitDaemon(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto code = QGuiApplication::exec();
 | 
				
			||||||
 | 
						delete app;
 | 
				
			||||||
 | 
						return code;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::launch
 | 
				
			||||||
							
								
								
									
										103
									
								
								src/launch/launch_p.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/launch/launch_p.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,103 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <CLI/App.hpp>
 | 
				
			||||||
 | 
					#include <qcoreapplication.h>
 | 
				
			||||||
 | 
					#include <qstring.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::launch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int DAEMON_PIPE; // NOLINT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class QStringOption {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						QStringOption() = default;
 | 
				
			||||||
 | 
						QStringOption& operator=(const std::string& str) {
 | 
				
			||||||
 | 
							this->str = QString::fromStdString(str);
 | 
				
			||||||
 | 
							return *this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QString& operator*() { return this->str; }
 | 
				
			||||||
 | 
						QString* operator->() { return &this->str; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						QString str;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct CommandState {
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							int argc = 0;
 | 
				
			||||||
 | 
							char** argv = nullptr;
 | 
				
			||||||
 | 
						} exec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							bool timestamp = false;
 | 
				
			||||||
 | 
							bool noColor = !qEnvironmentVariableIsEmpty("NO_COLOR");
 | 
				
			||||||
 | 
							bool sparse = false;
 | 
				
			||||||
 | 
							size_t verbosity = 0;
 | 
				
			||||||
 | 
							int tail = 0;
 | 
				
			||||||
 | 
							bool follow = false;
 | 
				
			||||||
 | 
							QStringOption rules;
 | 
				
			||||||
 | 
							QStringOption readoutRules;
 | 
				
			||||||
 | 
							QStringOption file;
 | 
				
			||||||
 | 
						} log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							QStringOption path;
 | 
				
			||||||
 | 
							QStringOption manifest;
 | 
				
			||||||
 | 
							QStringOption name;
 | 
				
			||||||
 | 
						} config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							int port = -1;
 | 
				
			||||||
 | 
							bool wait = false;
 | 
				
			||||||
 | 
						} debug;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							QStringOption id;
 | 
				
			||||||
 | 
							pid_t pid = -1; // NOLINT (include)
 | 
				
			||||||
 | 
							bool all = false;
 | 
				
			||||||
 | 
						} instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							bool json = false;
 | 
				
			||||||
 | 
						} output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							bool info = false;
 | 
				
			||||||
 | 
							QStringOption target;
 | 
				
			||||||
 | 
							QStringOption function;
 | 
				
			||||||
 | 
							std::vector<QStringOption> arguments;
 | 
				
			||||||
 | 
						} ipc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							CLI::App* log = nullptr;
 | 
				
			||||||
 | 
							CLI::App* list = nullptr;
 | 
				
			||||||
 | 
							CLI::App* kill = nullptr;
 | 
				
			||||||
 | 
							CLI::App* msg = nullptr;
 | 
				
			||||||
 | 
						} subcommand;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							bool checkCompat = false;
 | 
				
			||||||
 | 
							bool printVersion = false;
 | 
				
			||||||
 | 
							bool killAll = false;
 | 
				
			||||||
 | 
							bool noDuplicate = false;
 | 
				
			||||||
 | 
							bool daemonize = false;
 | 
				
			||||||
 | 
						} misc;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct LaunchArgs {
 | 
				
			||||||
 | 
						QString configPath;
 | 
				
			||||||
 | 
						int debugPort = -1;
 | 
				
			||||||
 | 
						bool waitForDebug = false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void exitDaemon(int code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int parseCommand(int argc, char** argv, CommandState& state);
 | 
				
			||||||
 | 
					int runCommand(int argc, char** argv, QCoreApplication* coreApplication);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplication);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::launch
 | 
				
			||||||
							
								
								
									
										116
									
								
								src/launch/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/launch/main.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,116 @@
 | 
				
			||||||
 | 
					#include "main.hpp"
 | 
				
			||||||
 | 
					#include <cerrno>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <qcoreapplication.h>
 | 
				
			||||||
 | 
					#include <qdatastream.h>
 | 
				
			||||||
 | 
					#include <qdatetime.h>
 | 
				
			||||||
 | 
					#include <qdebug.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qtenvironmentvariables.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../core/instanceinfo.hpp"
 | 
				
			||||||
 | 
					#include "../core/logging.hpp"
 | 
				
			||||||
 | 
					#include "../core/paths.hpp"
 | 
				
			||||||
 | 
					#include "build.hpp"
 | 
				
			||||||
 | 
					#include "launch_p.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if CRASH_REPORTER
 | 
				
			||||||
 | 
					#include "../crash/main.hpp"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::launch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void checkCrashRelaunch(char** argv, QCoreApplication* coreApplication);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int DAEMON_PIPE = -1; // NOLINT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void exitDaemon(int code) {
 | 
				
			||||||
 | 
						if (DAEMON_PIPE == -1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (write(DAEMON_PIPE, &code, sizeof(int)) == -1) {
 | 
				
			||||||
 | 
							qCritical().nospace() << "Failed to write daemon exit command with error code " << errno << ": "
 | 
				
			||||||
 | 
							                      << qt_error_string();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						close(DAEMON_PIPE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						close(STDIN_FILENO);
 | 
				
			||||||
 | 
						close(STDOUT_FILENO);
 | 
				
			||||||
 | 
						close(STDERR_FILENO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (open("/dev/null", O_RDONLY) != STDIN_FILENO) { // NOLINT
 | 
				
			||||||
 | 
							qFatal() << "Failed to open /dev/null on stdin";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (open("/dev/null", O_WRONLY) != STDOUT_FILENO) { // NOLINT
 | 
				
			||||||
 | 
							qFatal() << "Failed to open /dev/null on stdout";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (open("/dev/null", O_WRONLY) != STDERR_FILENO) { // NOLINT
 | 
				
			||||||
 | 
							qFatal() << "Failed to open /dev/null on stderr";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void checkCrashRelaunch(char** argv, QCoreApplication* coreApplication) {
 | 
				
			||||||
 | 
					#if CRASH_REPORTER
 | 
				
			||||||
 | 
						auto lastInfoFdStr = qEnvironmentVariable("__QUICKSHELL_CRASH_INFO_FD");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!lastInfoFdStr.isEmpty()) {
 | 
				
			||||||
 | 
							auto lastInfoFd = lastInfoFdStr.toInt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							QFile file;
 | 
				
			||||||
 | 
							file.open(lastInfoFd, QFile::ReadOnly, QFile::AutoCloseHandle);
 | 
				
			||||||
 | 
							file.seek(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto ds = QDataStream(&file);
 | 
				
			||||||
 | 
							RelaunchInfo info;
 | 
				
			||||||
 | 
							ds >> info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							LogManager::init(
 | 
				
			||||||
 | 
							    !info.noColor,
 | 
				
			||||||
 | 
							    info.timestamp,
 | 
				
			||||||
 | 
							    info.sparseLogsOnly,
 | 
				
			||||||
 | 
							    info.defaultLogLevel,
 | 
				
			||||||
 | 
							    info.logRules
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							qCritical().nospace() << "Quickshell has crashed under pid "
 | 
				
			||||||
 | 
							                      << qEnvironmentVariable("__QUICKSHELL_CRASH_DUMP_PID").toInt()
 | 
				
			||||||
 | 
							                      << " (Coredumps will be available under that pid.)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							qCritical() << "Further crash information is stored under"
 | 
				
			||||||
 | 
							            << QsPaths::crashDir(info.instance.instanceId).path();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (info.instance.launchTime.msecsTo(QDateTime::currentDateTime()) < 10000) {
 | 
				
			||||||
 | 
								qCritical() << "Quickshell crashed within 10 seconds of launching. Not restarting to avoid "
 | 
				
			||||||
 | 
								               "a crash loop.";
 | 
				
			||||||
 | 
								exit(-1); // NOLINT
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								qCritical() << "Quickshell has been restarted.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								launch({.configPath = info.instance.configPath}, argv, coreApplication);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char** argv) {
 | 
				
			||||||
 | 
						QCoreApplication::setApplicationName("quickshell");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if CRASH_REPORTER
 | 
				
			||||||
 | 
						qsCheckCrash(argc, argv);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto qArgC = 1;
 | 
				
			||||||
 | 
						auto* coreApplication = new QCoreApplication(qArgC, argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						checkCrashRelaunch(argv, coreApplication);
 | 
				
			||||||
 | 
						auto code = runCommand(argc, argv, coreApplication);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						exitDaemon(code);
 | 
				
			||||||
 | 
						return code;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::launch
 | 
				
			||||||
							
								
								
									
										7
									
								
								src/launch/main.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/launch/main.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::launch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char** argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										196
									
								
								src/launch/parsecommand.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								src/launch/parsecommand.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,196 @@
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <CLI/App.hpp>
 | 
				
			||||||
 | 
					#include <CLI/CLI.hpp> // NOLINT: Need to include this for impls of some CLI11 classes
 | 
				
			||||||
 | 
					#include <CLI/Validators.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "launch_p.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::launch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int parseCommand(int argc, char** argv, CommandState& state) {
 | 
				
			||||||
 | 
						state.exec = {
 | 
				
			||||||
 | 
						    .argc = argc,
 | 
				
			||||||
 | 
						    .argv = argv,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto addConfigSelection = [&](CLI::App* cmd) {
 | 
				
			||||||
 | 
							auto* group = cmd->add_option_group("Config Selection")
 | 
				
			||||||
 | 
							                  ->description("If no options in this group are specified,\n"
 | 
				
			||||||
 | 
							                                "$XDG_CONFIG_HOME/quickshell/shell.qml will be used.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* path = group->add_option("-p,--path", state.config.path)
 | 
				
			||||||
 | 
							                 ->description("Path to a QML file.")
 | 
				
			||||||
 | 
							                 ->envname("QS_CONFIG_PATH");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_option("-m,--manifest", state.config.manifest)
 | 
				
			||||||
 | 
							    ->description("Path to a quickshell manifest.\n"
 | 
				
			||||||
 | 
							                  "Defaults to $XDG_CONFIG_HOME/quickshell/manifest.conf")
 | 
				
			||||||
 | 
							    ->envname("QS_MANIFEST")
 | 
				
			||||||
 | 
							    ->excludes(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_option("-c,--config", state.config.name)
 | 
				
			||||||
 | 
							    ->description("Name of a quickshell configuration to run.\n"
 | 
				
			||||||
 | 
							                  "If -m is specified, this is a configuration in the manifest,\n"
 | 
				
			||||||
 | 
							                  "otherwise it is the name of a folder in $XDG_CONFIG_HOME/quickshell.")
 | 
				
			||||||
 | 
							    ->envname("QS_CONFIG_NAME");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return group;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto addDebugOptions = [&](CLI::App* cmd) {
 | 
				
			||||||
 | 
							auto* group = cmd->add_option_group("Debugging", "Options for QML debugging.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* debug = group->add_option("--debug", state.debug.port)
 | 
				
			||||||
 | 
							                  ->description("Open the given port for a QML debugger connection.")
 | 
				
			||||||
 | 
							                  ->check(CLI::Range(0, 65535));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_flag("--waitfordebug", state.debug.wait)
 | 
				
			||||||
 | 
							    ->description("Wait for a QML debugger to connect before executing the configuration.")
 | 
				
			||||||
 | 
							    ->needs(debug);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return group;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto addLoggingOptions = [&](CLI::App* cmd, bool noGroup, bool noDisplay = false) {
 | 
				
			||||||
 | 
							auto* group = noGroup ? cmd : cmd->add_option_group(noDisplay ? "" : "Logging");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_flag("--no-color", state.log.noColor)
 | 
				
			||||||
 | 
							    ->description("Disables colored logging.\n"
 | 
				
			||||||
 | 
							                  "Colored logging can also be disabled by specifying a non empty value\n"
 | 
				
			||||||
 | 
							                  "for the NO_COLOR environment variable.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_flag("--log-times", state.log.timestamp)
 | 
				
			||||||
 | 
							    ->description("Log timestamps with each message.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_option("--log-rules", state.log.rules)
 | 
				
			||||||
 | 
							    ->description("Log rules to apply, in the format of QT_LOGGING_RULES.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_flag("-v,--verbose", [&](size_t count) { state.log.verbosity = count; })
 | 
				
			||||||
 | 
							    ->description("Increases log verbosity.\n"
 | 
				
			||||||
 | 
							                  "-v will show INFO level internal logs.\n"
 | 
				
			||||||
 | 
							                  "-vv will show DEBUG level internal logs.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* hgroup = cmd->add_option_group("");
 | 
				
			||||||
 | 
							hgroup->add_flag("--no-detailed-logs", state.log.sparse);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto addInstanceSelection = [&](CLI::App* cmd) {
 | 
				
			||||||
 | 
							auto* group = cmd->add_option_group("Instance Selection");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_option("-i,--id", state.instance.id)
 | 
				
			||||||
 | 
							    ->description("The instance id to operate on.\n"
 | 
				
			||||||
 | 
							                  "You may also use a substring the id as long as it is unique,\n"
 | 
				
			||||||
 | 
							                  "for example \"abc\" will select \"abcdefg\".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							group->add_option("--pid", state.instance.pid)
 | 
				
			||||||
 | 
							    ->description("The process id of the instance to operate on.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return group;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto cli = CLI::App();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Require 0-1 subcommands. Without this, positionals can be parsed as more subcommands.
 | 
				
			||||||
 | 
						cli.require_subcommand(0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addConfigSelection(&cli);
 | 
				
			||||||
 | 
						addLoggingOptions(&cli, false);
 | 
				
			||||||
 | 
						addDebugOptions(&cli);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							cli.add_option_group("")->add_flag("--private-check-compat", state.misc.checkCompat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cli.add_flag("-V,--version", state.misc.printVersion)
 | 
				
			||||||
 | 
							    ->description("Print quickshell's version and exit.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cli.add_flag("-n,--no-duplicate", state.misc.noDuplicate)
 | 
				
			||||||
 | 
							    ->description("Exit immediately if another instance of the given config is running.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cli.add_flag("-d,--daemonize", state.misc.daemonize)
 | 
				
			||||||
 | 
							    ->description("Detach from the controlling terminal.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto* sub = cli.add_subcommand("log", "Print quickshell logs.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* file = sub->add_option("file", state.log.file, "Log file to read.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sub->add_option("-t,--tail", state.log.tail)
 | 
				
			||||||
 | 
							    ->description("Maximum number of lines to print, starting from the bottom.")
 | 
				
			||||||
 | 
							    ->check(CLI::Range(1, std::numeric_limits<int>::max(), "INT > 0"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sub->add_flag("-f,--follow", state.log.follow)
 | 
				
			||||||
 | 
							    ->description("Keep reading the log until the logging process terminates.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sub->add_option("-r,--rules", state.log.readoutRules, "Log file to read.")
 | 
				
			||||||
 | 
							    ->description("Rules to apply to the log being read, in the format of QT_LOGGING_RULES.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* instance = addInstanceSelection(sub)->excludes(file);
 | 
				
			||||||
 | 
							addConfigSelection(sub)->excludes(instance)->excludes(file);
 | 
				
			||||||
 | 
							addLoggingOptions(sub, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							state.subcommand.log = sub;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto* sub = cli.add_subcommand("list", "List running quickshell instances.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* all = sub->add_flag("-a,--all", state.instance.all)
 | 
				
			||||||
 | 
							                ->description("List all instances.\n"
 | 
				
			||||||
 | 
							                              "If unspecified, only instances of"
 | 
				
			||||||
 | 
							                              "the selected config will be listed.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sub->add_flag("-j,--json", state.output.json, "Output the list as a json.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							addConfigSelection(sub)->excludes(all);
 | 
				
			||||||
 | 
							addLoggingOptions(sub, false, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							state.subcommand.list = sub;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto* sub = cli.add_subcommand("kill", "Kill quickshell instances.");
 | 
				
			||||||
 | 
							//sub->add_flag("-a,--all", "Kill all matching instances instead of just one.");
 | 
				
			||||||
 | 
							auto* instance = addInstanceSelection(sub);
 | 
				
			||||||
 | 
							addConfigSelection(sub)->excludes(instance);
 | 
				
			||||||
 | 
							addLoggingOptions(sub, false, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							state.subcommand.kill = sub;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto* sub = cli.add_subcommand("msg", "Send messages to IpcHandlers.")->require_option();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* target = sub->add_option("target", state.ipc.target, "The target to message.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* function = sub->add_option("function", state.ipc.function)
 | 
				
			||||||
 | 
							                     ->description("The function to call in the target.")
 | 
				
			||||||
 | 
							                     ->needs(target);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* arguments = sub->add_option("arguments", state.ipc.arguments)
 | 
				
			||||||
 | 
							                      ->description("Arguments to the called function.")
 | 
				
			||||||
 | 
							                      ->needs(function)
 | 
				
			||||||
 | 
							                      ->allow_extra_args();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sub->add_flag("-s,--show", state.ipc.info)
 | 
				
			||||||
 | 
							    ->description("Print information about a function or target if given, or all available "
 | 
				
			||||||
 | 
							                  "targets if not.")
 | 
				
			||||||
 | 
							    ->excludes(arguments);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto* instance = addInstanceSelection(sub);
 | 
				
			||||||
 | 
							addConfigSelection(sub)->excludes(instance);
 | 
				
			||||||
 | 
							addLoggingOptions(sub, false, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sub->require_option();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							state.subcommand.msg = sub;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CLI11_PARSE(cli, argc, argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::launch
 | 
				
			||||||
							
								
								
									
										1031
									
								
								src/main.cpp
									
										
									
									
									
								
							
							
						
						
									
										1031
									
								
								src/main.cpp
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -11,9 +11,9 @@ qt_add_qml_module(quickshell-service-greetd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-service-greetd)
 | 
					install_qml_module(quickshell-service-greetd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-service-greetd PRIVATE ${QT_DEPS})
 | 
					# can't be Qt::Qml because generation.hpp pulls in gui types
 | 
				
			||||||
 | 
					target_link_libraries(quickshell-service-greetd PRIVATE Qt::Quick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-service-greetd)
 | 
					qs_module_pch(quickshell-service-greetd)
 | 
				
			||||||
qs_pch(quickshell-service-greetdplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-service-greetdplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-service-greetdplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,13 +30,15 @@ target_include_directories(quickshell-service-mpris PRIVATE ${CMAKE_CURRENT_BINA
 | 
				
			||||||
qt_add_qml_module(quickshell-service-mpris
 | 
					qt_add_qml_module(quickshell-service-mpris
 | 
				
			||||||
	URI Quickshell.Services.Mpris
 | 
						URI Quickshell.Services.Mpris
 | 
				
			||||||
  VERSION 0.1
 | 
					  VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell
 | 
						DEPENDENCIES QtQml
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-service-mpris Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-service-mpris)
 | 
					install_qml_module(quickshell-service-mpris)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-service-mpris PRIVATE ${QT_DEPS} quickshell-dbus)
 | 
					target_link_libraries(quickshell-service-mpris PRIVATE Qt::Qml Qt::DBus)
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-service-mprisplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-service-mpris)
 | 
					qs_module_pch(quickshell-service-mpris SET dbus)
 | 
				
			||||||
qs_pch(quickshell-service-mprisplugin)
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell PRIVATE quickshell-service-mprisplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,13 +20,13 @@ target_include_directories(quickshell-service-notifications PRIVATE ${CMAKE_CURR
 | 
				
			||||||
qt_add_qml_module(quickshell-service-notifications
 | 
					qt_add_qml_module(quickshell-service-notifications
 | 
				
			||||||
	URI Quickshell.Services.Notifications
 | 
						URI Quickshell.Services.Notifications
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-service-notifications Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-service-notifications)
 | 
					install_qml_module(quickshell-service-notifications)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-service-notifications PRIVATE ${QT_DEPS} quickshell-dbus)
 | 
					target_link_libraries(quickshell-service-notifications PRIVATE Qt::Quick Qt::DBus)
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-service-notificationsplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-service-notificationsplugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-service-notifications)
 | 
					qs_module_pch(quickshell-service-notifications SET dbus)
 | 
				
			||||||
qs_pch(quickshell-service-notificationsplugin)
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,9 +13,8 @@ qt_add_qml_module(quickshell-service-pam
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-service-pam)
 | 
					install_qml_module(quickshell-service-pam)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-service-pam PRIVATE ${QT_DEPS} pam ${PAM_LIBRARIES})
 | 
					target_link_libraries(quickshell-service-pam PRIVATE Qt::Qml pam ${PAM_LIBRARIES})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-service-pam)
 | 
					qs_module_pch(quickshell-service-pam)
 | 
				
			||||||
qs_pch(quickshell-service-pamplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-service-pamplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-service-pamplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,14 +16,17 @@ qt_add_library(quickshell-service-pipewire STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-service-pipewire
 | 
					qt_add_qml_module(quickshell-service-pipewire
 | 
				
			||||||
	URI Quickshell.Services.Pipewire
 | 
						URI Quickshell.Services.Pipewire
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell
 | 
						DEPENDENCIES QtQml
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-service-pipewire Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-service-pipewire)
 | 
					install_qml_module(quickshell-service-pipewire)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-service-pipewire PRIVATE ${QT_DEPS} PkgConfig::pipewire)
 | 
					target_link_libraries(quickshell-service-pipewire PRIVATE
 | 
				
			||||||
 | 
						Qt::Qml PkgConfig::pipewire
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-service-pipewire)
 | 
					qs_module_pch(quickshell-service-pipewire)
 | 
				
			||||||
qs_pch(quickshell-service-pipewireplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-service-pipewireplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-service-pipewireplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,13 +41,14 @@ target_include_directories(quickshell-service-statusnotifier PRIVATE ${CMAKE_CUR
 | 
				
			||||||
qt_add_qml_module(quickshell-service-statusnotifier
 | 
					qt_add_qml_module(quickshell-service-statusnotifier
 | 
				
			||||||
  URI Quickshell.Services.SystemTray
 | 
					  URI Quickshell.Services.SystemTray
 | 
				
			||||||
  VERSION 0.1
 | 
					  VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell Quickshell.DBusMenu
 | 
						DEPENDENCIES QtQml
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-service-statusnotifier Quickshell Quickshell.DBusMenu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-service-statusnotifier)
 | 
					install_qml_module(quickshell-service-statusnotifier)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-service-statusnotifier PRIVATE ${QT_DEPS} quickshell-dbus quickshell-dbusmenuplugin)
 | 
					target_link_libraries(quickshell-service-statusnotifier PRIVATE Qt::Quick Qt::DBus)
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-service-statusnotifierplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-service-statusnotifierplugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-service-statusnotifier)
 | 
					qs_module_pch(quickshell-service-statusnotifier SET dbus)
 | 
				
			||||||
qs_pch(quickshell-service-statusnotifierplugin)
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,13 +30,14 @@ target_include_directories(quickshell-service-upower PRIVATE ${CMAKE_CURRENT_BIN
 | 
				
			||||||
qt_add_qml_module(quickshell-service-upower
 | 
					qt_add_qml_module(quickshell-service-upower
 | 
				
			||||||
	URI Quickshell.Services.UPower
 | 
						URI Quickshell.Services.UPower
 | 
				
			||||||
  VERSION 0.1
 | 
					  VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell
 | 
						DEPENDENCIES QtQml
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-service-upower Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-service-upower)
 | 
					install_qml_module(quickshell-service-upower)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-service-upower PRIVATE ${QT_DEPS} quickshell-dbus)
 | 
					target_link_libraries(quickshell-service-upower PRIVATE Qt::Qml Qt::DBus quickshell-dbus)
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-service-upowerplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-service-upowerplugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-service-upower)
 | 
					qs_module_pch(quickshell-service-upower SET dbus)
 | 
				
			||||||
qs_pch(quickshell-service-upowerplugin)
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,14 @@ execute_process(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
 | 
					message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_pchset(wayland-protocol
 | 
				
			||||||
 | 
						DEPENDENCIES Qt::Core Qt::WaylandClient Qt::WaylandClientPrivate
 | 
				
			||||||
 | 
						HEADERS
 | 
				
			||||||
 | 
							<wayland-client.h>
 | 
				
			||||||
 | 
							<qbytearray.h>
 | 
				
			||||||
 | 
							<qstring.h>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function (wl_proto target name path)
 | 
					function (wl_proto target name path)
 | 
				
			||||||
	set(PROTO_BUILD_PATH ${CMAKE_CURRENT_BINARY_DIR}/wl-proto/${name})
 | 
						set(PROTO_BUILD_PATH ${CMAKE_CURRENT_BINARY_DIR}/wl-proto/${name})
 | 
				
			||||||
	make_directory(${PROTO_BUILD_PATH})
 | 
						make_directory(${PROTO_BUILD_PATH})
 | 
				
			||||||
| 
						 | 
					@ -53,13 +61,12 @@ function (wl_proto target name path)
 | 
				
			||||||
		DEPENDS Qt6::qtwaylandscanner "${path}"
 | 
							DEPENDS Qt6::qtwaylandscanner "${path}"
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	add_library(wl-proto-${name}
 | 
						add_library(wl-proto-${name}-wl STATIC ${WS_CLIENT_HEADER} ${WS_CLIENT_CODE})
 | 
				
			||||||
		${WS_CLIENT_HEADER} ${WS_CLIENT_CODE}
 | 
						add_library(wl-proto-${name} STATIC ${QWS_CLIENT_HEADER} ${QWS_CLIENT_CODE})
 | 
				
			||||||
		${QWS_CLIENT_HEADER} ${QWS_CLIENT_CODE}
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	target_include_directories(wl-proto-${name} INTERFACE ${PROTO_BUILD_PATH})
 | 
						target_include_directories(wl-proto-${name} INTERFACE ${PROTO_BUILD_PATH})
 | 
				
			||||||
	target_link_libraries(wl-proto-${name} Qt6::WaylandClient Qt6::WaylandClientPrivate)
 | 
						target_link_libraries(wl-proto-${name} wl-proto-${name}-wl Qt6::WaylandClient Qt6::WaylandClientPrivate)
 | 
				
			||||||
 | 
						qs_pch(wl-proto-${name} SET wayland-protocol)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	target_link_libraries(${target} PRIVATE wl-proto-${name})
 | 
						target_link_libraries(${target} PRIVATE wl-proto-${name})
 | 
				
			||||||
endfunction()
 | 
					endfunction()
 | 
				
			||||||
| 
						 | 
					@ -100,20 +107,24 @@ if (HYPRLAND)
 | 
				
			||||||
	add_subdirectory(hyprland)
 | 
						add_subdirectory(hyprland)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-wayland PRIVATE ${QT_DEPS})
 | 
					# widgets for qmenu
 | 
				
			||||||
target_link_libraries(quickshell-wayland-init PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-wayland PRIVATE
 | 
				
			||||||
 | 
						Qt::Quick Qt::Widgets Qt::WaylandClient Qt::WaylandClientPrivate
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(quickshell-wayland-init PRIVATE Qt::Quick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qt_add_qml_module(quickshell-wayland
 | 
					qt_add_qml_module(quickshell-wayland
 | 
				
			||||||
	URI Quickshell.Wayland
 | 
						URI Quickshell.Wayland
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQuick Quickshell
 | 
						DEPENDENCIES QtQuick
 | 
				
			||||||
	IMPORTS ${WAYLAND_MODULES}
 | 
						IMPORTS ${WAYLAND_MODULES}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-wayland Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-wayland)
 | 
					install_qml_module(quickshell-wayland)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-wayland)
 | 
					qs_module_pch(quickshell-wayland SET large)
 | 
				
			||||||
qs_pch(quickshell-waylandplugin)
 | 
					 | 
				
			||||||
qs_pch(quickshell-wayland-init)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-waylandplugin quickshell-wayland-init)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-waylandplugin quickshell-wayland-init)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,6 @@ qt_add_qml_module(quickshell-hyprland
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-hyprland)
 | 
					install_qml_module(quickshell-hyprland)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-hyprland)
 | 
					# intentionally no pch as the module is empty
 | 
				
			||||||
qs_pch(quickshell-hyprlandplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-hyprlandplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-hyprlandplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,9 +7,11 @@ qt_add_library(quickshell-hyprland-focus-grab STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-hyprland-focus-grab
 | 
					qt_add_qml_module(quickshell-hyprland-focus-grab
 | 
				
			||||||
	URI Quickshell.Hyprland._FocusGrab
 | 
						URI Quickshell.Hyprland._FocusGrab
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell
 | 
						DEPENDENCIES QtQml
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-hyprland-focus-grab Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-hyprland-focus-grab)
 | 
					install_qml_module(quickshell-hyprland-focus-grab)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
wl_proto(quickshell-hyprland-focus-grab
 | 
					wl_proto(quickshell-hyprland-focus-grab
 | 
				
			||||||
| 
						 | 
					@ -17,9 +19,10 @@ wl_proto(quickshell-hyprland-focus-grab
 | 
				
			||||||
	"${CMAKE_CURRENT_SOURCE_DIR}/hyprland-focus-grab-v1.xml"
 | 
						"${CMAKE_CURRENT_SOURCE_DIR}/hyprland-focus-grab-v1.xml"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-hyprland-focus-grab PRIVATE ${QT_DEPS} wayland-client)
 | 
					target_link_libraries(quickshell-hyprland-focus-grab PRIVATE
 | 
				
			||||||
 | 
						Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-hyprland-focus-grab)
 | 
					qs_module_pch(quickshell-hyprland-focus-grab SET large)
 | 
				
			||||||
qs_pch(quickshell-hyprland-focus-grabplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-hyprland-focus-grabplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-hyprland-focus-grabplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,9 +17,10 @@ wl_proto(quickshell-hyprland-global-shortcuts
 | 
				
			||||||
	"${CMAKE_CURRENT_SOURCE_DIR}/hyprland-global-shortcuts-v1.xml"
 | 
						"${CMAKE_CURRENT_SOURCE_DIR}/hyprland-global-shortcuts-v1.xml"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-hyprland-global-shortcuts PRIVATE ${QT_DEPS} wayland-client)
 | 
					target_link_libraries(quickshell-hyprland-global-shortcuts PRIVATE
 | 
				
			||||||
 | 
						Qt::Qml Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-hyprland-global-shortcuts)
 | 
					qs_module_pch(quickshell-hyprland-global-shortcuts)
 | 
				
			||||||
qs_pch(quickshell-hyprland-global-shortcutsplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-hyprland-global-shortcutsplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-hyprland-global-shortcutsplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,14 +8,15 @@ qt_add_library(quickshell-hyprland-ipc STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-hyprland-ipc
 | 
					qt_add_qml_module(quickshell-hyprland-ipc
 | 
				
			||||||
	URI Quickshell.Hyprland._Ipc
 | 
						URI Quickshell.Hyprland._Ipc
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell
 | 
						DEPENDENCIES QtQuick
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-hyprland-ipc Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-hyprland-ipc)
 | 
					install_qml_module(quickshell-hyprland-ipc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-hyprland-ipc PRIVATE ${QT_DEPS})
 | 
					target_link_libraries(quickshell-hyprland-ipc PRIVATE Qt::Quick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-hyprland-ipc)
 | 
					qs_module_pch(quickshell-hyprland-ipc SET large)
 | 
				
			||||||
qs_pch(quickshell-hyprland-ipcplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-hyprland-ipcplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-hyprland-ipcplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#include <qwindow.h>
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../core/platformmenu.hpp"
 | 
					#include "../core/platformmenu.hpp"
 | 
				
			||||||
 | 
					#include "../core/platformmenu_p.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace qs::menu::platform;
 | 
					using namespace qs::menu::platform;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ qt_add_library(quickshell-wayland-sessionlock STATIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
wl_proto(quickshell-wayland-sessionlock ext-session-lock-v1 "${WAYLAND_PROTOCOLS}/staging/ext-session-lock/ext-session-lock-v1.xml")
 | 
					wl_proto(quickshell-wayland-sessionlock ext-session-lock-v1 "${WAYLAND_PROTOCOLS}/staging/ext-session-lock/ext-session-lock-v1.xml")
 | 
				
			||||||
target_link_libraries(quickshell-wayland-sessionlock PRIVATE ${QT_DEPS} wayland-client)
 | 
					target_link_libraries(quickshell-wayland-sessionlock PRIVATE ${QT_DEPS} wayland-client)
 | 
				
			||||||
qs_pch(quickshell-wayland-sessionlock)
 | 
					
 | 
				
			||||||
 | 
					qs_pch(quickshell-wayland-sessionlock SET large)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-sessionlock)
 | 
					target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-sessionlock)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,11 @@ qt_add_library(quickshell-wayland-toplevel-management STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-wayland-toplevel-management
 | 
					qt_add_qml_module(quickshell-wayland-toplevel-management
 | 
				
			||||||
	URI Quickshell.Wayland._ToplevelManagement
 | 
						URI Quickshell.Wayland._ToplevelManagement
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQml Quickshell Quickshell.Wayland
 | 
						DEPENDENCIES QtQml
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-wayland-toplevel-management
 | 
				
			||||||
 | 
						Quickshell Quickshell.Wayland
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-wayland-toplevel-management)
 | 
					install_qml_module(quickshell-wayland-toplevel-management)
 | 
				
			||||||
| 
						 | 
					@ -17,9 +21,10 @@ wl_proto(quickshell-wayland-toplevel-management
 | 
				
			||||||
	"${CMAKE_CURRENT_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1.xml"
 | 
						"${CMAKE_CURRENT_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1.xml"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-wayland-toplevel-management PRIVATE ${QT_DEPS} wayland-client)
 | 
					target_link_libraries(quickshell-wayland-toplevel-management PRIVATE
 | 
				
			||||||
 | 
						Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-wayland-toplevel-management)
 | 
					qs_module_pch(quickshell-wayland-toplevel-management SET large)
 | 
				
			||||||
qs_pch(quickshell-wayland-toplevel-managementplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-wayland-toplevel-managementplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-wayland-toplevel-managementplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,17 +7,19 @@ qt_add_library(quickshell-wayland-layershell STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-wayland-layershell
 | 
					qt_add_qml_module(quickshell-wayland-layershell
 | 
				
			||||||
	URI Quickshell.Wayland._WlrLayerShell
 | 
						URI Quickshell.Wayland._WlrLayerShell
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	# Quickshell.Wayland currently creates a dependency cycle, add it here once the main
 | 
						DEPENDENCIES QtQuick
 | 
				
			||||||
	# ls class is moved to this module.
 | 
					 | 
				
			||||||
	DEPENDENCIES QtQuick Quickshell
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-wayland-layershell Quickshell Quickshell.Wayland)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-wayland-layershell)
 | 
					install_qml_module(quickshell-wayland-layershell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
wl_proto(quickshell-wayland-layershell wlr-layer-shell-unstable-v1 "${CMAKE_CURRENT_SOURCE_DIR}/wlr-layer-shell-unstable-v1.xml")
 | 
					wl_proto(quickshell-wayland-layershell wlr-layer-shell-unstable-v1 "${CMAKE_CURRENT_SOURCE_DIR}/wlr-layer-shell-unstable-v1.xml")
 | 
				
			||||||
target_link_libraries(quickshell-wayland-layershell PRIVATE ${QT_DEPS} wayland-client)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-wayland-layershell)
 | 
					target_link_libraries(quickshell-wayland-layershell PRIVATE
 | 
				
			||||||
qs_pch(quickshell-wayland-layershellplugin)
 | 
						Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_module_pch(quickshell-wayland-layershell SET large)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-layershellplugin)
 | 
					target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-layershellplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,6 @@ qt_add_qml_module(quickshell-widgets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-widgets)
 | 
					install_qml_module(quickshell-widgets)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-widgets)
 | 
					qs_module_pch(quickshell-widgets)
 | 
				
			||||||
qs_pch(quickshell-widgetsplugin)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-widgetsplugin)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-widgetsplugin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,20 +9,22 @@ qt_add_library(quickshell-window STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-window
 | 
					qt_add_qml_module(quickshell-window
 | 
				
			||||||
	URI Quickshell._Window
 | 
						URI Quickshell._Window
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
	DEPENDENCIES QtQuick Quickshell
 | 
						DEPENDENCIES QtQuick
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qs_add_module_deps_light(quickshell-window Quickshell)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-window)
 | 
					install_qml_module(quickshell-window)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_library(quickshell-window-init OBJECT init.cpp)
 | 
					add_library(quickshell-window-init OBJECT init.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-window PRIVATE ${QT_DEPS} Qt6::QuickPrivate)
 | 
					target_link_libraries(quickshell-window PRIVATE
 | 
				
			||||||
target_link_libraries(quickshell-windowplugin PRIVATE ${QT_DEPS})
 | 
						Qt::Core Qt::Gui Qt::Quick Qt6::QuickPrivate
 | 
				
			||||||
target_link_libraries(quickshell-window-init PRIVATE ${QT_DEPS})
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-window)
 | 
					target_link_libraries(quickshell-window-init PRIVATE Qt::Qml)
 | 
				
			||||||
qs_pch(quickshell-windowplugin)
 | 
					
 | 
				
			||||||
qs_pch(quickshell-window-init)
 | 
					qs_module_pch(quickshell-window SET large)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-windowplugin quickshell-window-init)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-windowplugin quickshell-window-init)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,6 @@
 | 
				
			||||||
 | 
					#include <qqml.h>
 | 
				
			||||||
 | 
					#include <qstring.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../core/plugin.hpp"
 | 
					#include "../core/plugin.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
function (qs_test name)
 | 
					function (qs_test name)
 | 
				
			||||||
	add_executable(${name} ${ARGN})
 | 
						add_executable(${name} ${ARGN})
 | 
				
			||||||
	target_link_libraries(${name} PRIVATE ${QT_DEPS} Qt6::Test quickshell-window quickshell-core)
 | 
						target_link_libraries(${name} PRIVATE Qt::Quick Qt::Test quickshell-window quickshell-core)
 | 
				
			||||||
	add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
 | 
						add_test(NAME ${name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $<TARGET_FILE:${name}>)
 | 
				
			||||||
endfunction()
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,17 +8,16 @@ qt_add_library(quickshell-x11 STATIC
 | 
				
			||||||
qt_add_qml_module(quickshell-x11
 | 
					qt_add_qml_module(quickshell-x11
 | 
				
			||||||
	URI Quickshell.X11
 | 
						URI Quickshell.X11
 | 
				
			||||||
	VERSION 0.1
 | 
						VERSION 0.1
 | 
				
			||||||
 | 
						DEPENDENCIES QtQuick
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_qml_module(quickshell-x11)
 | 
					install_qml_module(quickshell-x11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_library(quickshell-x11-init OBJECT init.cpp)
 | 
					add_library(quickshell-x11-init OBJECT init.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell-x11 PRIVATE ${QT_DEPS} ${XCB_LIBRARIES})
 | 
					target_link_libraries(quickshell-x11 PRIVATE Qt::Quick ${XCB_LIBRARIES})
 | 
				
			||||||
target_link_libraries(quickshell-x11-init PRIVATE ${QT_DEPS} ${XCB_LIBRARIES})
 | 
					target_link_libraries(quickshell-x11-init PRIVATE Qt::Quick Qt::Qml ${XCB_LIBRARIES})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qs_pch(quickshell-x11)
 | 
					qs_module_pch(quickshell-x11 SET large)
 | 
				
			||||||
qs_pch(quickshell-x11plugin)
 | 
					 | 
				
			||||||
qs_pch(quickshell-x11-init)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(quickshell PRIVATE quickshell-x11plugin quickshell-x11-init)
 | 
					target_link_libraries(quickshell PRIVATE quickshell-x11plugin quickshell-x11-init)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
#include <qguiapplication.h>
 | 
					#include <qguiapplication.h>
 | 
				
			||||||
 | 
					#include <qlist.h>
 | 
				
			||||||
#include <qqml.h>
 | 
					#include <qqml.h>
 | 
				
			||||||
 | 
					#include <qstring.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../core/plugin.hpp"
 | 
					#include "../core/plugin.hpp"
 | 
				
			||||||
#include "panel_window.hpp"
 | 
					#include "panel_window.hpp"
 | 
				
			||||||
| 
						 | 
					@ -8,6 +10,8 @@
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class X11Plugin: public QuickshellPlugin {
 | 
					class X11Plugin: public QuickshellPlugin {
 | 
				
			||||||
 | 
						QList<QString> dependencies() override { return {"window"}; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool applies() override { return QGuiApplication::platformName() == "xcb"; }
 | 
						bool applies() override { return QGuiApplication::platformName() == "xcb"; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void init() override { XAtom::initAtoms(); }
 | 
						void init() override { XAtom::initAtoms(); }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue