Skip to content
Open
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
3 changes: 3 additions & 0 deletions panels/dock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ file(
dockhelper.cpp
waylanddockhelper.h
waylanddockhelper.cpp
layershellextension.h
layershellextension.cpp
loadtrayplugins.h
loadtrayplugins.cpp
)
Expand Down Expand Up @@ -64,6 +66,7 @@ qt_generate_wayland_protocol_client_sources(dockpanel
FILES
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-wallpaper-color-v1.xml
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-dde-shell-v1.xml
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-layer-shell-extension-unstable-v1.xml
)

target_link_libraries(dockpanel PRIVATE
Expand Down
13 changes: 13 additions & 0 deletions panels/dock/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ enum Position {
Left = 3,
};

enum ResizeEdge {
ResizeEdgeTop = 1,
ResizeEdgeBottom = 2,
ResizeEdgeLeft = 4,
ResizeEdgeTopLeft = 5,
ResizeEdgeBottomLeft = 6,
ResizeEdgeRight = 8,
ResizeEdgeTopRight = 9,
ResizeEdgeBottomRight = 10,
};

enum HideState {
Unknown = 0,
Show = 1,
Expand Down Expand Up @@ -151,6 +162,7 @@ Q_ENUM_NS(ItemAlignment)
Q_ENUM_NS(ColorTheme)
Q_ENUM_NS(HideMode)
Q_ENUM_NS(Position)
Q_ENUM_NS(ResizeEdge)
Q_ENUM_NS(HideState)
Q_ENUM_NS(AniAction)
Q_ENUM_NS(TrayPopupType)
Expand All @@ -165,6 +177,7 @@ Q_DECLARE_METATYPE(dock::ItemAlignment)
Q_DECLARE_METATYPE(dock::ColorTheme)
Q_DECLARE_METATYPE(dock::HideMode)
Q_DECLARE_METATYPE(dock::HideState)
Q_DECLARE_METATYPE(dock::ResizeEdge)
Q_DECLARE_METATYPE(dock::AniAction)
Q_DECLARE_METATYPE(dock::Position)
Q_DECLARE_METATYPE(dock::TrayPopupType)
Expand Down
60 changes: 60 additions & 0 deletions panels/dock/dockpanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

#include "dockpanel.h"
#include "constants.h"
#include "dockadaptor.h"

Check warning on line 7 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "dockadaptor.h" not found.
#include "docksettings.h"
#include "layershellextension.h"
#include "panel.h"

Check warning on line 10 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "panel.h" not found.
#include "pluginfactory.h"

Check warning on line 11 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "pluginfactory.h" not found.
#include "waylanddockhelper.h"
#include "x11dockhelper.h"

Expand All @@ -24,10 +25,14 @@
#include <QQuickItem>
#include <QQuickWindow>

#include <wayland/xdgactivation.h>

Check warning on line 28 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

#include <QtWaylandClient/private/qwaylanddisplay_p.h>

Check warning on line 30 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QtWaylandClient/private/qwaylanddisplay_p.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtWaylandClient/private/qwaylandinputdevice_p.h>

Check warning on line 31 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QtWaylandClient/private/qwaylandinputdevice_p.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtWaylandClient/private/qwaylandwindow_p.h>

Check warning on line 32 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

#ifdef HAVE_DDE_API_EVENTLOGGER
#include <dde-api/eventlogger.hpp>

Check warning on line 35 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <dde-api/eventlogger.hpp> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#endif

#define SETTINGS DockSettings::instance()
Expand Down Expand Up @@ -167,6 +172,7 @@
m_helper = new WaylandDockHelper(this);
connect(static_cast<WaylandDockHelper *>(m_helper), &WaylandDockHelper::xembedWindowMoveResult,
this, &DockPanel::xembedWindowMoveResult);
m_dockShellExtensionManager.reset(new TreeLandLayerShellExtensionManager());
// Fallback to DGuiApplicationHelper for theme color when wayland wallpaper color is not available.
// TODO: remove this when initWallpaperColorManager is re-enabled
QObject::connect(Dtk::Gui::DGuiApplicationHelper::instance(), &Dtk::Gui::DGuiApplicationHelper::themeTypeChanged,
Expand Down Expand Up @@ -520,6 +526,60 @@
}
return false;
}

bool DockPanel::beginDockResize(uint edges)
{
// The manager is created in DockPanel::init() on the Wayland platform. On
// X11 (or any other) platform it stays null, so fall back to the legacy
// client-side drag logic.
if (!m_dockShellExtensionManager)
return false;
if (!m_dockShellExtensionManager->isActive())
return false;

auto *waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(window()->handle());
if (!waylandWindow)
return false;

auto *surface = waylandWindow->wlSurface();
if (!surface)
return false;

auto *inputDevice = waylandWindow->display()->lastInputDevice();
if (!inputDevice)
return false;

if (!m_dockShellExtensionObject || m_dockShellExtensionObject->nativeSurface() != surface) {
m_dockShellExtensionObject.reset();
auto *dockSurface = m_dockShellExtensionManager->getLayerShellExtensionObject(surface);
if (!dockSurface)
return false;

m_dockShellExtensionObject.reset(new TreeLandLayerShellExtensionObject(dockSurface, surface));
connect(m_dockShellExtensionObject.get(), &TreeLandLayerShellExtensionObject::resizingChanged, this, &DockPanel::setIsResizing);
}

int minW = 0, maxW = 0, minH = 0, maxH = 0;
switch (position()) {
case Position::Left:
case Position::Right:
minW = MIN_DOCK_SIZE;
maxW = MAX_DOCK_SIZE;
break;
case Position::Top:
case Position::Bottom:
minH = MIN_DOCK_SIZE;
maxH = MAX_DOCK_SIZE;
break;
default:
Q_UNREACHABLE();
break;
}

m_dockShellExtensionObject->beginResize(inputDevice->wl_seat(), inputDevice->serial(), edges, minW, minH, maxW, maxH);
inputDevice->handleEndDrag();
return true;
}
}

