Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@
"outputOnFailure": true
},
"execution": {
"noTestsAction": "error"
"noTestsAction": "error",
"excludeLabel": "manual"
}
}
]
}
}
1 change: 1 addition & 0 deletions src/core/lockscreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class LockScreen : public SurfaceContainer
void shutdown();
void switchUser();
void setPrimaryOutputName(const QString &primaryOutputName);
QString primaryOutputName() const { return m_primaryOutputName; }

Q_SIGNALS:
void unlock();
Expand Down
3 changes: 3 additions & 0 deletions src/core/rootsurfacecontainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#pragma once

// TODO(unit-test): RootSurfaceContainer depends on WCursor and WOutputLayout which
// require a running compositor with outputs. Ref: WM-29. Solution: Extract layout/priority logic for unit testing.

#include "surface/surfacecontainer.h"

Check warning on line 8 in src/core/rootsurfacecontainer.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "surface/surfacecontainer.h" not found.
#include "surface/seatsurfacemanager.h"

Check warning on line 9 in src/core/rootsurfacecontainer.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "surface/seatsurfacemanager.h" not found.

#include <wglobal.h>

Expand Down
3 changes: 3 additions & 0 deletions src/core/shellhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

#pragma once

// TODO(unit-test): ShellHandler depends on the running Wayland compositor for wl_client
// and surface resources. Ref: WM-29. Solution: Extract protocol interaction logic into testable pure components.

#include "modules/foreign-toplevel/foreigntoplevelmanagerv1.h"

Check warning on line 9 in src/core/shellhandler.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "modules/foreign-toplevel/foreigntoplevelmanagerv1.h" not found.

#include <xcb/xcb.h>

Check warning on line 11 in src/core/shellhandler.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <xcb/xcb.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <wglobal.h>

Expand Down
12 changes: 11 additions & 1 deletion src/greeter/greeterproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ GreeterProxy::GreeterProxy(QObject *parent)
updateAuthSocket();
}

GreeterProxy::GreeterProxy(bool testMode, QObject *parent)
: QObject(parent)
, m_testMode(testMode)
{
}

GreeterProxy::~GreeterProxy() { }

////////////////////////
Expand Down Expand Up @@ -234,6 +240,10 @@ void GreeterProxy::logout()

