mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 09:23:03 +00:00
feat: 拖动任务栏图标实现分屏效果
拖动任务栏图标到屏幕中间,如果在左侧,显示左分屏效果,在右侧,显示右分屏效果 Log: 完成任务栏图标分屏效果的功能 Influence: 从任务栏拖动图标到屏幕上方,查看是否有分屏功能 Task: https://pms.uniontech.com/task-view-163465.html Change-Id: I1a7a33646edb6f55972b8e5fa2c5f39ce026fe8e
This commit is contained in:
parent
f938f66bb5
commit
9c1eb32e24
@ -6,6 +6,11 @@ configure_file(dde-dock.pc.in dde-dock.pc @ONLY)
|
|||||||
|
|
||||||
project(dde-dock)
|
project(dde-dock)
|
||||||
|
|
||||||
|
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||||
|
set(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||||
|
set(CMAKE_USE_PTHREADS_INIT 1)
|
||||||
|
set(CMAKE_PREFER_PTHREAD_FLAG ON)
|
||||||
|
|
||||||
#set(CMAKE_VERBOSE_MAKEFILE ON)
|
#set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
5
debian/control
vendored
5
debian/control
vendored
@ -26,7 +26,10 @@ Build-Depends: debhelper (>= 8.0.0),
|
|||||||
libgtest-dev,
|
libgtest-dev,
|
||||||
libgmock-dev,
|
libgmock-dev,
|
||||||
qttools5-dev,
|
qttools5-dev,
|
||||||
libxcursor-dev
|
libxcursor-dev,
|
||||||
|
libqt5waylandclient5-dev,
|
||||||
|
qtwayland5-private-dev,
|
||||||
|
libdwayland-dev
|
||||||
Standards-Version: 3.9.8
|
Standards-Version: 3.9.8
|
||||||
Homepage: http://www.deepin.org/
|
Homepage: http://www.deepin.org/
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ set(BIN_NAME dde-dock)
|
|||||||
configure_file(environments.h.in environments.h @ONLY)
|
configure_file(environments.h.in environments.h @ONLY)
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address -O2")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address -O0")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -O2")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -O0")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Sources files
|
# Sources files
|
||||||
@ -19,6 +19,8 @@ find_package(Qt5Concurrent REQUIRED)
|
|||||||
find_package(Qt5X11Extras REQUIRED)
|
find_package(Qt5X11Extras REQUIRED)
|
||||||
find_package(Qt5DBus REQUIRED)
|
find_package(Qt5DBus REQUIRED)
|
||||||
find_package(Qt5Svg REQUIRED)
|
find_package(Qt5Svg REQUIRED)
|
||||||
|
find_package(Qt5WaylandClient REQUIRED)
|
||||||
|
find_package(Qt5XkbCommonSupport REQUIRED)
|
||||||
find_package(DtkWidget REQUIRED)
|
find_package(DtkWidget REQUIRED)
|
||||||
find_package(DtkCMake REQUIRED)
|
find_package(DtkCMake REQUIRED)
|
||||||
find_package(dbusmenu-qt5 REQUIRED)
|
find_package(dbusmenu-qt5 REQUIRED)
|
||||||
@ -28,6 +30,9 @@ pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus)
|
|||||||
pkg_check_modules(QGSettings REQUIRED gsettings-qt)
|
pkg_check_modules(QGSettings REQUIRED gsettings-qt)
|
||||||
pkg_check_modules(DtkGUI REQUIRED dtkgui)
|
pkg_check_modules(DtkGUI REQUIRED dtkgui)
|
||||||
|
|
||||||
|
set(Wayland_INCLUDE_DIRS /usr/include/DWayland/Client)
|
||||||
|
set(Wayland_LIBRARIES /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/libDWaylandClient.so)
|
||||||
|
|
||||||
# driver-manager
|
# driver-manager
|
||||||
add_executable(${BIN_NAME}
|
add_executable(${BIN_NAME}
|
||||||
${SRCS}
|
${SRCS}
|
||||||
@ -45,6 +50,10 @@ target_include_directories(${BIN_NAME} PUBLIC
|
|||||||
${DtkGUI_INCLUDE_DIRS}
|
${DtkGUI_INCLUDE_DIRS}
|
||||||
${Qt5Svg_INCLUDE_DIRS}
|
${Qt5Svg_INCLUDE_DIRS}
|
||||||
${dbusmenu-qt5_INCLUDE_DIRS}
|
${dbusmenu-qt5_INCLUDE_DIRS}
|
||||||
|
${Wayland_INCLUDE_DIRS}
|
||||||
|
${Qt5WaylandClient_INCLUDE_DIRS}
|
||||||
|
${Qt5WaylandClient_PRIVATE_INCLUDE_DIRS}
|
||||||
|
${Qt5XkbCommonSupport_PRIVATE_INCLUDE_DIRS}
|
||||||
../interfaces
|
../interfaces
|
||||||
../widgets
|
../widgets
|
||||||
accessible
|
accessible
|
||||||
@ -54,6 +63,7 @@ target_include_directories(${BIN_NAME} PUBLIC
|
|||||||
item
|
item
|
||||||
item/components
|
item/components
|
||||||
model
|
model
|
||||||
|
screenspliter
|
||||||
util
|
util
|
||||||
window
|
window
|
||||||
window/components
|
window/components
|
||||||
@ -82,6 +92,10 @@ target_link_libraries(${BIN_NAME} PRIVATE
|
|||||||
${QGSettings_LIBRARIES}
|
${QGSettings_LIBRARIES}
|
||||||
${DtkGUI_LIBRARIES}
|
${DtkGUI_LIBRARIES}
|
||||||
${Qt5Svg_LIBRARIES}
|
${Qt5Svg_LIBRARIES}
|
||||||
|
${Wayland_LIBRARIES}
|
||||||
|
${Qt5Wayland_LIBRARIES}
|
||||||
|
${Qt5WaylandClient_LIBRARIES}
|
||||||
|
${Qt5XkbCommonSupport_LIBRARIES}
|
||||||
-lpthread -lm
|
-lpthread -lm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ void registerWindowInfoMetaType()
|
|||||||
|
|
||||||
QDebug operator<<(QDebug argument, const WindowInfo &info)
|
QDebug operator<<(QDebug argument, const WindowInfo &info)
|
||||||
{
|
{
|
||||||
argument << '(' << info.title << ',' << info.attention << ')';
|
argument << '(' << info.title << ',' << info.attention << info.uuid << ')';
|
||||||
|
|
||||||
return argument;
|
return argument;
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ QDebug operator<<(QDebug argument, const WindowInfo &info)
|
|||||||
QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info)
|
QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info)
|
||||||
{
|
{
|
||||||
argument.beginStructure();
|
argument.beginStructure();
|
||||||
argument << info.title << info.attention;
|
argument << info.title << info.attention << info.uuid;
|
||||||
argument.endStructure();
|
argument.endStructure();
|
||||||
|
|
||||||
return argument;
|
return argument;
|
||||||
@ -66,7 +66,7 @@ QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info)
|
|||||||
const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info)
|
const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info)
|
||||||
{
|
{
|
||||||
argument.beginStructure();
|
argument.beginStructure();
|
||||||
argument >> info.title >> info.attention;
|
argument >> info.title >> info.attention >> info.uuid;
|
||||||
argument.endStructure();
|
argument.endStructure();
|
||||||
|
|
||||||
return argument;
|
return argument;
|
||||||
@ -74,14 +74,20 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info)
|
|||||||
|
|
||||||
bool WindowInfo::operator==(const WindowInfo &rhs) const
|
bool WindowInfo::operator==(const WindowInfo &rhs) const
|
||||||
{
|
{
|
||||||
return attention == rhs.attention &&
|
return (attention == rhs.attention &&
|
||||||
title == rhs.title;
|
title == rhs.title &&
|
||||||
|
uuid == rhs.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntryPrivate
|
class EntryPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EntryPrivate() = default;
|
EntryPrivate()
|
||||||
|
: CurrentWindow(0)
|
||||||
|
, IsActive(false)
|
||||||
|
, IsDocked(false)
|
||||||
|
, mode(0)
|
||||||
|
{}
|
||||||
|
|
||||||
// begin member variables
|
// begin member variables
|
||||||
uint CurrentWindow;
|
uint CurrentWindow;
|
||||||
|
@ -53,6 +53,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
bool attention;
|
bool attention;
|
||||||
QString title;
|
QString title;
|
||||||
|
QString uuid;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(WindowInfo)
|
Q_DECLARE_METATYPE(WindowInfo)
|
||||||
|
@ -69,6 +69,17 @@ QScreen *DisplayManager::screen(const QString &screenName) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScreen *DisplayManager::screenAt(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
for (QScreen *screen : m_screens) {
|
||||||
|
QRect screenGeometry = screen->geometry();
|
||||||
|
if (screenGeometry.contains(pos))
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief DisplayManager::primary
|
* @brief DisplayManager::primary
|
||||||
* @return 主屏幕名称
|
* @return 主屏幕名称
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
|
|
||||||
QList<QScreen *> screens() const;
|
QList<QScreen *> screens() const;
|
||||||
QScreen *screen(const QString &screenName) const;
|
QScreen *screen(const QString &screenName) const;
|
||||||
|
QScreen *screenAt(const QPoint &pos) const;
|
||||||
QString primary() const;
|
QString primary() const;
|
||||||
int screenRawWidth() const;
|
int screenRawWidth() const;
|
||||||
int screenRawHeight() const;
|
int screenRawHeight() const;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "xcb_misc.h"
|
#include "xcb_misc.h"
|
||||||
#include "appswingeffectbuilder.h"
|
#include "appswingeffectbuilder.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "screenspliter.h"
|
||||||
|
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
@ -70,6 +71,7 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
|
|||||||
, m_refershIconTimer(new QTimer(this))
|
, m_refershIconTimer(new QTimer(this))
|
||||||
, m_themeType(DGuiApplicationHelper::instance()->themeType())
|
, m_themeType(DGuiApplicationHelper::instance()->themeType())
|
||||||
, m_createMSecs(QDateTime::currentMSecsSinceEpoch())
|
, m_createMSecs(QDateTime::currentMSecsSinceEpoch())
|
||||||
|
, m_screenSpliter(ScreenSpliterFactory::createScreenSpliter(this, m_itemEntryInter))
|
||||||
{
|
{
|
||||||
QHBoxLayout *centralLayout = new QHBoxLayout;
|
QHBoxLayout *centralLayout = new QHBoxLayout;
|
||||||
centralLayout->setMargin(0);
|
centralLayout->setMargin(0);
|
||||||
@ -103,7 +105,6 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
|
|||||||
connect(this, &AppItem::requestUpdateEntryGeometries, this, &AppItem::updateWindowIconGeometries);
|
connect(this, &AppItem::requestUpdateEntryGeometries, this, &AppItem::updateWindowIconGeometries);
|
||||||
|
|
||||||
updateWindowInfos(m_itemEntryInter->windowInfos());
|
updateWindowInfos(m_itemEntryInter->windowInfos());
|
||||||
refreshIcon();
|
|
||||||
|
|
||||||
if (m_appSettings)
|
if (m_appSettings)
|
||||||
connect(m_appSettings, &QGSettings::changed, this, &AppItem::onGSettingsChanged);
|
connect(m_appSettings, &QGSettings::changed, this, &AppItem::onGSettingsChanged);
|
||||||
@ -182,6 +183,31 @@ void AppItem::setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppItem::setDraging(bool drag)
|
||||||
|
{
|
||||||
|
if (drag == isDragging())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DockItem::setDraging(drag);
|
||||||
|
if (!drag)
|
||||||
|
m_screenSpliter->releaseSplit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppItem::startSplit(const QRect &rect)
|
||||||
|
{
|
||||||
|
m_screenSpliter->startSplit(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AppItem::supportSplitWindow()
|
||||||
|
{
|
||||||
|
return m_screenSpliter->suportSplitScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AppItem::splitWindowOnScreen(ScreenSpliter::SplitDirection direction)
|
||||||
|
{
|
||||||
|
return m_screenSpliter->split(direction);
|
||||||
|
}
|
||||||
|
|
||||||
QString AppItem::accessibleName()
|
QString AppItem::accessibleName()
|
||||||
{
|
{
|
||||||
return m_itemEntryInter->name();
|
return m_itemEntryInter->name();
|
||||||
@ -636,7 +662,9 @@ void AppItem::refreshIcon()
|
|||||||
update();
|
update();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (m_retryTimes > 0) {
|
}
|
||||||
|
|
||||||
|
if (m_retryTimes > 0) {
|
||||||
// reset times
|
// reset times
|
||||||
m_retryTimes = 0;
|
m_retryTimes = 0;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <DGuiApplicationHelper>
|
#include <DGuiApplicationHelper>
|
||||||
|
|
||||||
class QGSettings;
|
class QGSettings;
|
||||||
|
class ScreenSpliter;
|
||||||
|
|
||||||
class AppItem : public DockItem
|
class AppItem : public DockItem
|
||||||
{
|
{
|
||||||
@ -52,7 +53,14 @@ public:
|
|||||||
void undock();
|
void undock();
|
||||||
QWidget *appDragWidget();
|
QWidget *appDragWidget();
|
||||||
void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry);
|
void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry);
|
||||||
|
void setDraging(bool drag) override;
|
||||||
|
|
||||||
|
void startSplit(const QRect &rect);
|
||||||
|
bool supportSplitWindow();
|
||||||
|
bool splitWindowOnScreen(ScreenSpliter::SplitDirection direction);
|
||||||
|
#ifdef USE_AM
|
||||||
|
int mode() const;
|
||||||
|
#endif
|
||||||
inline ItemType itemType() const override { return App; }
|
inline ItemType itemType() const override { return App; }
|
||||||
QPixmap appIcon(){ return m_appIcon; }
|
QPixmap appIcon(){ return m_appIcon; }
|
||||||
virtual QString accessibleName() override;
|
virtual QString accessibleName() override;
|
||||||
@ -146,6 +154,8 @@ private:
|
|||||||
qint64 m_createMSecs;
|
qint64 m_createMSecs;
|
||||||
|
|
||||||
static QPoint MousePressPos;
|
static QPoint MousePressPos;
|
||||||
|
|
||||||
|
ScreenSpliter *m_screenSpliter;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPITEM_H
|
#endif // APPITEM_H
|
||||||
|
@ -22,6 +22,15 @@
|
|||||||
#include "../appitem.h"
|
#include "../appitem.h"
|
||||||
#include "appdragwidget.h"
|
#include "appdragwidget.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "displaymanager.h"
|
||||||
|
|
||||||
|
#include <com_deepin_api_xeventmonitor.h>
|
||||||
|
|
||||||
|
#define SPLIT_NONE 0
|
||||||
|
#define SPLIT_LEFT 1
|
||||||
|
#define SPLIT_RIGHT 2
|
||||||
|
|
||||||
|
using XEventMonitor = ::com::deepin::api::XEventMonitor;
|
||||||
|
|
||||||
AppDragWidget::AppDragWidget(QWidget *parent)
|
AppDragWidget::AppDragWidget(QWidget *parent)
|
||||||
: QGraphicsView(parent)
|
: QGraphicsView(parent)
|
||||||
@ -34,16 +43,11 @@ AppDragWidget::AppDragWidget(QWidget *parent)
|
|||||||
, m_animGroup(new QParallelAnimationGroup(this))
|
, m_animGroup(new QParallelAnimationGroup(this))
|
||||||
, m_goBackAnim(new QPropertyAnimation(this, "pos", this))
|
, m_goBackAnim(new QPropertyAnimation(this, "pos", this))
|
||||||
, m_dockPosition(Dock::Position::Bottom)
|
, m_dockPosition(Dock::Position::Bottom)
|
||||||
, m_removeTips(new TipsWidget(this))
|
|
||||||
, m_popupWindow(new DockPopupWindow(nullptr))
|
, 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_distanceMultiple(Utils::SettingValue("com.deepin.dde.dock.distancemultiple", "/com/deepin/dde/dock/distancemultiple/", "distance-multiple", 1.5).toDouble())
|
||||||
, m_item(nullptr)
|
, m_item(nullptr)
|
||||||
|
, m_dockScreen(nullptr)
|
||||||
{
|
{
|
||||||
m_removeTips->setText(tr("Remove"));
|
|
||||||
m_removeTips->setObjectName("AppRemoveTips");
|
|
||||||
m_removeTips->setVisible(false);
|
|
||||||
m_removeTips->installEventFilter(this);
|
|
||||||
|
|
||||||
m_popupWindow->setShadowBlurRadius(20);
|
m_popupWindow->setShadowBlurRadius(20);
|
||||||
m_popupWindow->setRadius(18);
|
m_popupWindow->setRadius(18);
|
||||||
m_popupWindow->setShadowYOffset(2);
|
m_popupWindow->setShadowYOffset(2);
|
||||||
@ -55,11 +59,13 @@ AppDragWidget::AppDragWidget(QWidget *parent)
|
|||||||
m_scene->addItem(m_object.get());
|
m_scene->addItem(m_object.get());
|
||||||
setScene(m_scene);
|
setScene(m_scene);
|
||||||
|
|
||||||
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
setAttribute(Qt::WA_TranslucentBackground);
|
||||||
if (Utils::IS_WAYLAND_DISPLAY) {
|
if (Utils::IS_WAYLAND_DISPLAY) {
|
||||||
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Window);
|
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Window | Qt::FramelessWindowHint);
|
||||||
setAttribute(Qt::WA_NativeWindow);
|
setAttribute(Qt::WA_NativeWindow);
|
||||||
|
initWaylandEnv();
|
||||||
|
} else {
|
||||||
|
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
|
||||||
}
|
}
|
||||||
viewport()->setAutoFillBackground(false);
|
viewport()->setAutoFillBackground(false);
|
||||||
setFrameShape(QFrame::NoFrame);
|
setFrameShape(QFrame::NoFrame);
|
||||||
@ -71,10 +77,20 @@ AppDragWidget::AppDragWidget(QWidget *parent)
|
|||||||
|
|
||||||
initAnimations();
|
initAnimations();
|
||||||
|
|
||||||
m_followMouseTimer->setInterval(16);
|
if (!Utils::IS_WAYLAND_DISPLAY) {
|
||||||
connect(m_followMouseTimer, &QTimer::timeout, this, &AppDragWidget::onFollowMouse);
|
m_followMouseTimer->setInterval(16);
|
||||||
m_followMouseTimer->start();
|
connect(m_followMouseTimer, &QTimer::timeout, this, &AppDragWidget::onFollowMouse);
|
||||||
QTimer::singleShot(0, this, &AppDragWidget::onFollowMouse);
|
m_followMouseTimer->start();
|
||||||
|
QTimer::singleShot(0, this, &AppDragWidget::onFollowMouse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::execFinished()
|
||||||
|
{
|
||||||
|
if (!m_bDragDrop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dropHandler(QCursor::pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppDragWidget::mouseMoveEvent(QMouseEvent *event)
|
void AppDragWidget::mouseMoveEvent(QMouseEvent *event)
|
||||||
@ -95,11 +111,11 @@ void AppDragWidget::dragEnterEvent(QDragEnterEvent *event)
|
|||||||
|
|
||||||
void AppDragWidget::dragMoveEvent(QDragMoveEvent *event)
|
void AppDragWidget::dragMoveEvent(QDragMoveEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
if (Utils::IS_WAYLAND_DISPLAY)
|
||||||
showRemoveTips();
|
return QGraphicsView::dragMoveEvent(event);
|
||||||
if (isRemoveItem() && m_bDragDrop) {
|
|
||||||
emit requestRemoveItem();
|
if (m_bDragDrop)
|
||||||
}
|
moveHandler(QCursor::pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**获取应用的左上角坐标
|
/**获取应用的左上角坐标
|
||||||
@ -156,18 +172,32 @@ const QPoint AppDragWidget::popupMarkPoint(Dock::Position pos)
|
|||||||
|
|
||||||
void AppDragWidget::dropEvent(QDropEvent *event)
|
void AppDragWidget::dropEvent(QDropEvent *event)
|
||||||
{
|
{
|
||||||
|
if (Utils::IS_WAYLAND_DISPLAY)
|
||||||
|
return dropEvent(event);
|
||||||
|
|
||||||
m_followMouseTimer->stop();
|
m_followMouseTimer->stop();
|
||||||
|
dropHandler(QCursor::pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::hideEvent(QHideEvent *event)
|
||||||
|
{
|
||||||
|
deleteLater();
|
||||||
|
if (Utils::IS_WAYLAND_DISPLAY)
|
||||||
|
QGraphicsView::hideEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::dropHandler(const QPoint &pos)
|
||||||
|
{
|
||||||
m_bDragDrop = false;
|
m_bDragDrop = false;
|
||||||
|
|
||||||
if (isRemoveAble(QCursor::pos())) {
|
if (canSplitWindow(pos)) {
|
||||||
if (DWindowManagerHelper::instance()->hasComposite()) {
|
if (DWindowManagerHelper::instance()->hasComposite()) {
|
||||||
showRemoveAnimation();
|
showRemoveAnimation();
|
||||||
} else {
|
} else {
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
AppItem *appItem = static_cast<AppItem *>((Utils::IS_WAYLAND_DISPLAY && m_item) ? m_item : event->source());
|
|
||||||
appItem->undock();
|
|
||||||
m_popupWindow->setVisible(false);
|
m_popupWindow->setVisible(false);
|
||||||
|
Q_EMIT requestSplitWindow(splitPosition());
|
||||||
} else {
|
} else {
|
||||||
if (DWindowManagerHelper::instance()->hasComposite()) {
|
if (DWindowManagerHelper::instance()->hasComposite()) {
|
||||||
showGoBackAnimation();
|
showGoBackAnimation();
|
||||||
@ -177,11 +207,26 @@ void AppDragWidget::dropEvent(QDropEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppDragWidget::hideEvent(QHideEvent *event)
|
void AppDragWidget::moveHandler(const QPoint &pos)
|
||||||
{
|
{
|
||||||
deleteLater();
|
if (canSplitWindow(pos)) {
|
||||||
if (Utils::IS_WAYLAND_DISPLAY)
|
QRect screenGeometry = splitGeometry(pos);
|
||||||
QGraphicsView::hideEvent(event);
|
if (screenGeometry.isValid() && screenGeometry != m_lastMouseGeometry) {
|
||||||
|
qDebug() << "change area:" << screenGeometry;
|
||||||
|
Q_EMIT requestChangedArea(screenGeometry);
|
||||||
|
m_lastMouseGeometry = screenGeometry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::moveCurrent(const QPoint &destPos)
|
||||||
|
{
|
||||||
|
if (DWindowManagerHelper::instance()->hasComposite()) {
|
||||||
|
move(destPos.x() - width() / 2, destPos.y() - height() / 2);
|
||||||
|
} else {
|
||||||
|
// 窗口特效未开启时会隐藏m_object绘制的图标,移动的图标为QDrag绘制的图标
|
||||||
|
move(destPos.x(), destPos.y());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppDragWidget::setAppPixmap(const QPixmap &pix)
|
void AppDragWidget::setAppPixmap(const QPixmap &pix)
|
||||||
@ -211,7 +256,7 @@ void AppDragWidget::setOriginPos(const QPoint position)
|
|||||||
|
|
||||||
void AppDragWidget::setPixmapOpacity(qreal opacity)
|
void AppDragWidget::setPixmapOpacity(qreal opacity)
|
||||||
{
|
{
|
||||||
if (isRemoveAble(QCursor::pos())) {
|
if (canSplitWindow(QCursor::pos())) {
|
||||||
m_object->setOpacity(opacity);
|
m_object->setOpacity(opacity);
|
||||||
m_animOpacity->setStartValue(opacity);
|
m_animOpacity->setStartValue(opacity);
|
||||||
} else {
|
} else {
|
||||||
@ -220,34 +265,6 @@ void AppDragWidget::setPixmapOpacity(qreal opacity)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppDragWidget::initAnimations()
|
void AppDragWidget::initAnimations()
|
||||||
{
|
{
|
||||||
m_animScale->setDuration(300);
|
m_animScale->setDuration(300);
|
||||||
@ -303,79 +320,212 @@ void AppDragWidget::onRemoveAnimationStateChanged(QAbstractAnimation::State newS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**判断图标拖到一定高度(默认任务栏高度的1.5倍)后是否可以移除
|
/** 判断应用区域图标是否被拖出任务栏
|
||||||
* @brief AppDragWidget::isRemoveAble
|
* @brief AppDragWidget::canSplitWindow
|
||||||
* @param curPos 当前鼠标所在位置
|
* @return 返回true应用移出任务栏,false应用在任务栏内
|
||||||
* @return 返回true可移除,false不可移除
|
|
||||||
*/
|
*/
|
||||||
bool AppDragWidget::isRemoveAble(const QPoint &curPos)
|
bool AppDragWidget::canSplitWindow(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
const QPoint &p = curPos;
|
|
||||||
switch (m_dockPosition) {
|
switch (m_dockPosition) {
|
||||||
case Dock::Position::Left:
|
case Dock::Position::Left:
|
||||||
if ((p.x() - m_dockGeometry.topRight().x()) > (m_dockGeometry.width() * m_distanceMultiple)) {
|
if ((pos.x() > m_dockGeometry.topRight().x())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Dock::Position::Top:
|
case Dock::Position::Top:
|
||||||
if ((p.y() - m_dockGeometry.bottomLeft().y()) > (m_dockGeometry.height() * m_distanceMultiple)) {
|
if ((pos.y() > m_dockGeometry.bottomLeft().y())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Dock::Position::Right:
|
case Dock::Position::Right:
|
||||||
if ((m_dockGeometry.topLeft().x() - p.x()) > (m_dockGeometry.width() * m_distanceMultiple)) {
|
if ((m_dockGeometry.topLeft().x() > pos.x())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Dock::Position::Bottom:
|
case Dock::Position::Bottom:
|
||||||
if ((m_dockGeometry.topLeft().y() - p.y()) > (m_dockGeometry.height() * m_distanceMultiple)) {
|
if ((m_dockGeometry.topLeft().y() > pos.y())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**判断应用区域图标是否被拖出任务栏
|
/**
|
||||||
* @brief AppDragWidget::isRemoveItem
|
* @brief AppDragWidget::splitPosition
|
||||||
* @return 返回true应用移出任务栏,false应用在任务栏内
|
* @return 1 左分屏;2 右分屏;5 左上;6 右上;9 左下;10 右下;15全屏。这些值是窗管给的
|
||||||
*/
|
*/
|
||||||
bool AppDragWidget::isRemoveItem()
|
ScreenSpliter::SplitDirection AppDragWidget::splitPosition() const
|
||||||
{
|
{
|
||||||
const QPoint &p = QCursor::pos();
|
QPoint pos = QCursor::pos();
|
||||||
|
QScreen *currentScreen = DisplayManager::instance()->screenAt(pos);
|
||||||
|
|
||||||
|
if (!currentScreen)
|
||||||
|
return ScreenSpliter::None;
|
||||||
|
|
||||||
|
int xCenter = currentScreen->geometry().x() + currentScreen->size().width() / 2;
|
||||||
|
// 1表示左分屏
|
||||||
|
if (pos.x() < xCenter)
|
||||||
|
return ScreenSpliter::Left;
|
||||||
|
|
||||||
|
// 2表示右分屏
|
||||||
|
if (pos.x() > xCenter)
|
||||||
|
return ScreenSpliter::Right;
|
||||||
|
|
||||||
|
return ScreenSpliter::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::adjustDesktopGeometry(QRect &rect) const
|
||||||
|
{
|
||||||
|
QRect rectGeometry = m_dockGeometry;
|
||||||
|
rectGeometry.setWidth(rectGeometry.width() * qApp->devicePixelRatio());
|
||||||
|
rectGeometry.setHeight(rectGeometry.height() * qApp->devicePixelRatio());
|
||||||
switch (m_dockPosition) {
|
switch (m_dockPosition) {
|
||||||
case Dock::Position::Left:
|
case Dock::Position::Left: {
|
||||||
if ((p.x() > m_dockGeometry.topRight().x())) {
|
int leftX = (rectGeometry.x() + rectGeometry.width()) * qApp->devicePixelRatio();
|
||||||
return true;
|
if (rect.x() < leftX) {
|
||||||
}
|
rect.setX(leftX);
|
||||||
break;
|
rect.setWidth(rect.width() - (leftX - rect.x()));
|
||||||
case Dock::Position::Top:
|
|
||||||
if ((p.y() > m_dockGeometry.bottomLeft().y())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Dock::Position::Right:
|
|
||||||
if ((m_dockGeometry.topLeft().x() > p.x())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Dock::Position::Bottom:
|
|
||||||
if ((m_dockGeometry.topLeft().y() > p.y())) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
case Dock::Position::Top: {
|
||||||
|
int topY = (rectGeometry.y() + rectGeometry.height()) * qApp->devicePixelRatio();
|
||||||
|
if (rect.y() < topY) {
|
||||||
|
rect.setY(topY);
|
||||||
|
rect.setHeight(rect.height() - (topY - rect.y()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Dock::Position::Right: {
|
||||||
|
int rightX = rectGeometry.x() * qApp->devicePixelRatio();
|
||||||
|
if (rightX < rect.x() + rect.width() * qApp->devicePixelRatio())
|
||||||
|
rect.setWidth(rect.width() - (rect.x() + rect.width() - rightX));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Dock::Position::Bottom: {
|
||||||
|
int bottomY = rectGeometry.y() * qApp->devicePixelRatio();
|
||||||
|
if (bottomY < rect.y() + rect.height() * qApp->devicePixelRatio())
|
||||||
|
rect.setHeight(rect.height() - (rect.y() + rect.height() - bottomY));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect AppDragWidget::splitGeometry(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
QList<QScreen *> screens = DisplayManager::instance()->screens();
|
||||||
|
for (QScreen *screen : screens) {
|
||||||
|
QRect screenGeometry = screen->geometry();
|
||||||
|
screenGeometry.setWidth(screenGeometry.width() * qApp->devicePixelRatio());
|
||||||
|
screenGeometry.setHeight(screenGeometry.height() * qApp->devicePixelRatio());
|
||||||
|
if (!screenGeometry.contains(pos))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 左右分屏即可
|
||||||
|
int centerX = screenGeometry.x() + screenGeometry.width() / 2;
|
||||||
|
if (pos.x() < centerX) {
|
||||||
|
// 左分屏
|
||||||
|
QRect rectLeft = screenGeometry;
|
||||||
|
rectLeft.setWidth(screenGeometry.width() / 2);
|
||||||
|
adjustDesktopGeometry(rectLeft);
|
||||||
|
return rectLeft;
|
||||||
|
}
|
||||||
|
if (pos.x() > centerX) {
|
||||||
|
// 右分屏
|
||||||
|
QRect rectRight = screenGeometry;
|
||||||
|
rectRight.setLeft(screenGeometry.x() + screenGeometry.width() / 2);
|
||||||
|
rectRight.setWidth(screenGeometry.width() / 2);
|
||||||
|
adjustDesktopGeometry(rectRight);
|
||||||
|
return rectRight;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::initWaylandEnv()
|
||||||
|
{
|
||||||
|
if (!Utils::IS_WAYLAND_DISPLAY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 由于在wayland环境下无法触发drop事件,导致鼠标无法释放,所以这里暂时用XEventMonitor的方式(具体原因待查)
|
||||||
|
Dock::Position position = qApp->property(PROP_POSITION).value<Dock::Position>();
|
||||||
|
XEventMonitor *extralEventInter = new XEventMonitor("com.deepin.api.XEventMonitor", "/com/deepin/api/XEventMonitor", QDBusConnection::sessionBus());
|
||||||
|
QList<MonitRect> extralRectList;
|
||||||
|
QList<QScreen *> screens = DisplayManager::instance()->screens();
|
||||||
|
for (QScreen *screen : screens) {
|
||||||
|
MonitRect monitorRect;
|
||||||
|
QRect screenRect = screen->geometry();
|
||||||
|
screenRect.setSize(screenRect.size() * screen->devicePixelRatio());
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case Top: {
|
||||||
|
monitorRect.x1 = screenRect.x();
|
||||||
|
monitorRect.y1 = screenRect.y();
|
||||||
|
monitorRect.x2 = screenRect.x() + screenRect.width();
|
||||||
|
monitorRect.y2 = screenRect.y();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Bottom: {
|
||||||
|
monitorRect.x1 = screenRect.x();
|
||||||
|
monitorRect.y1 = screenRect.y() + screenRect.height();
|
||||||
|
monitorRect.x2 = screenRect.x() + screenRect.width();
|
||||||
|
monitorRect.y2 = screenRect.y() + screenRect.height();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Left: {
|
||||||
|
monitorRect.x1 = screenRect.x();
|
||||||
|
monitorRect.y1 = screenRect.y();
|
||||||
|
monitorRect.x2 = screenRect.x();
|
||||||
|
monitorRect.y2 = screenRect.y() + screenRect.height();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Right: {
|
||||||
|
monitorRect.x1 = screenRect.x() + screenRect.width();
|
||||||
|
monitorRect.y1 = screenRect.y();
|
||||||
|
monitorRect.x2 = screenRect.x() + screenRect.width();
|
||||||
|
monitorRect.y2 = screenRect.y() + screenRect.height();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!extralRectList.contains(monitorRect))
|
||||||
|
extralRectList << monitorRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString key = extralEventInter->RegisterAreas(extralRectList, 1 << 1);
|
||||||
|
connect(this, &AppDragWidget::destroyed, this, [ key, extralEventInter ] {
|
||||||
|
extralEventInter->UnregisterArea(key);
|
||||||
|
delete extralEventInter;
|
||||||
|
QDrag::cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(extralEventInter, &XEventMonitor::ButtonRelease, this, &AppDragWidget::onButtonRelease);
|
||||||
|
connect(extralEventInter, &XEventMonitor::CursorMove,this, &AppDragWidget::onCursorMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::onButtonRelease(int, int x, int y, const QString &)
|
||||||
|
{
|
||||||
|
if (!m_bDragDrop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dropHandler(QPoint(x, y));
|
||||||
|
|
||||||
|
QDrag::cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDragWidget::onCursorMove(int x, int y, const QString &)
|
||||||
|
{
|
||||||
|
QPoint pos = QPoint(x, y);
|
||||||
|
moveCurrent(pos);
|
||||||
|
moveHandler(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppDragWidget::onFollowMouse()
|
void AppDragWidget::onFollowMouse()
|
||||||
{
|
{
|
||||||
QPoint destPos = QCursor::pos();
|
moveCurrent(QCursor::pos());
|
||||||
if (DWindowManagerHelper::instance()->hasComposite()) {
|
|
||||||
move(destPos.x() - width() / 2, destPos.y() - height() / 2);
|
|
||||||
} else {
|
|
||||||
move(destPos.x(), destPos.y()); // 窗口特效未开启时会隐藏m_object绘制的图标,移动的图标为QDrag绘制的图标
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppDragWidget::enterEvent(QEvent *event)
|
void AppDragWidget::enterEvent(QEvent *event)
|
||||||
@ -388,50 +538,6 @@ void AppDragWidget::enterEvent(QEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**显示移除应用提示窗口
|
|
||||||
* @brief AppDragWidget::showRemoveTips
|
|
||||||
*/
|
|
||||||
void AppDragWidget::showRemoveTips()
|
|
||||||
{
|
|
||||||
Dock::Position pos = Dock::Position::Bottom;
|
|
||||||
|
|
||||||
DockPopupWindow *popup = m_popupWindow.data();
|
|
||||||
if (isRemoveAble(QCursor::pos())) {
|
|
||||||
QWidget *lastContent = popup->getContent();
|
|
||||||
if (lastContent)
|
|
||||||
lastContent->setVisible(false);
|
|
||||||
|
|
||||||
switch (pos) {
|
|
||||||
case Top: popup->setArrowDirection(DockPopupWindow::ArrowTop); break;
|
|
||||||
case Bottom: popup->setArrowDirection(DockPopupWindow::ArrowBottom); break;
|
|
||||||
case Left: popup->setArrowDirection(DockPopupWindow::ArrowLeft); break;
|
|
||||||
case Right: popup->setArrowDirection(DockPopupWindow::ArrowRight); break;
|
|
||||||
}
|
|
||||||
popup->resize(m_removeTips->sizeHint());
|
|
||||||
popup->setContent(m_removeTips);
|
|
||||||
|
|
||||||
const QPoint p = popupMarkPoint(pos);
|
|
||||||
if (!popup->isVisible())
|
|
||||||
QMetaObject::invokeMethod(popup, "show", Qt::QueuedConnection, Q_ARG(QPoint, p), Q_ARG(bool, true));
|
|
||||||
else
|
|
||||||
popup->show(p, true);
|
|
||||||
|
|
||||||
m_object->setOpacity(0.5);
|
|
||||||
m_animOpacity->setStartValue(0.5);
|
|
||||||
} else {
|
|
||||||
m_object->setOpacity(1.0);
|
|
||||||
m_animOpacity->setStartValue(1.0);
|
|
||||||
if (popup->isVisible())
|
|
||||||
popup->setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppDragWidget::moveEvent(QMoveEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event);
|
|
||||||
showRemoveTips();
|
|
||||||
}
|
|
||||||
|
|
||||||
QuickDragWidget::QuickDragWidget(QWidget *parent)
|
QuickDragWidget::QuickDragWidget(QWidget *parent)
|
||||||
: AppDragWidget(parent)
|
: AppDragWidget(parent)
|
||||||
{
|
{
|
||||||
@ -471,3 +577,36 @@ void QuickDragWidget::dragMoveEvent(QDragMoveEvent *event)
|
|||||||
AppDragWidget::dragMoveEvent(event);
|
AppDragWidget::dragMoveEvent(event);
|
||||||
requestDragMove(event);
|
requestDragMove(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**判断图标拖到一定高度(默认任务栏高度的1.5倍)后是否可以移除
|
||||||
|
* @brief AppDragWidget::isRemoveAble
|
||||||
|
* @param curPos 当前鼠标所在位置
|
||||||
|
* @return 返回true可移除,false不可移除
|
||||||
|
*/
|
||||||
|
bool QuickDragWidget::isRemoveAble(const QPoint &curPos)
|
||||||
|
{
|
||||||
|
const QPoint &p = curPos;
|
||||||
|
switch (m_dockPosition) {
|
||||||
|
case Dock::Position::Left:
|
||||||
|
if ((p.x() - m_dockGeometry.topRight().x()) > (m_dockGeometry.width() * m_distanceMultiple)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Dock::Position::Top:
|
||||||
|
if ((p.y() - m_dockGeometry.bottomLeft().y()) > (m_dockGeometry.height() * m_distanceMultiple)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Dock::Position::Right:
|
||||||
|
if ((m_dockGeometry.topLeft().x() - p.x()) > (m_dockGeometry.width() * m_distanceMultiple)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Dock::Position::Bottom:
|
||||||
|
if ((m_dockGeometry.topLeft().y() - p.y()) > (m_dockGeometry.height() * m_distanceMultiple)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#define APPDRAGWIDGET_H
|
#define APPDRAGWIDGET_H
|
||||||
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "screenspliter.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QGraphicsObject>
|
#include <QGraphicsObject>
|
||||||
@ -38,6 +40,9 @@
|
|||||||
#include "dockpopupwindow.h"
|
#include "dockpopupwindow.h"
|
||||||
#include "dockitem.h"
|
#include "dockitem.h"
|
||||||
|
|
||||||
|
class QDrag;
|
||||||
|
class DockScreen;
|
||||||
|
|
||||||
class AppGraphicsObject : public QGraphicsObject
|
class AppGraphicsObject : public QGraphicsObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -85,18 +90,18 @@ class AppDragWidget : public QGraphicsView
|
|||||||
public:
|
public:
|
||||||
explicit AppDragWidget(QWidget *parent = Q_NULLPTR);
|
explicit AppDragWidget(QWidget *parent = Q_NULLPTR);
|
||||||
|
|
||||||
|
void execFinished();
|
||||||
void setAppPixmap(const QPixmap &pix);
|
void setAppPixmap(const QPixmap &pix);
|
||||||
void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry);
|
void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry);
|
||||||
void setOriginPos(const QPoint position);
|
void setOriginPos(const QPoint position);
|
||||||
void setPixmapOpacity(qreal opacity);
|
void setPixmapOpacity(qreal opacity);
|
||||||
bool isRemoveAble(const QPoint &curPos);
|
|
||||||
void setItem(DockItem *item) { m_item = item; }
|
void setItem(DockItem *item) { m_item = item; }
|
||||||
static bool isRemoveable(const Dock::Position &dockPos, const QRect &doctRect);
|
|
||||||
void showRemoveAnimation();
|
void showRemoveAnimation();
|
||||||
void showGoBackAnimation();
|
void showGoBackAnimation();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestRemoveItem();
|
void requestChangedArea(QRect);
|
||||||
|
void requestSplitWindow(ScreenSpliter::SplitDirection);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
@ -104,7 +109,6 @@ protected:
|
|||||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||||
void dropEvent(QDropEvent *event) override;
|
void dropEvent(QDropEvent *event) override;
|
||||||
void hideEvent(QHideEvent *event) override;
|
void hideEvent(QHideEvent *event) override;
|
||||||
void moveEvent(QMoveEvent *event) override;
|
|
||||||
void enterEvent(QEvent *event) override;
|
void enterEvent(QEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -113,11 +117,20 @@ private:
|
|||||||
QAbstractAnimation::State oldState);
|
QAbstractAnimation::State oldState);
|
||||||
const QPoint popupMarkPoint(Dock::Position pos);
|
const QPoint popupMarkPoint(Dock::Position pos);
|
||||||
const QPoint topleftPoint() const;
|
const QPoint topleftPoint() const;
|
||||||
void showRemoveTips();
|
bool canSplitWindow(const QPoint &pos) const;
|
||||||
bool isRemoveItem();
|
ScreenSpliter::SplitDirection splitPosition() const;
|
||||||
|
QRect splitGeometry(const QPoint &pos) const;
|
||||||
|
void initWaylandEnv();
|
||||||
|
|
||||||
|
void dropHandler(const QPoint &pos);
|
||||||
|
void moveHandler(const QPoint &pos);
|
||||||
|
void moveCurrent(const QPoint &destPos);
|
||||||
|
void adjustDesktopGeometry(QRect &rect) const;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void onFollowMouse();
|
void onFollowMouse();
|
||||||
|
void onButtonRelease(int, int x, int y, const QString &);
|
||||||
|
void onCursorMove(int x, int y, const QString &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QScopedPointer<AppGraphicsObject> m_object;
|
QScopedPointer<AppGraphicsObject> m_object;
|
||||||
@ -133,7 +146,6 @@ protected:
|
|||||||
QRect m_dockGeometry;
|
QRect m_dockGeometry;
|
||||||
QPoint m_originPoint;
|
QPoint m_originPoint;
|
||||||
QSize m_iconSize;
|
QSize m_iconSize;
|
||||||
Dock::TipsWidget *m_removeTips;
|
|
||||||
QScopedPointer<DockPopupWindow> m_popupWindow;
|
QScopedPointer<DockPopupWindow> m_popupWindow;
|
||||||
/**
|
/**
|
||||||
* @brief m_distanceMultiple: 倍数
|
* @brief m_distanceMultiple: 倍数
|
||||||
@ -143,6 +155,8 @@ protected:
|
|||||||
|
|
||||||
bool m_bDragDrop = false; // 图标是否被拖拽
|
bool m_bDragDrop = false; // 图标是否被拖拽
|
||||||
DockItem *m_item;
|
DockItem *m_item;
|
||||||
|
QRect m_lastMouseGeometry;
|
||||||
|
DockScreen *m_dockScreen;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QuickDragWidget : public AppDragWidget
|
class QuickDragWidget : public AppDragWidget
|
||||||
@ -160,6 +174,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void dropEvent(QDropEvent *event) override;
|
void dropEvent(QDropEvent *event) override;
|
||||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isRemoveAble(const QPoint &curPos);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* APPDRAGWIDGET_H */
|
#endif /* APPDRAGWIDGET_H */
|
||||||
|
60
frame/screenspliter/screenspliter.cpp
Normal file
60
frame/screenspliter/screenspliter.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||||
|
*
|
||||||
|
* Author: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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 "screenspliter.h"
|
||||||
|
#include "appitem.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "screenspliter_xcb.h"
|
||||||
|
#include "screenspliter_wayland.h"
|
||||||
|
|
||||||
|
bool ScreenSpliter::releaseSplit()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenSpliter::ScreenSpliter(AppItem *appItem, DockEntryInter *entryInter, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_appItem(appItem)
|
||||||
|
, m_entryInter(entryInter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenSpliter::~ScreenSpliter()
|
||||||
|
{
|
||||||
|
m_appItem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppItem *ScreenSpliter::appItem() const
|
||||||
|
{
|
||||||
|
return m_appItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
DockEntryInter *ScreenSpliter::entryInter() const
|
||||||
|
{
|
||||||
|
return m_entryInter;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenSpliter *ScreenSpliterFactory::createScreenSpliter(AppItem *appItem, DockEntryInter *entryInter)
|
||||||
|
{
|
||||||
|
if (Utils::IS_WAYLAND_DISPLAY)
|
||||||
|
return new ScreenSpliter_Wayland(appItem, entryInter, appItem);
|
||||||
|
|
||||||
|
return new ScreenSpliter_Xcb(appItem, entryInter, appItem);
|
||||||
|
}
|
71
frame/screenspliter/screenspliter.h
Normal file
71
frame/screenspliter/screenspliter.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||||
|
*
|
||||||
|
* Author: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef SCREENSPLITER_H
|
||||||
|
#define SCREENSPLITER_H
|
||||||
|
|
||||||
|
#include "dbusutil.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class AppItem;
|
||||||
|
|
||||||
|
class ScreenSpliter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum SplitDirection {
|
||||||
|
None, // 无操作
|
||||||
|
Left, // 左分屏
|
||||||
|
Right, // 右分屏
|
||||||
|
Top, // 上分屏
|
||||||
|
Bottom, // 下分屏
|
||||||
|
LeftTop, // 左上
|
||||||
|
RightTop, // 右上
|
||||||
|
LeftBottom, // 左下
|
||||||
|
RightBottom, // 右下
|
||||||
|
Full // 全屏
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void startSplit(const QRect &) = 0; // 触发分屏提示效果
|
||||||
|
virtual bool split(SplitDirection) = 0; // 开始触发分屏
|
||||||
|
virtual bool suportSplitScreen() = 0; // 是否支持分屏
|
||||||
|
virtual bool releaseSplit(); // 释放分屏
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit ScreenSpliter(AppItem *appItem, DockEntryInter *entryInter, QObject *parent = nullptr);
|
||||||
|
virtual ~ScreenSpliter();
|
||||||
|
AppItem *appItem() const;
|
||||||
|
DockEntryInter *entryInter() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppItem *m_appItem;
|
||||||
|
DockEntryInter *m_entryInter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScreenSpliterFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static ScreenSpliter *createScreenSpliter(AppItem *appItem, DockEntryInter *entryInter);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCREENSPLITER_H
|
247
frame/screenspliter/screenspliter_wayland.cpp
Normal file
247
frame/screenspliter/screenspliter_wayland.cpp
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||||
|
*
|
||||||
|
* Author: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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 "screenspliter_wayland.h"
|
||||||
|
#include "appitem.h"
|
||||||
|
|
||||||
|
#include <QWindow>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QX11Info>
|
||||||
|
#include <QtWaylandClient>
|
||||||
|
#define private public
|
||||||
|
#include <private/qwaylandintegration_p.h>
|
||||||
|
#include <private/qwaylandshellsurface_p.h>
|
||||||
|
#include <private/qwaylandwindow_p.h>
|
||||||
|
#include <private/qwaylandcursor_p.h>
|
||||||
|
#undef private
|
||||||
|
|
||||||
|
#include <registry.h>
|
||||||
|
#include <ddeshell.h>
|
||||||
|
#include <event_queue.h>
|
||||||
|
#include <plasmashell.h>
|
||||||
|
#include <compositor.h>
|
||||||
|
#include <clientmanagement.h>
|
||||||
|
#include <connection_thread.h>
|
||||||
|
|
||||||
|
SplitWindowManager *ScreenSpliter_Wayland::m_splitManager = nullptr;
|
||||||
|
|
||||||
|
/** wayland下的分屏功能
|
||||||
|
* @brief ScreenSpliter_Wayland::ScreenSpliter_Wayland
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
ScreenSpliter_Wayland::ScreenSpliter_Wayland(AppItem *appItem, DockEntryInter *entryInter, QObject *parent)
|
||||||
|
: ScreenSpliter(appItem, entryInter, parent)
|
||||||
|
, m_checkedNotSupport(false)
|
||||||
|
{
|
||||||
|
if (!m_splitManager)
|
||||||
|
m_splitManager = new SplitWindowManager;
|
||||||
|
|
||||||
|
connect(m_splitManager, &SplitWindowManager::splitStateChange, this, &ScreenSpliter_Wayland::onSplitStateChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenSpliter_Wayland::~ScreenSpliter_Wayland()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSpliter_Wayland::startSplit(const QRect &rect)
|
||||||
|
{
|
||||||
|
if (entryInter()->windowInfos().size() == 0) {
|
||||||
|
// 如果默认打开的子窗口的数量为0,则无需操作,同时记录标记,在打开新的窗口的时候,设置遮罩
|
||||||
|
m_splitRect = rect;
|
||||||
|
entryInter()->Activate(QX11Info::getTimestamp());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMaskVisible(rect, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSpliter_Wayland::setMaskVisible(const QRect &rect, bool visible)
|
||||||
|
{
|
||||||
|
static QWidget *desktopWidget = nullptr;
|
||||||
|
if (!desktopWidget) {
|
||||||
|
desktopWidget = new QWidget;
|
||||||
|
DPalette palette = DGuiApplicationHelper::instance()->applicationPalette();
|
||||||
|
QColor backColor = palette.color(QPalette::Highlight);
|
||||||
|
backColor.setAlpha(255 * 0.3);
|
||||||
|
palette.setBrush(QPalette::ColorRole::Background, backColor);
|
||||||
|
desktopWidget->setPalette(palette);
|
||||||
|
desktopWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
|
||||||
|
}
|
||||||
|
desktopWidget->setVisible(visible);
|
||||||
|
desktopWidget->setGeometry(rect);
|
||||||
|
desktopWidget->raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenSpliter_Wayland::split(SplitDirection direction)
|
||||||
|
{
|
||||||
|
setMaskVisible(QRect(), false);
|
||||||
|
const QString windowUuid = splitUuid();
|
||||||
|
if (windowUuid.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string sUuid = windowUuid.toStdString();
|
||||||
|
const char *uuid = sUuid.c_str();
|
||||||
|
m_splitManager->requestSplitWindow(uuid, direction);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenSpliter_Wayland::splitUuid() const
|
||||||
|
{
|
||||||
|
#ifdef USE_AM
|
||||||
|
WindowInfoMap windowsInfo = entryInter()->windowInfos();
|
||||||
|
if (windowsInfo.isEmpty())
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
const QString uuid = windowsInfo.values()[0].uuid;
|
||||||
|
if (windowSupportSplit(uuid))
|
||||||
|
return uuid;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenSpliter_Wayland::windowSupportSplit(const QString &uuid) const
|
||||||
|
{
|
||||||
|
return m_splitManager->canSplit(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenSpliter_Wayland::firstWindowUuid() const
|
||||||
|
{
|
||||||
|
#ifdef USE_AM
|
||||||
|
WindowInfoMap winInfos = entryInter()->windowInfos();
|
||||||
|
if (winInfos.size() == 0)
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
return winInfos.begin().value().uuid;
|
||||||
|
#else
|
||||||
|
return QString();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSpliter_Wayland::onSplitStateChange(const char *uuid, int splitable)
|
||||||
|
{
|
||||||
|
#ifdef USE_AM
|
||||||
|
const QString windowUuid = firstWindowUuid();
|
||||||
|
qDebug() << "Split State Changed, window uuid:" << windowUuid << "split uuid:" << uuid << "split value:" << splitable;
|
||||||
|
if (QString(uuid) != windowUuid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_splitRect.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (splitable > 0) {
|
||||||
|
setMaskVisible(m_splitRect, true);
|
||||||
|
} else {
|
||||||
|
// 如果不支持二分屏,则退出当前的窗体,且标记当前不支持二分屏,下次打开的时候不再进行打开窗口来检测
|
||||||
|
entryInter()->ForceQuit();
|
||||||
|
m_checkedNotSupport = true;
|
||||||
|
}
|
||||||
|
m_splitRect = QRect(0, 0, 0, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenSpliter_Wayland::suportSplitScreen()
|
||||||
|
{
|
||||||
|
// 如果之前检测过是否不支持分屏(m_checkedNotSupport默认为false,如果不支持分屏,m_checkedNotSupport就会变为true),则直接返回不支持分屏
|
||||||
|
if (m_checkedNotSupport)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 如果存在未打开的窗口,就默认让其认为支持,后续会根据这个来打开一个新的窗口
|
||||||
|
if (entryInter()->windowInfos().size() == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 如果存在已经打开的窗口
|
||||||
|
m_checkedNotSupport = splitUuid().isEmpty();
|
||||||
|
return (!m_checkedNotSupport);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SplitWindowManager::SplitWindowManager
|
||||||
|
* @param wayland下的分屏的管理
|
||||||
|
*/
|
||||||
|
SplitWindowManager::SplitWindowManager(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_clientManagement(nullptr)
|
||||||
|
, m_connectionThread(new QThread(nullptr))
|
||||||
|
, m_connectionThreadObject(new ConnectionThread)
|
||||||
|
{
|
||||||
|
connect(m_connectionThreadObject, &ConnectionThread::connected, this, &SplitWindowManager::onConnectionFinished, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
m_connectionThreadObject->moveToThread(m_connectionThread);
|
||||||
|
m_connectionThread->start();
|
||||||
|
m_connectionThreadObject->initConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
SplitWindowManager::~SplitWindowManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SplitWindowManager::canSplit(const QString &uuid) const
|
||||||
|
{
|
||||||
|
if (!m_clientManagement)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const QVector <ClientManagement::WindowState> &clientWindowStates = m_clientManagement->getWindowStates();
|
||||||
|
qInfo() << "client window states count:" << clientWindowStates.size();
|
||||||
|
for (ClientManagement::WindowState windowState : clientWindowStates) {
|
||||||
|
qDebug() << "window uuid:" << uuid << "window state uuid:" << windowState.uuid
|
||||||
|
<< "active:" << windowState.isActive << "resource name:" << windowState.resourceName;
|
||||||
|
if (windowState.splitable > 0 && QString(windowState.uuid) == uuid)
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientManagement::SplitType convertSplitType(ScreenSpliter::SplitDirection direction)
|
||||||
|
{
|
||||||
|
static QMap<ScreenSpliter::SplitDirection, ClientManagement::SplitType> direcionMapping = {
|
||||||
|
{ ScreenSpliter::Left, ClientManagement::SplitType::Left },
|
||||||
|
{ ScreenSpliter::Right, ClientManagement::SplitType::Right},
|
||||||
|
{ ScreenSpliter::Top, ClientManagement::SplitType::Top },
|
||||||
|
{ ScreenSpliter::Bottom, ClientManagement::SplitType::Bottom },
|
||||||
|
{ ScreenSpliter::LeftTop, ClientManagement::SplitType::LeftTop },
|
||||||
|
{ ScreenSpliter::RightTop, ClientManagement::SplitType::RightTop },
|
||||||
|
{ ScreenSpliter::LeftBottom, ClientManagement::SplitType::LeftBottom },
|
||||||
|
{ ScreenSpliter::RightBottom, ClientManagement::SplitType::RightBottom }
|
||||||
|
};
|
||||||
|
|
||||||
|
return direcionMapping.value(direction, ClientManagement::SplitType::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplitWindowManager::requestSplitWindow(const char *uuid, const ScreenSpliter::SplitDirection &direction)
|
||||||
|
{
|
||||||
|
m_clientManagement->requestSplitWindow(uuid, convertSplitType(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplitWindowManager::onConnectionFinished()
|
||||||
|
{
|
||||||
|
EventQueue *eventQueue = new EventQueue(this);
|
||||||
|
eventQueue->setup(m_connectionThreadObject);
|
||||||
|
|
||||||
|
Registry *registry = new Registry(this);
|
||||||
|
connect(registry, &Registry::clientManagementAnnounced, this, [ this, registry ](quint32 name, quint32 version) {
|
||||||
|
m_clientManagement = registry->createClientManagement(name, version, this);
|
||||||
|
connect(m_clientManagement, &ClientManagement::splitStateChange, this, &SplitWindowManager::splitStateChange);
|
||||||
|
});
|
||||||
|
registry->setEventQueue(eventQueue);
|
||||||
|
registry->create(m_connectionThreadObject);
|
||||||
|
registry->setup();
|
||||||
|
}
|
103
frame/screenspliter/screenspliter_wayland.h
Normal file
103
frame/screenspliter/screenspliter_wayland.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||||
|
*
|
||||||
|
* Author: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef SCREENSPLITER_WAYLAND_H
|
||||||
|
#define SCREENSPLITER_WAYLAND_H
|
||||||
|
|
||||||
|
#include "screenspliter.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace KWayland {
|
||||||
|
namespace Client {
|
||||||
|
class Registry;
|
||||||
|
class DDEShell;
|
||||||
|
class DDEShellSurface;
|
||||||
|
class EventQueue;
|
||||||
|
class Compositor;
|
||||||
|
class Surface;
|
||||||
|
class ClientManagement;
|
||||||
|
class ConnectionThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppItem;
|
||||||
|
class QWindow;
|
||||||
|
class QThread;
|
||||||
|
class SplitWindowManager;
|
||||||
|
|
||||||
|
class WindowInfo;
|
||||||
|
typedef QMap<quint32, WindowInfo> WindowInfoMap;
|
||||||
|
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
|
||||||
|
class ScreenSpliter_Wayland : public ScreenSpliter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ScreenSpliter_Wayland(AppItem *appItem, DockEntryInter *entryInter, QObject *parent);
|
||||||
|
~ScreenSpliter_Wayland() override;
|
||||||
|
|
||||||
|
void startSplit(const QRect &rect) override;
|
||||||
|
bool split(SplitDirection direction) override;
|
||||||
|
bool suportSplitScreen() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setMaskVisible(const QRect &rect, bool visible);
|
||||||
|
QString splitUuid() const;
|
||||||
|
bool windowSupportSplit(const QString &uuid) const;
|
||||||
|
QString firstWindowUuid() const;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onSplitStateChange(const char* uuid, int splitable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static SplitWindowManager *m_splitManager;
|
||||||
|
QRect m_splitRect;
|
||||||
|
bool m_checkedNotSupport;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SplitWindowManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ScreenSpliter_Wayland;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit SplitWindowManager(QObject *parent = Q_NULLPTR);
|
||||||
|
~SplitWindowManager() override;
|
||||||
|
|
||||||
|
bool canSplit(const QString &uuid) const;
|
||||||
|
void requestSplitWindow(const char *uuid, const ScreenSpliter::SplitDirection &direction);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void splitStateChange(const char *, int);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onConnectionFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ClientManagement *m_clientManagement;
|
||||||
|
QThread *m_connectionThread;
|
||||||
|
ConnectionThread *m_connectionThreadObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCREENSPLITER_WAYLAND_H
|
240
frame/screenspliter/screenspliter_xcb.cpp
Normal file
240
frame/screenspliter/screenspliter_xcb.cpp
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||||
|
*
|
||||||
|
* Author: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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 "screenspliter_xcb.h"
|
||||||
|
#include "appitem.h"
|
||||||
|
|
||||||
|
#include <QX11Info>
|
||||||
|
|
||||||
|
#include <X11/X.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#define LEFT 1
|
||||||
|
#define RIGHT 2
|
||||||
|
#define TOP 3
|
||||||
|
#define BOTTOM 4
|
||||||
|
#define LEFTTOP 5
|
||||||
|
#define RIGHTTOP 6
|
||||||
|
#define LEFTBOTTOM 9
|
||||||
|
#define RIGHTBOTTOM 10
|
||||||
|
#define SPLITUNKNOW 0
|
||||||
|
|
||||||
|
static xcb_atom_t internAtom(const char *name, bool only_if_exist)
|
||||||
|
{
|
||||||
|
if (!name || *name == 0)
|
||||||
|
return XCB_NONE;
|
||||||
|
|
||||||
|
xcb_connection_t *connection = QX11Info::connection();
|
||||||
|
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, only_if_exist, strlen(name), name);
|
||||||
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookie, 0);
|
||||||
|
if (!reply)
|
||||||
|
return XCB_NONE;
|
||||||
|
|
||||||
|
xcb_atom_t atom = reply->atom;
|
||||||
|
free(reply);
|
||||||
|
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray windowProperty(quint32 WId, xcb_atom_t propAtom, xcb_atom_t typeAtom, quint32 len)
|
||||||
|
{
|
||||||
|
xcb_connection_t *conn = QX11Info::connection();
|
||||||
|
xcb_get_property_cookie_t cookie = xcb_get_property(conn, false, WId, propAtom, typeAtom, 0, len);
|
||||||
|
xcb_generic_error_t *err = nullptr;
|
||||||
|
xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, &err);
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
if (reply != nullptr) {
|
||||||
|
int valueLen = xcb_get_property_value_length(reply);
|
||||||
|
const char *buf = static_cast<const char *>(xcb_get_property_value(reply));
|
||||||
|
data.append(buf, valueLen);
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != nullptr) {
|
||||||
|
free(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenSpliter_Xcb::ScreenSpliter_Xcb(AppItem *appItem, DockEntryInter *entryInter, QObject *parent)
|
||||||
|
: ScreenSpliter(appItem, entryInter, parent)
|
||||||
|
, m_isSplitCreateWindow(false)
|
||||||
|
{
|
||||||
|
connect(entryInter, &DockEntryInter::WindowInfosChanged,
|
||||||
|
this, &ScreenSpliter_Xcb::onUpdateWindowInfo, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSpliter_Xcb::startSplit(const QRect &rect)
|
||||||
|
{
|
||||||
|
if (!openWindow()) {
|
||||||
|
m_effectRect = rect;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showSplitScreenEffect(rect, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenSpliter_Xcb::split(ScreenSpliter::SplitDirection direction)
|
||||||
|
{
|
||||||
|
showSplitScreenEffect(QRect(), false);
|
||||||
|
if (!openWindow())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 如果当前的应用不支持分屏,也无需分屏,检查分屏的时候至少需要一个窗口,因此这里写在打开窗口之后
|
||||||
|
quint32 WId = splittingWindowWId();
|
||||||
|
if (WId == 0) {
|
||||||
|
// 如果当前存在主动打开的窗口,那么就关闭当前主动打开的窗口
|
||||||
|
if (m_isSplitCreateWindow) {
|
||||||
|
entryInter()->ForceQuit();
|
||||||
|
m_isSplitCreateWindow = false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_client_message_event_t xev;
|
||||||
|
|
||||||
|
xev.response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
xev.type = internAtom("_DEEPIN_SPLIT_WINDOW", false);
|
||||||
|
xev.window = WId;
|
||||||
|
xev.format = 32;
|
||||||
|
xev.data.data32[0] = direction_x11(direction); // 1: 左分屏 2: 右分屏 5 左上 6 右上 9 左下 10 右下 15: 全屏
|
||||||
|
xev.data.data32[1] = 1; // 1 进入预览 0 不进入预览
|
||||||
|
|
||||||
|
xcb_send_event(QX11Info::connection(), false, QX11Info::appRootWindow(QX11Info::appScreen()),
|
||||||
|
SubstructureNotifyMask, (const char *)&xev);
|
||||||
|
xcb_flush(QX11Info::connection());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ScreenSpliter_Xcb::direction_x11(ScreenSpliter::SplitDirection direction)
|
||||||
|
{
|
||||||
|
static QMap<ScreenSpliter::SplitDirection, int> directionMapping = {
|
||||||
|
{ ScreenSpliter::Left, LEFT },
|
||||||
|
{ ScreenSpliter::Right, RIGHT },
|
||||||
|
{ ScreenSpliter::Top, TOP },
|
||||||
|
{ ScreenSpliter::Bottom, TOP },
|
||||||
|
{ ScreenSpliter::LeftTop, LEFTTOP },
|
||||||
|
{ ScreenSpliter::RightTop, RIGHTTOP },
|
||||||
|
{ ScreenSpliter::LeftBottom, LEFTBOTTOM },
|
||||||
|
{ ScreenSpliter::RightBottom, RIGHTBOTTOM }
|
||||||
|
};
|
||||||
|
|
||||||
|
return directionMapping.value(direction, SPLITUNKNOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenSpliter_Xcb::openWindow()
|
||||||
|
{
|
||||||
|
// 查看当前应用是否有打开的窗口,如果没有,则先打开一个窗口
|
||||||
|
const WindowInfoMap windowlist = entryInter()->windowInfos();
|
||||||
|
if (!windowlist.isEmpty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!m_isSplitCreateWindow) {
|
||||||
|
// 如果当前没有打开窗口,且未执行打开操作
|
||||||
|
entryInter()->Activate(QX11Info::getTimestamp());
|
||||||
|
m_isSplitCreateWindow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSpliter_Xcb::showSplitScreenEffect(const QRect &rect, bool visible)
|
||||||
|
{
|
||||||
|
quint32 WId = splittingWindowWId();
|
||||||
|
if (WId == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 触发分屏的效果
|
||||||
|
xcb_client_message_event_t xev;
|
||||||
|
|
||||||
|
xev.response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
xev.type = internAtom("_DEEPIN_SPLIT_OUTLINE", false);
|
||||||
|
xev.window = WId;
|
||||||
|
xev.format = 32;
|
||||||
|
xev.data.data32[0] = visible ? 1 : 0; // 1: 显示 0: 取消
|
||||||
|
xev.data.data32[1] = rect.x(); // X坐标
|
||||||
|
xev.data.data32[2] = rect.y(); // Y坐标
|
||||||
|
xev.data.data32[3] = rect.width(); // width
|
||||||
|
xev.data.data32[4] = rect.height(); // height
|
||||||
|
|
||||||
|
xcb_send_event(QX11Info::connection(), false, QX11Info::appRootWindow(QX11Info::appScreen()),
|
||||||
|
SubstructureNotifyMask, (const char *)&xev);
|
||||||
|
xcb_flush(QX11Info::connection());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenSpliter_Xcb::onUpdateWindowInfo(const WindowInfoMap &info)
|
||||||
|
{
|
||||||
|
// 如果打开的是第一个窗口,且这个打开的窗口是通过拖动二分屏的方式打开,且当前是结束拖拽
|
||||||
|
// 并且不支持分屏那么这个窗口就需要关闭
|
||||||
|
if (!appItem()->isDragging()) {
|
||||||
|
releaseSplit();
|
||||||
|
} else if (!m_effectRect.isEmpty() && info.size() > 0) {
|
||||||
|
// 只有当需要触发分屏效果的时候,发现当前没有窗口,则记录当前分屏的区域,保存在m_effectRect中
|
||||||
|
// 在新增窗口的时候,如果返现m_effectRect有值,则重新触发分屏,并且清空m_effectRect,防止再次打开窗口的时候再次触发分屏效果
|
||||||
|
showSplitScreenEffect(m_effectRect, true);
|
||||||
|
m_effectRect.setRect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenSpliter_Xcb::suportSplitScreen()
|
||||||
|
{
|
||||||
|
// 如果当前的窗口的数量为0,则不知道它是否支持分屏,则始终让其返回true,然后打开窗口,因为窗口打开后,
|
||||||
|
// 要过一段事件才能收到信号,等收到信号后才知道它是否支持分屏,在窗口显示后会根据当前是否请求过执行分屏操作
|
||||||
|
// 来决定是否执行分屏的操作
|
||||||
|
if (entryInter()->windowInfos().size() == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (splittingWindowWId() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenSpliter_Xcb::releaseSplit()
|
||||||
|
{
|
||||||
|
if (!m_isSplitCreateWindow)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!entryInter()->windowInfos().isEmpty() && splittingWindowWId() == 0) {
|
||||||
|
// 释放后,如果当前的窗口是通过验证是否支持二分屏的方式来新建的窗口(m_isSplitCreateWindow == true)
|
||||||
|
// 并且存在打开的窗口(也有可能不存在打开的窗口,打开的窗口最后才出来,时机上不好控制,所以这种情况
|
||||||
|
// 在updateWindowInfos函数里面做了处理),并且打开的窗口不支持二分屏,则此时关闭新打开的窗口
|
||||||
|
entryInter()->ForceQuit();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_isSplitCreateWindow = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 ScreenSpliter_Xcb::splittingWindowWId()
|
||||||
|
{
|
||||||
|
WindowInfoMap windowsInfo = entryInter()->windowInfos();
|
||||||
|
if (windowsInfo.size() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
quint32 WId = windowsInfo.keys().first();
|
||||||
|
xcb_atom_t propAtom = internAtom("_DEEPIN_NET_SUPPORTED", true);
|
||||||
|
QByteArray data = windowProperty(WId, propAtom, XCB_ATOM_CARDINAL, 4);
|
||||||
|
|
||||||
|
bool supported = false;
|
||||||
|
if (const char *cdata = data.constData())
|
||||||
|
supported = *(reinterpret_cast<const quint8 *>(cdata));
|
||||||
|
|
||||||
|
return supported ? WId : 0;
|
||||||
|
}
|
55
frame/screenspliter/screenspliter_xcb.h
Normal file
55
frame/screenspliter/screenspliter_xcb.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||||
|
*
|
||||||
|
* Author: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef SCREENSPLITER_XCB_H
|
||||||
|
#define SCREENSPLITER_XCB_H
|
||||||
|
|
||||||
|
#include "screenspliter.h"
|
||||||
|
|
||||||
|
#include <QRect>
|
||||||
|
|
||||||
|
class WindowInfo;
|
||||||
|
typedef QMap<quint32, WindowInfo> WindowInfoMap;
|
||||||
|
|
||||||
|
class ScreenSpliter_Xcb : public ScreenSpliter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ScreenSpliter_Xcb(AppItem *appItem, DockEntryInter *entryInter, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void startSplit(const QRect &rect) override;
|
||||||
|
bool split(ScreenSpliter::SplitDirection direction) override;
|
||||||
|
bool suportSplitScreen() override;
|
||||||
|
bool releaseSplit() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
quint32 splittingWindowWId();
|
||||||
|
uint32_t direction_x11(ScreenSpliter::SplitDirection direction);
|
||||||
|
void showSplitScreenEffect(const QRect &rect, bool visible);
|
||||||
|
bool openWindow();
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onUpdateWindowInfo(const WindowInfoMap &info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_isSplitCreateWindow;
|
||||||
|
QRect m_effectRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCREENSPLITER_XCB_H
|
@ -47,17 +47,16 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
|
#include <QX11Info>
|
||||||
|
|
||||||
#include <qpa/qplatformnativeinterface.h>
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
#include <qpa/qplatformintegration.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 <DGuiApplicationHelper>
|
||||||
#include <DWindowManagerHelper>
|
#include <DWindowManagerHelper>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
#define SPLITER_SIZE 2
|
#define SPLITER_SIZE 2
|
||||||
#define TRASH_MARGIN 20
|
#define TRASH_MARGIN 20
|
||||||
#define PLUGIN_MAX_SIZE 40
|
#define PLUGIN_MAX_SIZE 40
|
||||||
@ -794,8 +793,25 @@ void MainPanelControl::startDrag(DockItem *dockItem)
|
|||||||
|
|
||||||
m_appDragWidget = appDrag->appDragWidget();
|
m_appDragWidget = appDrag->appDragWidget();
|
||||||
|
|
||||||
|
connect(m_appDragWidget, &AppDragWidget::requestChangedArea, this, [ = ](QRect rect) {
|
||||||
|
// 在区域改变的时候,出现分屏提示效果
|
||||||
|
AppItem *appItem = static_cast<AppItem *>(dockItem);
|
||||||
|
if (appItem->supportSplitWindow())
|
||||||
|
appItem->startSplit(rect);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_appDragWidget, &AppDragWidget::requestSplitWindow, this, [ = ](ScreenSpliter::SplitDirection dir) {
|
||||||
|
AppItem *appItem = static_cast<AppItem *>(dockItem);
|
||||||
|
if (appItem->supportSplitWindow())
|
||||||
|
appItem->splitWindowOnScreen(dir);
|
||||||
|
});
|
||||||
|
|
||||||
connect(m_appDragWidget, &AppDragWidget::destroyed, this, [ = ] {
|
connect(m_appDragWidget, &AppDragWidget::destroyed, this, [ = ] {
|
||||||
m_appDragWidget = nullptr;
|
m_appDragWidget = nullptr;
|
||||||
|
AppItem *appItem = static_cast<AppItem *>(dockItem);
|
||||||
|
if (appItem->supportSplitWindow())
|
||||||
|
return;
|
||||||
|
|
||||||
if (!item.isNull() && qobject_cast<AppItem *>(item)->isValid()) {
|
if (!item.isNull() && qobject_cast<AppItem *>(item)->isValid()) {
|
||||||
// 如果是从最近打开区域移动到应用区域的,则需要将其固定
|
// 如果是从最近打开区域移动到应用区域的,则需要将其固定
|
||||||
dockRecentApp(item);
|
dockRecentApp(item);
|
||||||
@ -811,13 +827,6 @@ void MainPanelControl::startDrag(DockItem *dockItem)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_appDragWidget, &AppDragWidget::requestRemoveItem, this, [ = ] {
|
|
||||||
if (-1 != m_appAreaSonLayout->indexOf(item)) {
|
|
||||||
m_dragIndex = m_appAreaSonLayout->indexOf(item);
|
|
||||||
removeItem(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
appDrag->appDragWidget()->setOriginPos((m_appAreaSonWidget->mapToGlobal(item->pos())));
|
appDrag->appDragWidget()->setOriginPos((m_appAreaSonWidget->mapToGlobal(item->pos())));
|
||||||
appDrag->appDragWidget()->setDockInfo(m_position, QRect(mapToGlobal(pos()), size()));
|
appDrag->appDragWidget()->setDockInfo(m_position, QRect(mapToGlobal(pos()), size()));
|
||||||
const QPixmap &dragPix = qobject_cast<AppItem *>(item)->appIcon();
|
const QPixmap &dragPix = qobject_cast<AppItem *>(item)->appIcon();
|
||||||
@ -852,6 +861,11 @@ void MainPanelControl::startDrag(DockItem *dockItem)
|
|||||||
drag->setMimeData(new QMimeData);
|
drag->setMimeData(new QMimeData);
|
||||||
drag->exec(Qt::MoveAction);
|
drag->exec(Qt::MoveAction);
|
||||||
|
|
||||||
|
if (item->itemType() == DockItem::App && m_appDragWidget) {
|
||||||
|
// TODO AppDragWidget中偶尔会出现拖拽结束后没有触发dropEvent的情况,因此exec结束后处理dropEvent中未执行的操作(临时处理方式)
|
||||||
|
m_appDragWidget->execFinished();
|
||||||
|
}
|
||||||
|
|
||||||
if (item->itemType() != DockItem::App || m_dragIndex == -1) {
|
if (item->itemType() != DockItem::App || m_dragIndex == -1) {
|
||||||
m_appDragWidget = nullptr;
|
m_appDragWidget = nullptr;
|
||||||
item->setDraging(false);
|
item->setDraging(false);
|
||||||
@ -1368,8 +1382,7 @@ void MainPanelControl::calcuDockIconSize(int w, int h, int traySize)
|
|||||||
if (!layout || !layout->itemAt(0))
|
if (!layout || !layout->itemAt(0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PluginsItem *pItem = static_cast<PluginsItem *>(layout->itemAt(0)->widget());
|
PluginsItem *pItem = qobject_cast<PluginsItem *>(layout->itemAt(0)->widget());
|
||||||
qInfo() << pItem->pluginItem()->pluginDisplayName();
|
|
||||||
if (!pItem)
|
if (!pItem)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ void QuickPluginWindow::startDrag(PluginsItemInterface *moveItem)
|
|||||||
drag->setPixmap(dragPixmap);
|
drag->setPixmap(dragPixmap);
|
||||||
drag->setHotSpot(QPoint(0, 0));
|
drag->setHotSpot(QPoint(0, 0));
|
||||||
|
|
||||||
connect(drag->appDragWidget(), &AppDragWidget::requestRemoveItem, this, [ this, moveItem ] {
|
connect(drag->appDragWidget(), &AppDragWidget::requestSplitWindow, this, [ this, moveItem ] {
|
||||||
removePlugin(moveItem);
|
removePlugin(moveItem);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user