[xwl] Fix coding style issues

icc-effect-5.17.5
Vlad Zagorodniy 2019-07-02 22:56:03 +03:00
parent bb6d1153f7
commit 88c4c58072
22 changed files with 567 additions and 459 deletions

View File

@ -19,35 +19,37 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "clipboard.h"
#include "xwayland.h"
#include "databridge.h"
#include "selection_source.h"
#include "transfer.h"
#include "xwayland.h"
#include "client.h"
#include "wayland_server.h"
#include "workspace.h"
#include "client.h"
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/datadevice.h>
#include <KWayland/Client/datasource.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/datadevice_interface.h>
#include <KWayland/Server/datasource_interface.h>
#include <KWayland/Server/seat_interface.h>
#include <xcb/xcb_event.h>
#include <xcb/xfixes.h>
#include <xwayland_logging.h>
namespace KWin {
namespace Xwl {
namespace KWin
{
namespace Xwl
{
Clipboard::Clipboard(xcb_atom_t atom, QObject *parent)
: Selection(atom, parent)
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
const uint32_t clipboardValues[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
XCB_EVENT_MASK_PROPERTY_CHANGE };
@ -135,53 +137,56 @@ void Clipboard::checkWlSource()
void Clipboard::doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event)
{
createX11Source(NULL);
createX11Source(nullptr);
const auto *ac = workspace()->activeClient();
if (!qobject_cast<const KWin::Client *>(ac)) {
const AbstractClient *client = workspace()->activeClient();
if (!qobject_cast<const Client *>(client)) {
// clipboard is only allowed to be acquired when Xwayland has focus
// TODO: can we make this stronger (window id comparision)?
return;
}
createX11Source(event);
auto *xSrc = x11Source();
if (xSrc) {
xSrc->getTargets();
if (X11Source *source = x11Source()) {
source->getTargets();
}
}
void Clipboard::x11OffersChanged(const QVector<QString> &added, const QVector<QString> &removed)
void Clipboard::x11OffersChanged(const QStringList &added, const QStringList &removed)
{
auto *xSrc = x11Source();
if (!xSrc) {
X11Source *source = x11Source();
if (!source) {
return;
}
const auto offers = xSrc->offers();
const bool hasOffers = offers.size() > 0;
const Mimes offers = source->offers();
if (hasOffers) {
if (!xSrc->dataSource() || !removed.isEmpty()) {
if (!offers.isEmpty()) {
if (!source->dataSource() || !removed.isEmpty()) {
// create new Wl DataSource if there is none or when types
// were removed (Wl Data Sources can only add types)
auto *ddm = waylandServer()->internalDataDeviceManager();
auto *ds = ddm->createDataSource(xSrc);
KWayland::Client::DataDeviceManager *dataDeviceManager =
waylandServer()->internalDataDeviceManager();
KWayland::Client::DataSource *dataSource =
dataDeviceManager->createDataSource(source);
// also offers directly the currently available types
xSrc->setDataSource(ds);
DataBridge::self()->dataDevice()->setSelection(0, ds);
source->setDataSource(dataSource);
DataBridge::self()->dataDevice()->setSelection(0, dataSource);
waylandServer()->seat()->setSelection(DataBridge::self()->dataDeviceIface());
} else if (auto *ds = xSrc->dataSource()) {
for (const auto &mime : added) {
ds->offer(mime);
} else if (auto *dataSource = source->dataSource()) {
for (const QString &mime : added) {
dataSource->offer(mime);
}
}
} else {
waylandServer()->seat()->setSelection(nullptr);
}
waylandServer()->internalClientConection()->flush();
waylandServer()->dispatch();
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -38,30 +38,33 @@ namespace Xwl
/**
* Represents the X clipboard, which is on Wayland side just called
* @e selection.
*/
**/
class Clipboard : public Selection
{
Q_OBJECT
public:
Clipboard(xcb_atom_t atom, QObject *parent);
private:
void doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event) override;
void x11OffersChanged(const QVector<QString> &added, const QVector<QString> &removed) override;
void x11OffersChanged(const QStringList &added, const QStringList &removed) override;
/**
* React to Wl selection change.
*/
**/
void wlSelectionChanged(KWayland::Server::DataDeviceInterface *ddi);
/**
* Check the current state of the selection and if a source needs
* to be created or destroyed.
*/
**/
void checkWlSource();
QMetaObject::Connection m_checkConnection;
Q_DISABLE_COPY(Clipboard)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -18,29 +18,34 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "databridge.h"
#include "xwayland.h"
#include "selection.h"
#include "clipboard.h"
#include "dnd.h"
#include "selection.h"
#include "xwayland.h"
#include "abstract_client.h"
#include "atoms.h"
#include "wayland_server.h"
#include "workspace.h"
#include "abstract_client.h"
// KWayland
#include <KWayland/Client/seat.h>
#include <KWayland/Client/datadevicemanager.h>
#include <KWayland/Client/seat.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/datadevicemanager_interface.h>
#include <KWayland/Server/datadevice_interface.h>
#include <KWayland/Server/seat_interface.h>
namespace KWin {
namespace Xwl {
using namespace KWayland::Client;
using namespace KWayland::Server;
namespace KWin
{
namespace Xwl
{
static DataBridge *s_self = nullptr;
DataBridge* DataBridge::self()
DataBridge *DataBridge::self()
{
return s_self;
}
@ -49,23 +54,29 @@ DataBridge::DataBridge(QObject *parent)
: QObject(parent)
{
s_self = this;
auto *ddm = waylandServer()->internalDataDeviceManager();
auto *seat = waylandServer()->internalSeat();
m_dd = ddm->getDataDevice(seat, this);
DataDeviceManager *dataDeviceManager = waylandServer()->internalDataDeviceManager();
Seat *seat = waylandServer()->internalSeat();
m_dataDevice = dataDeviceManager->getDataDevice(seat, this);
waylandServer()->dispatch();
const auto *ddmi = waylandServer()->dataDeviceManager();
const DataDeviceManagerInterface *dataDeviceManagerInterface =
waylandServer()->dataDeviceManager();
auto *dc = new QMetaObject::Connection();
*dc = connect(ddmi, &KWayland::Server::DataDeviceManagerInterface::dataDeviceCreated, this,
[this, dc](KWayland::Server::DataDeviceInterface *ddi) {
if (m_ddi || ddi->client() != waylandServer()->internalConnection()) {
return;
}
QObject::disconnect(*dc);
delete dc;
m_ddi = ddi;
init();
}
*dc = connect(dataDeviceManagerInterface, &DataDeviceManagerInterface::dataDeviceCreated, this,
[this, dc](DataDeviceInterface *dataDeviceInterface) {
if (m_dataDeviceInterface) {
return;
}
if (dataDeviceInterface->client() != waylandServer()->internalConnection()) {
return;
}
QObject::disconnect(*dc);
delete dc;
m_dataDeviceInterface = dataDeviceInterface;
init();
}
);
}
@ -97,20 +108,22 @@ bool DataBridge::filterEvent(xcb_generic_event_t *event)
bool DataBridge::handleXfixesNotify(xcb_xfixes_selection_notify_event_t *event)
{
auto getSelection = [this](xcb_atom_t atom) -> Selection* {
if (atom == atoms->clipboard) {
return m_clipboard;
}
if (atom == atoms->xdnd_selection) {
return m_dnd;
}
return nullptr;
};
auto *sel = getSelection(event->selection);
return sel && sel->handleXfixesNotify(event);
Selection *selection = nullptr;
if (event->selection == atoms->clipboard) {
selection = m_clipboard;
} else if (event->selection == atoms->xdnd_selection) {
selection = m_dnd;
}
if (!selection) {
return false;
}
return selection->handleXfixesNotify(event);
}
DragEventReply DataBridge::dragMoveFilter(Toplevel *target, QPoint pos)
DragEventReply DataBridge::dragMoveFilter(Toplevel *target, const QPoint &pos)
{
if (!m_dnd) {
return DragEventReply::Wayland;
@ -118,5 +131,5 @@ DragEventReply DataBridge::dragMoveFilter(Toplevel *target, QPoint pos)
return m_dnd->dragMoveFilter(target, pos);
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -27,11 +27,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
class xcb_xfixes_selection_notify_event_t;
namespace KWayland {
namespace Client {
namespace KWayland
{
namespace Client
{
class DataDevice;
}
namespace Server {
namespace Server
{
class DataDeviceInterface;
class SurfaceInterface;
}
@ -48,33 +51,34 @@ class Clipboard;
class Dnd;
enum class DragEventReply;
/*
/**
* Interface class for all data sharing in the context of X selections
* and Wayland's internal mechanism.
*
* Exists only once per Xwayland session.
*/
**/
class DataBridge : public QObject
{
Q_OBJECT
public:
static DataBridge* self();
static DataBridge *self();
explicit DataBridge(QObject *parent = nullptr);
~DataBridge();
bool filterEvent(xcb_generic_event_t *event);
DragEventReply dragMoveFilter(Toplevel *target, QPoint pos);
DragEventReply dragMoveFilter(Toplevel *target, const QPoint &pos);
KWayland::Client::DataDevice *dataDevice() const
{
return m_dd;
return m_dataDevice;
}
KWayland::Server::DataDeviceInterface *dataDeviceIface() const
{
return m_ddi;
return m_dataDeviceInterface;
}
Dnd* dnd() const
Dnd *dnd() const
{
return m_dnd;
}
@ -88,11 +92,13 @@ private:
Dnd *m_dnd = nullptr;
/* Internal data device interface */
KWayland::Client::DataDevice *m_dd = nullptr;
KWayland::Server::DataDeviceInterface *m_ddi = nullptr;
KWayland::Client::DataDevice *m_dataDevice = nullptr;
KWayland::Server::DataDeviceInterface *m_dataDeviceInterface = nullptr;
Q_DISABLE_COPY(DataBridge)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -20,21 +20,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dnd.h"
#include "databridge.h"
#include "selection_source.h"
#include "drag_wl.h"
#include "drag_x.h"
#include "selection_source.h"
#include "abstract_client.h"
#include "atoms.h"
#include "wayland_server.h"
#include "workspace.h"
#include "xwayland.h"
#include "abstract_client.h"
#include <KWayland/Client/compositor.h>
#include <KWayland/Client/surface.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/compositor_interface.h>
#include <KWayland/Server/seat_interface.h>
#include <QMouseEvent>
@ -55,7 +55,7 @@ uint32_t Dnd::version()
Dnd::Dnd(xcb_atom_t atom, QObject *parent)
: Selection(atom, parent)
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
const uint32_t dndValues[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
XCB_EVENT_MASK_PROPERTY_CHANGE };
@ -124,7 +124,7 @@ Dnd::Dnd(xcb_atom_t atom, QObject *parent)
void Dnd::doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event)
{
if (qobject_cast<XToWlDrag*>(m_currentDrag)) {
if (qobject_cast<XToWlDrag *>(m_currentDrag)) {
// X drag is in progress, rogue X client took over the selection.
return;
}
@ -134,7 +134,7 @@ void Dnd::doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event)
ownSelection(true);
return;
}
createX11Source(NULL);
createX11Source(nullptr);
const auto *seat = waylandServer()->seat();
auto *originSurface = seat->focusedPointerSurface();
if (!originSurface) {
@ -151,15 +151,15 @@ void Dnd::doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event)
return;
}
createX11Source(event);
auto *xSrc = x11Source();
if (!xSrc) {
X11Source *source = x11Source();
if (!source) {
return;
}
DataBridge::self()->dataDeviceIface()->updateProxy(originSurface);
m_currentDrag = new XToWlDrag(xSrc);
m_currentDrag = new XToWlDrag(source);
}
void Dnd::x11OffersChanged(const QVector<QString> &added, const QVector<QString> &removed)
void Dnd::x11OffersChanged(const QStringList &added, const QStringList &removed)
{
Q_UNUSED(added);
Q_UNUSED(removed);
@ -168,7 +168,7 @@ void Dnd::x11OffersChanged(const QVector<QString> &added, const QVector<QString>
bool Dnd::handleClientMessage(xcb_client_message_event_t *event)
{
for (auto *drag : m_oldDrags) {
for (Drag *drag : m_oldDrags) {
if (drag->handleClientMessage(event)) {
return true;
}
@ -179,9 +179,9 @@ bool Dnd::handleClientMessage(xcb_client_message_event_t *event)
return false;
}
DragEventReply Dnd::dragMoveFilter(Toplevel *target, QPoint pos)
DragEventReply Dnd::dragMoveFilter(Toplevel *target, const QPoint &pos)
{
// this filter only is used when a drag is in process
// This filter only is used when a drag is in process.
Q_ASSERT(m_currentDrag);
return m_currentDrag->moveFilter(target, pos);
}
@ -190,24 +190,26 @@ void Dnd::startDrag()
{
auto *ddi = waylandServer()->seat()->dragSource();
if (ddi == DataBridge::self()->dataDeviceIface()) {
// X to Wl drag, started by us, is in progress
// X to Wl drag, started by us, is in progress.
Q_ASSERT(m_currentDrag);
return;
}
// there can only ever be one Wl native drag at the same time
// There can only ever be one Wl native drag at the same time.
Q_ASSERT(!m_currentDrag);
// new Wl to X drag, init drag and Wl source
// New Wl to X drag, init drag and Wl source.
m_currentDrag = new WlToXDrag();
auto *wls = new WlSource(this, ddi);
wls->setDataSourceIface(ddi->dragSource());
setWlSource(wls);
auto source = new WlSource(this, ddi);
source->setDataSourceIface(ddi->dragSource());
setWlSource(source);
ownSelection(true);
}
void Dnd::endDrag()
{
Q_ASSERT(m_currentDrag);
if (m_currentDrag->end()) {
delete m_currentDrag;
} else {
@ -223,5 +225,5 @@ void Dnd::clearOldDrag(Drag *drag)
delete drag;
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -48,20 +48,21 @@ enum class DragEventReply;
/**
* Represents the drag and drop mechanism, on X side this is the XDND protocol.
* For more information on XDND see: https://johnlindal.wixsite.com/xdnd
*/
**/
class Dnd : public Selection
{
Q_OBJECT
public:
explicit Dnd(xcb_atom_t atom, QObject *parent);
static uint32_t version();
void doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event) override;
void x11OffersChanged(const QVector<QString> &added, const QVector<QString> &removed) override;
void x11OffersChanged(const QStringList &added, const QStringList &removed) override;
bool handleClientMessage(xcb_client_message_event_t *event) override;
DragEventReply dragMoveFilter(Toplevel *target, QPoint pos);
DragEventReply dragMoveFilter(Toplevel *target, const QPoint &pos);
KWayland::Server::SurfaceInterface *surfaceIface() const {
return m_surfaceIface;
@ -78,13 +79,15 @@ private:
// active drag or null when no drag active
Drag *m_currentDrag = nullptr;
QVector<Drag*> m_oldDrags;
QVector<Drag *> m_oldDrags;
KWayland::Client::Surface *m_surface;
KWayland::Server::SurfaceInterface *m_surfaceIface = nullptr;
Q_DISABLE_COPY(Dnd)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -26,6 +26,15 @@ namespace KWin
namespace Xwl
{
Drag::Drag(QObject *parent)
: QObject(parent)
{
}
Drag::~Drag()
{
}
void Drag::sendClientMessage(xcb_window_t target, xcb_atom_t type, xcb_client_message_data_t *data)
{
xcb_client_message_event_t event {
@ -37,7 +46,7 @@ void Drag::sendClientMessage(xcb_window_t target, xcb_atom_t type, xcb_client_me
*data, // data
};
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_send_event(xcbConn,
0,
target,
@ -74,5 +83,5 @@ xcb_atom_t Drag::clientActionToAtom(DnDAction action)
return XCB_ATOM_NONE;
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -38,26 +38,32 @@ using DnDAction = KWayland::Client::DataDeviceManager::DnDAction;
/**
* An ongoing drag operation.
*/
**/
class Drag : public QObject
{
Q_OBJECT
public:
explicit Drag(QObject *parent = nullptr);
~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 ~Drag() = default;
virtual bool handleClientMessage(xcb_client_message_event_t *event) = 0;
virtual DragEventReply moveFilter(Toplevel *target, QPoint pos) = 0;
virtual DragEventReply moveFilter(Toplevel *target, const QPoint &pos) = 0;
virtual bool end() = 0;
Q_SIGNALS:
void finish(Drag *self);
private:
Q_DISABLE_COPY(Drag)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -19,22 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "drag_wl.h"
#include "xwayland.h"
#include "databridge.h"
#include "dnd.h"
#include "xwayland.h"
#include "atoms.h"
#include "client.h"
#include "wayland_server.h"
#include "workspace.h"
#include "client.h"
#include <KWayland/Client/datadevice.h>
#include <KWayland/Client/datasource.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/surface_interface.h>
#include <KWayland/Server/datadevice_interface.h>
#include <KWayland/Server/datasource_interface.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/surface_interface.h>
#include <QMouseEvent>
#include <QTimer>
@ -49,9 +49,9 @@ WlToXDrag::WlToXDrag()
m_dsi = waylandServer()->seat()->dragSource()->dragSource();
}
DragEventReply WlToXDrag::moveFilter(Toplevel *target, QPoint pos)
DragEventReply WlToXDrag::moveFilter(Toplevel *target, const QPoint &pos)
{
AbstractClient *ac = qobject_cast<AbstractClient*>(target);
AbstractClient *ac = qobject_cast<AbstractClient *>(target);
auto *seat = waylandServer()->seat();
if (m_visit && m_visit->target() == ac) {
// no target change
@ -64,7 +64,7 @@ DragEventReply WlToXDrag::moveFilter(Toplevel *target, QPoint pos)
delete m_visit;
m_visit = nullptr;
}
if (!qobject_cast<KWin::Client *>(ac)) {
if (!qobject_cast<Client *>(ac)) {
// no target or wayland native target,
// handled by input code directly
return DragEventReply::Wayland;
@ -107,15 +107,15 @@ Xvisit::Xvisit(WlToXDrag *drag, AbstractClient *target)
m_target(target)
{
// first check supported DND version
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_get_property_cookie_t cookie = xcb_get_property(xcbConn,
0,
m_target->window(),
atoms->xdnd_aware,
XCB_GET_PROPERTY_TYPE_ANY,
0, 1);
auto *reply = xcb_get_property_reply(xcbConn, cookie, NULL);
if (reply == NULL) {
auto *reply = xcb_get_property_reply(xcbConn, cookie, nullptr);
if (!reply) {
doFinish();
return;
}
@ -124,7 +124,7 @@ Xvisit::Xvisit(WlToXDrag *drag, AbstractClient *target)
free(reply);
return;
}
xcb_atom_t *value = static_cast<xcb_atom_t*>(xcb_get_property_value(reply));
xcb_atom_t *value = static_cast<xcb_atom_t *>(xcb_get_property_value(reply));
m_version = qMin(*value, Dnd::version());
if (m_version < 1) {
// minimal version we accept is 1
@ -136,9 +136,9 @@ Xvisit::Xvisit(WlToXDrag *drag, AbstractClient *target)
const auto *dd = DataBridge::self()->dataDevice();
// proxy drop
m_enterCon = connect(dd, &KWayland::Client::DataDevice::dragEntered,
m_enterConnection = connect(dd, &KWayland::Client::DataDevice::dragEntered,
this, &Xvisit::receiveOffer);
m_dropCon = connect(dd, &KWayland::Client::DataDevice::dropped,
m_dropConnection = connect(dd, &KWayland::Client::DataDevice::dropped,
this, &Xvisit::drop);
}
@ -152,9 +152,9 @@ bool Xvisit::handleClientMessage(xcb_client_message_event_t *event)
return false;
}
bool Xvisit::handleStatus(xcb_client_message_event_t *ev)
bool Xvisit::handleStatus(xcb_client_message_event_t *event)
{
xcb_client_message_data_t *data = &ev->data;
xcb_client_message_data_t *data = &event->data;
if (data->data32[0] != m_target->window()) {
// wrong target window
return false;
@ -186,9 +186,9 @@ bool Xvisit::handleStatus(xcb_client_message_event_t *ev)
return true;
}
bool Xvisit::handleFinished(xcb_client_message_event_t *ev)
bool Xvisit::handleFinished(xcb_client_message_event_t *event)
{
xcb_client_message_data_t *data = &ev->data;
xcb_client_message_data_t *data = &event->data;
if (data->data32[0] != m_target->window()) {
// different target window
@ -264,7 +264,7 @@ void Xvisit::receiveOffer()
Q_ASSERT(!m_dataOffer.isNull());
retrieveSupportedActions();
m_actionCon = connect(m_dataOffer, &KWayland::Client::DataOffer::sourceDragAndDropActionsChanged,
m_actionConnection = connect(m_dataOffer, &KWayland::Client::DataOffer::sourceDragAndDropActionsChanged,
this, &Xvisit::retrieveSupportedActions);
enter();
}
@ -277,7 +277,7 @@ void Xvisit::enter()
sendPosition(waylandServer()->seat()->pointerPos());
// proxy future pointer position changes
m_motionCon = connect(waylandServer()->seat(),
m_motionConnection = connect(waylandServer()->seat(),
&KWayland::Server::SeatInterface::pointerPosChanged,
this, &Xvisit::sendPosition);
}
@ -431,16 +431,16 @@ void Xvisit::stopConnections()
{
// final outcome has been determined from Wayland side
// no more updates needed
disconnect(m_enterCon);
m_enterCon = QMetaObject::Connection();
disconnect(m_dropCon);
m_dropCon = QMetaObject::Connection();
disconnect(m_enterConnection);
m_enterConnection = QMetaObject::Connection();
disconnect(m_dropConnection);
m_dropConnection = QMetaObject::Connection();
disconnect(m_motionCon);
m_motionCon = QMetaObject::Connection();
disconnect(m_actionCon);
m_actionCon = QMetaObject::Connection();
disconnect(m_motionConnection);
m_motionConnection = QMetaObject::Connection();
disconnect(m_actionConnection);
m_actionConnection = QMetaObject::Connection();
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -58,10 +58,11 @@ using DnDActions = KWayland::Client::DataDeviceManager::DnDActions;
class WlToXDrag : public Drag
{
Q_OBJECT
public:
explicit WlToXDrag();
DragEventReply moveFilter(Toplevel *target, QPoint pos) override;
DragEventReply moveFilter(Toplevel *target, const QPoint &pos) override;
bool handleClientMessage(xcb_client_message_event_t *event) override;
bool end() override;
@ -73,20 +74,23 @@ public:
private:
KWayland::Server::DataSourceInterface *m_dsi;
Xvisit *m_visit = nullptr;
Q_DISABLE_COPY(WlToXDrag)
};
// visit to an X window
class Xvisit : public QObject
{
Q_OBJECT
public:
// TODO: handle ask action
Xvisit(WlToXDrag *drag, AbstractClient *target);
bool handleClientMessage(xcb_client_message_event_t *event);
bool handleStatus(xcb_client_message_event_t *ev);
bool handleFinished(xcb_client_message_event_t *ev);
bool handleStatus(xcb_client_message_event_t *event);
bool handleFinished(xcb_client_message_event_t *event);
void sendPosition(const QPointF &globalPos);
void leave();
@ -123,10 +127,10 @@ private:
AbstractClient *m_target;
uint32_t m_version = 0;
QMetaObject::Connection m_enterCon;
QMetaObject::Connection m_motionCon;
QMetaObject::Connection m_actionCon;
QMetaObject::Connection m_dropCon;
QMetaObject::Connection m_enterConnection;
QMetaObject::Connection m_motionConnection;
QMetaObject::Connection m_actionConnection;
QMetaObject::Connection m_dropConnection;
struct {
bool pending = false;
@ -152,9 +156,11 @@ private:
} m_state;
bool m_accepts = false;
Q_DISABLE_COPY(Xvisit)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -39,8 +39,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QMouseEvent>
#include <QTimer>
namespace KWin {
namespace Xwl {
namespace KWin
{
namespace Xwl
{
static QStringList atomToMimeTypes(xcb_atom_t atom)
{
@ -61,7 +63,7 @@ static QStringList atomToMimeTypes(xcb_atom_t atom)
}
XToWlDrag::XToWlDrag(X11Source *source)
: m_src(source)
: m_source(source)
{
connect(DataBridge::self()->dnd(), &Dnd::transferFinished, this, [this](xcb_timestamp_t eventTime) {
// we use this mechanism, because the finished call is not
@ -80,7 +82,7 @@ XToWlDrag::XToWlDrag(X11Source *source)
connect(source, &X11Source::transferReady, this, [this](xcb_atom_t target, qint32 fd) {
Q_UNUSED(target);
Q_UNUSED(fd);
m_dataRequests << QPair<xcb_timestamp_t, bool>(m_src->timestamp(), false);
m_dataRequests << QPair<xcb_timestamp_t, bool>(m_source->timestamp(), false);
});
auto *ddm = waylandServer()->internalDataDeviceManager();
m_dataSource = ddm->createDataSource(this);
@ -142,7 +144,7 @@ XToWlDrag::~XToWlDrag()
m_dataSource = nullptr;
}
DragEventReply XToWlDrag::moveFilter(Toplevel *target, QPoint pos)
DragEventReply XToWlDrag::moveFilter(Toplevel *target, const QPoint &pos)
{
Q_UNUSED(pos);
@ -220,7 +222,7 @@ DnDAction XToWlDrag::selectedDragAndDropAction()
void XToWlDrag::setOffers(const Mimes &offers)
{
m_src->setOffers(offers);
m_source->setOffers(offers);
if (offers.isEmpty()) {
// There are no offers, so just directly set the drag target,
// no transfer possible anyways.
@ -288,7 +290,7 @@ WlVisit::WlVisit(AbstractClient *target, XToWlDrag *drag)
m_target(target),
m_drag(drag)
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
m_window = xcb_generate_id(xcbConn);
DataBridge::self()->dnd()->overwriteRequestorWindow(m_window);
@ -325,7 +327,7 @@ WlVisit::WlVisit(AbstractClient *target, XToWlDrag *drag)
WlVisit::~WlVisit()
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_destroy_window(xcbConn, m_window);
xcb_flush(xcbConn);
}
@ -362,7 +364,7 @@ static bool hasMimeName(const Mimes &mimes, const QString &name)
[name](const Mime &m) { return m.first == name; });
}
bool WlVisit::handleEnter(xcb_client_message_event_t *ev)
bool WlVisit::handleEnter(xcb_client_message_event_t *event)
{
if (m_entered) {
// a drag already entered
@ -370,7 +372,7 @@ bool WlVisit::handleEnter(xcb_client_message_event_t *ev)
}
m_entered = true;
xcb_client_message_data_t *data = &ev->data;
xcb_client_message_data_t *data = &event->data;
m_srcWindow = data->data32[0];
m_version = data->data32[1] >> 24;
@ -398,7 +400,7 @@ bool WlVisit::handleEnter(xcb_client_message_event_t *ev)
void WlVisit::getMimesFromWinProperty(Mimes &offers)
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
auto cookie = xcb_get_property(xcbConn,
0,
m_srcWindow,
@ -416,10 +418,10 @@ void WlVisit::getMimesFromWinProperty(Mimes &offers)
return;
}
xcb_atom_t *mimeAtoms = static_cast<xcb_atom_t*>(xcb_get_property_value(reply));
xcb_atom_t *mimeAtoms = static_cast<xcb_atom_t *>(xcb_get_property_value(reply));
for (size_t i = 0; i < reply->value_len; ++i) {
const auto mimeStrings = atomToMimeTypes(mimeAtoms[i]);
for (const auto mime : mimeStrings ) {
for (const auto mime : mimeStrings) {
if (!hasMimeName(offers, mime)) {
offers << Mime(mime, mimeAtoms[i]);
}
@ -428,9 +430,9 @@ void WlVisit::getMimesFromWinProperty(Mimes &offers)
free(reply);
}
bool WlVisit::handlePosition(xcb_client_message_event_t *ev)
bool WlVisit::handlePosition(xcb_client_message_event_t *event)
{
xcb_client_message_data_t *data = &ev->data;
xcb_client_message_data_t *data = &event->data;
m_srcWindow = data->data32[0];
if (!m_target) {
@ -466,11 +468,11 @@ bool WlVisit::handlePosition(xcb_client_message_event_t *ev)
return true;
}
bool WlVisit::handleDrop(xcb_client_message_event_t *ev)
bool WlVisit::handleDrop(xcb_client_message_event_t *event)
{
m_dropHandled = true;
xcb_client_message_data_t *data = &ev->data;
xcb_client_message_data_t *data = &event->data;
m_srcWindow = data->data32[0];
const xcb_timestamp_t timestamp = data->data32[2];
m_drag->x11Source()->setTimestamp(timestamp);
@ -488,10 +490,10 @@ void WlVisit::doFinish()
Q_EMIT finish(this);
}
bool WlVisit::handleLeave(xcb_client_message_event_t *ev)
bool WlVisit::handleLeave(xcb_client_message_event_t *event)
{
m_entered = false;
xcb_client_message_data_t *data = &ev->data;
xcb_client_message_data_t *data = &event->data;
m_srcWindow = data->data32[0];
doFinish();
return true;
@ -536,7 +538,7 @@ void WlVisit::unmapProxyWindow()
if (!m_mapped) {
return;
}
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_unmap_window(xcbConn, m_window);
workspace()->removeManualOverlay(m_window);
workspace()->updateStackingOrder(true);
@ -544,5 +546,5 @@ void WlVisit::unmapProxyWindow()
m_mapped = false;
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -31,8 +31,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QPointer>
#include <QVector>
namespace KWayland {
namespace Client {
namespace KWayland
{
namespace Client
{
class DataSource;
}
}
@ -53,11 +55,12 @@ using Mimes = QVector<QPair<QString, xcb_atom_t> >;
class XToWlDrag : public Drag
{
Q_OBJECT
public:
explicit XToWlDrag(X11Source *source);
~XToWlDrag() override;
DragEventReply moveFilter(Toplevel *target, QPoint pos) override;
DragEventReply moveFilter(Toplevel *target, const QPoint &pos) override;
bool handleClientMessage(xcb_client_message_event_t *event) override;
void setDragAndDropAction(DnDAction action);
@ -66,8 +69,8 @@ public:
bool end() override {
return false;
}
X11Source* x11Source() const {
return m_src;
X11Source *x11Source() const {
return m_source;
}
private:
@ -82,19 +85,22 @@ private:
Mimes m_offers;
Mimes m_offersPending;
X11Source *m_src;
X11Source *m_source;
QVector<QPair<xcb_timestamp_t, bool> > m_dataRequests;
WlVisit *m_visit = nullptr;
QVector<WlVisit*> m_oldVisits;
QVector<WlVisit *> m_oldVisits;
bool m_performed = false;
DnDAction m_lastSelectedDragAndDropAction = DnDAction::None;
Q_DISABLE_COPY(XToWlDrag)
};
class WlVisit : public QObject
{
Q_OBJECT
public:
WlVisit(AbstractClient *target, XToWlDrag *drag);
~WlVisit();
@ -124,10 +130,10 @@ Q_SIGNALS:
void finish(WlVisit *self);
private:
bool handleEnter(xcb_client_message_event_t *ev);
bool handlePosition(xcb_client_message_event_t *ev);
bool handleDrop(xcb_client_message_event_t *ev);
bool handleLeave(xcb_client_message_event_t *ev);
bool handleEnter(xcb_client_message_event_t *event);
bool handlePosition(xcb_client_message_event_t *event);
bool handleDrop(xcb_client_message_event_t *event);
bool handleLeave(xcb_client_message_event_t *event);
void sendStatus();
@ -154,9 +160,10 @@ private:
bool m_dropHandled = false;
bool m_finished = false;
Q_DISABLE_COPY(WlVisit)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -23,24 +23,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "transfer.h"
#include "atoms.h"
#include "workspace.h"
#include "client.h"
#include "workspace.h"
#include <xcb/xcb_event.h>
#include <xcb/xfixes.h>
#include <QTimer>
namespace KWin {
namespace Xwl {
namespace KWin
{
namespace Xwl
{
xcb_atom_t Selection::mimeTypeToAtom(const QString &mimeType)
{
if (mimeType == QLatin1String("text/plain;charset=utf-8")) {
return atoms->utf8_string;
} else if (mimeType == QLatin1String("text/plain")) {
}
if (mimeType == QLatin1String("text/plain")) {
return atoms->text;
} else if (mimeType == QLatin1String("text/x-uri")) {
}
if (mimeType == QLatin1String("text/x-uri")) {
return atoms->uri_list;
}
return mimeTypeToAtomLiteral(mimeType);
@ -53,15 +57,15 @@ xcb_atom_t Selection::mimeTypeToAtomLiteral(const QString &mimeType)
QString Selection::atomName(xcb_atom_t atom)
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_get_atom_name_cookie_t nameCookie = xcb_get_atom_name(xcbConn, atom);
xcb_get_atom_name_reply_t *nameReply = xcb_get_atom_name_reply(xcbConn, nameCookie, NULL);
if (nameReply == NULL) {
xcb_get_atom_name_reply_t *nameReply = xcb_get_atom_name_reply(xcbConn, nameCookie, nullptr);
if (!nameReply) {
return QString();
}
size_t len = xcb_get_atom_name_name_length(nameReply);
QString name = QString::fromLatin1(xcb_get_atom_name_name(nameReply), len);
const size_t length = xcb_get_atom_name_name_length(nameReply);
QString name = QString::fromLatin1(xcb_get_atom_name_name(nameReply), length);
free(nameReply);
return name;
}
@ -83,10 +87,10 @@ QStringList Selection::atomToMimeTypes(xcb_atom_t atom)
}
Selection::Selection(xcb_atom_t atom, QObject *parent)
: QObject(parent),
m_atom(atom)
: QObject(parent)
, m_atom(atom)
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
m_window = xcb_generate_id(kwinApp()->x11Connection());
m_requestorWindow = m_window;
xcb_flush(xcbConn);
@ -105,11 +109,11 @@ bool Selection::handleXfixesNotify(xcb_xfixes_selection_notify_event_t *event)
m_disownPending = false;
return true;
}
if (event->owner == m_window && m_wlSrc) {
if (event->owner == m_window && m_waylandSource) {
// When we claim a selection we must use XCB_TIME_CURRENT,
// grab the actual timestamp here to answer TIMESTAMP requests
// correctly
m_wlSrc->setTimestamp(event->timestamp);
m_waylandSource->setTimestamp(event->timestamp);
m_timestamp = event->timestamp;
return true;
}
@ -123,22 +127,22 @@ bool Selection::filterEvent(xcb_generic_event_t *event)
{
switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) {
case XCB_SELECTION_NOTIFY:
if (handleSelNotify(reinterpret_cast<xcb_selection_notify_event_t*>(event))) {
if (handleSelectionNotify(reinterpret_cast<xcb_selection_notify_event_t *>(event))) {
return true;
}
Q_FALLTHROUGH();
case XCB_PROPERTY_NOTIFY:
if (handlePropNotify(reinterpret_cast<xcb_property_notify_event_t*>(event))) {
if (handlePropertyNotify(reinterpret_cast<xcb_property_notify_event_t *>(event))) {
return true;
}
Q_FALLTHROUGH();
case XCB_SELECTION_REQUEST:
if (handleSelRequest(reinterpret_cast<xcb_selection_request_event_t*>(event))) {
if (handleSelectionRequest(reinterpret_cast<xcb_selection_request_event_t *>(event))) {
return true;
}
Q_FALLTHROUGH();
case XCB_CLIENT_MESSAGE:
if (handleClientMessage(reinterpret_cast<xcb_client_message_event_t*>(event))) {
if (handleClientMessage(reinterpret_cast<xcb_client_message_event_t *>(event))) {
return true;
}
Q_FALLTHROUGH();
@ -147,7 +151,7 @@ bool Selection::filterEvent(xcb_generic_event_t *event)
}
}
void Selection::sendSelNotify(xcb_selection_request_event_t *event, bool success)
void Selection::sendSelectionNotify(xcb_selection_request_event_t *event, bool success)
{
xcb_selection_notify_event_t notify;
notify.response_type = XCB_SELECTION_NOTIFY;
@ -156,9 +160,9 @@ void Selection::sendSelNotify(xcb_selection_request_event_t *event, bool success
notify.requestor = event->requestor;
notify.selection = event->selection;
notify.target = event->target;
notify.property = success ? event->property : (xcb_atom_t)XCB_ATOM_NONE;
notify.property = success ? event->property : xcb_atom_t(XCB_ATOM_NONE);
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_send_event(xcbConn,
0,
event->requestor,
@ -169,7 +173,7 @@ void Selection::sendSelNotify(xcb_selection_request_event_t *event, bool success
void Selection::registerXfixes()
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
@ -180,36 +184,36 @@ void Selection::registerXfixes()
xcb_flush(xcbConn);
}
void Selection::setWlSource(WlSource *src)
void Selection::setWlSource(WlSource *source)
{
delete m_wlSrc;
delete m_xSrc;
m_wlSrc = nullptr;
m_xSrc = nullptr;
if (src) {
m_wlSrc = src;
connect(src, &WlSource::transferReady, this, &Selection::startTransferToX);
delete m_waylandSource;
delete m_xSource;
m_waylandSource = nullptr;
m_xSource = nullptr;
if (source) {
m_waylandSource = source;
connect(source, &WlSource::transferReady, this, &Selection::startTransferToX);
}
}
void Selection::createX11Source(xcb_xfixes_selection_notify_event_t *event)
{
delete m_wlSrc;
delete m_xSrc;
m_wlSrc = nullptr;
m_xSrc = nullptr;
delete m_waylandSource;
delete m_xSource;
m_waylandSource = nullptr;
m_xSource = nullptr;
if (!event || event->owner == XCB_WINDOW_NONE) {
return;
}
m_xSrc = new X11Source(this, event);
m_xSource = new X11Source(this, event);
connect(m_xSrc, &X11Source::offersChanged, this, &Selection::x11OffersChanged);
connect(m_xSrc, &X11Source::transferReady, this, &Selection::startTransferToWayland);
connect(m_xSource, &X11Source::offersChanged, this, &Selection::x11OffersChanged);
connect(m_xSource, &X11Source::transferReady, this, &Selection::startTransferToWayland);
}
void Selection::ownSelection(bool own)
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
if (own) {
xcb_set_selection_owner(xcbConn,
m_window,
@ -227,16 +231,16 @@ void Selection::ownSelection(bool own)
void Selection::overwriteRequestorWindow(xcb_window_t window)
{
Q_ASSERT(m_xSrc);
Q_ASSERT(m_xSource);
if (window == XCB_WINDOW_NONE) {
// reset
window = m_window;
}
m_requestorWindow = window;
m_xSrc->setRequestor(window);
m_xSource->setRequestor(window);
}
bool Selection::handleSelRequest(xcb_selection_request_event_t *event)
bool Selection::handleSelectionRequest(xcb_selection_request_event_t *event)
{
if (event->selection != m_atom) {
return false;
@ -245,44 +249,44 @@ bool Selection::handleSelRequest(xcb_selection_request_event_t *event)
if (qobject_cast<Client *>(workspace()->activeClient()) == nullptr) {
// Receiving Wayland selection not allowed when no Xwayland surface active
// filter the event, but don't act upon it
sendSelNotify(event, false);
sendSelectionNotify(event, false);
return true;
}
if (m_window != event->owner || !m_wlSrc) {
if (m_window != event->owner || !m_waylandSource) {
if (event->time < m_timestamp) {
// cancel earlier attempts at receiving a selection
// TODO: is this for sure without problems?
sendSelNotify(event, false);
sendSelectionNotify(event, false);
return true;
}
return false;
}
return m_wlSrc->handleSelRequest(event);
return m_waylandSource->handleSelectionRequest(event);
}
bool Selection::handleSelNotify(xcb_selection_notify_event_t *event)
bool Selection::handleSelectionNotify(xcb_selection_notify_event_t *event)
{
if (m_xSrc && m_xSrc->handleSelNotify(event)) {
if (m_xSource && m_xSource->handleSelectionNotify(event)) {
return true;
}
for (auto *transfer : m_xToWlTransfers) {
if (transfer->handleSelNotify(event)) {
for (TransferXtoWl *transfer : m_xToWlTransfers) {
if (transfer->handleSelectionNotify(event)) {
return true;
}
}
return false;
}
bool Selection::handlePropNotify(xcb_property_notify_event_t *event)
bool Selection::handlePropertyNotify(xcb_property_notify_event_t *event)
{
for (auto *transfer : m_xToWlTransfers) {
if (transfer->handlePropNotify(event)) {
for (TransferXtoWl *transfer : m_xToWlTransfers) {
if (transfer->handlePropertyNotify(event)) {
return true;
}
}
for (auto *transfer : m_wlToXTransfers) {
if (transfer->handlePropNotify(event)) {
for (TransferWltoX *transfer : m_wlToXTransfers) {
if (transfer->handlePropertyNotify(event)) {
return true;
}
}
@ -292,7 +296,7 @@ bool Selection::handlePropNotify(xcb_property_notify_event_t *event)
void Selection::startTransferToWayland(xcb_atom_t target, qint32 fd)
{
// create new x to wl data transfer object
auto *transfer = new TransferXtoWl(m_atom, target, fd, m_xSrc->timestamp(), m_requestorWindow, this);
auto *transfer = new TransferXtoWl(m_atom, target, fd, m_xSource->timestamp(), m_requestorWindow, this);
m_xToWlTransfers << transfer;
connect(transfer, &TransferXtoWl::finished, this, [this, transfer]() {
@ -309,7 +313,7 @@ void Selection::startTransferToX(xcb_selection_request_event_t *event, qint32 fd
// create new wl to x data transfer object
auto *transfer = new TransferWltoX(m_atom, event, fd, this);
connect(transfer, &TransferWltoX::selNotify, this, &Selection::sendSelNotify);
connect(transfer, &TransferWltoX::selectionNotify, this, &Selection::sendSelectionNotify);
connect(transfer, &TransferWltoX::finished, this, [this, transfer]() {
Q_EMIT transferFinished(transfer->timestamp());
@ -355,13 +359,13 @@ void Selection::endTimeoutTransfersTimer()
void Selection::timeoutTransfers()
{
for (auto *transfer : m_xToWlTransfers) {
for (TransferXtoWl *transfer : m_xToWlTransfers) {
transfer->timeout();
}
for (auto *transfer : m_wlToXTransfers) {
for (TransferWltoX *transfer : m_wlToXTransfers) {
transfer->timeout();
}
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -38,7 +38,7 @@ class TransferXtoWl;
class WlSource;
class X11Source;
/*
/**
* Base class representing generic X selections and their respective
* Wayland counter-parts.
*
@ -52,16 +52,17 @@ class X11Source;
* Independently of each other the class holds the currently active
* source instance and active transfers relative to the represented
* selection.
*/
**/
class Selection : public QObject
{
Q_OBJECT
public:
static xcb_atom_t mimeTypeToAtom(const QString &mimeType);
static xcb_atom_t mimeTypeToAtomLiteral(const QString &mimeType);
static QStringList atomToMimeTypes(xcb_atom_t atom);
static QString atomName(xcb_atom_t atom);
static void sendSelNotify(xcb_selection_request_event_t *event, bool success);
static void sendSelectionNotify(xcb_selection_request_event_t *event, bool success);
// on selection owner changes by X clients (Xwl -> Wl)
bool handleXfixesNotify(xcb_xfixes_selection_notify_event_t *event);
@ -83,20 +84,20 @@ protected:
void registerXfixes();
virtual void doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event) = 0;
virtual void x11OffersChanged(const QVector<QString> &added, const QVector<QString> &removed) = 0;
virtual void x11OffersChanged(const QStringList &added, const QStringList &removed) = 0;
virtual bool handleClientMessage(xcb_client_message_event_t *event) {
Q_UNUSED(event);
return false;
}
// sets the current provider of the selection
void setWlSource(WlSource *src);
WlSource* wlSource() const {
return m_wlSrc;
void setWlSource(WlSource *source);
WlSource *wlSource() const {
return m_waylandSource;
}
void createX11Source(xcb_xfixes_selection_notify_event_t *event);
X11Source* x11Source() const {
return m_xSrc;
X11Source *x11Source() const {
return m_xSource;
}
// must be called in order to provide data from Wl to X
void ownSelection(bool own);
@ -105,9 +106,9 @@ protected:
}
private:
bool handleSelRequest(xcb_selection_request_event_t *event);
bool handleSelNotify(xcb_selection_notify_event_t *event);
bool handlePropNotify(xcb_property_notify_event_t *event);
bool handleSelectionRequest(xcb_selection_request_event_t *event);
bool handleSelectionNotify(xcb_selection_notify_event_t *event);
bool handlePropertyNotify(xcb_property_notify_event_t *event);
void startTransferToWayland(xcb_atom_t target, qint32 fd);
void startTransferToX(xcb_selection_request_event_t *event, qint32 fd);
@ -124,18 +125,20 @@ private:
// Active source, if any. Only one of them at max can exist
// at the same time.
WlSource *m_wlSrc = nullptr;
X11Source *m_xSrc = nullptr;
WlSource *m_waylandSource = nullptr;
X11Source *m_xSource = nullptr;
// active transfers
QVector<TransferWltoX*> m_wlToXTransfers;
QVector<TransferXtoWl*> m_xToWlTransfers;
QVector<TransferWltoX *> m_wlToXTransfers;
QVector<TransferXtoWl *> m_xToWlTransfers;
QTimer *m_timeoutTransfers = nullptr;
bool m_disownPending = false;
Q_DISABLE_COPY(Selection)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -29,27 +29,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KWayland/Client/datadevice.h>
#include <KWayland/Client/datasource.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/datadevice_interface.h>
#include <KWayland/Server/datasource_interface.h>
#include <KWayland/Server/seat_interface.h>
#include <unistd.h>
#include <xwayland_logging.h>
namespace KWin {
namespace Xwl {
namespace KWin
{
namespace Xwl
{
SelectionSource::SelectionSource(Selection *sel)
: QObject(sel),
m_sel(sel),
m_window(sel->window())
SelectionSource::SelectionSource(Selection *selection)
: QObject(selection)
, m_selection(selection)
, m_window(selection->window())
{
}
WlSource::WlSource(Selection *sel, KWayland::Server::DataDeviceInterface *ddi)
: SelectionSource(sel),
m_ddi(ddi)
WlSource::WlSource(Selection *selection, KWayland::Server::DataDeviceInterface *ddi)
: SelectionSource(selection)
, m_ddi(ddi)
{
Q_ASSERT(ddi);
}
@ -62,7 +64,7 @@ void WlSource::setDataSourceIface(KWayland::Server::DataSourceInterface *dsi)
for (const auto &mime : dsi->mimeTypes()) {
m_offers << mime;
}
m_offerCon = connect(dsi,
m_offerConnection = connect(dsi,
&KWayland::Server::DataSourceInterface::mimeTypeOffered,
this, &WlSource::receiveOffer);
m_dsi = dsi;
@ -73,23 +75,23 @@ void WlSource::receiveOffer(const QString &mime)
m_offers << mime;
}
void WlSource::sendSelNotify(xcb_selection_request_event_t *event, bool success)
void WlSource::sendSelectionNotify(xcb_selection_request_event_t *event, bool success)
{
Selection::sendSelNotify(event, success);
Selection::sendSelectionNotify(event, success);
}
bool WlSource::handleSelRequest(xcb_selection_request_event_t *event)
bool WlSource::handleSelectionRequest(xcb_selection_request_event_t *event)
{
if (event->target == atoms->targets) {
sendTargets(event);
} else if (event->target == atoms->timestamp) {
sendTimestamp(event);
} else if (event->target == atoms->delete_atom) {
sendSelNotify(event, true);
sendSelectionNotify(event, true);
} else {
// try to send mime data
if (!checkStartTransfer(event)) {
sendSelNotify(event, false);
sendSelectionNotify(event, false);
}
}
return true;
@ -114,7 +116,7 @@ void WlSource::sendTargets(xcb_selection_request_event_t *event)
event->property,
XCB_ATOM_ATOM,
32, cnt, targets.data());
sendSelNotify(event, true);
sendSelectionNotify(event, true);
}
void WlSource::sendTimestamp(xcb_selection_request_event_t *event)
@ -127,7 +129,7 @@ void WlSource::sendTimestamp(xcb_selection_request_event_t *event)
XCB_ATOM_INTEGER,
32, 1, &time);
sendSelNotify(event, true);
sendSelectionNotify(event, true);
}
bool WlSource::checkStartTransfer(xcb_selection_request_event_t *event)
@ -172,16 +174,16 @@ bool WlSource::checkStartTransfer(xcb_selection_request_event_t *event)
return true;
}
X11Source::X11Source(Selection *sel, xcb_xfixes_selection_notify_event_t *event)
: SelectionSource(sel),
m_owner(event->owner)
X11Source::X11Source(Selection *selection, xcb_xfixes_selection_notify_event_t *event)
: SelectionSource(selection)
, m_owner(event->owner)
{
setTimestamp(event->timestamp);
}
void X11Source::getTargets()
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
/* will lead to a selection request event for the new owner */
xcb_convert_selection(xcbConn,
window(),
@ -197,7 +199,7 @@ using Mime = QPair<QString, xcb_atom_t>;
void X11Source::handleTargets()
{
// receive targets
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_get_property_cookie_t cookie = xcb_get_property(xcbConn,
1,
window(),
@ -206,8 +208,8 @@ void X11Source::handleTargets()
0,
4096
);
auto *reply = xcb_get_property_reply(xcbConn, cookie, NULL);
if (reply == NULL) {
auto *reply = xcb_get_property_reply(xcbConn, cookie, nullptr);
if (!reply) {
return;
}
if (reply->type != XCB_ATOM_ATOM) {
@ -215,9 +217,11 @@ void X11Source::handleTargets()
return;
}
QStringList added;
QStringList removed;
Mimes all;
QVector<QString> add, rm;
xcb_atom_t *value = static_cast<xcb_atom_t*>(xcb_get_property_value(reply));
xcb_atom_t *value = static_cast<xcb_atom_t *>(xcb_get_property_value(reply));
for (uint32_t i = 0; i < reply->value_len; i++) {
if (value[i] == XCB_ATOM_NONE) {
continue;
@ -231,12 +235,14 @@ void X11Source::handleTargets()
const auto mimeIt = std::find_if(m_offers.begin(), m_offers.end(),
[value, i](const Mime &m)
{ return m.second == value[i]; });
[value, i](const Mime &mime) {
return mime.second == value[i];
}
);
auto mimePair = Mime(mimeStrings[0], value[i]);
if (mimeIt == m_offers.end()) {
add << mimePair.first;
added << mimePair.first;
} else {
m_offers.removeAll(mimePair);
}
@ -244,31 +250,32 @@ void X11Source::handleTargets()
}
// all left in m_offers are not in the updated targets
for (const auto mimePair : m_offers) {
rm << mimePair.first;
removed << mimePair.first;
}
m_offers = all;
if (!add.isEmpty() || !rm.isEmpty()) {
Q_EMIT offersChanged(add, rm);
if (!added.isEmpty() || !removed.isEmpty()) {
Q_EMIT offersChanged(added, removed);
}
free(reply);
}
void X11Source::setDataSource(KWayland::Client::DataSource *ds)
void X11Source::setDataSource(KWayland::Client::DataSource *dataSource)
{
Q_ASSERT(ds);
if (m_ds) {
delete m_ds;
Q_ASSERT(dataSource);
if (m_dataSource) {
delete m_dataSource;
}
m_ds = ds;
std::for_each(m_offers.begin(), m_offers.end(),
[ds](const Mime &offer){
ds->offer(offer.first);
});
connect(ds, &KWayland::Client::DataSource::sendDataRequested,
this, &X11Source::startTransfer);
m_dataSource = dataSource;
for (const Mime &offer : m_offers) {
dataSource->offer(offer.first);
}
connect(dataSource, &KWayland::Client::DataSource::sendDataRequested,
this, &X11Source::startTransfer);
}
void X11Source::setOffers(const Mimes &offers)
@ -277,7 +284,7 @@ void X11Source::setOffers(const Mimes &offers)
m_offers = offers;
}
bool X11Source::handleSelNotify(xcb_selection_notify_event_t *event)
bool X11Source::handleSelectionNotify(xcb_selection_notify_event_t *event)
{
if (event->requestor != window()) {
return false;
@ -299,8 +306,10 @@ bool X11Source::handleSelNotify(xcb_selection_notify_event_t *event)
void X11Source::startTransfer(const QString &mimeName, qint32 fd)
{
const auto mimeIt = std::find_if(m_offers.begin(), m_offers.end(),
[mimeName](const Mime &m)
{ return m.first == mimeName; });
[mimeName](const Mime &mime) {
return mime.first == mimeName;
}
);
if (mimeIt == m_offers.end()) {
qCDebug(KWIN_XWL) << "Sending X11 clipboard to Wayland failed: unsupported MIME.";
close(fd);
@ -310,6 +319,5 @@ void X11Source::startTransfer(const QString &mimeName, qint32 fd)
Q_EMIT transferReady((*mimeIt).second, fd);
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -51,12 +51,13 @@ class Selection;
/**
* Base class representing a data source.
*/
**/
class SelectionSource : public QObject
{
Q_OBJECT
public:
SelectionSource(Selection *sel);
SelectionSource(Selection *selection);
xcb_timestamp_t timestamp() const {
return m_timestamp;
@ -67,7 +68,7 @@ public:
protected:
Selection *selection() const {
return m_sel;
return m_selection;
}
void setWindow(xcb_window_t window) {
m_window = window;
@ -78,26 +79,29 @@ protected:
private:
xcb_timestamp_t m_timestamp = XCB_CURRENT_TIME;
Selection *m_sel;
Selection *m_selection;
xcb_window_t m_window;
Q_DISABLE_COPY(SelectionSource)
};
/**
* Representing a Wayland native data source.
*/
**/
class WlSource : public SelectionSource
{
Q_OBJECT
public:
WlSource(Selection *sel, KWayland::Server::DataDeviceInterface *ddi);
WlSource(Selection *selection, KWayland::Server::DataDeviceInterface *ddi);
void setDataSourceIface(KWayland::Server::DataSourceInterface *dsi);
bool handleSelRequest(xcb_selection_request_event_t *event);
bool handleSelectionRequest(xcb_selection_request_event_t *event);
void sendTargets(xcb_selection_request_event_t *event);
void sendTimestamp(xcb_selection_request_event_t *event);
void receiveOffer(const QString &mime);
void sendSelNotify(xcb_selection_request_event_t *event, bool success);
void sendSelectionNotify(xcb_selection_request_event_t *event, bool success);
Q_SIGNALS:
void transferReady(xcb_selection_request_event_t *event, qint32 fd);
@ -109,29 +113,32 @@ private:
KWayland::Server::DataSourceInterface *m_dsi = nullptr;
QVector<QString> m_offers;
QMetaObject::Connection m_offerCon;
QMetaObject::Connection m_offerConnection;
Q_DISABLE_COPY(WlSource)
};
using Mimes = QVector<QPair<QString, xcb_atom_t> >;
/**
* Representing an X data source.
*/
**/
class X11Source : public SelectionSource
{
Q_OBJECT
public:
X11Source(Selection *sel, xcb_xfixes_selection_notify_event_t *event);
X11Source(Selection *selection, xcb_xfixes_selection_notify_event_t *event);
/**
* @param ds must exist.
*
* X11Source does not take ownership of it in general, but if the function
* is called again, it will delete the previous data source.
*/
void setDataSource(KWayland::Client::DataSource *ds);
KWayland::Client::DataSource* dataSource() const {
return m_ds;
**/
void setDataSource(KWayland::Client::DataSource *dataSource);
KWayland::Client::DataSource *dataSource() const {
return m_dataSource;
}
void getTargets();
@ -140,14 +147,14 @@ public:
}
void setOffers(const Mimes &offers);
bool handleSelNotify(xcb_selection_notify_event_t *event);
bool handleSelectionNotify(xcb_selection_notify_event_t *event);
void setRequestor(xcb_window_t window) {
setWindow(window);
}
Q_SIGNALS:
void offersChanged(QVector<QString> added, QVector<QString> removed);
void offersChanged(const QStringList &added, const QStringList &removed);
void transferReady(xcb_atom_t target, qint32 fd);
private:
@ -155,12 +162,14 @@ private:
void startTransfer(const QString &mimeName, qint32 fd);
xcb_window_t m_owner;
KWayland::Client::DataSource *m_ds = nullptr;
KWayland::Client::DataSource *m_dataSource = nullptr;
Mimes m_offers;
Q_DISABLE_COPY(X11Source)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -19,22 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "transfer.h"
#include "xwayland.h"
#include "databridge.h"
#include "xwayland.h"
#include "abstract_client.h"
#include "atoms.h"
#include "wayland_server.h"
#include "workspace.h"
#include "abstract_client.h"
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/datadevicemanager.h>
#include <KWayland/Client/datadevice.h>
#include <KWayland/Client/datasource.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/datadevice_interface.h>
#include <KWayland/Server/datasource_interface.h>
#include <KWayland/Server/seat_interface.h>
#include <xcb/xcb_event.h>
#include <xcb/xfixes.h>
@ -44,31 +44,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <xwayland_logging.h>
namespace KWin {
namespace Xwl {
namespace KWin
{
namespace Xwl
{
// in Bytes: equals 64KB
static const uint32_t s_incrChunkSize = 63 * 1024;
Transfer::Transfer(xcb_atom_t selection, qint32 fd, xcb_timestamp_t timestamp, QObject *parent)
: QObject(parent),
m_atom(selection),
m_fd(fd),
m_timestamp(timestamp)
: QObject(parent)
, m_atom(selection)
, m_fd(fd)
, m_timestamp(timestamp)
{
}
void Transfer::createSocketNotifier(QSocketNotifier::Type type)
{
delete m_sn;
m_sn = new QSocketNotifier(m_fd, type, this);
delete m_notifier;
m_notifier = new QSocketNotifier(m_fd, type, this);
}
void Transfer::clearSocketNotifier()
{
delete m_sn;
m_sn = nullptr;
delete m_notifier;
m_notifier = nullptr;
}
void Transfer::timeout()
@ -97,8 +98,8 @@ void Transfer::closeFd()
TransferWltoX::TransferWltoX(xcb_atom_t selection, xcb_selection_request_event_t *request,
qint32 fd, QObject *parent)
: Transfer(selection, fd, 0, parent),
m_request(request)
: Transfer(selection, fd, 0, parent)
, m_request(request)
{
}
@ -121,7 +122,7 @@ void TransferWltoX::startTransferFromSource()
int TransferWltoX::flushSourceData()
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_change_property(xcbConn,
XCB_PROP_MODE_REPLACE,
@ -129,22 +130,22 @@ int TransferWltoX::flushSourceData()
m_request->property,
m_request->target,
8,
chunks.first().first.size(),
chunks.first().first.data());
m_chunks.first().first.size(),
m_chunks.first().first.data());
xcb_flush(xcbConn);
propertyIsSet = true;
m_propertyIsSet = true;
resetTimeout();
const auto rm = chunks.takeFirst();
const auto rm = m_chunks.takeFirst();
return rm.first.size();
}
void TransferWltoX::startIncr()
{
Q_ASSERT(chunks.size() == 1);
Q_ASSERT(m_chunks.size() == 1);
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
uint32_t mask[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
xcb_change_window_attributes (xcbConn,
@ -164,27 +165,27 @@ void TransferWltoX::startIncr()
setIncr(true);
// first data will be flushed after the property has been deleted
// again by the requestor
flushPropOnDelete = true;
propertyIsSet = true;
Q_EMIT selNotify(m_request, true);
m_flushPropertyOnDelete = true;
m_propertyIsSet = true;
Q_EMIT selectionNotify(m_request, true);
}
void TransferWltoX::readWlSource()
{
if (chunks.size() == 0 ||
chunks.last().second == s_incrChunkSize) {
if (m_chunks.size() == 0 ||
m_chunks.last().second == s_incrChunkSize) {
// append new chunk
auto next = QPair<QByteArray, int>();
next.first.resize(s_incrChunkSize);
next.second = 0;
chunks.append(next);
m_chunks.append(next);
}
const auto oldLen = chunks.last().second;
const auto avail = s_incrChunkSize - chunks.last().second;
const auto oldLen = m_chunks.last().second;
const auto avail = s_incrChunkSize - m_chunks.last().second;
Q_ASSERT(avail > 0);
ssize_t readLen = read(fd(), chunks.last().first.data() + oldLen, avail);
ssize_t readLen = read(fd(), m_chunks.last().first.data() + oldLen, avail);
if (readLen == -1) {
qCWarning(KWIN_XWL) << "Error reading in Wl data.";
@ -192,16 +193,16 @@ void TransferWltoX::readWlSource()
endTransfer();
return;
}
chunks.last().second = oldLen + readLen;
m_chunks.last().second = oldLen + readLen;
if (readLen == 0) {
// at the fd end - complete transfer now
chunks.last().first.resize(chunks.last().second);
m_chunks.last().first.resize(m_chunks.last().second);
if (incr()) {
// incremental transfer is to be completed now
flushPropOnDelete = true;
if (!propertyIsSet) {
m_flushPropertyOnDelete = true;
if (!m_propertyIsSet) {
// flush if target's property is not set at the moment
flushSourceData();
}
@ -210,14 +211,14 @@ void TransferWltoX::readWlSource()
// non incremental transfer is to be completed now,
// data can be transferred to X client via a single property set
flushSourceData();
Q_EMIT selNotify(m_request, true);
Q_EMIT selectionNotify(m_request, true);
endTransfer();
}
} else if (chunks.last().second == s_incrChunkSize) {
} else if (m_chunks.last().second == s_incrChunkSize) {
// first chunk full, but not yet at fd end -> go incremental
if (incr()) {
flushPropOnDelete = true;
if (!propertyIsSet) {
m_flushPropertyOnDelete = true;
if (!m_propertyIsSet) {
// flush if target's property is not set at the moment
flushSourceData();
}
@ -229,30 +230,30 @@ void TransferWltoX::readWlSource()
resetTimeout();
}
bool TransferWltoX::handlePropNotify(xcb_property_notify_event_t *event)
bool TransferWltoX::handlePropertyNotify(xcb_property_notify_event_t *event)
{
if (event->window == m_request->requestor) {
if (event->state == XCB_PROPERTY_DELETE &&
event->atom == m_request->property) {
handlePropDelete();
handlePropertyDelete();
}
return true;
}
return false;
}
void TransferWltoX::handlePropDelete()
void TransferWltoX::handlePropertyDelete()
{
if (!incr()) {
// non-incremental transfer: nothing to do
return;
}
propertyIsSet = false;
m_propertyIsSet = false;
if (flushPropOnDelete) {
if (!socketNotifier() && chunks.isEmpty()) {
if (m_flushPropertyOnDelete) {
if (!socketNotifier() && m_chunks.isEmpty()) {
// transfer complete
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
uint32_t mask[] = {0};
xcb_change_window_attributes (xcbConn,
@ -266,7 +267,7 @@ void TransferWltoX::handlePropDelete()
m_request->target,
8, 0, NULL);
xcb_flush(xcbConn);
flushPropOnDelete = false;
m_flushPropertyOnDelete = false;
endTransfer();
} else {
flushSourceData();
@ -280,7 +281,7 @@ TransferXtoWl::TransferXtoWl(xcb_atom_t selection, xcb_atom_t target, qint32 fd,
: Transfer(selection, fd, timestamp, parent)
{
// create transfer window
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
m_window = xcb_generate_id(xcbConn);
const uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
XCB_EVENT_MASK_PROPERTY_CHANGE };
@ -307,7 +308,7 @@ TransferXtoWl::TransferXtoWl(xcb_atom_t selection, xcb_atom_t target, qint32 fd,
TransferXtoWl::~TransferXtoWl()
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_destroy_window(xcbConn, m_window);
xcb_flush(xcbConn);
@ -315,7 +316,7 @@ TransferXtoWl::~TransferXtoWl()
m_receiver = nullptr;
}
bool TransferXtoWl::handlePropNotify(xcb_property_notify_event_t *event)
bool TransferXtoWl::handlePropertyNotify(xcb_property_notify_event_t *event)
{
if (event->window == m_window) {
if (event->state == XCB_PROPERTY_NEW_VALUE &&
@ -327,7 +328,7 @@ bool TransferXtoWl::handlePropNotify(xcb_property_notify_event_t *event)
return false;
}
bool TransferXtoWl::handleSelNotify(xcb_selection_notify_event_t *event)
bool TransferXtoWl::handleSelectionNotify(xcb_selection_notify_event_t *event)
{
if (event->requestor != m_window) {
return false;
@ -364,7 +365,7 @@ bool TransferXtoWl::handleSelNotify(xcb_selection_notify_event_t *event)
void TransferXtoWl::startTransfer()
{
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
auto cookie = xcb_get_property(xcbConn,
1,
m_window,
@ -402,7 +403,7 @@ void TransferXtoWl::getIncrChunk()
// receive mechanism has not yet been setup
return;
}
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
auto cookie = xcb_get_property(xcbConn,
0,
@ -412,8 +413,8 @@ void TransferXtoWl::getIncrChunk()
0,
0x1fffffff);
auto *reply = xcb_get_property_reply(xcbConn, cookie, NULL);
if (reply == NULL) {
auto *reply = xcb_get_property_reply(xcbConn, cookie, nullptr);
if (!reply) {
qCWarning(KWIN_XWL) << "Can't get selection property.";
endTransfer();
return;
@ -443,11 +444,11 @@ void DataReceiver::transferFromProperty(xcb_get_property_reply_t *reply)
m_propertyStart = 0;
m_propertyReply = reply;
setData(static_cast<char*>(xcb_get_property_value(reply)),
setData(static_cast<char *>(xcb_get_property_value(reply)),
xcb_get_property_value_length(reply));
}
void DataReceiver::setData(char *value, int length)
void DataReceiver::setData(const char *value, int length)
{
// simply set data without copy
m_data = QByteArray::fromRawData(value, length);
@ -469,7 +470,7 @@ void DataReceiver::partRead(int length)
}
}
void NetscapeUrlReceiver::setData(char *value, int length)
void NetscapeUrlReceiver::setData(const char *value, int length)
{
auto origData = QByteArray::fromRawData(value, length);
@ -507,14 +508,14 @@ void NetscapeUrlReceiver::setData(char *value, int length)
setDataInternal(data);
}
void MozUrlReceiver::setData(char *value, int length)
void MozUrlReceiver::setData(const char *value, int length)
{
// represent as QByteArray (guaranteed '\0'-terminated)
const auto origData = QByteArray::fromRawData(value, length);
// text/x-moz-url data is sent in utf-16 - copies the content
// and converts it into 8 byte representation
const auto byteData = QString::fromUtf16(reinterpret_cast<const char16_t*>(origData.data())).toLatin1();
const auto byteData = QString::fromUtf16(reinterpret_cast<const char16_t *>(origData.data())).toLatin1();
if (byteData.indexOf('\n') == -1) {
// there are no line breaks, not in text/x-moz-url format or empty,
@ -566,7 +567,7 @@ void TransferXtoWl::dataSourceWrite()
// property completely transferred
if (incr()) {
clearSocketNotifier();
auto *xcbConn = kwinApp()->x11Connection();
xcb_connection_t *xcbConn = kwinApp()->x11Connection();
xcb_delete_property(xcbConn,
m_window,
atoms->wl_selection);
@ -579,15 +580,15 @@ void TransferXtoWl::dataSourceWrite()
if (!socketNotifier()) {
createSocketNotifier(QSocketNotifier::Write);
connect(socketNotifier(), &QSocketNotifier::activated, this,
[this](int socket) {
Q_UNUSED(socket);
dataSourceWrite();
}
[this](int socket) {
Q_UNUSED(socket);
dataSourceWrite();
}
);
}
}
resetTimeout();
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -26,12 +26,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <xcb/xcb.h>
namespace KWayland {
namespace Client {
namespace KWayland
{
namespace Client
{
class DataDevice;
class DataSource;
}
namespace Server {
namespace Server
{
class DataDeviceInterface;
}
}
@ -48,17 +51,18 @@ namespace Xwl
* Lives for the duration of the transfer and must be cleaned up
* externally afterwards. For that the owner should connect to the
* @c finished() signal.
*/
**/
class Transfer : public QObject
{
Q_OBJECT
public:
Transfer(xcb_atom_t selection,
qint32 fd,
xcb_timestamp_t timestamp,
QObject *parent = nullptr);
virtual bool handlePropNotify(xcb_property_notify_event_t *event) = 0;
virtual bool handlePropertyNotify(xcb_property_notify_event_t *event) = 0;
void timeout();
xcb_timestamp_t timestamp() const {
return m_timestamp;
@ -88,8 +92,8 @@ protected:
}
void createSocketNotifier(QSocketNotifier::Type type);
void clearSocketNotifier();
QSocketNotifier* socketNotifier() const {
return m_sn;
QSocketNotifier *socketNotifier() const {
return m_notifier;
}
private:
void closeFd();
@ -98,17 +102,20 @@ private:
qint32 m_fd;
xcb_timestamp_t m_timestamp = XCB_CURRENT_TIME;
QSocketNotifier *m_sn = nullptr;
QSocketNotifier *m_notifier = nullptr;
bool m_incr = false;
bool m_timeout = false;
Q_DISABLE_COPY(Transfer)
};
/**
* Represents a transfer from a Wayland native source to an X window.
*/
**/
class TransferWltoX : public Transfer
{
Q_OBJECT
public:
TransferWltoX(xcb_atom_t selection,
xcb_selection_request_event_t *request,
@ -117,31 +124,33 @@ public:
~TransferWltoX();
void startTransferFromSource();
bool handlePropNotify(xcb_property_notify_event_t *event) override;
bool handlePropertyNotify(xcb_property_notify_event_t *event) override;
Q_SIGNALS:
void selNotify(xcb_selection_request_event_t *event, bool success);
void selectionNotify(xcb_selection_request_event_t *event, bool success);
private:
void startIncr();
void readWlSource();
int flushSourceData();
void handlePropDelete();
void handlePropertyDelete();
xcb_selection_request_event_t *m_request = nullptr;
/* contains all received data portioned in chunks
* TODO: explain second QPair component
*/
QVector<QPair<QByteArray, int> > chunks;
QVector<QPair<QByteArray, int> > m_chunks;
bool propertyIsSet = false;
bool flushPropOnDelete = false;
bool m_propertyIsSet = false;
bool m_flushPropertyOnDelete = false;
Q_DISABLE_COPY(TransferWltoX)
};
/**
* Helper class for X to Wl transfers
*/
* Helper class for X to Wl transfers.
**/
class DataReceiver
{
public:
@ -150,7 +159,7 @@ public:
void transferFromProperty(xcb_get_property_reply_t *reply);
virtual void setData(char *value, int length);
virtual void setData(const char *value, int length);
QByteArray data() const;
void partRead(int length);
@ -169,29 +178,30 @@ private:
/**
* Compatibility receiver for clients only
* supporting the NETSCAPE_URL scheme (Firefox)
*/
**/
class NetscapeUrlReceiver : public DataReceiver
{
public:
void setData(char *value, int length) override;
void setData(const char *value, int length) override;
};
/**
* Compatibility receiver for clients only
* supporting the text/x-moz-url scheme (Chromium on own drags)
*/
**/
class MozUrlReceiver : public DataReceiver
{
public:
void setData(char *value, int length) override;
void setData(const char *value, int length) override;
};
/**
* Represents a transfer from an X window to a Wayland native client.
*/
**/
class TransferXtoWl : public Transfer
{
Q_OBJECT
public:
TransferXtoWl(xcb_atom_t selection,
xcb_atom_t target,
@ -200,8 +210,8 @@ public:
QObject *parent = nullptr);
~TransferXtoWl();
bool handleSelNotify(xcb_selection_notify_event_t *event);
bool handlePropNotify(xcb_property_notify_event_t *event) override;
bool handleSelectionNotify(xcb_selection_notify_event_t *event);
bool handlePropertyNotify(xcb_property_notify_event_t *event) override;
private:
void dataSourceWrite();
@ -210,9 +220,11 @@ private:
xcb_window_t m_window;
DataReceiver *m_receiver = nullptr;
Q_DISABLE_COPY(TransferXtoWl)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -21,22 +21,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "xwayland.h"
#include "databridge.h"
#include "wayland_server.h"
#include "main_wayland.h"
#include "utils.h"
#include "wayland_server.h"
#include "xcbutils.h"
#include <KLocalizedString>
#include <KSelectionOwner>
#include "xcbutils.h"
#include <QAbstractEventDispatcher>
#include <QtConcurrentRun>
#include <QFile>
#include <QFutureWatcher>
#include <QProcess>
#include <QSocketNotifier>
#include <QThread>
#include <QtConcurrentRun>
// system
#ifdef HAVE_UNISTD_H
@ -68,19 +67,21 @@ static void readDisplay(int pipe)
close(pipe);
}
namespace KWin {
namespace KWin
{
namespace Xwl
{
Xwayland *s_self = nullptr;
Xwayland* Xwayland::self()
Xwayland *Xwayland::self()
{
return s_self;
}
Xwayland::Xwayland(ApplicationWaylandAbstract *app, QObject *parent)
: XwaylandInterface(parent),
m_app(app)
: XwaylandInterface(parent)
, m_app(app)
{
s_self = this;
}
@ -211,7 +212,7 @@ void Xwayland::createX11Connection()
void Xwayland::continueStartupWithX()
{
createX11Connection();
auto *xcbConn = m_app->x11Connection();
xcb_connection_t *xcbConn = m_app->x11Connection();
if (!xcbConn) {
// about to quit
Q_EMIT criticalError(1);
@ -268,7 +269,7 @@ void Xwayland::continueStartupWithX()
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
}
DragEventReply Xwayland::dragMoveFilter(Toplevel *target, QPoint pos)
DragEventReply Xwayland::dragMoveFilter(Toplevel *target, const QPoint &pos)
{
if (!m_dataBridge) {
return DragEventReply::Wayland;
@ -276,5 +277,5 @@ DragEventReply Xwayland::dragMoveFilter(Toplevel *target, QPoint pos)
return m_dataBridge->dragMoveFilter(target, pos);
}
}
}
} // namespace Xwl
} // namespace KWin

View File

@ -39,11 +39,12 @@ class DataBridge;
class Xwayland : public XwaylandInterface
{
Q_OBJECT
public:
static Xwayland* self();
static Xwayland *self();
Xwayland(ApplicationWaylandAbstract *app, QObject *parent = nullptr);
virtual ~Xwayland();
~Xwayland() override;
void init();
void prepareDestroy();
@ -63,7 +64,7 @@ private:
void createX11Connection();
void continueStartupWithX();
DragEventReply dragMoveFilter(Toplevel *target, QPoint pos) override;
DragEventReply dragMoveFilter(Toplevel *target, const QPoint &pos) override;
int m_xcbConnectionFd = -1;
QProcess *m_xwaylandProcess = nullptr;
@ -74,9 +75,11 @@ private:
DataBridge *m_dataBridge = nullptr;
ApplicationWaylandAbstract *m_app;
Q_DISABLE_COPY(Xwayland)
};
}
}
} // namespace Xwl
} // namespace KWin
#endif

View File

@ -40,4 +40,4 @@ XwaylandInterface::~XwaylandInterface()
s_self = nullptr;
}
}
} // namespace KWin

View File

@ -39,25 +39,30 @@ enum class DragEventReply {
// event should be handled as a Wayland native one
Wayland,
};
}
} // namespace Xwl
class KWIN_EXPORT XwaylandInterface : public QObject
{
Q_OBJECT
public:
static XwaylandInterface *self();
virtual Xwl::DragEventReply dragMoveFilter(Toplevel *target, QPoint pos) = 0;
virtual Xwl::DragEventReply dragMoveFilter(Toplevel *target, const QPoint &pos) = 0;
protected:
explicit XwaylandInterface(QObject *parent = nullptr);
virtual ~XwaylandInterface();
private:
Q_DISABLE_COPY(XwaylandInterface)
};
inline XwaylandInterface *xwayland() {
inline XwaylandInterface *xwayland()
{
return XwaylandInterface::self();
}
}
} // namespace KWin
#endif