void GreeterProxy::lock()
{
if (m_testMode) {
setLock(true);
return;
}
auto session = Helper::instance()->sessionManager()->activeSession().lock();
if (!session || session->username() == "dde") {
qCInfo(lcTlGreeter) << "Trying to lock when no user session active, show lockscreen directly.";
Expand Down Expand Up @@ -390,7 +400,7 @@ void GreeterProxy::onSessionUnlock()

bool GreeterProxy::isConnected() const
{
return m_socket->state() == QLocalSocket::ConnectedState;
return m_socket && m_socket->state() == QLocalSocket::ConnectedState;
}

void GreeterProxy::connected()
Expand Down
12 changes: 7 additions & 5 deletions src/greeter/greeterproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class GreeterProxy

public:
explicit GreeterProxy(QObject *parent = nullptr);
explicit GreeterProxy(bool testMode, QObject *parent = nullptr);
~GreeterProxy();

//////////////////////
Expand Down Expand Up @@ -89,7 +90,7 @@ class GreeterProxy
*
* @return true if is locked
*/
inline bool isLocked() const { return m_isLocked; };
virtual bool isLocked() const { return m_isLocked; };

/**
* @brief Get the number of failed login attempts (password incorrect)
Expand All @@ -106,7 +107,7 @@ class GreeterProxy
*
* @return true if shutdown view is shown
*/
inline bool showShutdownView() const { return m_showShutdownView; };
virtual bool showShutdownView() const { return m_showShutdownView; };

/**
* @brief Get whether to show animation on lock/unlock
Expand Down Expand Up @@ -134,7 +135,7 @@ class GreeterProxy
*
* @param show true to show shutdown view, false to hide
*/
void setShowShutdownView(bool show);
virtual void setShowShutdownView(bool show);

////////////////////
// Public methods //
Expand Down Expand Up @@ -194,7 +195,7 @@ public Q_SLOTS:
* Listen to org.freedesktop.login1.Session.Lock signal to detect
* if the session is successfully locked.
*/
void lock();
virtual void lock();

/** @brief Unlock given user with given password.
* This function will call DDM to perform the unlock.
Expand Down Expand Up @@ -246,7 +247,7 @@ private Q_SLOTS:
Q_SIGNALS:
void informationMessage(const QString &message);

void switchUser();
virtual void switchUser();

void socketDisconnected();

Expand Down Expand Up @@ -314,6 +315,7 @@ private Q_SLOTS:

QLocalSocket *m_socket{ nullptr };
LockScreen *m_lockScreen{ nullptr };
bool m_testMode{ false };

QString m_hostName{};

Expand Down
10 changes: 10 additions & 0 deletions src/input/gestures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ void GestureRecognizer::unregisterSwipeGesture(SwipeGesture *gesture)
if (m_activeSwipeGestures.removeOne(gesture)) {
Q_EMIT gesture->cancelled();
}
}

void GestureRecognizer::removeSwipeGesture(SwipeGesture *gesture)
{
unregisterSwipeGesture(gesture);
gesture->deleteLater();
}

Expand Down Expand Up @@ -404,6 +409,11 @@ void GestureRecognizer::unregisterHoldGesture(HoldGesture *gesture)
if (m_activeHoldGestures.removeOne(gesture)) {
Q_EMIT gesture->cancelled();
}
}

void GestureRecognizer::removeHoldGesture(HoldGesture *gesture)
{
unregisterHoldGesture(gesture);
gesture->deleteLater();
}

Expand Down
3 changes: 2 additions & 1 deletion src/input/gestures.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

// Copyright (C) 2024-2026 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

Expand Down Expand Up @@ -134,9 +133,11 @@ class GestureRecognizer : public QObject

void registerSwipeGesture(SwipeGesture *gesture);
void unregisterSwipeGesture(SwipeGesture *gesture);
void removeSwipeGesture(SwipeGesture *gesture);

void registerHoldGesture(HoldGesture *gesture);
void unregisterHoldGesture(HoldGesture *gesture);
void removeHoldGesture(HoldGesture *gesture);

int startSwipeGesture(uint fingerCount);
int startSwipeGesture(const QPointF &startPos);
Expand Down
4 changes: 2 additions & 2 deletions src/input/inputdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,15 +419,15 @@

void InputDevice::unregisterTouchpadSwipe(SwipeGesture *gesture)
{
m_touchpadRecognizer->unregisterSwipeGesture(gesture);
m_touchpadRecognizer->removeSwipeGesture(gesture);
}

void InputDevice::unregisterTouchpadHold(HoldGesture *gesture)
{
m_touchpadRecognizer->unregisterHoldGesture(gesture);
m_touchpadRecognizer->removeHoldGesture(gesture);
}

void InputDevice::processSwipeStart(uint finger)

Check warning on line 430 in src/input/inputdevice.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'processSwipeStart' is never used.
{
m_touchpadFingerCount = finger;
if (m_touchpadFingerCount >= MIN_SWIPE_FINGERS) {
Expand Down
45 changes: 34 additions & 11 deletions src/output/backlight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,42 @@

QW_USE_NAMESPACE

Backlight::Backlight(const QString &name)
: m_name(name)
Backlight::Backlight(const QString &name, const QString &basePath)
: m_maxBrightness(0)
, m_brightnessLevel(0)
, m_name(name)
, m_basePath(basePath)
{
QFile maxBrightnessFile(QString("/sys/class/backlight/%1/max_brightness").arg(name));
Q_ASSERT(maxBrightnessFile.open(QIODevice::ReadOnly));
QFile maxBrightnessFile(QString("%1/%2/max_brightness").arg(m_basePath, name));
if (!maxBrightnessFile.open(QIODevice::ReadOnly)) {
qCWarning(lcTlOutput) << "Backlight: Failed to open max_brightness for" << name;
return;
}

bool ok = false;
m_maxBrightness = maxBrightnessFile.readLine().trimmed().toLongLong(&ok);
maxBrightnessFile.close();
Q_ASSERT(ok);
Q_ASSERT(m_maxBrightness > 0);
if (!ok || m_maxBrightness <= 0) {
qCWarning(lcTlOutput) << "Backlight: Invalid max_brightness for" << name;
m_maxBrightness = 0;
return;
}

QFile brightnessFile(QString("/sys/class/backlight/%1/brightness").arg(name));
Q_ASSERT(brightnessFile.open(QIODevice::ReadOnly));
QFile brightnessFile(QString("%1/%2/brightness").arg(m_basePath, name));
if (!brightnessFile.open(QIODevice::ReadOnly)) {
qCWarning(lcTlOutput) << "Backlight: Failed to open brightness for" << name;
m_maxBrightness = 0;
return;
}

m_brightnessLevel = brightnessFile.readLine().trimmed().toLongLong(&ok);
brightnessFile.close();
Q_ASSERT(ok);
if (!ok) {
qCWarning(lcTlOutput) << "Backlight: Invalid brightness for" << name;
m_maxBrightness = 0;
m_brightnessLevel = 0;
return;
}
}

Backlight::~Backlight()
Expand All @@ -37,6 +55,8 @@ Backlight::~Backlight()

qreal Backlight::brightness() const
{
if (m_maxBrightness <= 0)
return 0.0;
return m_brightnessLevel / static_cast<qreal>(m_maxBrightness);
}

Expand All @@ -48,7 +68,7 @@ qreal Backlight::setBrightness(qreal brightness)
return this->brightness();
}

QFile brightnessFile(QString("/sys/class/backlight/%1/brightness").arg(m_name));
QFile brightnessFile(QString("%1/%2/brightness").arg(m_basePath, m_name));
if (!brightnessFile.open(QIODevice::WriteOnly)) {
qCWarning(lcTlOutput) << "Output" << m_name << ": Failed to open backlight brightness file for writing.";
return this->brightness();
Expand All @@ -57,7 +77,10 @@ qreal Backlight::setBrightness(qreal brightness)
QByteArray brightnessStr = QByteArray::number(brightnessLevel);
qint64 written = brightnessFile.write(brightnessStr);
brightnessFile.close();
Q_ASSERT(written == brightnessStr.size());
if (written != brightnessStr.size()) {
qCWarning(lcTlOutput) << "Output" << m_name << ": Failed to write backlight brightness.";
return this->brightness();
}

m_brightnessLevel = brightnessLevel;
return this->brightness();
Expand Down
5 changes: 3 additions & 2 deletions src/output/backlight.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2025 UnionTech Software Technology Co., Ltd.
// Copyright (C) 2025-2026 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#pragma once
Expand All @@ -14,7 +14,7 @@ WAYLIB_SERVER_USE_NAMESPACE
class Backlight
{
public:
Backlight(const QString &name);
explicit Backlight(const QString &name, const QString &basePath = QString("/sys/class/backlight"));
~Backlight();
static Backlight* createForOutput(WOutput* output);
qreal brightness() const;
Expand All @@ -23,4 +23,5 @@ class Backlight
qlonglong m_maxBrightness;
qlonglong m_brightnessLevel;
QString m_name;
QString m_basePath;
};
6 changes: 3 additions & 3 deletions src/output/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ class Output : public SurfaceListModel
double heightPx,
double widthMm,
double heightMm);
static QPointF constrainToValidArea(const QPointF &pos,
const QSizeF &windowSize,
const QRectF &validGeo);
qreal preferredScaleFactor(const QSize &pixelSize) const;

OutputConfig* config() const;
Expand Down Expand Up @@ -136,9 +139,6 @@ public Q_SLOTS:
const QRectF &normalGeo,
const QRectF &validGeo,
const QSizeF &offset);
QPointF constrainToValidArea(const QPointF &pos,
const QSizeF &windowSize,
const QRectF &validGeo);
qreal preferredScaleFactor() const;

QPointF calculateBasePosition(SurfaceWrapper *surface, const QPointF &dPos) const;
Expand Down
4 changes: 4 additions & 0 deletions src/seat/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@

#pragma once

// TODO(unit-test): Helper is a singleton with deep coupling to the compositor runtime
// (WServer, WSeat, WBackend, session manager, etc.), making it impossible to instantiate
// in isolation. Ref: WM-29. Solution: Refactor to accept dependencies via constructor/parameters.

#include "core/qmlengine.h"

Check warning on line 10 in src/seat/helper.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "core/qmlengine.h" not found.
#include "modules/activation/activationmanagerinterfacev1.h"

Check warning on line 11 in src/seat/helper.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "modules/activation/activationmanagerinterfacev1.h" not found.
#include "modules/shortcut/shortcutmanager.h"

Check warning on line 12 in src/seat/helper.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "modules/shortcut/shortcutmanager.h" not found.
#include "modules/virtual-output/virtualoutputmanagerinterfacev1.h"
#include "modules/wallpaper/wallpapermanagerinterfacev1.h"
#include "modules/wallpaper/wallpapernotifierinterfacev1.h"
Expand Down
7 changes: 5 additions & 2 deletions src/surface/surfacecontainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,11 @@ void SurfaceContainer::removeOutput(Output *output)

void SurfaceContainer::ensureQmlContext()
{
if (QQmlEngine *engine = qmlEngine(parentContainer())) {
parentContainer()->setQmlEngine(engine);
auto *pc = parentContainer();
if (!pc)
return;
if (QQmlEngine *engine = qmlEngine(pc)) {
pc->setQmlEngine(engine);
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/surface/surfacewrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#pragma once

// TODO(unit-test): SurfaceWrapper inherits QQuickItem and requires the Qt Scene Graph
// rendering pipeline. Ref: WM-29. Solution: Separate business logic from rendering.

#include <wsurfaceitem.h>
#include <wtoplevelsurface.h>
#include <qwglobal.h>
Expand Down
10 changes: 5 additions & 5 deletions src/wallpaper/wallpaperconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

class WallpaperWorkspaceConfig {
public:
int workspaceId;
int workspaceId = 0;
QString desktopWallpaper;
TreelandWallpaperInterfaceV1::WallpaperType desktopWallpapertype;
bool enable;
TreelandWallpaperInterfaceV1::WallpaperType desktopWallpapertype = TreelandWallpaperInterfaceV1::Image;
bool enable = true;

QJsonObject toJson() const;

Expand All @@ -26,8 +26,8 @@ class WallpaperOutputConfig {
QString outputName;
QString lockscreenWallpaper;
QList<WallpaperWorkspaceConfig> workspaces;
TreelandWallpaperInterfaceV1::WallpaperType lockScreenWallpapertype;
bool enable;
TreelandWallpaperInterfaceV1::WallpaperType lockScreenWallpapertype = TreelandWallpaperInterfaceV1::Image;
bool enable = true;

QJsonObject toJson() const;
bool containsWorkspace(int id) const;
Expand Down
3 changes: 3 additions & 0 deletions src/workspace/workspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#pragma once

// TODO(unit-test): Workspace depends on the Helper singleton for surface management.
// Ref: WM-29. Solution: Inject workspace dependencies to enable isolated testing.

#include "surface/surfacecontainer.h"

Check warning on line 8 in src/workspace/workspace.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "surface/surfacecontainer.h" not found.
#include "surface/surfacefilterproxymodel.h"

Check warning on line 9 in src/workspace/workspace.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "surface/surfacefilterproxymodel.h" not found.
#include "workspace/workspacemodel.h"

#include <QPointer>
Expand Down
2 changes: 1 addition & 1 deletion src/xsettings/xresource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#define XRESOURCE_ATOM_NAME "RESOURCE_MANAGER"

static QPair<QByteArray, QByteArray> splitXResourceLine(const QByteArray &line)
QPair<QByteArray, QByteArray> XResource::splitXResourceLine(const QByteArray &line)
{
int pos = -1;
bool escaped = false;
Expand Down
Loading
Loading