fix: 任务栏拖拽无法移除驻留

wayland回合主线master分支,原始提交: https://gerrit.uniontech.com/c/dde-dock/+/9595

Log: 社区版适配wayland
Influence: wayland适配
Task: https://pms.uniontech.com/zentao/task-view-81916.html
Change-Id: I2cc33e38951a284a826800fdd2d56bc1c71298ae
This commit is contained in:
范朋程 2021-11-05 21:23:22 +08:00
parent 7710cd8e76
commit dee837e8dd
4 changed files with 169 additions and 14 deletions

View File

@ -37,6 +37,7 @@ AppDragWidget::AppDragWidget(QWidget *parent)
, m_removeTips(new TipsWidget(this))
, m_popupWindow(new DockPopupWindow(nullptr))
, m_distanceMultiple(Utils::SettingValue("com.deepin.dde.dock.distancemultiple", "/com/deepin/dde/dock/distancemultiple/", "distance-multiple", 1.5).toDouble())
, m_item(nullptr)
{
m_removeTips->setText(tr("Remove"));
m_removeTips->setObjectName("AppRemoveTips");
@ -56,6 +57,10 @@ AppDragWidget::AppDragWidget(QWidget *parent)
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
setAttribute(Qt::WA_TranslucentBackground);
if (Utils::IS_WAYLAND_DISPLAY) {
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Window);
setAttribute(Qt::WA_NativeWindow);
}
viewport()->setAutoFillBackground(false);
setFrameShape(QFrame::NoFrame);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -65,8 +70,8 @@ AppDragWidget::AppDragWidget(QWidget *parent)
setAcceptDrops(true);
initAnimations();
m_followMouseTimer->setSingleShot(false);
m_followMouseTimer->setSingleShot(Utils::IS_WAYLAND_DISPLAY);
m_followMouseTimer->setInterval(1);
connect(m_followMouseTimer, &QTimer::timeout, this, &AppDragWidget::onFollowMouse);
m_followMouseTimer->start();
@ -160,7 +165,7 @@ void AppDragWidget::dropEvent(QDropEvent *event)
} else {
hide();
}
AppItem *appItem = static_cast<AppItem *>(event->source());
AppItem *appItem = static_cast<AppItem *>((Utils::IS_WAYLAND_DISPLAY && m_item) ? m_item : event->source());
appItem->undock();
m_popupWindow->setVisible(false);
} else {
@ -175,6 +180,8 @@ void AppDragWidget::dropEvent(QDropEvent *event)
void AppDragWidget::hideEvent(QHideEvent *event)
{
deleteLater();
if (Utils::IS_WAYLAND_DISPLAY)
QGraphicsView::hideEvent(event);
}
void AppDragWidget::setAppPixmap(const QPixmap &pix)
@ -202,6 +209,47 @@ void AppDragWidget::setOriginPos(const QPoint position)
m_originPoint = position;
}
void AppDragWidget::setPixmapOpacity(qreal opacity)
{
if (isRemoveAble(QCursor::pos())) {
m_object->setOpacity(opacity);
m_animOpacity->setStartValue(opacity);
} else {
m_object->setOpacity(1.0);
m_animOpacity->setStartValue(1.0);
}
}
bool AppDragWidget::isRemoveable(const Position &dockPos, const QRect &doctRect)
{
const QPoint &p = QCursor::pos();
switch (dockPos) {
case Dock::Position::Left:
if ((p.x() - doctRect.topRight().x()) > (doctRect.width() * 3)) {
return true;
}
break;
case Dock::Position::Top:
if ((p.y() - doctRect.bottomLeft().y()) > (doctRect.height() * 3)) {
return true;
}
break;
case Dock::Position::Right:
if ((doctRect.topLeft().x() - p.x()) > (doctRect.width() * 3)) {
return true;
}
break;
case Dock::Position::Bottom:
if ((doctRect.topLeft().y() - p.y()) > (doctRect.height() * 3)) {
return true;
}
break;
default:
break;
}
return false;
}
void AppDragWidget::initAnimations()
{
m_animScale->setDuration(300);

View File

@ -36,6 +36,7 @@
#include "../widgets/tipswidget.h"
#include "dockpopupwindow.h"
#include "dockitem.h"
class AppGraphicsObject : public QGraphicsObject
{
@ -86,7 +87,12 @@ public:
void setAppPixmap(const QPixmap &pix);
void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry);
void setOriginPos(const QPoint position);
void setPixmapOpacity(qreal opacity);
bool isRemoveAble(const QPoint &curPos);
void setItem(DockItem *item) { m_item = item; }
static bool isRemoveable(const Dock::Position &dockPos, const QRect &doctRect);
void showRemoveAnimation();
void showGoBackAnimation();
signals:
void requestRemoveItem();
@ -102,8 +108,6 @@ protected:
private:
void initAnimations();
void showRemoveAnimation();
void showGoBackAnimation();
void onRemoveAnimationStateChanged(QAbstractAnimation::State newState,
QAbstractAnimation::State oldState);
const QPoint popupMarkPoint(Dock::Position pos);
@ -137,6 +141,7 @@ private:
double m_distanceMultiple;
bool m_bDragDrop = false; // 图标是否被拖拽
DockItem *m_item;
};
#endif /* APPDRAGWIDGET_H */

