debug: add lint for zero sized items

This commit is contained in:
outfoxxed 2024-11-19 15:25:42 -08:00
parent 66b494d760
commit 6ceee06884
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
7 changed files with 109 additions and 0 deletions

View file

@ -5,6 +5,7 @@ install(TARGETS quickshell RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
add_subdirectory(build)
add_subdirectory(launch)
add_subdirectory(core)
add_subdirectory(debug)
add_subdirectory(ipc)
add_subdirectory(window)
add_subdirectory(io)

7
src/debug/CMakeLists.txt Normal file
View file

@ -0,0 +1,7 @@
qt_add_library(quickshell-debug STATIC
lint.cpp
)
qs_pch(quickshell-debug)
target_link_libraries(quickshell-debug PRIVATE Qt::Quick)
target_link_libraries(quickshell PRIVATE quickshell-debug)

81
src/debug/lint.cpp Normal file
View file

@ -0,0 +1,81 @@
#include "lint.hpp"
#include <algorithm>
#include <qlogging.h>
#include <qloggingcategory.h>
#include <qobject.h>
#include <qqmlcontext.h>
#include <qqmlengine.h>
#include <qqmlinfo.h>
#include <qquickframebufferobject.h>
#include <qquickitem.h>
#include <qquickpainteditem.h>
#include <qquickrhiitem.h>
#include <qquickwindow.h>
#include <qstringliteral.h>
namespace qs::debug {
Q_LOGGING_CATEGORY(logLint, "quickshell.linter", QtWarningMsg);
void lintZeroSized(QQuickItem* item);
bool isRenderable(QQuickItem* item);
void lintObjectTree(QObject* object) {
if (!logLint().isWarningEnabled()) return;
qCDebug(logLint) << "Walking children of object" << object;
for (auto* child: object->children()) {
if (child->isQuickItemType()) {
auto* item = static_cast<QQuickItem*>(child); // NOLINT;
lintItemTree(item);
} else {
lintObjectTree(child);
}
}
}
void lintItemTree(QQuickItem* item) {
if (!logLint().isWarningEnabled()) return;
qCDebug(logLint) << "Running lints for item" << item;
lintZeroSized(item);
qCDebug(logLint) << "Walking visual children of item" << item;
for (auto* child: item->childItems()) {
lintItemTree(child);
}
}
void lintZeroSized(QQuickItem* item) {
if (!item->isEnabled() || !item->isVisible()) return;
if (item->childItems().isEmpty()) return;
auto zeroWidth = item->width() == 0;
auto zeroHeight = item->height() == 0;
if (!zeroWidth && !zeroHeight) return;
if (!isRenderable(item)) return;
auto* ctx = QQmlEngine::contextForObject(item);
if (!ctx || ctx->baseUrl().scheme() != QStringLiteral("qsintercept")) return;
qmlWarning(item) << "Item is visible and has visible children, but has zero "
<< (zeroWidth && zeroHeight ? "width and height"
: zeroWidth ? "width"
: "height");
}
bool isRenderable(QQuickItem* item) {
if (!item->isEnabled() || !item->isVisible()) return false;
if (item->flags().testFlags(QQuickItem::ItemHasContents)) {
return true;
}
return std::ranges::any_of(item->childItems(), [](auto* item) { return isRenderable(item); });
}
} // namespace qs::debug

11
src/debug/lint.hpp Normal file
View file

@ -0,0 +1,11 @@
#pragma once
#include <qobject.h>
#include <qquickitem.h>
namespace qs::debug {
void lintObjectTree(QObject* object);
void lintItemTree(QQuickItem* item);
} // namespace qs::debug

View file

@ -22,6 +22,8 @@ target_link_libraries(quickshell-window PRIVATE
Qt::Core Qt::Gui Qt::Quick Qt6::QuickPrivate
)
qs_add_link_dependencies(quickshell-window quickshell-debug)
target_link_libraries(quickshell-window-init PRIVATE Qt::Qml)
qs_module_pch(quickshell-window SET large)

View file

@ -19,6 +19,7 @@
#include "../core/qmlscreen.hpp"
#include "../core/region.hpp"
#include "../core/reload.hpp"
#include "../debug/lint.hpp"
#include "windowinterface.hpp"
ProxyWindowBase::ProxyWindowBase(QObject* parent)
@ -214,6 +215,11 @@ void ProxyWindowBase::polishItems() {
// This hack manually polishes the item tree right before showing the window so it will
// always be created with the correct size.
QQuickWindowPrivate::get(this->window)->polishItems();
if (!this->ranLints) {
qs::debug::lintItemTree(this->mContentItem);
this->ranLints = true;
}
}
qint32 ProxyWindowBase::x() const {

View file

@ -130,6 +130,7 @@ protected:
QQuickWindow* window = nullptr;
QQuickItem* mContentItem = nullptr;
bool reloadComplete = false;
bool ranLints = false;
private:
void polishItems();