#include "dockpanel.moc"

Check warning on line 585 in panels/dock/dockpanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "dockpanel.moc" not found.
6 changes: 6 additions & 0 deletions panels/dock/dockpanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
namespace dock {
class DockHelper;
class LoadTrayPlugins;
class TreeLandLayerShellExtensionManager;
class TreeLandLayerShellExtensionObject;

class DockPanel : public DS_NAMESPACE::DPanel, public QDBusContext
{
Expand Down Expand Up @@ -89,6 +91,8 @@ class DockPanel : public DS_NAMESPACE::DPanel, public QDBusContext
// anchorWindow: the window containing the plugin item (dock panel or popup window)
Q_INVOKABLE bool moveXEmbedWindow(uint32_t wid, double dx, double dy, QQuickWindow *anchorWindow = nullptr);

Q_INVOKABLE bool beginDockResize(uint edges);

bool showInPrimary() const;
void setShowInPrimary(bool newShowInPrimary);

Expand Down Expand Up @@ -156,6 +160,8 @@ private Q_SLOTS:
bool m_contextDragging;
bool m_isResizing;
QRect m_frontendWindowRect;
QScopedPointer<TreeLandLayerShellExtensionManager> m_dockShellExtensionManager;
QScopedPointer<TreeLandLayerShellExtensionObject> m_dockShellExtensionObject;
};

}
56 changes: 56 additions & 0 deletions panels/dock/layershellextension.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "layershellextension.h"

namespace dock
{

TreeLandLayerShellExtensionManager::TreeLandLayerShellExtensionManager()
: QWaylandClientExtensionTemplate<TreeLandLayerShellExtensionManager>(treeland_layer_shell_extension_manager_v1_interface.version)
{
}

struct ::treeland_layer_shell_extension_object_v1 *TreeLandLayerShellExtensionManager::getLayerShellExtensionObject(struct ::wl_surface *surface)

Check warning on line 15 in panels/dock/layershellextension.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getLayerShellExtensionObject' is never used.
{
return get_layer_shell_extension_object(surface);
}

TreeLandLayerShellExtensionObject::TreeLandLayerShellExtensionObject(struct ::treeland_layer_shell_extension_object_v1 *surface,
struct ::wl_surface *nativeSurface)
: QWaylandClientExtensionTemplate<TreeLandLayerShellExtensionObject>(treeland_layer_shell_extension_object_v1_interface.version)
, m_nativeSurface(nativeSurface)
{
init(surface);
}

TreeLandLayerShellExtensionObject::~TreeLandLayerShellExtensionObject()
{
if (object()) {
destroy();
}
}

struct ::wl_surface *TreeLandLayerShellExtensionObject::nativeSurface() const
{
return m_nativeSurface;
}

void TreeLandLayerShellExtensionObject::beginResize(struct ::wl_seat *seat,
uint32_t serial,
uint32_t edges,
int32_t minWidth,
int32_t minHeight,
int32_t maxWidth,
int32_t maxHeight)
{
begin_resize(seat, serial, edges, minWidth, minHeight, maxWidth, maxHeight);
}

void TreeLandLayerShellExtensionObject::treeland_layer_shell_extension_object_v1_resizing(uint32_t resizing)
{
Q_EMIT resizingChanged(resizing != 0);
}

}
62 changes: 62 additions & 0 deletions panels/dock/layershellextension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include "qwayland-treeland-layer-shell-extension-unstable-v1.h"

#include <QtWaylandClient/QWaylandClientExtension>

#include <QObject>

