server side drag icons

This commit is contained in:
David Edmundson 2024-07-16 16:32:42 +01:00
parent f8d8589ce7
commit 0726ae6cfa
6 changed files with 49 additions and 6 deletions

View file

@ -22,6 +22,7 @@
#include "mousebuttons.h"
#include "osd.h"
#include "screenedge.h"
#include "wayland/abstract_data_source.h"
#include "wayland/display.h"
#include "wayland/pointer.h"
#include "wayland/pointerconstraints_v1.h"
@ -964,6 +965,7 @@ CursorImage::CursorImage(PointerInputRedirection *parent)
m_decoration.cursor = std::make_unique<ShapeCursorSource>();
m_serverCursor.surface = std::make_unique<SurfaceCursorSource>();
m_serverCursor.shape = std::make_unique<ShapeCursorSource>();
m_dragCursor = std::make_unique<ShapeCursorSource>();
#if KWIN_BUILD_SCREENLOCKER
if (kwinApp()->supportsLockScreen()) {
@ -988,6 +990,7 @@ CursorImage::CursorImage(PointerInputRedirection *parent)
m_windowSelectionCursor->setTheme(m_waylandImage.theme());
m_decoration.cursor->setTheme(m_waylandImage.theme());
m_serverCursor.shape->setTheme(m_waylandImage.theme());
m_dragCursor->setTheme(m_waylandImage.theme());
connect(&m_waylandImage, &WaylandCursorImage::themeChanged, this, [this] {
m_effectsCursor->setTheme(m_waylandImage.theme());
@ -996,6 +999,14 @@ CursorImage::CursorImage(PointerInputRedirection *parent)
m_windowSelectionCursor->setTheme(m_waylandImage.theme());
m_decoration.cursor->setTheme(m_waylandImage.theme());
m_serverCursor.shape->setTheme(m_waylandImage.theme());
m_dragCursor->setTheme(m_waylandImage.theme());
});
connect(waylandServer()->seat(), &SeatInterface::dragStarted, this, [this]() {
m_dragCursor->setShape(Qt::ForbiddenCursor);
connect(waylandServer()->seat()->dragSource(), &AbstractDataSource::dndActionChanged, this, &CursorImage::updateDragCursor);
connect(waylandServer()->seat()->dragSource(), &AbstractDataSource::acceptedChanged, this, &CursorImage::updateDragCursor);
reevaluteSource();
});
PointerInterface *pointer = waylandServer()->seat()->pointer();
@ -1064,6 +1075,32 @@ void CursorImage::updateMoveResize()
reevaluteSource();
}
void CursorImage::updateDragCursor()
{
AbstractDataSource *dragSource = waylandServer()->seat()->dragSource();
if (dragSource && dragSource->isAccepted()) {
switch (dragSource->selectedDndAction()) {
case DataDeviceManagerInterface::DnDAction::None:
m_dragCursor->setShape(Qt::ClosedHandCursor);
break;
case DataDeviceManagerInterface::DnDAction::Copy:
m_dragCursor->setShape(Qt::DragCopyCursor);
break;
case DataDeviceManagerInterface::DnDAction::Move:
m_dragCursor->setShape(Qt::DragMoveCursor);
break;
case DataDeviceManagerInterface::DnDAction::Ask:
// Cursor themes don't have anything better in the themes yet
// a dnd-drag-ask is proposed
m_dragCursor->setShape(Qt::ClosedHandCursor);
break;
}
} else {
m_dragCursor->setShape(Qt::ForbiddenCursor);
}
reevaluteSource();
}
void CursorImage::updateServerCursor(const PointerCursor &cursor)
{
if (auto surfaceCursor = std::get_if<PointerSurfaceCursor *>(&cursor)) {
@ -1153,6 +1190,10 @@ void CursorImage::reevaluteSource()
setSource(m_serverCursor.cursor);
return;
}
if (waylandServer()->seat()->isDrag()) {
setSource(m_dragCursor.get());
return;
}
if (input()->isSelectingWindow()) {
setSource(m_windowSelectionCursor.get());
return;

View file

@ -244,6 +244,7 @@ private:
void updateDecoration();
void updateDecorationCursor();
void updateMoveResize();
void updateDragCursor();
void handleFocusedSurfaceChanged();
@ -255,6 +256,7 @@ private:
std::unique_ptr<ShapeCursorSource> m_fallbackCursor;
std::unique_ptr<ShapeCursorSource> m_moveResizeCursor;
std::unique_ptr<ShapeCursorSource> m_windowSelectionCursor;
std::unique_ptr<ShapeCursorSource> m_dragCursor;
struct
{

View file

@ -110,6 +110,8 @@ Q_SIGNALS:
void mimeTypeOffered(const QString &);
void supportedDragAndDropActionsChanged();
void keyboardModifiersChanged();
void dndActionChanged();
void acceptedChanged();
protected:
explicit AbstractDataSource(QObject *parent = nullptr);

View file

@ -91,6 +91,7 @@ void DataSourceInterface::accept(const QString &mimeType)
{
d->send_target(mimeType);
d->isAccepted = !mimeType.isNull();
Q_EMIT acceptedChanged();
}
void DataSourceInterface::requestData(const QString &mimeType, qint32 fd)
@ -148,6 +149,7 @@ void DataSourceInterface::dndFinished()
void DataSourceInterface::dndAction(DataDeviceManagerInterface::DnDAction action)
{
d->selectedDndAction = action;
Q_EMIT dndActionChanged();
if (d->resource()->version() < WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
return;
@ -188,11 +190,6 @@ bool DataSourceInterface::isAccepted() const
return d->isAccepted;
}
void DataSourceInterface::setAccepted(bool accepted)
{
d->isAccepted = accepted;
}
XdgToplevelDragV1Interface *DataSourceInterface::xdgToplevelDrag() const
{
return d->xdgToplevelDrag;

View file

@ -48,7 +48,6 @@ public:
wl_client *client() const override;
bool isAccepted() const override;
void setAccepted(bool accepted);
XdgToplevelDragV1Interface *xdgToplevelDrag() const;

View file

@ -35,6 +35,7 @@ void XwlDataSource::setMimeTypes(const QStringList &mimeTypes)
void XwlDataSource::accept(const QString &mimeType)
{
m_accepted = !mimeType.isEmpty();
Q_EMIT acceptedChanged();
}
DataDeviceManagerInterface::DnDActions XwlDataSource::supportedDragAndDropActions() const
@ -56,6 +57,7 @@ DataDeviceManagerInterface::DnDAction XwlDataSource::selectedDndAction() const
void XwlDataSource::dndAction(DataDeviceManagerInterface::DnDAction action)
{
m_dndAction = action;
Q_EMIT dndActionChanged();
}
bool XwlDataSource::isAccepted() const