Skip to content
Merged
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
16 changes: 12 additions & 4 deletions panels/dock/DockCompositor.qml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Item {
property alias dockSize: pluginManager.dockSize
property var moveXEmbedWindowHandler: null

function notifyXEmbedWindowMoveResult(wid, success) {
pluginManager.notifyXEmbedWindowMoveResult(wid, success)
}

property ListModel trayPluginSurfaces: ListModel {}
property ListModel quickPluginSurfaces: ListModel {}
property ListModel fixedPluginSurfaces: ListModel {}
Expand Down Expand Up @@ -115,11 +119,15 @@ Item {
dockCompositor.popupClosed()
}

onMoveXEmbedWindowRequested: (wid, pluginId, itemKey, dx, dy) => {
console.log("move xembed window requested:", wid, pluginId, itemKey, dx, dy)
onMoveXEmbedWindowRequested: (wid, pluginId, itemKey, dx, dy, anchorWindow) => {
console.log("move xembed window requested:", wid, pluginId, itemKey, dx, dy, "anchorWindow:", anchorWindow)
if (typeof dockCompositor.moveXEmbedWindowHandler === 'function') {
var success = dockCompositor.moveXEmbedWindowHandler(wid, dx, dy)
pluginManager.notifyXEmbedWindowMoveResult(wid, success)
var sent = dockCompositor.moveXEmbedWindowHandler(wid, dx, dy, anchorWindow)
if (!sent) {
// Pre-check failed (e.g. manager not ready) — no wl_callback registered
pluginManager.notifyXEmbedWindowMoveResult(wid, false)
}
// If sent, result arrives asynchronously via xembedWindowMoveResult signal
} else {
console.warn("moveXEmbedWindowHandler not available")
pluginManager.notifyXEmbedWindowMoveResult(wid, false)
Expand Down
5 changes: 3 additions & 2 deletions panels/dock/dockhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
#include "constants.h"
#include "dockpanel.h"

#include <QObject>

Check warning on line 10 in panels/dock/dockhelper.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QObject> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QQuickWindow>

Check warning on line 11 in panels/dock/dockhelper.h

View workflow job for this annotation

GitHub Actions / cppcheck

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

namespace dock {
class DockWakeUpArea;
Expand All @@ -22,8 +23,8 @@
void enterScreen(QScreen *screen);
void leaveScreen();

// Move XEmbed window relative to dock surface (no-op on X11)
virtual bool moveXEmbedWindow(uint32_t wid, double dx, double dy) { return false; }
// Move XEmbed window relative to anchor window's surface (no-op on X11)
virtual bool moveXEmbedWindow(uint32_t wid, double dx, double dy, QQuickWindow *anchorWindow = nullptr) { return false; }

Q_SIGNALS:
void isWindowOverlapChanged(bool overlap);
Expand Down
6 changes: 4 additions & 2 deletions panels/dock/dockpanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ bool DockPanel::init()
auto platformName = QGuiApplication::platformName();
if (QStringLiteral("wayland") == platformName) {
m_helper = new WaylandDockHelper(this);
connect(static_cast<WaylandDockHelper *>(m_helper), &WaylandDockHelper::xembedWindowMoveResult,
this, &DockPanel::xembedWindowMoveResult);
// 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 @@ -495,10 +497,10 @@ void DockPanel::setIsResizing(bool resizing)
emit isResizingChanged(m_isResizing);
}

bool DockPanel::moveXEmbedWindow(uint32_t wid, double dx, double dy)
bool DockPanel::moveXEmbedWindow(uint32_t wid, double dx, double dy, QQuickWindow *anchorWindow)
{
if (m_helper) {
return m_helper->moveXEmbedWindow(wid, dx, dy);
return m_helper->moveXEmbedWindow(wid, dx, dy, anchorWindow);
}
return false;
}
Expand Down
8 changes: 6 additions & 2 deletions panels/dock/dockpanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ class DockPanel : public DS_NAMESPACE::DPanel, public QDBusContext

Q_INVOKABLE void notifyDockPositionChanged(int offsetX, int offsetY);

// Move XEmbed window relative to dock surface (Wayland only)
Q_INVOKABLE bool moveXEmbedWindow(uint32_t wid, double dx, double dy);
// Move XEmbed window relative to anchor window's surface (Wayland only)
// 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);

bool showInPrimary() const;
void setShowInPrimary(bool newShowInPrimary);
Expand Down Expand Up @@ -138,6 +139,9 @@ private Q_SLOTS:
void contextDraggingChanged();
void isResizingChanged(bool isResizing);

// Emitted when async XEmbed window move completes
void xembedWindowMoveResult(uint32_t wid, bool success);

private:
ColorTheme m_theme;
HideState m_hideState;
Expand Down
10 changes: 8 additions & 2 deletions panels/dock/package/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -855,10 +855,16 @@ Window {
return Panel.devicePixelRatio
})

DockCompositor.moveXEmbedWindowHandler = function(wid, dx, dy) {
return Panel.moveXEmbedWindow(wid, dx, dy)
DockCompositor.moveXEmbedWindowHandler = function(wid, dx, dy, anchorWindow) {
return Panel.moveXEmbedWindow(wid, dx, dy, anchorWindow)
// If true: result arrives asynchronously via Panel.xembedWindowMoveResult signal
// If false: pre-check failed, caller should notify failure immediately
}

Panel.xembedWindowMoveResult.connect(function(wid, success) {
DockCompositor.notifyXEmbedWindowMoveResult(wid, success)
})

dock.itemIconSizeBase = dock.dockItemMaxSize
dock.visible = Panel.hideState !== Dock.Hide
changeDragAreaAnchor()
Expand Down
14 changes: 12 additions & 2 deletions panels/dock/pluginmanagerextension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ QPoint PluginSurface::itemPosition() const
return m_itemPosition;
}

void PluginSurface::setAnchorWindow(QQuickWindow *window)
{
m_anchorWindow = window;
}

QQuickWindow *PluginSurface::anchorWindow() const
{
return m_anchorWindow;
}

void PluginSurface::plugin_mouse_event(QtWaylandServer::plugin::Resource *resource, int32_t type)
{
Q_UNUSED(resource)
Expand Down Expand Up @@ -706,8 +716,8 @@ void PluginManager::plugin_manager_v1_move_xembed_window(Resource *resource, uin
// Store pending callback for later response (supports concurrent requests)
m_pendingXEmbedCallbacks[xembed_winid] = {callback, resource->handle};

// Emit signal with position info for QML to handle
Q_EMIT moveXEmbedWindowRequested(xembed_winid, plugin_id, item_key, dx, dy);
// Emit signal with position info and anchor window for QML to handle
Q_EMIT moveXEmbedWindowRequested(xembed_winid, plugin_id, item_key, dx, dy, pluginSurface->anchorWindow());
}

void PluginManager::notifyXEmbedWindowMoveResult(uint32_t wid, bool success)
Expand Down
13 changes: 9 additions & 4 deletions panels/dock/pluginmanagerextension_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

#pragma once

#include <QMap>

Check warning on line 7 in panels/dock/pluginmanagerextension_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QMap> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QPointer>

Check warning on line 8 in panels/dock/pluginmanagerextension_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QPointer> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QQuickWindow>

Check warning on line 9 in panels/dock/pluginmanagerextension_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QQuickWindow> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtWaylandCompositor/QWaylandCompositor>

Check warning on line 10 in panels/dock/pluginmanagerextension_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QtWaylandCompositor/QWaylandCompositor> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtWaylandCompositor/QWaylandQuickExtension>

Check warning on line 11 in panels/dock/pluginmanagerextension_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QtWaylandCompositor/QWaylandQuickExtension> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtWaylandCompositor/QWaylandResource>

Check warning on line 12 in panels/dock/pluginmanagerextension_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QtWaylandCompositor/QWaylandResource> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtWaylandCompositor/QWaylandSeat>
#include <QtWaylandCompositor/QWaylandShellSurfaceTemplate>
#include <QtWaylandCompositor/QWaylandSurface>
Expand Down Expand Up @@ -99,10 +100,10 @@
void dockSizeChanged();
void requestShutdown(const QString &type);
// Signal emitted when XEmbed window move is requested
// Parameters: wid (window ID), pluginId, itemKey, dx (relative x offset), dy (relative y offset)
void moveXEmbedWindowRequested(uint32_t wid, const QString &pluginId, const QString &itemKey, double dx, double dy);
// Parameters: wid (window ID), pluginId, itemKey, dx, dy, anchorWindow (the window containing the plugin item)
void moveXEmbedWindowRequested(uint32_t wid, const QString &pluginId, const QString &itemKey, double dx, double dy, QQuickWindow *anchorWindow);

private Q_SLOTS:

Check warning on line 106 in panels/dock/pluginmanagerextension_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

There is an unknown macro here somewhere. Configuration is required. If Q_SLOTS is a macro then please configure it.
void onFontChanged();
void onActiveColorChanged();
void onThemeChanged();
Expand Down Expand Up @@ -192,10 +193,13 @@

Q_INVOKABLE void updatePluginGeometry(const QRect &geometry);
Q_INVOKABLE void setGlobalPos(const QPoint &pos);
Q_INVOKABLE void setAnchorWindow(QQuickWindow *window);

// Position relative to the dock window, set from QML via updatePluginGeometry
// Position relative to the containing window, set from QML via updatePluginGeometry
QPoint itemPosition() const;

QQuickWindow *anchorWindow() const;

int margins() const;
void setMargins(int newMargins);

Expand Down Expand Up @@ -234,7 +238,8 @@
int m_margins = 0;
int m_height;
int m_width;
QPoint m_itemPosition; // Position relative to dock window, for XEmbed window positioning
QPoint m_itemPosition;
QPointer<QQuickWindow> m_anchorWindow;
};

class PluginPopup : public QWaylandShellSurfaceTemplate<PluginPopup>, public QtWaylandServer::plugin_popup
Expand Down
2 changes: 2 additions & 0 deletions panels/dock/tray/package/ActionLegacyTrayPluginDelegate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ AppletItemButton {
if (!pluginItem.plugin || !itemVisible)
return
updatePluginMargins()
pluginItem.plugin.setAnchorWindow(pluginItem.Window.window)
pluginItem.plugin.updatePluginGeometry(Qt.rect(pluginItem.itemGlobalPoint.x, pluginItem.itemGlobalPoint.y, 0, 0))
pluginItem.plugin.setGlobalPos(pluginItem.itemGlobalPos)
}
Expand All @@ -105,6 +106,7 @@ AppletItemButton {
if (!pluginItem.plugin || !itemVisible)
return
updatePluginMargins()
pluginItem.plugin.setAnchorWindow(pluginItem.Window.window)
if (pluginItem.itemGlobalPoint.x >= 0 && pluginItem.itemGlobalPoint.y >= 0) {
pluginItem.plugin.updatePluginGeometry(Qt.rect(pluginItem.itemGlobalPoint.x, pluginItem.itemGlobalPoint.y, 0, 0))
}
Expand Down
37 changes: 33 additions & 4 deletions panels/dock/waylanddockhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void WaylandDockHelper::setDockColorTheme(const ColorTheme &theme)
m_panel->setColorTheme(theme);
}

bool WaylandDockHelper::moveXEmbedWindow(uint32_t wid, double dx, double dy)
bool WaylandDockHelper::moveXEmbedWindow(uint32_t wid, double dx, double dy, QQuickWindow *anchorWindow)
{
// Update dock wl_surface if needed
if (!m_dockWlSurface && m_panel->window()) {
Expand All @@ -168,14 +168,43 @@ bool WaylandDockHelper::moveXEmbedWindow(uint32_t wid, double dx, double dy)
}
}

if (!m_ddeShellManager || !m_ddeShellManager->isActive() || !m_dockWlSurface) {
struct ::wl_surface *anchorSurface = m_dockWlSurface;

if (anchorWindow) {
auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow*>(anchorWindow->handle());
if (waylandWindow && waylandWindow->waylandSurface()) {
anchorSurface = waylandWindow->waylandSurface()->object();
}
}

if (!m_ddeShellManager || !m_ddeShellManager->isActive() || !anchorSurface) {
qWarning() << "WaylandDockHelper::moveXEmbedWindow: not ready, manager active:"
<< (m_ddeShellManager && m_ddeShellManager->isActive())
<< "surface:" << (m_dockWlSurface != nullptr);
<< "surface:" << (anchorSurface != nullptr);
return false;
}

m_ddeShellManager->setXWindowPositionRelative(wid, m_dockWlSurface, dx, dy);
struct wl_callback *cb = m_ddeShellManager->setXWindowPositionRelative(wid, anchorSurface, dx, dy);

// Register wl_callback listener — result arrives asynchronously
if (!cb) {
qWarning() << "WaylandDockHelper::moveXEmbedWindow: setXWindowPositionRelative returned null callback";
Q_EMIT xembedWindowMoveResult(wid, false);
return true;
}

struct CallbackData { uint32_t wid; WaylandDockHelper *helper; };
static struct wl_callback_listener s_callbackListener = {
.done = [](void *data, wl_callback *callback, uint32_t callback_data) {
auto *d = static_cast<CallbackData *>(data);
bool success = (callback_data == 0);
Q_EMIT d->helper->xembedWindowMoveResult(d->wid, success);
wl_callback_destroy(callback);
delete d;
}
};
wl_callback_add_listener(cb, &s_callbackListener, new CallbackData{wid, this});

return true;
}

Expand Down
12 changes: 8 additions & 4 deletions panels/dock/waylanddockhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ class WaylandDockHelper : public DockHelper
void setDockColorTheme(const ColorTheme &theme);
QString dockScreenName();

// Move XEmbed window relative to dock surface
// dx, dy: offset relative to dock surface top-left
// Returns true if the request was sent successfully
bool moveXEmbedWindow(uint32_t wid, double dx, double dy) override;
// Move XEmbed window relative to anchor window's surface
// anchorWindow: the window containing the plugin item; falls back to dock panel if null
// dx, dy: offset relative to anchor window top-left
// Returns true if the request was sent (does NOT guarantee completion)
bool moveXEmbedWindow(uint32_t wid, double dx, double dy, QQuickWindow *anchorWindow = nullptr) override;

Q_SIGNALS:
void xembedWindowMoveResult(uint32_t wid, bool success);

protected:
bool currentActiveWindowFullscreened() override;
Expand Down
Loading