namespace dock
{

// Client wrapper for the treeland_layer_shell_extension_manager_v1 protocol global.
// Lets the dock opt in to compositor-driven interactive resize: the compositor
// owns the drag state machine and drives the surface size through the standard
// layer-surface configure events (see treeland-layer-shell-extension-unstable-v1.xml).
class TreeLandLayerShellExtensionManager : public QWaylandClientExtensionTemplate<TreeLandLayerShellExtensionManager>,
public QtWayland::treeland_layer_shell_extension_manager_v1
{
Q_OBJECT

public:
explicit TreeLandLayerShellExtensionManager();

// Creates an interactive object for an existing wl_surface and returns the
// raw protocol object; the caller wraps it in a TreeLandLayerShellExtensionObject.
struct ::treeland_layer_shell_extension_object_v1 *getLayerShellExtensionObject(struct ::wl_surface *surface);
};

// Client wrapper for the treeland_layer_shell_extension_object_v1 protocol object bound
// to the layer surface. This is the single entry point for every interactive
// operation on a treeland layer-shell surface (resize today, move later).
class TreeLandLayerShellExtensionObject : public QWaylandClientExtensionTemplate<TreeLandLayerShellExtensionObject>,
public QtWayland::treeland_layer_shell_extension_object_v1
{
Q_OBJECT

public:
explicit TreeLandLayerShellExtensionObject(struct ::treeland_layer_shell_extension_object_v1 *surface, struct ::wl_surface *nativeSurface);
~TreeLandLayerShellExtensionObject();

void beginResize(struct ::wl_seat *seat, uint32_t serial, uint32_t edges, int32_t minWidth, int32_t minHeight, int32_t maxWidth, int32_t maxHeight);

// Returns the wl_surface this object was bound to. Does not validate
// lifetime; callers must compare it against the window's current surface
// and re-bind (a new object) when it changed, before issuing any request.
struct ::wl_surface *nativeSurface() const;

Q_SIGNALS:
void resizingChanged(bool resizing);

protected:
void treeland_layer_shell_extension_object_v1_resizing(uint32_t resizing) override;

private:
struct ::wl_surface *m_nativeSurface = nullptr;
};

}
60 changes: 60 additions & 0 deletions panels/dock/package/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Window {
property int itemSpacing: 0

property bool isDragging: false
property bool compositorOwnsResize: false
property bool resizingReceived: false

property real dockItemIconSize: dockItemMaxSize * 9 / 14

Expand Down Expand Up @@ -650,6 +652,21 @@ Window {
oldDockSize = dockSize
recentDeltas = []
Panel.requestClosePopup()

var edges = 0
if (Panel.position === Dock.Bottom) {
edges = Dock.ResizeEdgeTop
} else if (Panel.position === Dock.Top) {
edges = Dock.ResizeEdgeBottom
} else if (Panel.position === Dock.Right) {
edges = Dock.ResizeEdgeLeft
} else if (Panel.position === Dock.Left) {
edges = Dock.ResizeEdgeRight
}
dock.resizingReceived = false
var accepted = Panel.beginDockResize(edges)
dock.compositorOwnsResize = accepted

DS.grabMouse(Panel.rootObject, true)
}
Comment thread
sourcery-ai[bot] marked this conversation as resolved.

Expand All @@ -658,6 +675,9 @@ Window {

onPositionChanged: function(mouse) {
if (Panel.locked || !dock.isDragging) return

if (dock.compositorOwnsResize) return

var newPos = mapToGlobal(mouse.x, mouse.y)
var xChange = newPos.x - oldMousePos.x
var yChange = newPos.y - oldMousePos.y
Expand Down Expand Up @@ -694,7 +714,19 @@ Window {

onReleased: function(mouse) {
if (Panel.locked) return
// Compositor-driven path: the compositor owns the release. If a
// stray release still reaches us, ignore it - resizing(0) ends
// the resize and finishResize() then. (Without this guard a stray
// release would clear compositorOwnsResize and cut the resize short.)
if (dock.compositorOwnsResize && dock.resizingReceived) return

finishResize()
}

function finishResize() {
dock.isDragging = false
dock.compositorOwnsResize = false
dock.resizingReceived = false
Applet.dockSize = dockSize
itemIconSizeBase = dockItemMaxSize
pressedAndDragging(false)
Expand Down Expand Up @@ -730,7 +762,35 @@ Window {
anchors.top = parent.top
dragArea.width = 5
}
}

Connections {
target: Panel
function onIsResizingChanged(resizing) {
if (resizing) {
dock.resizingReceived = true
return
}
if (dock.isDragging) {
dragArea.finishResize()
}
}
}

Connections {
function onWidthChanged() {
if (dock.compositorOwnsResize && dock.useColumnLayout) {
dock.dockSize = dock.width
}
}

function onHeightChanged() {
if (dock.compositorOwnsResize && !dock.useColumnLayout) {
dock.dockSize = dock.height
}
}

target: dock
}

function changeDragAreaAnchor() {
Expand Down
Loading