From 64a24998869ef3ab6fbc4d2398a17f439dc053c2 Mon Sep 17 00:00:00 2001 From: yeshanshan Date: Wed, 11 Jan 2023 16:10:20 +0800 Subject: [PATCH] feat: Support multi split screen (#151) Add function to be compatible with two split screen. Log: x11和wayland下支持多分屏 Task: https://pms.uniontech.com/task-view-180357.html Influence: 需要依赖窗管升级,才能实现多分屏效果 Change-Id: I4abd73b8418f280a97caa9d5a46b76454a5d105e --- src/global.h | 2 ++ wayland/dwayland/dwaylandinterfacehook.cpp | 30 ++++++++++++++++++++++-------- wayland/dwayland/dwaylandinterfacehook.h | 2 ++ wayland/wayland-shell/dwaylandshellmanager.cpp | 26 ++++++++++++++++++++------ xcb/dplatformnativeinterfacehook.cpp | 4 +++- xcb/utility.h | 2 ++ xcb/utility_x11.cpp | 21 ++++++++++++++++----- 7 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/global.h b/src/global.h index 564ab67..0806a64 100644 --- a/src/global.h +++ b/src/global.h @@ -95,4 +95,6 @@ DEFINE_CONST_CHAR(splitWindowOnScreen); DEFINE_CONST_CHAR(supportForSplittingWindow); DEFINE_CONST_CHAR(sendEndStartupNotifition); +DEFINE_CONST_CHAR(splitWindowOnScreenByType); +DEFINE_CONST_CHAR(supportForSplittingWindowByType); // others diff --git a/wayland/dwayland/dwaylandinterfacehook.cpp b/wayland/dwayland/dwaylandinterfacehook.cpp index b3d31c1..042e836 100755 --- a/wayland/dwayland/dwaylandinterfacehook.cpp +++ b/wayland/dwayland/dwaylandinterfacehook.cpp @@ -40,5 +40,7 @@ static QFunctionPointer getFunction(const QByteArray &function) {isEnableDwayland, reinterpret_cast(&DWaylandInterfaceHook::isEnableDwayland)}, {splitWindowOnScreen, reinterpret_cast(&DWaylandInterfaceHook::splitWindowOnScreen)}, - {supportForSplittingWindow, reinterpret_cast(&DWaylandInterfaceHook::supportForSplittingWindow)} + {supportForSplittingWindow, reinterpret_cast(&DWaylandInterfaceHook::supportForSplittingWindow)}, + {splitWindowOnScreenByType, reinterpret_cast(&DWaylandInterfaceHook::splitWindowOnScreenByType)}, + {supportForSplittingWindowByType, reinterpret_cast(&DWaylandInterfaceHook::supportForSplittingWindowByType)} }; return functionCache.value(function); @@ -150,28 +152,40 @@ bool DWaylandInterfaceHook::isEnableDwayland(const QWindow *window) void DWaylandInterfaceHook::splitWindowOnScreen(WId wid, quint32 type) { + return splitWindowOnScreenByType(wid, 1, type); +} + +void DWaylandInterfaceHook::splitWindowOnScreenByType(WId wid, quint32 position, quint32 type) +{ QWindow *window = fromQtWinId(wid); if(!window || !window->handle()) return; - // 1 left,2 right,15 fullscreen - if (type == 15) { + // position: 15 not preview + if (position == 15) { if (window->windowStates().testFlag(Qt::WindowMaximized)) { window->showNormal(); } else { window->showMaximized(); } - } else if (type == 1 || type == 2) { - DNoTitlebarWlWindowHelper::setWindowProperty(window, ::splitWindowOnScreen, type); } else { - qCWarning(dwli) << "invalid split type: " << type; + // type 1:two splitting 2:three splitting 4:four splitting + // position enum class SplitType in kwin-dev, Left=0x1, Right=0x10, Top=0x100, Bottom=0x1000 + QVariantList value{position, type}; + DNoTitlebarWlWindowHelper::setWindowProperty(window, ::splitWindowOnScreen, value); } } bool DWaylandInterfaceHook::supportForSplittingWindow(WId wid) { + return supportForSplittingWindowByType(wid, 1); +} + +// screenSplittingType: 0: can't splitting, 1:two splitting, 2: four splitting(includ three splitting) +bool DWaylandInterfaceHook::supportForSplittingWindowByType(quint32 wid, quint32 screenSplittingType) +{ QWindow *window = fromQtWinId(wid); if(!window || !window->handle()) return false; - DNoTitlebarWlWindowHelper::requestByWindowProperty(window, ::supportForSplittingWindow); - return window->property(::supportForSplittingWindow).toBool(); + DNoTitlebarWlWindowHelper::setWindowProperty(window, ::supportForSplittingWindow, false); + return window->property(::supportForSplittingWindow).toInt() >= screenSplittingType; } diff --git a/wayland/dwayland/dwaylandinterfacehook.h b/wayland/dwayland/dwaylandinterfacehook.h index 56f85d2..aed1477 100755 --- a/wayland/dwayland/dwaylandinterfacehook.h +++ b/wayland/dwayland/dwaylandinterfacehook.h @@ -44,5 +44,7 @@ public: static bool isEnableDwayland(const QWindow *window); static void splitWindowOnScreen(WId wid, quint32 type); + static void splitWindowOnScreenByType(WId wid, quint32 position, quint32 type); static bool supportForSplittingWindow(WId wid); + static bool supportForSplittingWindowByType(quint32 wid, quint32 screenSplittingType); }; diff --git a/wayland/wayland-shell/dwaylandshellmanager.cpp b/wayland/wayland-shell/dwaylandshellmanager.cpp index beb7801..7d78cda 100644 --- a/wayland/wayland-shell/dwaylandshellmanager.cpp +++ b/wayland/wayland-shell/dwaylandshellmanager.cpp @@ -142,4 +142,11 @@ static Region *ensureRegion(QObject *parent = nullptr) } +static void checkIsDWayland(const QString &function) +{ +#ifndef D_DEEPIN_IS_DWAYLAND + qCWarning(dwlp) << "This package is not compiled as dwayland, and [" << function << "] not support in this version."; +#endif +} + DWaylandShellManager::DWaylandShellManager() : m_registry (new Registry()) @@ -197,16 +204,23 @@ void DWaylandShellManager::sendProperty(QWaylandShellSurface *self, const QStrin if (!name.compare(splitWindowOnScreen)) { using KWayland::Client::DDEShellSurface; - bool ok = false; - qreal leftOrRight = value.toInt(&ok); - if (ok) { - dde_shell_surface->requestSplitWindow(DDEShellSurface::SplitType(leftOrRight)); - qCDebug(dwlp) << "requestSplitWindow value: " << leftOrRight; + const auto tmp = value.toList(); + if (tmp.size() >= 2) { + const auto &position = tmp[0].toInt(); + const auto &type = tmp[1].toInt(); + checkIsDWayland("requestSplitWindow()"); +#ifdef D_DEEPIN_IS_DWAYLAND + dde_shell_surface->requestSplitWindow(DDEShellSurface::SplitType(position), DDEShellSurface::SplitMode(type)); + qCDebug(dwlp) << "requestSplitWindow splitType: " << position << " mode: " << type; +#endif } else { qCWarning(dwlp) << "invalid property: " << name << value; } wlWindow->window()->setProperty(splitWindowOnScreen, 0); } if (!name.compare(supportForSplittingWindow)) { - wlWindow->window()->setProperty(supportForSplittingWindow, dde_shell_surface->isSplitable()); + checkIsDWayland("getSplitable()"); +#ifdef D_DEEPIN_IS_DWAYLAND + wlWindow->window()->setProperty(supportForSplittingWindow, dde_shell_surface->getSplitable()); +#endif return; } diff --git a/xcb/dplatformnativeinterfacehook.cpp b/xcb/dplatformnativeinterfacehook.cpp index fc018dd..d9af2ac 100644 --- a/xcb/dplatformnativeinterfacehook.cpp +++ b/xcb/dplatformnativeinterfacehook.cpp @@ -78,5 +78,7 @@ static QFunctionPointer getFunction(const QByteArray &function) {splitWindowOnScreen, reinterpret_cast(&Utility::splitWindowOnScreen)}, {supportForSplittingWindow, reinterpret_cast(&Utility::supportForSplittingWindow)}, - {sendEndStartupNotifition, reinterpret_cast(&DPlatformIntegration::sendEndStartupNotifition)} + {sendEndStartupNotifition, reinterpret_cast(&DPlatformIntegration::sendEndStartupNotifition)}, + {splitWindowOnScreenByType, reinterpret_cast(&Utility::splitWindowOnScreenByType)}, + {supportForSplittingWindowByType, reinterpret_cast(&Utility::supportForSplittingWindowByType)} }; diff --git a/xcb/utility.h b/xcb/utility.h index e3454cb..f98ddc4 100644 --- a/xcb/utility.h +++ b/xcb/utility.h @@ -65,5 +65,7 @@ public: static void setNoTitlebar(quint32 WId, bool on); static void splitWindowOnScreen(quint32 WId, quint32 type); + static void splitWindowOnScreenByType(quint32 WId, quint32 position, quint32 type); static bool supportForSplittingWindow(quint32 WId); + static bool supportForSplittingWindowByType(quint32 WId, quint32 screenSplittingType); struct BlurArea { diff --git a/xcb/utility_x11.cpp b/xcb/utility_x11.cpp index 48d450b..b8c01c8 100644 --- a/xcb/utility_x11.cpp +++ b/xcb/utility_x11.cpp @@ -462,12 +462,18 @@ void Utility::setNoTitlebar(quint32 WId, bool on) void Utility::splitWindowOnScreen(quint32 WId, quint32 type) { + splitWindowOnScreenByType(WId, type, 1); +} + +void Utility::splitWindowOnScreenByType(quint32 WId, quint32 position, quint32 type) +{ 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] = type; /* 1: 左 2: 右 15: 全屏 */ - xev.data.data32[1] = type < 15 ? 1 : 0; /* 1: 左右 0: 全屏 */ + xev.data.data32[0] = position; /* enum class SplitType in kwin-dev, Left=0x1, Right=0x10, Top=0x100, Bottom=0x1000*/ + xev.data.data32[1] = position == 15 ? 0 : 1; /* 0: not preview 1: preview*/ + xev.data.data32[2] = type; /* 1:two splitting 2:three splitting 4:four splitting*/ xcb_send_event(QX11Info::connection(), false, QX11Info::appRootWindow(QX11Info::appScreen()), @@ -478,12 +484,17 @@ void Utility::splitWindowOnScreen(quint32 WId, quint32 type) bool Utility::supportForSplittingWindow(quint32 WId) { + return Utility::supportForSplittingWindowByType(WId, 1); +} + +// screenSplittingType: 0: can't splitting, 1:two splitting, 2: four splitting(includ three splitting) +bool Utility::supportForSplittingWindowByType(quint32 WId, quint32 screenSplittingType) +{ auto propAtom = internAtom("_DEEPIN_NET_SUPPORTED"); QByteArray data = windowProperty(WId, propAtom, XCB_ATOM_CARDINAL, 4); - bool supported = false; if (const char *cdata = data.constData()) - supported = *(reinterpret_cast(cdata)); + return *(reinterpret_cast(cdata)) >= screenSplittingType; - return supported; + return false; } -- libgit2 1.3.2