View File

@ -39,6 +39,15 @@
#include <QPointer>
#include <QBoxLayout>
#include <QLabel>
#include <QPixmap>
#include <QtConcurrent/QtConcurrentRun>
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformintegration.h>
#define protected public
#include <QtGui/private/qsimpledrag_p.h>
#undef protected
#include <QtGui/private/qshapedpixmapdndwindow_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <DGuiApplicationHelper>
#include <DWindowManagerHelper>
@ -540,15 +549,16 @@ void MainPanelControl::handleDragMove(QDragMoveEvent *e, bool isFilter)
DockItem *targetItem = nullptr;
if (isFilter) {
// appItem调整顺序或者移除驻留
targetItem = dropTargetItem(sourceItem, mapFromGlobal(m_appDragWidget->mapToGlobal(e->pos())));
if (!Utils::IS_WAYLAND_DISPLAY) {
// appItem调整顺序或者移除驻留
targetItem = dropTargetItem(sourceItem, mapFromGlobal(m_appDragWidget->mapToGlobal(e->pos())));
if (targetItem) {
m_appDragWidget->setOriginPos((m_appAreaSonWidget->mapToGlobal(targetItem->pos())));
} else {
targetItem = sourceItem;
if (targetItem) {
m_appDragWidget->setOriginPos((m_appAreaSonWidget->mapToGlobal(targetItem->pos())));
} else {
targetItem = sourceItem;
}
}
} else {
// other dockItem调整顺序
targetItem = dropTargetItem(sourceItem, e->pos());
@ -578,6 +588,9 @@ void MainPanelControl::dragMoveEvent(QDragMoveEvent *e)
return;
}
if (Utils::IS_WAYLAND_DISPLAY)
return;
// 拖app到dock上
const char *RequestDockKey = "RequestDock";
const char *RequestDockKeyFallback = "text/plain";
@ -653,7 +666,7 @@ bool MainPanelControl::eventFilter(QObject *watched, QEvent *event)
moveAppSonWidget();
}
if (m_appDragWidget && watched == static_cast<QGraphicsView *>(m_appDragWidget)->viewport()) {
if (Utils::IS_WAYLAND_DISPLAY && m_appDragWidget && watched == static_cast<QGraphicsView *>(m_appDragWidget)->viewport()) {
bool isContains = rect().contains(mapFromGlobal(QCursor::pos()));
if (isContains) {
if (event->type() == QEvent::DragMove) {
@ -693,7 +706,7 @@ bool MainPanelControl::eventFilter(QObject *watched, QEvent *event)
static const QGSettings *g_settings = Utils::ModuleSettingsPtr("app");
if (!g_settings || !g_settings->keys().contains("removeable") || g_settings->get("removeable").toBool())
startDrag(item);
Utils::IS_WAYLAND_DISPLAY ? startDragWayland(item) : startDrag(item);
return QWidget::eventFilter(watched, event);
}
@ -783,6 +796,94 @@ void MainPanelControl::startDrag(DockItem *dockItem)
}
}
void MainPanelControl::startDragWayland(DockItem *item)
{
QPixmap pixmap = item->grab();
/*TODO: pixmap半透明处理
QPixmap pixmap1;
{
QPixmap temp(pixmap.size());
temp.fill(Qt::transparent);
QPainter p1(&temp);
p1.setCompositionMode(QPainter::CompositionMode_Source);
p1.drawPixmap(0, 0, pixmap);
p1.setCompositionMode(QPainter::CompositionMode_DestinationIn);
//根据QColor中第四个参数设置透明度0255
p1.fillRect(temp.rect(), QColor(0, 0, 0, 125));
p1.end();
pixmap1 = temp;
}*/
item->setDraging(true);
item->update();
QDrag *drag = new QDrag(item);
drag->setPixmap(pixmap);
drag->setHotSpot(pixmap.rect().center() / pixmap.devicePixelRatioF());
drag->setMimeData(new QMimeData);
/*TODO: 开启线程,在移动中设置图片是否为半透明, 当前接口调用QShapedPixmapWindow找不到动态库的实现
bool isRun = true;
QtConcurrent::run([&isRun, &pixmap, &pixmap1, this]{
while (isRun) {
QPlatformDrag *platformDrag = QGuiApplicationPrivate::platformIntegration()->drag();
QShapedPixmapWindow *dragIconWindow = nullptr;
if (platformDrag)
dragIconWindow = static_cast<QSimpleDrag *>(platformDrag)->shapedPixmapWindow();
if (!dragIconWindow)
continue;
if (AppDragWidget::isRemoveable(m_position, QRect(mapToGlobal(pos()), size()))) {
// dragIconWindow->setPixmap(pixmap1);
} else {
// dragIconWindow->setPixmap(pixmap);
}
}
});*/
drag->exec(Qt::MoveAction);
//isRun = false;
if (drag->target() == this) {
item->setDraging(false);
item->update();
return;
}
//开启动画效果
auto appDragWidget = new AppDragWidget();
appDragWidget->setAppPixmap(pixmap);
appDragWidget->setItem(item);
appDragWidget->setDockInfo(m_position, QRect(mapToGlobal(pos()), size()));
appDragWidget->setOriginPos(m_appAreaSonWidget->mapToGlobal(item->pos()));
appDragWidget->setPixmapOpacity(0.5);
appDragWidget->show();
QGuiApplication::platformNativeInterface()->setWindowProperty(appDragWidget->windowHandle()->handle(),
"_d_dwayland_window-type" , "menu");
QTimer::singleShot(10, [item, appDragWidget]{
if (appDragWidget->isRemoveAble(QCursor::pos())) {
appDragWidget->showRemoveAnimation();
AppItem *appItem = static_cast<AppItem *>(item);
appItem->undock();
item->setDraging(false);
item->update();
} else {
appDragWidget->showGoBackAnimation();
item->setDraging(false);
item->update();
}
});
}
DockItem *MainPanelControl::dropTargetItem(DockItem *sourceItem, QPoint point)
{
QWidget *parentWidget = m_appAreaSonWidget;

View File

@ -77,6 +77,7 @@ private:
// 拖拽相关
void startDrag(DockItem *);
void startDragWayland(DockItem *item);
DockItem *dropTargetItem(DockItem *sourceItem, QPoint point);
void moveItem(DockItem *sourceItem, DockItem *targetItem);
void handleDragMove(QDragMoveEvent *e, bool isFilter);