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
Comment thread
gugullll marked this conversation as resolved.
)

target_link_libraries(dockpanel PRIVATE
Expand Down
94 changes: 94 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,94 @@
}
return false;
}

bool DockPanel::beginResize()
{
uint edges = 0;
int minW = 0, maxW = 0, minH = 0, maxH = 0;
switch (position()) {
case Position::Left:
edges = TreeLandLayerShellExtensionObject::resize_edge_right;
minW = MIN_DOCK_SIZE;
maxW = MAX_DOCK_SIZE;
break;
case Position::Right:
edges = TreeLandLayerShellExtensionObject::resize_edge_left;
minW = MIN_DOCK_SIZE;
maxW = MAX_DOCK_SIZE;
break;
case Position::Top:
edges = TreeLandLayerShellExtensionObject::resize_edge_bottom;
minH = MIN_DOCK_SIZE;
maxH = MAX_DOCK_SIZE;
break;
case Position::Bottom:
edges = TreeLandLayerShellExtensionObject::resize_edge_top;
minH = MIN_DOCK_SIZE;
maxH = MAX_DOCK_SIZE;
break;
default:
Q_UNREACHABLE();
break;
}

if (!m_dockShellExtensionManager) {
qCWarning(dockLog) << "beginResize: layer shell extension manager is null";
return false;
}

if (!m_dockShellExtensionManager->isActive()) {
qCWarning(dockLog) << "beginResize: layer shell extension manager inactive";
return false;
}

auto *w = window();
if (!w) {
qCWarning(dockLog) << "beginResize: window is null";
return false;
}

auto *waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(w->handle());
if (!waylandWindow) {
qCWarning(dockLog) << "beginResize: failed to get QWaylandWindow";
return false;
}

auto *surface = waylandWindow->wlSurface();

if (!surface) {
qCWarning(dockLog) << "beginResize: wl_surface is null";
return false;
}

auto *inputDevice = waylandWindow->display()->lastInputDevice();

if (!inputDevice) {
qCWarning(dockLog) << "beginResize: no last input device";
return false;
}

auto *dockSurface = m_dockShellExtensionManager->getLayerShellExtensionObject(surface);

if (!dockSurface) {
qCWarning(dockLog) << "beginResize: failed to get layer shell extension object";
return false;
}
if (m_dockShellExtensionObject)
return false;
m_dockShellExtensionObject = new TreeLandLayerShellExtensionObject(dockSurface, surface);
m_dockShellExtensionObject->setParent(this);
connect(m_dockShellExtensionObject, &TreeLandLayerShellExtensionObject::resizingChanged, this, [this](bool resizing) {
setIsResizing(resizing);
if (!resizing) {
m_dockShellExtensionObject->deleteLater();
}
});

m_dockShellExtensionObject->beginResize(inputDevice->wl_seat(), inputDevice->serial(), edges, minW, minH, maxW, maxH);
inputDevice->handleEndDrag();
Comment thread
gugullll marked this conversation as resolved.
return true;
}
}

#include "dockpanel.moc"

Check warning on line 619 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 beginResize();

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;
QPointer<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 *object,
struct ::wl_surface *nativeSurface)
: QWaylandClientExtensionTemplate<TreeLandLayerShellExtensionObject>(treeland_layer_shell_extension_object_v1_interface.version)
, m_nativeSurface(nativeSurface)
{
init(object);
}

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 *object, 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;
};

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

property bool isDragging: false

readonly property bool compositorDrivenResize: Qt.platform.pluginName !== "xcb"

property real dockItemIconSize: dockItemMaxSize * 9 / 14

// NOTE: -1 means not set its size, follow the platform size
Expand Down Expand Up @@ -650,6 +652,10 @@ Window {
oldDockSize = dockSize
recentDeltas = []
Panel.requestClosePopup()

if (dock.compositorDrivenResize) {
Panel.beginResize()
}
DS.grabMouse(Panel.rootObject, true)
}

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

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

if (dock.compositorDrivenResize) 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,6 +703,13 @@ Window {

onReleased: function(mouse) {
if (Panel.locked) return

if (dock.compositorDrivenResize && Applet.isResizing) return

finishResize()
}

function finishResize() {
dock.isDragging = false
Applet.dockSize = dockSize
itemIconSizeBase = dockItemMaxSize
Expand Down Expand Up @@ -730,9 +746,32 @@ Window {
anchors.top = parent.top
dragArea.width = 5
}
}

Connections {
target: Panel
function onIsResizingChanged(resizing) {
if (!resizing && dock.isDragging) {
dragArea.finishResize()
}
}
}

Connections {
target: dock
enabled: dock.compositorDrivenResize && Applet.isResizing
function onWidthChanged() {
if (dock.useColumnLayout) {
dock.dockSize = dock.width
}
}

function onHeightChanged() {
if (!dock.useColumnLayout) {
dock.dockSize = dock.height
}
}
}
function changeDragAreaAnchor() {
switch(dock.positionForAnimation) {
case Dock.Top: {
Expand Down
Loading