From 4a16e188080e1409b3be5d3aaeca4428b6ef5c18 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Thu, 3 Jun 2021 09:04:26 +0000 Subject: [PATCH] Remove Wayland::Client usage in wl->xwl drags --- src/xwl/drag.cpp | 28 ------------ src/xwl/drag.h | 7 +-- src/xwl/drag_wl.cpp | 104 ++++++++++++++++++++++++++------------------ src/xwl/drag_wl.h | 21 ++------- src/xwl/drag_x.cpp | 33 +++++++++++++- src/xwl/drag_x.h | 11 ++--- 6 files changed, 103 insertions(+), 101 deletions(-) diff --git a/src/xwl/drag.cpp b/src/xwl/drag.cpp index 30469643f8..0c1493a8e6 100644 --- a/src/xwl/drag.cpp +++ b/src/xwl/drag.cpp @@ -44,33 +44,5 @@ void Drag::sendClientMessage(xcb_window_t target, xcb_atom_t type, xcb_client_me xcb_flush(xcbConn); } -DnDAction Drag::atomToClientAction(xcb_atom_t atom) -{ - if (atom == atoms->xdnd_action_copy) { - return DnDAction::Copy; - } else if (atom == atoms->xdnd_action_move) { - return DnDAction::Move; - } else if (atom == atoms->xdnd_action_ask) { - // we currently do not support it - need some test client first - return DnDAction::None; -// return DnDAction::Ask; - } - return DnDAction::None; -} - -xcb_atom_t Drag::clientActionToAtom(DnDAction action) -{ - if (action == DnDAction::Copy) { - return atoms->xdnd_action_copy; - } else if (action == DnDAction::Move) { - return atoms->xdnd_action_move; - } else if (action == DnDAction::Ask) { - // we currently do not support it - need some test client first - return XCB_ATOM_NONE; -// return atoms->xdnd_action_ask; - } - return XCB_ATOM_NONE; -} - } // namespace Xwl } // namespace KWin diff --git a/src/xwl/drag.h b/src/xwl/drag.h index dfba8f528a..f8964c17ae 100644 --- a/src/xwl/drag.h +++ b/src/xwl/drag.h @@ -9,9 +9,8 @@ #ifndef KWIN_XWL_DRAG #define KWIN_XWL_DRAG -#include - #include +#include #include @@ -23,8 +22,6 @@ namespace Xwl { enum class DragEventReply; -using DnDAction = KWayland::Client::DataDeviceManager::DnDAction; - /** * An ongoing drag operation. */ @@ -37,8 +34,6 @@ public: ~Drag() override; static void sendClientMessage(xcb_window_t target, xcb_atom_t type, xcb_client_message_data_t *data); - static DnDAction atomToClientAction(xcb_atom_t atom); - static xcb_atom_t clientActionToAtom(DnDAction action); virtual bool handleClientMessage(xcb_client_message_event_t *event) = 0; virtual DragEventReply moveFilter(Toplevel *target, const QPoint &pos) = 0; diff --git a/src/xwl/drag_wl.cpp b/src/xwl/drag_wl.cpp index 6b22e09a2b..283af0a28f 100644 --- a/src/xwl/drag_wl.cpp +++ b/src/xwl/drag_wl.cpp @@ -17,9 +17,6 @@ #include "wayland_server.h" #include "workspace.h" -#include -#include - #include #include #include @@ -33,6 +30,37 @@ namespace KWin namespace Xwl { +using DnDAction = KWaylandServer::DataDeviceManagerInterface::DnDAction; +using DnDActions = KWaylandServer::DataDeviceManagerInterface::DnDActions; + +static DnDAction atomToClientAction(xcb_atom_t atom) +{ + if (atom == atoms->xdnd_action_copy) { + return DnDAction::Copy; + } else if (atom == atoms->xdnd_action_move) { + return DnDAction::Move; + } else if (atom == atoms->xdnd_action_ask) { + // we currently do not support it - need some test client first + return DnDAction::None; +// return DnDAction::Ask; + } + return DnDAction::None; +} + +static xcb_atom_t clientActionToAtom(DnDAction action) +{ + if (action == DnDAction::Copy) { + return atoms->xdnd_action_copy; + } else if (action == DnDAction::Move) { + return atoms->xdnd_action_move; + } else if (action == DnDAction::Ask) { + // we currently do not support it - need some test client first + return XCB_ATOM_NONE; +// return atoms->xdnd_action_ask; + } + return XCB_ATOM_NONE; +} + WlToXDrag::WlToXDrag() { m_dsi = waylandServer()->seat()->dragSource()->dragSource(); @@ -129,12 +157,8 @@ Xvisit::Xvisit(WlToXDrag *drag, AbstractClient *target) } free(reply); - const auto *dd = DataBridge::self()->dataDevice(); - // proxy drop - m_enterConnection = connect(dd, &KWayland::Client::DataDevice::dragEntered, - this, &Xvisit::receiveOffer); - m_dropConnection = connect(dd, &KWayland::Client::DataDevice::dropped, - this, &Xvisit::drop); + m_dropConnection = connect(waylandServer()->seat(), &KWaylandServer::SeatInterface::dragDropped, this, &Xvisit::drop); + receiveOffer(); } bool Xvisit::handleClientMessage(xcb_client_message_event_t *event) @@ -158,9 +182,9 @@ bool Xvisit::handleStatus(xcb_client_message_event_t *event) m_accepts = data->data32[1] & 1; xcb_atom_t actionAtom = data->data32[4]; - auto drag = m_drag->dataSourceIface(); - if (drag && !drag->mimeTypes().isEmpty()) { - drag->accept(m_accepts ? drag->mimeTypes().constFirst() : QString()); + auto dataSource = m_drag->dataSourceIface(); + if (dataSource && !dataSource->mimeTypes().isEmpty()) { + dataSource->accept(m_accepts ? dataSource->mimeTypes().constFirst() : QString()); } // TODO: we could optimize via rectangle in data32[2] and data32[3] @@ -169,7 +193,7 @@ bool Xvisit::handleStatus(xcb_client_message_event_t *event) if (!m_state.dropped) { // as long as the drop is not yet done determine requested action - m_preferredAction = Drag::atomToClientAction(actionAtom); + m_preferredAction = atomToClientAction(actionAtom); determineProposedAction(); requestDragAndDropAction(); } @@ -206,11 +230,8 @@ bool Xvisit::handleFinished(xcb_client_message_event_t *event) Q_UNUSED(success); Q_UNUSED(usedActionAtom); - // data offer might have been deleted already by the DataDevice - if (!m_dataOffer.isNull()) { - m_dataOffer->dragAndDropFinished(); - delete m_dataOffer; - m_dataOffer = nullptr; + if (auto dataSource = m_drag->dataSourceIface()) { + dataSource->dndFinished(); } doFinish(); return true; @@ -232,14 +253,17 @@ void Xvisit::sendPosition(const QPointF &globalPos) data.data32[0] = DataBridge::self()->dnd()->window(); data.data32[2] = (x << 16) | y; data.data32[3] = XCB_CURRENT_TIME; - data.data32[4] = Drag::clientActionToAtom(m_proposedAction); + data.data32[4] = clientActionToAtom(m_proposedAction); Drag::sendClientMessage(m_target->window(), atoms->xdnd_position, &data); } void Xvisit::leave() { - Q_ASSERT(!m_state.dropped); + if (m_state.dropped) { + // dropped, but not yet finished, it'll be cleaned up when the drag finishes + return; + } if (m_state.finished) { // was already finished return; @@ -253,17 +277,9 @@ void Xvisit::leave() void Xvisit::receiveOffer() { - if (m_state.finished) { - // already ended - return; - } - - Q_ASSERT(m_dataOffer.isNull()); - m_dataOffer = DataBridge::self()->dataDevice()->dragOffer(); - Q_ASSERT(!m_dataOffer.isNull()); - retrieveSupportedActions(); - m_actionConnection = connect(m_dataOffer, &KWayland::Client::DataOffer::sourceDragAndDropActionsChanged, + auto dragSource = m_drag->dataSourceIface(); + connect(dragSource, &KWaylandServer::AbstractDataSource::supportedDragAndDropActionsChanged, this, &Xvisit::retrieveSupportedActions); enter(); } @@ -283,8 +299,8 @@ void Xvisit::enter() void Xvisit::sendEnter() { - auto drag = m_drag->dataSourceIface(); - if (!drag) { + auto dataSource = m_drag->dataSourceIface(); + if (!dataSource) { return; } @@ -292,9 +308,7 @@ void Xvisit::sendEnter() data.data32[0] = DataBridge::self()->dnd()->window(); data.data32[1] = m_version << 24; - // TODO: replace this with the mime type getter from m_dataOffer, - // then we can get rid of m_drag. - const auto mimeTypesNames = drag->mimeTypes(); + const auto mimeTypesNames = dataSource->mimeTypes(); const int mimesCount = mimeTypesNames.size(); size_t cnt = 0; size_t totalCnt = 0; @@ -363,7 +377,7 @@ void Xvisit::sendLeave() void Xvisit::retrieveSupportedActions() { - m_supportedActions = m_dataOffer->sourceDragAndDropActions(); + m_supportedActions = m_drag->dataSourceIface()->supportedDragAndDropActions(); determineProposedAction(); requestDragAndDropAction(); } @@ -386,16 +400,22 @@ void Xvisit::determineProposedAction() void Xvisit::requestDragAndDropAction() { - if (m_dataOffer.isNull()) { - return; - } - const auto pref = m_preferredAction != DnDAction::None ? m_preferredAction: + DnDAction action = m_preferredAction != DnDAction::None ? m_preferredAction: DnDAction::Copy; // we assume the X client supports Move, but this might be wrong - then // the drag just cancels, if the user tries to force it. - m_dataOffer->setDragAndDropActions(DnDAction::Copy | DnDAction::Move, pref); - waylandServer()->dispatch(); + // As we skip the client data device, we do action negotiation directly then tell the source. + if (m_supportedActions.testFlag(action)) { + // everything is supported, no changes are needed + } else if (m_supportedActions.testFlag(DnDAction::Copy)) { + action = DnDAction::Copy; + } else if (m_supportedActions.testFlag(DnDAction::Move)) { + action = DnDAction::Move; + } + if (auto dataSource = m_drag->dataSourceIface()) { + dataSource->dndAction(action); + } } void Xvisit::drop() diff --git a/src/xwl/drag_wl.h b/src/xwl/drag_wl.h index f294de2640..9e702e94c3 100644 --- a/src/xwl/drag_wl.h +++ b/src/xwl/drag_wl.h @@ -11,19 +11,12 @@ #include "drag.h" -#include +#include #include #include #include -namespace KWayland -{ -namespace Client -{ -class Surface; -} -} namespace KWaylandServer { class DataDeviceInterface; @@ -42,8 +35,6 @@ class X11Source; enum class DragEventReply; class Xvisit; -using DnDActions = KWayland::Client::DataDeviceManager::DnDActions; - class WlToXDrag : public Drag { Q_OBJECT @@ -125,16 +116,12 @@ private: QPoint cache; } m_pos; - // Must be QPointer, because KWayland::Client::DataDevice - // might delete it. - QPointer m_dataOffer; - // supported by the Wl source - DnDActions m_supportedActions = DnDAction::None; + KWaylandServer::DataDeviceManagerInterface::DnDActions m_supportedActions = KWaylandServer::DataDeviceManagerInterface::DnDAction::None; // preferred by the X client - DnDAction m_preferredAction = DnDAction::None; + KWaylandServer::DataDeviceManagerInterface::DnDAction m_preferredAction = KWaylandServer::DataDeviceManagerInterface::DnDAction::None; // decided upon by the compositor - DnDAction m_proposedAction = DnDAction::None; + KWaylandServer::DataDeviceManagerInterface::DnDAction m_proposedAction = KWaylandServer::DataDeviceManagerInterface::DnDAction::None; struct { bool entered = false; diff --git a/src/xwl/drag_x.cpp b/src/xwl/drag_x.cpp index ff6479b5ba..feaeb1fdfd 100644 --- a/src/xwl/drag_x.cpp +++ b/src/xwl/drag_x.cpp @@ -33,6 +33,37 @@ namespace KWin namespace Xwl { +using DnDAction = KWayland::Client::DataDeviceManager::DnDAction; +using DnDActions = KWayland::Client::DataDeviceManager::DnDActions; + +static DnDAction atomToClientAction(xcb_atom_t atom) +{ + if (atom == atoms->xdnd_action_copy) { + return DnDAction::Copy; + } else if (atom == atoms->xdnd_action_move) { + return DnDAction::Move; + } else if (atom == atoms->xdnd_action_ask) { + // we currently do not support it - need some test client first + return DnDAction::None; +// return DnDAction::Ask; + } + return DnDAction::None; +} + +xcb_atom_t clientActionToAtom(DnDAction action) +{ + if (action == DnDAction::Copy) { + return atoms->xdnd_action_copy; + } else if (action == DnDAction::Move) { + return atoms->xdnd_action_move; + } else if (action == DnDAction::Ask) { + // we currently do not support it - need some test client first + return XCB_ATOM_NONE; +// return atoms->xdnd_action_ask; + } + return XCB_ATOM_NONE; +} + static QStringList atomToMimeTypes(xcb_atom_t atom) { QStringList mimeTypes; @@ -438,7 +469,7 @@ bool WlVisit::handlePosition(xcb_client_message_event_t *event) xcb_atom_t actionAtom = m_version > 1 ? data->data32[4] : atoms->xdnd_action_copy; - auto action = Drag::atomToClientAction(actionAtom); + auto action = atomToClientAction(actionAtom); if (action == DnDAction::None) { // copy action is always possible in XDND diff --git a/src/xwl/drag_x.h b/src/xwl/drag_x.h index a4c3d575c7..ccaa3f5bf1 100644 --- a/src/xwl/drag_x.h +++ b/src/xwl/drag_x.h @@ -12,9 +12,6 @@ #include "drag.h" #include -#include - -#include #include #include @@ -52,8 +49,8 @@ public: DragEventReply moveFilter(Toplevel *target, const QPoint &pos) override; bool handleClientMessage(xcb_client_message_event_t *event) override; - void setDragAndDropAction(DnDAction action); - DnDAction selectedDragAndDropAction(); + void setDragAndDropAction(KWayland::Client::DataDeviceManager::DnDAction action); + KWayland::Client::DataDeviceManager::DnDAction selectedDragAndDropAction(); bool end() override { return false; @@ -81,7 +78,7 @@ private: QVector m_oldVisits; bool m_performed = false; - DnDAction m_lastSelectedDragAndDropAction = DnDAction::None; + KWayland::Client::DataDeviceManager::DnDAction m_lastSelectedDragAndDropAction = KWayland::Client::DataDeviceManager::DnDAction::None; Q_DISABLE_COPY(XToWlDrag) }; @@ -142,7 +139,7 @@ private: uint32_t m_version = 0; xcb_atom_t m_actionAtom; - DnDAction m_action = DnDAction::None; + KWayland::Client::DataDeviceManager::DnDAction m_action = KWayland::Client::DataDeviceManager::DnDAction::None; bool m_mapped = false; bool m_entered = false;