From b1f79e6685a353ec59f77139d9d5d10e377048d9 Mon Sep 17 00:00:00 2001 From: Tsic Liu Date: Tue, 29 Oct 2024 20:00:07 +0800 Subject: [PATCH 1/5] fix: protocols error when layershell screen changed log: as title --- frame/layershell/qwaylandlayershellsurface.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/frame/layershell/qwaylandlayershellsurface.cpp b/frame/layershell/qwaylandlayershellsurface.cpp index 080b7b3d7..fad77a1ab 100644 --- a/frame/layershell/qwaylandlayershellsurface.cpp +++ b/frame/layershell/qwaylandlayershellsurface.cpp @@ -6,6 +6,8 @@ #include "dlayershellwindow.h" #include "qwaylandlayershellsurface_p.h" +#include +#include #include #include @@ -30,7 +32,13 @@ QWaylandLayerShellSurface::QWaylandLayerShellSurface(QtWayland::zwlr_layer_shell auto waylandScreen = dynamic_cast(window->window()->screen()->handle()); connect(window->window(), &QWindow::screenChanged, this, [window](){ window->reset(); - window->reinit(); + // make sure window has been cleaned completed + QMetaObject::invokeMethod( + window, + [window]() { + window->reinit(); + }, + Qt::QueuedConnection); }); if (!waylandScreen) { qCWarning(layershellsurface) << "failed to get screen for wayland"; From 5b52bca5c7137a1a3f306b01f21dfe7583c475de Mon Sep 17 00:00:00 2001 From: Tsic Liu Date: Tue, 29 Oct 2024 20:01:34 +0800 Subject: [PATCH 2/5] fix: protocol error caused by window size log: as title --- frame/layershell/qwaylandlayershellsurface.cpp | 2 -- panels/dock/package/main.qml | 8 ++------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/frame/layershell/qwaylandlayershellsurface.cpp b/frame/layershell/qwaylandlayershellsurface.cpp index fad77a1ab..785ff2b70 100644 --- a/frame/layershell/qwaylandlayershellsurface.cpp +++ b/frame/layershell/qwaylandlayershellsurface.cpp @@ -6,8 +6,6 @@ #include "dlayershellwindow.h" #include "qwaylandlayershellsurface_p.h" -#include -#include #include #include diff --git a/panels/dock/package/main.qml b/panels/dock/package/main.qml index c30d8a702..12f925f7e 100644 --- a/panels/dock/package/main.qml +++ b/panels/dock/package/main.qml @@ -84,10 +84,6 @@ Window { anchors.fill: parent cornerRadius: 0 blendColor: { - // TODO: when dtk support treeland blur, remove following - if (Qt.platform.pluginName === "wayland") - return "transparent" - if (valid) { return DStyle.Style.control.selectColor(undefined, Qt.rgba(235 / 255.0, 235 / 255.0, 235 / 255.0, dock.blendColorAlpha(0.6)), @@ -103,13 +99,13 @@ Window { id: hideShowAnimation; target: dock; property: useColumnLayout ? "width" : "height"; - to: Panel.hideState != Dock.Hide ? Panel.dockSize : 0; + to: Panel.hideState != Dock.Hide ? Panel.dockSize : 1; duration: 500 onStarted: { dock.visible = true } onStopped: { - dock.visible = (useColumnLayout ? dock.width : dock.height != 0) + dock.visible = ((useColumnLayout ? dock.width : dock.height) != 1) } } From 04ec17b01633e0b0ad24a6b0cdf1f30f73a21826 Mon Sep 17 00:00:00 2001 From: Tsic Liu Date: Tue, 29 Oct 2024 20:03:59 +0800 Subject: [PATCH 3/5] fix: dock item empty icon caused by window icon is empty log: as title --- panels/dock/taskmanager/appitem.cpp | 2 +- panels/dock/taskmanager/taskmanager.cpp | 10 +++++++++- panels/dock/taskmanager/x11window.cpp | 8 +++++--- panels/dock/taskmanager/x11windowmonitor.cpp | 6 +++--- panels/dock/taskmanager/x11windowmonitor.h | 4 ++-- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/panels/dock/taskmanager/appitem.cpp b/panels/dock/taskmanager/appitem.cpp index cf55c30ac..715099d20 100644 --- a/panels/dock/taskmanager/appitem.cpp +++ b/panels/dock/taskmanager/appitem.cpp @@ -52,7 +52,7 @@ QString AppItem::type() const QString AppItem::icon() const { - if (m_currentActiveWindow.isNull() || (m_desktopfileParser && m_desktopfileParser->isValied().first)) + if (m_currentActiveWindow.isNull() || m_currentActiveWindow->icon().isEmpty() || (m_desktopfileParser && m_desktopfileParser->isValied().first)) return m_desktopfileParser ? m_desktopfileParser->desktopIcon() : "application-default-icon"; else { return m_currentActiveWindow->icon(); diff --git a/panels/dock/taskmanager/taskmanager.cpp b/panels/dock/taskmanager/taskmanager.cpp index 73bddbdaa..dc3b47bce 100644 --- a/panels/dock/taskmanager/taskmanager.cpp +++ b/panels/dock/taskmanager/taskmanager.cpp @@ -91,6 +91,10 @@ bool TaskManager::init() auto indentifies = data.toStringList(); for (auto id : indentifies) { + if (id.isEmpty()) { + continue; + } + for (auto identifiedOrder : identifiedOrders) { auto res = model->match(model->index(0, 0), roleNames.key(identifiedOrder), id); if (res.size() > 0 && res.first().isValid()) { @@ -129,7 +133,11 @@ void TaskManager::handleWindowAdded(QPointer window) } if (desktopfile.isNull() || !desktopfile->isValied().first) { - desktopfile = DESKTOPFILEFACTORY::createByWindow(window); + if (res.size() > 0) { + desktopfile = DESKTOPFILEFACTORY::createById(res.first().data(m_activeAppModel->roleNames().key("desktopId")).toString(), "asbtractAPP"); + } else { + desktopfile = DESKTOPFILEFACTORY::createByWindow(window); + } } auto appitem = desktopfile->getAppItem(); diff --git a/panels/dock/taskmanager/x11window.cpp b/panels/dock/taskmanager/x11window.cpp index ddff8fe6f..fa4e9d1a1 100644 --- a/panels/dock/taskmanager/x11window.cpp +++ b/panels/dock/taskmanager/x11window.cpp @@ -48,6 +48,7 @@ QStringList X11Window::identity() { if (m_identity.isEmpty()) { m_identity = X11->getWindowWMClass(m_windowID); + m_identity.append(QString::number(pid())); } return m_identity; @@ -167,11 +168,12 @@ void X11Window::updatePid() void X11Window::updateIdentify() { - auto newWmclas = X11->getWindowWMClass(m_windowID); - if (newWmclas == m_identity) + auto newWMclass = X11->getWindowWMClass(m_windowID); + newWMclass.append(QString::number(pid())); + if (newWMclass == m_identity) return; - m_identity = newWmclas; + m_identity = newWMclass; Q_EMIT identityChanged(); } diff --git a/panels/dock/taskmanager/x11windowmonitor.cpp b/panels/dock/taskmanager/x11windowmonitor.cpp index ded2878a0..50f43fa62 100644 --- a/panels/dock/taskmanager/x11windowmonitor.cpp +++ b/panels/dock/taskmanager/x11windowmonitor.cpp @@ -48,7 +48,7 @@ X11WindowMonitor::X11WindowMonitor(QObject* parent) { monitor = this; connect(this, &X11WindowMonitor::windowMapped, this, &X11WindowMonitor::onWindowMapped); - connect(this, &X11WindowMonitor::windowDestoried, this, &X11WindowMonitor::onWindowDestoried); + connect(this, &X11WindowMonitor::windowDestroyed, this, &X11WindowMonitor::onWindowDestroyed); connect(this, &X11WindowMonitor::windowPropertyChanged, this, &X11WindowMonitor::onWindowPropertyChanged); } @@ -155,7 +155,7 @@ void X11WindowMonitor::onWindowMapped(xcb_window_t xcb_window) Q_EMIT AbstractWindowMonitor::windowAdded(static_cast>(window.get())); } -void X11WindowMonitor::onWindowDestoried(xcb_window_t xcb_window) +void X11WindowMonitor::onWindowDestroyed(xcb_window_t xcb_window) { auto window = m_windows.value(xcb_window, nullptr); if (window) { @@ -219,7 +219,7 @@ void X11WindowMonitor::handleRootWindowClientListChanged() for (auto alreadyOpenedWindow : m_windows.keys()) { if (!currentOpenedWindowList.contains(alreadyOpenedWindow)) { - windowDestoried(alreadyOpenedWindow); + Q_EMIT windowDestroyed(alreadyOpenedWindow); } } diff --git a/panels/dock/taskmanager/x11windowmonitor.h b/panels/dock/taskmanager/x11windowmonitor.h index 8df550ae0..74c54f982 100644 --- a/panels/dock/taskmanager/x11windowmonitor.h +++ b/panels/dock/taskmanager/x11windowmonitor.h @@ -44,12 +44,12 @@ class X11WindowMonitor : public AbstractWindowMonitor Q_SIGNALS: void windowMapped(xcb_window_t window); - void windowDestoried(xcb_window_t window); + void windowDestroyed(xcb_window_t window); void windowPropertyChanged(xcb_window_t window, xcb_atom_t atom); private Q_SLOTS: void onWindowMapped(xcb_window_t window); - void onWindowDestoried(xcb_window_t window); + void onWindowDestroyed(xcb_window_t window); void onWindowPropertyChanged(xcb_window_t window, xcb_atom_t atom); private: From 83f0df76d5133fc96a4771ae3ac26e379a5f00a1 Mon Sep 17 00:00:00 2001 From: Tsic Liu Date: Tue, 29 Oct 2024 20:04:53 +0800 Subject: [PATCH 4/5] feat: treeland weak area implement log: as title --- panels/dock/CMakeLists.txt | 3 + panels/dock/dockhelper.cpp | 216 +++++++++++++++++++++++++++++- panels/dock/dockhelper.h | 48 ++++++- panels/dock/dockpanel.cpp | 14 +- panels/dock/waylanddockhelper.cpp | 120 +++++++++++++++-- panels/dock/waylanddockhelper.h | 55 +++++++- panels/dock/x11dockhelper.cpp | 23 +--- panels/dock/x11dockhelper.h | 6 +- 8 files changed, 430 insertions(+), 55 deletions(-) diff --git a/panels/dock/CMakeLists.txt b/panels/dock/CMakeLists.txt index 93731ffbf..3d8ac1f22 100644 --- a/panels/dock/CMakeLists.txt +++ b/panels/dock/CMakeLists.txt @@ -64,11 +64,14 @@ add_library(dockpanel SHARED qt_generate_wayland_protocol_client_sources(dockpanel FILES ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-wallpaper-color-v1.xml + ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-dde-shell-v1.xml ) target_link_libraries(dockpanel PRIVATE PkgConfig::WaylandClient Qt${QT_VERSION_MAJOR}::WaylandClient + Qt${QT_VERSION_MAJOR}::WaylandClientPrivate + Qt${QT_VERSION_MAJOR}::Widgets dde-shell-frame ) diff --git a/panels/dock/dockhelper.cpp b/panels/dock/dockhelper.cpp index 40a662f63..d42d99f16 100644 --- a/panels/dock/dockhelper.cpp +++ b/panels/dock/dockhelper.cpp @@ -3,21 +3,225 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "dockhelper.h" +#include "constants.h" #include "dockpanel.h" -#include "dsglobal.h" #include -namespace dock { - -DockHelper::DockHelper(DockPanel* parent) +namespace dock +{ +DockHelper::DockHelper(DockPanel *parent) : QObject(parent) - , m_panel(parent) + , m_hideTimer(new QTimer(this)) + , m_showTimer(new QTimer(this)) +{ + m_hideTimer->setInterval(400); + m_showTimer->setInterval(400); + m_hideTimer->setSingleShot(true); + m_showTimer->setSingleShot(true); + + connect(m_hideTimer, &QTimer::timeout, this, [this, parent]() { + if (parent->hideMode() == KeepShowing) + return; + + for (auto enter : m_enters) { + if (enter) + return; + } + + parent->setHideState(Hide); + }); + + connect(m_showTimer, &QTimer::timeout, this, [this, parent]() { + bool res = false; + for (auto enter : m_enters) { + res |= enter; + } + + if (res) + parent->setHideState(Show); + }); + + auto initAreas = [this, parent]() { + // clear old area + for (auto area : m_areas) { + area->close(); + delete area; + } + + m_areas.clear(); + qApp->disconnect(this); + + if (!parent->rootObject()) + return; + + // init areas + for (auto screen : qApp->screens()) { + m_areas.insert(screen, createArea(screen)); + } + + connect(qApp, &QGuiApplication::screenAdded, this, [this](QScreen *screen) { + if (m_areas.contains(screen)) + return; + m_areas.insert(screen, createArea(screen)); + }); + + connect(qApp, &QGuiApplication::screenRemoved, this, [this](QScreen *screen) { + if (!m_areas.contains(screen)) + return; + + destroyArea(m_areas.value(screen)); + m_areas.remove(screen); + }); + + // init state + updateAllDockWakeArea(); + }; + + connect(parent, &DockPanel::rootObjectChanged, this, initAreas); + connect(parent, &DockPanel::showInPrimaryChanged, this, &DockHelper::updateAllDockWakeArea); + connect(parent, &DockPanel::hideStateChanged, this, &DockHelper::updateAllDockWakeArea); + connect(parent, &DockPanel::positionChanged, this, [this](Position pos) { + for (auto area : m_areas) { + if (!area) + continue; + + area->updateDockWakeArea(pos); + } + }); + + qApp->installEventFilter(this); + QMetaObject::invokeMethod(this, initAreas); +} + +bool DockHelper::eventFilter(QObject *watched, QEvent *event) +{ + if (!watched->isWindowType()) { + return false; + } + + auto window = static_cast(watched); + if (!window) { + return false; + } + + switch (event->type()) { + case QEvent::Enter: { + m_enters.insert(window, true); + if (m_hideTimer->isActive()) { + m_hideTimer->stop(); + } + + m_showTimer->start(); + break; + } + case QEvent::Leave: { + m_enters.insert(window, false); + if (m_showTimer->isActive()) { + m_showTimer->stop(); + } + + m_hideTimer->start(); + break; + } + + case QEvent::Hide: { + m_enters.remove(window); + break; + } + default: { + } + } + + return false; +} + +bool DockHelper::wakeUpAreaNeedShowOnThisScreen(QScreen *screen) +{ + auto isDockAllowedShownOnThisScreen = [this, screen]() -> bool { + return (parent()->showInPrimary() && screen == qApp->primaryScreen()) || !parent()->showInPrimary(); + }; + + auto isDockShownThisScreen = [this, screen]() -> bool { + return parent()->dockScreen() == screen && parent()->hideState() == Show; + }; + + return (isDockAllowedShownOnThisScreen() && !isDockShownThisScreen()); +} + +void DockHelper::enterScreen(QScreen *screen) +{ + auto nowScreen = parent()->dockScreen(); + + if (nowScreen == screen) { + parent()->setHideState(Show); + return; + } + + QTimer::singleShot(200, [this, screen]() { + parent()->setDockScreen(screen); + parent()->setHideState(Show); + updateAllDockWakeArea(); + }); +} + +void DockHelper::leaveScreen() +{ + m_hideTimer->start(); +} + +DockWakeUpArea *DockHelper::createArea(QScreen *screen) { + return new DockWakeUpArea(screen, this); +} + +void DockHelper::destroyArea(DockWakeUpArea *area) +{ + if (area) { + area->close(); + delete area; + } +} + +void DockHelper::updateAllDockWakeArea() +{ + for (auto screen : m_areas.keys()) { + auto area = m_areas.value(screen); + if (nullptr == area) + continue; + + area->updateDockWakeArea(parent()->position()); + if (wakeUpAreaNeedShowOnThisScreen(screen)) { + area->open(); + } else { + area->close(); + } + } } DockPanel* DockHelper::parent() { - return m_panel; + return static_cast(QObject::parent()); +} + +DockWakeUpArea::DockWakeUpArea(QScreen *screen, DockHelper *helper) + : m_screen(screen) + , m_helper(helper) +{ +} + +void DockWakeUpArea::open() +{ + qDebug() << "create wake up area at " << m_screen->name(); +} + +void DockWakeUpArea::close() +{ + qDebug() << "close wake up area at " << m_screen->name(); +} + +void DockWakeUpArea::updateDockWakeArea(Position pos) +{ + qDebug() << "update wake up area pos to " << pos; } } diff --git a/panels/dock/dockhelper.h b/panels/dock/dockhelper.h index 9becdec79..a97cabb26 100644 --- a/panels/dock/dockhelper.h +++ b/panels/dock/dockhelper.h @@ -4,35 +4,69 @@ #pragma once +#include "constants.h" #include "dockpanel.h" -#include "dsglobal.h" #include - namespace dock { +class DockWakeUpArea; class DockHelper : public QObject { Q_OBJECT - Q_PROPERTY(HideState hideState READ hideState NOTIFY hideStateChanged FINAL) public: [[nodiscard]] DockHelper* getHelper(DockPanel* parent); - virtual HideState hideState() = 0; + virtual HideState hideState() + { + return Show; + } -Q_SIGNALS: - void hideStateChanged(); + bool eventFilter(QObject *watched, QEvent *event) override; public Q_SLOTS: + void enterScreen(QScreen *screen); + void leaveScreen(); + virtual void updateDockTriggerArea() = 0; +Q_SIGNALS: + void hideStateChanged(); + +protected: + bool wakeUpAreaNeedShowOnThisScreen(QScreen *screen); + [[nodiscard]] virtual DockWakeUpArea *createArea(QScreen *screen); + virtual void destroyArea(DockWakeUpArea *area); + +private: + void updateAllDockWakeArea(); + protected: DockHelper(DockPanel* parent); DockPanel* parent(); private: - DockPanel* m_panel; + QHash m_areas; + QHash m_enters; + QTimer *m_hideTimer; + QTimer *m_showTimer; +}; + +class DockWakeUpArea +{ +public: + virtual void open(); + virtual void close(); + +protected: + explicit DockWakeUpArea(QScreen *screen, DockHelper *helper); + virtual void updateDockWakeArea(Position pos); + +protected: + friend class DockHelper; + QScreen *m_screen; + DockHelper *m_helper; }; } diff --git a/panels/dock/dockpanel.cpp b/panels/dock/dockpanel.cpp index 240b0406d..7642ad31c 100644 --- a/panels/dock/dockpanel.cpp +++ b/panels/dock/dockpanel.cpp @@ -2,15 +2,14 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -#include "panel.h" -#include "constants.h" #include "dockpanel.h" +#include "constants.h" #include "dockadaptor.h" -#include "environments.h" #include "docksettings.h" +#include "panel.h" #include "pluginfactory.h" -#include "x11dockhelper.h" #include "waylanddockhelper.h" +#include "x11dockhelper.h" // for old api compatible #include "dockdbusproxy.h" @@ -101,6 +100,7 @@ bool DockPanel::init() connect(SETTINGS, &DockSettings::showInPrimaryChanged, this, [this, dockDaemonAdaptor](){ updateDockScreen(); Q_EMIT dockDaemonAdaptor->FrontendWindowRectChanged(frontendWindowRect()); + Q_EMIT showInPrimaryChanged(showInPrimary()); }); connect(this, &DockPanel::frontendWindowRectChanged, dockDaemonAdaptor, &DockDaemonAdaptor::FrontendWindowRectChanged); @@ -126,7 +126,7 @@ bool DockPanel::init() QObject::connect(this, &DApplet::rootObjectChanged, this, [this]() { if (rootObject()) { // those connections need connect after DPanel::init() which create QQuickWindow - // xChanged yChanged not woker on wayland, so use above positionChanged instead + // xChanged yChanged not worked on wayland, so use above positionChanged instead // connect(window(), &QQuickWindow::xChanged, this, &DockPanel::onWindowGeometryChanged); // connect(window(), &QQuickWindow::yChanged, this, &DockPanel::onWindowGeometryChanged); connect(window(), &QQuickWindow::widthChanged, this, &DockPanel::onWindowGeometryChanged); @@ -134,6 +134,9 @@ bool DockPanel::init() QMetaObject::invokeMethod(this, &DockPanel::onWindowGeometryChanged); if (showInPrimary()) updateDockScreen(); + else { + m_dockScreen = window()->screen(); + } } }); @@ -369,7 +372,6 @@ void DockPanel::setShowInPrimary(bool newShowInPrimary) connect(qApp, &QGuiApplication::primaryScreenChanged, this, &DockPanel::updateDockScreen, Qt::UniqueConnection); else disconnect(qApp, &QGuiApplication::primaryScreenChanged, this, &DockPanel::updateDockScreen); - Q_EMIT showInPrimaryChanged(showInPrimary()); } D_APPLET_CLASS(DockPanel) diff --git a/panels/dock/waylanddockhelper.cpp b/panels/dock/waylanddockhelper.cpp index ffcd5448d..2f1685066 100644 --- a/panels/dock/waylanddockhelper.cpp +++ b/panels/dock/waylanddockhelper.cpp @@ -4,7 +4,14 @@ #include "waylanddockhelper.h" #include "constants.h" +#include "dockhelper.h" #include "dockpanel.h" +#include "layershell/dlayershellwindow.h" +#include "wayland-treeland-dde-shell-v1-client-protocol.h" + +#include +#include +#include namespace dock { WaylandDockHelper::WaylandDockHelper(DockPanel *panel) @@ -17,10 +24,6 @@ WaylandDockHelper::WaylandDockHelper(DockPanel *panel) m_wallpaperColorManager->watchScreen(dockScreenName()); }); - connect(m_panel, &DockPanel::dockScreenChanged, this, [this]() { - m_wallpaperColorManager->watchScreen(dockScreenName()); - }); - connect(m_wallpaperColorManager.get(), &WallpaperColorManager::activeChanged, this, [this]() { if (m_panel->rootObject() != nullptr) { m_wallpaperColorManager->watchScreen(dockScreenName()); @@ -32,14 +35,13 @@ WaylandDockHelper::WaylandDockHelper(DockPanel *panel) } } -void WaylandDockHelper::updateDockTriggerArea() +DockWakeUpArea *WaylandDockHelper::createArea(QScreen *screen) { - + return new TreeLandDockWakeUpArea(screen, this, m_panel); } -HideState WaylandDockHelper::hideState() +void WaylandDockHelper::updateDockTriggerArea() { - return Show; } QString WaylandDockHelper::dockScreenName() @@ -74,4 +76,106 @@ void WallpaperColorManager::watchScreen(const QString &screeName) watch(screeName); } } + +TreeLandDDEShellManager::TreeLandDDEShellManager() + : QWaylandClientExtensionTemplate(treeland_dde_shell_manager_v1_interface.version) +{ +} + +TreeLandWindowOverlapChecker::TreeLandWindowOverlapChecker(QtWaylandClient::QWaylandWindow *window, struct ::treeland_window_overlap_checker *checker) + : QWaylandClientExtensionTemplate(treeland_dde_shell_manager_v1_interface.version) +{ + init(checker); + auto waylandScreen = dynamic_cast(window->window()->screen()->handle()); + update(100, 100, anchor_right | anchor_left | anchor_bottom, waylandScreen->output()); +} + +void TreeLandWindowOverlapChecker::treeland_window_overlap_checker_enter() +{ +} + +void TreeLandWindowOverlapChecker::treeland_window_overlap_checker_leave() +{ +} + +TreeLandDockWakeUpArea::TreeLandDockWakeUpArea(QScreen *screen, WaylandDockHelper *helper, DockPanel *panel) + : QWidget() + , DockWakeUpArea(screen, helper) +{ + winId(); + window()->setScreen(screen); + window()->resize(QSize(15, 15)); + + auto window = ds::DLayerShellWindow::get(windowHandle()); + window->setLayer(ds::DLayerShellWindow::LayerOverlay); + window->setAnchors({ds::DLayerShellWindow::AnchorBottom | ds::DLayerShellWindow::AnchorLeft | ds::DLayerShellWindow::AnchorRight}); + window->setExclusiveZone(-1); +} + +void TreeLandDockWakeUpArea::open() +{ + show(); +} + +void TreeLandDockWakeUpArea::close() +{ + hide(); +} + +void TreeLandDockWakeUpArea::updateDockWakeArea(Position pos) +{ + m_pos = pos; + ds::DLayerShellWindow::Anchors anchors = {0 | ds::DLayerShellWindow::AnchorNone}; + switch (pos) { + case Top: { + anchors = {ds::DLayerShellWindow::AnchorLeft | ds::DLayerShellWindow::AnchorRight | ds::DLayerShellWindow::AnchorTop}; + break; + } + case Right: { + anchors = {ds::DLayerShellWindow::AnchorRight | ds::DLayerShellWindow::AnchorTop | ds::DLayerShellWindow::AnchorBottom}; + break; + } + case Bottom: { + anchors = {ds::DLayerShellWindow::AnchorLeft | ds::DLayerShellWindow::AnchorRight | ds::DLayerShellWindow::AnchorBottom}; + break; + } + case Left: { + anchors = {ds::DLayerShellWindow::AnchorLeft | ds::DLayerShellWindow::AnchorTop | ds::DLayerShellWindow::AnchorBottom}; + break; + } + } + + window()->resize(QSize(15, 15)); + auto window = ds::DLayerShellWindow::get(windowHandle()); + window->setAnchors(anchors); +} + +TreeLandWindowOverlapChecker::~TreeLandWindowOverlapChecker() +{ + destroy(); +} + +void TreeLandDockWakeUpArea::enterEvent(QEnterEvent *event) +{ + m_helper->enterScreen(screen()); +} + +void TreeLandDockWakeUpArea::leaveEvent(QEvent *event) +{ + m_helper->leaveScreen(); +} + +void TreeLandDockWakeUpArea::resizeEvent(QResizeEvent *event) +{ + auto size = event->size(); + if (m_pos == Left || m_pos == Right) { + size.setHeight(m_screen->size().height()); + size.setWidth(15); + } else { + size.setHeight(15); + size.setWidth(m_screen->size().width()); + } + + window()->resize(size); +} } diff --git a/panels/dock/waylanddockhelper.h b/panels/dock/waylanddockhelper.h index 10342577a..8c0613acf 100644 --- a/panels/dock/waylanddockhelper.h +++ b/panels/dock/waylanddockhelper.h @@ -1,26 +1,35 @@ // SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later +#pragma once +#include "constants.h" #include "dockhelper.h" #include "dockpanel.h" +#include "qwayland-treeland-dde-shell-v1.h" #include "qwayland-treeland-wallpaper-color-v1.h" +#include + #include +#include namespace dock { class WallpaperColorManager; +class TreeLandDockTriggerArea; class WaylandDockHelper : public DockHelper { Q_OBJECT public: - WaylandDockHelper(DockPanel* panel); - HideState hideState() override; + WaylandDockHelper(DockPanel *panel); void setDockColorTheme(const ColorTheme &theme); QString dockScreenName(); +protected: + [[nodiscard]] virtual DockWakeUpArea *createArea(QScreen *screen) override; + public Q_SLOTS: void updateDockTriggerArea() override; @@ -44,4 +53,46 @@ class WallpaperColorManager : public QWaylandClientExtensionTemplate, public QtWayland::treeland_dde_shell_manager_v1 +{ + Q_OBJECT + +public: + explicit TreeLandDDEShellManager(); +}; + +class TreeLandWindowOverlapChecker : public QWaylandClientExtensionTemplate, public QtWayland::treeland_window_overlap_checker +{ + Q_OBJECT + +public: + TreeLandWindowOverlapChecker(QtWaylandClient::QWaylandWindow *window, struct ::treeland_window_overlap_checker *); + ~TreeLandWindowOverlapChecker(); + +protected: + void treeland_window_overlap_checker_enter() override; + void treeland_window_overlap_checker_leave() override; +}; + +class TreeLandDockWakeUpArea : public QWidget, public DockWakeUpArea +{ + Q_OBJECT +public: + explicit TreeLandDockWakeUpArea(QScreen *screen, WaylandDockHelper *helper, DockPanel *panel); + +public: + void open() override; + void close() override; + + void updateDockWakeArea(Position pos) override; + +protected: + void enterEvent(QEnterEvent *event) override; + void leaveEvent(QEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private: + Position m_pos; +}; } diff --git a/panels/dock/x11dockhelper.cpp b/panels/dock/x11dockhelper.cpp index 2f1787ec3..0974d62c4 100644 --- a/panels/dock/x11dockhelper.cpp +++ b/panels/dock/x11dockhelper.cpp @@ -2,10 +2,9 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +#include "x11dockhelper.h" #include "constants.h" -#include "dsglobal.h" #include "dockpanel.h" -#include "x11dockhelper.h" #include #include @@ -363,16 +362,6 @@ X11DockHelper::X11DockHelper(DockPanel* panel) connect(panel, &DockPanel::geometryChanged, this, &X11DockHelper::updateDockArea); connect(panel, &DockPanel::showInPrimaryChanged, this, &X11DockHelper::updateDockArea); connect(panel, &DockPanel::dockScreenChanged, this, &X11DockHelper::updateDockArea); - connect(panel, &DockPanel::rootObjectChanged, this, [ this, panel ] { - connect(panel->window(), &QWindow::visibleChanged, this, &X11DockHelper::updateWindowState, Qt::UniqueConnection); - updateWindowState(); - }); - - if (panel->rootObject()) { - connect(panel->window(), &QWindow::visibleChanged, this, &X11DockHelper::updateWindowState, Qt::UniqueConnection); - updateDockArea(); - updateWindowState(); - } qGuiApp->installNativeEventFilter(m_xcbHelper); onHideModeChanged(panel->hideMode()); @@ -565,16 +554,6 @@ void X11DockHelper::updateDockArea() } } -void X11DockHelper::updateWindowState() -{ - if (parent()->window()->isVisible()) { - xcb_atom_t atoms[] = { - m_xcbHelper->getAtomByName("_NET_WM_STATE_ABOVE") - }; - m_xcbHelper->setWindowState(parent()->window()->winId(), sizeof(atoms) / sizeof(atoms[0]), atoms); - } -} - HideState X11DockHelper::hideState() { return m_hideState; diff --git a/panels/dock/x11dockhelper.h b/panels/dock/x11dockhelper.h index dc1aa2a33..883a19860 100644 --- a/panels/dock/x11dockhelper.h +++ b/panels/dock/x11dockhelper.h @@ -1,13 +1,12 @@ // SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later +#pragma once #include "dockhelper.h" -#include "dsglobal.h" #include -#include #include - +#include namespace dock { class X11DockHelper; @@ -116,7 +115,6 @@ private Q_SLOTS: void updateDockHideState(); void delayedUpdateState(); void updateDockArea(); - void updateWindowState(); private: inline void updateWakeArea(); From 9d9092ff328e399ffd9af7f10140fc7bcf2d307c Mon Sep 17 00:00:00 2001 From: Tsic Liu Date: Wed, 30 Oct 2024 13:30:00 +0800 Subject: [PATCH 5/5] chore: adjust x11 wake area adjust wake area log: as title --- panels/dock/dockhelper.cpp | 204 ++++++++++-------- panels/dock/dockhelper.h | 41 ++-- panels/dock/dockpanel.cpp | 28 +-- panels/dock/taskmanager/x11utils.cpp | 72 +++++++ panels/dock/taskmanager/x11utils.h | 2 + panels/dock/waylanddockhelper.cpp | 104 +++++++-- panels/dock/waylanddockhelper.h | 23 +- panels/dock/x11dockhelper.cpp | 311 +++++++-------------------- panels/dock/x11dockhelper.h | 85 +++----- 9 files changed, 439 insertions(+), 431 deletions(-) diff --git a/panels/dock/dockhelper.cpp b/panels/dock/dockhelper.cpp index d42d99f16..9cf990f2c 100644 --- a/panels/dock/dockhelper.cpp +++ b/panels/dock/dockhelper.cpp @@ -20,78 +20,31 @@ DockHelper::DockHelper(DockPanel *parent) m_hideTimer->setSingleShot(true); m_showTimer->setSingleShot(true); - connect(m_hideTimer, &QTimer::timeout, this, [this, parent]() { - if (parent->hideMode() == KeepShowing) - return; - - for (auto enter : m_enters) { - if (enter) - return; - } - - parent->setHideState(Hide); - }); - - connect(m_showTimer, &QTimer::timeout, this, [this, parent]() { - bool res = false; - for (auto enter : m_enters) { - res |= enter; - } - - if (res) - parent->setHideState(Show); - }); - - auto initAreas = [this, parent]() { - // clear old area - for (auto area : m_areas) { - area->close(); - delete area; - } - - m_areas.clear(); - qApp->disconnect(this); - - if (!parent->rootObject()) - return; - - // init areas - for (auto screen : qApp->screens()) { - m_areas.insert(screen, createArea(screen)); - } - - connect(qApp, &QGuiApplication::screenAdded, this, [this](QScreen *screen) { - if (m_areas.contains(screen)) - return; - m_areas.insert(screen, createArea(screen)); - }); - - connect(qApp, &QGuiApplication::screenRemoved, this, [this](QScreen *screen) { - if (!m_areas.contains(screen)) - return; - - destroyArea(m_areas.value(screen)); - m_areas.remove(screen); - }); - - // init state - updateAllDockWakeArea(); - }; + qApp->installEventFilter(this); + QMetaObject::invokeMethod(this, &DockHelper::initAreas, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &DockHelper::checkNeedShowOrNot, Qt::QueuedConnection); - connect(parent, &DockPanel::rootObjectChanged, this, initAreas); + connect(parent, &DockPanel::rootObjectChanged, this, &DockHelper::initAreas); connect(parent, &DockPanel::showInPrimaryChanged, this, &DockHelper::updateAllDockWakeArea); connect(parent, &DockPanel::hideStateChanged, this, &DockHelper::updateAllDockWakeArea); connect(parent, &DockPanel::positionChanged, this, [this](Position pos) { - for (auto area : m_areas) { + std::for_each(m_areas.begin(), m_areas.end(), [pos](const auto &area) { if (!area) - continue; - + return; area->updateDockWakeArea(pos); - } + }); }); - qApp->installEventFilter(this); - QMetaObject::invokeMethod(this, initAreas); + connect(m_hideTimer, &QTimer::timeout, this, &DockHelper::checkNeedHideOrNot); + connect(m_showTimer, &QTimer::timeout, this, &DockHelper::checkNeedShowOrNot); + + connect(this, &DockHelper::isWindowOverlapChanged, this, [this](bool overlap) { + if (overlap) { + m_hideTimer->start(); + } else { + m_showTimer->start(); + } + }); } bool DockHelper::eventFilter(QObject *watched, QEvent *event) @@ -170,19 +123,6 @@ void DockHelper::leaveScreen() m_hideTimer->start(); } -DockWakeUpArea *DockHelper::createArea(QScreen *screen) -{ - return new DockWakeUpArea(screen, this); -} - -void DockHelper::destroyArea(DockWakeUpArea *area) -{ - if (area) { - area->close(); - delete area; - } -} - void DockHelper::updateAllDockWakeArea() { for (auto screen : m_areas.keys()) { @@ -190,38 +130,124 @@ void DockHelper::updateAllDockWakeArea() if (nullptr == area) continue; - area->updateDockWakeArea(parent()->position()); if (wakeUpAreaNeedShowOnThisScreen(screen)) { area->open(); + area->updateDockWakeArea(parent()->position()); } else { area->close(); } } } -DockPanel* DockHelper::parent() +void DockHelper::checkNeedHideOrNot() { - return static_cast(QObject::parent()); + bool needHide; + switch (parent()->hideMode()) { + case KeepShowing: { + // KeepShow. current activeWindow is maximized. + needHide = currentActiveWindowMaximized(); + break; + } + case SmartHide: { + // SmartHide. window overlap. + needHide = isWindowOverlap(); + break; + } + case KeepHidden: { + // only any enter + needHide = true; + break; + } + } + + // any enter will not make hide + for (auto enter : m_enters) { + needHide &= !enter; + } + + if (needHide) + parent()->setHideState(Hide); } -DockWakeUpArea::DockWakeUpArea(QScreen *screen, DockHelper *helper) - : m_screen(screen) - , m_helper(helper) +void DockHelper::checkNeedShowOrNot() +{ + bool needShow; + switch (parent()->hideMode()) { + case KeepShowing: { + // KeepShow. currentWindow is not maximized. + needShow = !currentActiveWindowMaximized(); + break; + } + case SmartHide: { + // SmartHide. no window overlap. + needShow = !isWindowOverlap(); + break; + } + case KeepHidden: { + // KeepHidden only any enter. + needShow = false; + break; + } + } + + for (auto enter : m_enters) { + needShow |= enter; + } + + if (needShow) + parent()->setHideState(Show); +} + +DockPanel* DockHelper::parent() { + return static_cast(QObject::parent()); } -void DockWakeUpArea::open() +void DockHelper::initAreas() { - qDebug() << "create wake up area at " << m_screen->name(); + // clear old area + for (auto area : m_areas) { + area->close(); + delete area; + } + + m_areas.clear(); + qApp->disconnect(this); + + if (!parent()->rootObject()) + return; + + // init areas + for (auto screen : qApp->screens()) { + m_areas.insert(screen, createArea(screen)); + } + + connect(qApp, &QGuiApplication::screenAdded, this, [this](QScreen *screen) { + if (m_areas.contains(screen)) + return; + m_areas.insert(screen, createArea(screen)); + }); + + connect(qApp, &QGuiApplication::screenRemoved, this, [this](QScreen *screen) { + if (!m_areas.contains(screen)) + return; + + destroyArea(m_areas.value(screen)); + m_areas.remove(screen); + }); + + // init state + updateAllDockWakeArea(); } -void DockWakeUpArea::close() +DockWakeUpArea::DockWakeUpArea(QScreen *screen, DockHelper *helper) + : m_screen(screen) + , m_helper(helper) { - qDebug() << "close wake up area at " << m_screen->name(); } -void DockWakeUpArea::updateDockWakeArea(Position pos) +QScreen *DockWakeUpArea::screen() { - qDebug() << "update wake up area pos to " << pos; + return m_screen; } } diff --git a/panels/dock/dockhelper.h b/panels/dock/dockhelper.h index a97cabb26..5f8a226ee 100644 --- a/panels/dock/dockhelper.h +++ b/panels/dock/dockhelper.h @@ -16,35 +16,35 @@ class DockHelper : public QObject Q_OBJECT public: - [[nodiscard]] DockHelper* getHelper(DockPanel* parent); - - virtual HideState hideState() - { - return Show; - } - + DockHelper(DockPanel *parent); bool eventFilter(QObject *watched, QEvent *event) override; -public Q_SLOTS: void enterScreen(QScreen *screen); void leaveScreen(); - virtual void updateDockTriggerArea() = 0; - Q_SIGNALS: - void hideStateChanged(); + void isWindowOverlapChanged(bool overlap); + void currentActiveWindowMaximizedChanged(bool maximized); protected: - bool wakeUpAreaNeedShowOnThisScreen(QScreen *screen); - [[nodiscard]] virtual DockWakeUpArea *createArea(QScreen *screen); - virtual void destroyArea(DockWakeUpArea *area); + DockPanel *parent(); + [[nodiscard]] virtual DockWakeUpArea *createArea(QScreen *screen) = 0; + virtual void destroyArea(DockWakeUpArea *area) = 0; + + virtual bool currentActiveWindowMaximized() = 0; + virtual bool isWindowOverlap() = 0; private: + bool wakeUpAreaNeedShowOnThisScreen(QScreen *screen); + void updateAllDockWakeArea(); -protected: - DockHelper(DockPanel* parent); - DockPanel* parent(); +private Q_SLOTS: + void checkNeedHideOrNot(); + void checkNeedShowOrNot(); + +private: + void initAreas(); private: QHash m_areas; @@ -56,12 +56,13 @@ public Q_SLOTS: class DockWakeUpArea { public: - virtual void open(); - virtual void close(); + QScreen *screen(); + virtual void open() = 0; + virtual void close() = 0; protected: explicit DockWakeUpArea(QScreen *screen, DockHelper *helper); - virtual void updateDockWakeArea(Position pos); + virtual void updateDockWakeArea(Position pos) = 0; protected: friend class DockHelper; diff --git a/panels/dock/dockpanel.cpp b/panels/dock/dockpanel.cpp index 7642ad31c..c8122d4db 100644 --- a/panels/dock/dockpanel.cpp +++ b/panels/dock/dockpanel.cpp @@ -30,10 +30,10 @@ Q_LOGGING_CATEGORY(dockLog, "dde.shell.dock") namespace dock { -DockPanel::DockPanel(QObject * parent) +DockPanel::DockPanel(QObject *parent) : DPanel(parent) , m_theme(ColorTheme::Dark) - , m_hideState(Hide) + , m_hideState(Show) , m_dockScreen(nullptr) , m_loadTrayPlugins(new LoadTrayPlugins(this)) , m_compositorReady(false) @@ -153,17 +153,7 @@ bool DockPanel::init() m_helper = new X11DockHelper(this); } - - connect(m_helper, &DockHelper::hideStateChanged, this, [this](){ - if (hideMode() == KeepShowing || m_launcherShown) return; - m_hideState = m_helper->hideState(); - Q_EMIT hideStateChanged(m_hideState); - }); - QMetaObject::invokeMethod(this, [this, dockDaemonAdaptor]() { - m_hideState = hideMode() == KeepShowing ? Show : m_helper->hideState(); - Q_EMIT hideStateChanged(m_hideState); - Q_EMIT dockDaemonAdaptor->FrontendWindowRectChanged(frontendWindowRect()); }); @@ -301,6 +291,10 @@ void DockPanel::setCompositorReady(bool ready) HideState DockPanel::hideState() { + if (m_launcherShown) { + return Show; + } + return m_hideState; } @@ -339,15 +333,7 @@ void DockPanel::launcherVisibleChanged(bool visible) if (visible == m_launcherShown) return; m_launcherShown = visible; - if (m_launcherShown) { - setHideState(Show); - } else { - if (hideMode() != KeepShowing) { - setHideState(m_helper->hideState()); - } else { - setHideState(Show); - } - } + Q_EMIT hideStateChanged(hideState()); } void DockPanel::updateDockScreen() diff --git a/panels/dock/taskmanager/x11utils.cpp b/panels/dock/taskmanager/x11utils.cpp index 6aef135ee..2fcda4143 100644 --- a/panels/dock/taskmanager/x11utils.cpp +++ b/panels/dock/taskmanager/x11utils.cpp @@ -271,6 +271,78 @@ QStringList X11Utils::getWindowWMClass(const xcb_window_t &window) return {"", ""}; } +QRect X11Utils::getWindowGeometry(const xcb_window_t &window) +{ + QRect geometry; + xcb_get_geometry_cookie_t cookie = xcb_get_geometry(m_connection, window); + xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(m_connection, cookie, nullptr); + if (geom) { + int x = geom->x, y = geom->y; + xcb_translate_coordinates_reply_t *trans = + xcb_translate_coordinates_reply(m_connection, xcb_translate_coordinates(m_connection, window, m_rootWindow, 0, 0), nullptr); + if (trans) { + x = trans->dst_x; + y = trans->dst_y; + free(trans); + } + geometry.setRect(x, y, geom->width, geom->height); + + xcb_window_t dwin = getDecorativeWindow(window); + if (dwin == 0) { + return QRect(); + } + xcb_get_geometry_reply_t *dgeom = xcb_get_geometry_reply(m_connection, xcb_get_geometry(m_connection, dwin), nullptr); + if (dgeom) { + if (geometry.x() == dgeom->x && geometry.y() == dgeom->y) { + // 无标题栏窗口,比如 deepin-editor, dconf-editor + xcb_get_property_reply_t *pro = + xcb_get_property_reply(m_connection, xcb_get_property(m_connection, false, window, getAtomByName("_NET_FRAME_EXTENTS"), 6, 0, 4), nullptr); + if (pro) { + if (pro->format == 0) { + free(pro); + pro = xcb_get_property_reply(m_connection, + xcb_get_property(m_connection, false, window, getAtomByName("_GTK_FRAME_EXTENTS"), 6, 0, 4), + nullptr); + } + if (pro && pro->format == 32) { + uint32_t values[4]; + memcpy(values, xcb_get_property_value(pro), sizeof(values)); + geometry.setRect(geometry.x() + values[0], + geometry.y() + values[2], + geometry.width() - values[0] - values[1], + geometry.height() - values[2] - values[3]); + } + free(pro); + } + } else { + geometry.setRect(dgeom->x, dgeom->y, dgeom->width, dgeom->height); + } + free(dgeom); + } + free(geom); + } + return geometry; +} + +xcb_window_t X11Utils::getDecorativeWindow(const xcb_window_t &window) +{ + xcb_window_t win = window; + for (int i = 0; i < 10; i++) { + xcb_query_tree_reply_t *qTree = xcb_query_tree_reply(m_connection, xcb_query_tree(m_connection, win), nullptr); + if (!qTree) { + free(qTree); + return 0; + } + if (qTree->root == qTree->parent) { + free(qTree); + return win; + } + win = qTree->parent; + free(qTree); + } + return 0; +} + QList X11Utils::getWindowTypes(const xcb_window_t &window) { QList ret; diff --git a/panels/dock/taskmanager/x11utils.h b/panels/dock/taskmanager/x11utils.h index 6670f7058..2a860eda4 100644 --- a/panels/dock/taskmanager/x11utils.h +++ b/panels/dock/taskmanager/x11utils.h @@ -56,6 +56,8 @@ class X11Utils QList getWindowAllowedActions(const xcb_window_t &window); MotifWMHints getWindowMotifWMHints(const xcb_window_t &window); QStringList getWindowWMClass(const xcb_window_t &window); + QRect getWindowGeometry(const xcb_window_t &window); + xcb_window_t getDecorativeWindow(const xcb_window_t &window); void minimizeWindow(const xcb_window_t &window); void maxmizeWindow(const xcb_window_t &window); diff --git a/panels/dock/waylanddockhelper.cpp b/panels/dock/waylanddockhelper.cpp index 2f1685066..21a11b521 100644 --- a/panels/dock/waylanddockhelper.cpp +++ b/panels/dock/waylanddockhelper.cpp @@ -7,6 +7,7 @@ #include "dockhelper.h" #include "dockpanel.h" #include "layershell/dlayershellwindow.h" +#include "qwayland-treeland-dde-shell-v1.h" #include "wayland-treeland-dde-shell-v1-client-protocol.h" #include @@ -17,8 +18,11 @@ namespace dock { WaylandDockHelper::WaylandDockHelper(DockPanel *panel) : DockHelper(panel) , m_panel(panel) + , m_isWindowOverlap(false) + , m_isCurrentActiveWindowMaximized(false) { m_wallpaperColorManager.reset(new WallpaperColorManager(this)); + m_ddeShellManager.reset(new TreeLandDDEShellManager()); connect(m_panel, &DockPanel::rootObjectChanged, this, [this]() { m_wallpaperColorManager->watchScreen(dockScreenName()); @@ -30,18 +34,78 @@ WaylandDockHelper::WaylandDockHelper(DockPanel *panel) } }); + connect(m_panel, &DockPanel::positionChanged, this, &WaylandDockHelper::updateOverlapCheckerPos); + connect(m_panel, &DockPanel::dockSizeChanged, this, &WaylandDockHelper::updateOverlapCheckerPos); + connect(m_panel, &DockPanel::rootObjectChanged, this, &WaylandDockHelper::updateOverlapCheckerPos); + + connect(m_ddeShellManager.get(), &TreeLandDDEShellManager::activeChanged, this, [this]() { + if (m_panel->hideMode() == HideMode::SmartHide && m_ddeShellManager->isActive()) { + m_overlapChecker.reset(new TreeLandWindowOverlapChecker(this, m_ddeShellManager->get_window_overlap_checker())); + updateOverlapCheckerPos(); + } else { + m_overlapChecker.reset(nullptr); + } + }); + + connect(m_panel, &DockPanel::hideModeChanged, this, [this](HideMode mode) { + if (mode == HideMode::SmartHide && m_ddeShellManager->isActive()) { + m_overlapChecker.reset(new TreeLandWindowOverlapChecker(this, m_ddeShellManager->get_window_overlap_checker())); + updateOverlapCheckerPos(); + } else { + m_overlapChecker.reset(nullptr); + } + }); + if (m_panel->rootObject() != nullptr) { m_wallpaperColorManager->watchScreen(dockScreenName()); } + + // TODO: get taskmanager applet and use it to update m_isCurrentActiveWindowMaximized. +} + +void WaylandDockHelper::updateOverlapCheckerPos() +{ + if (!m_overlapChecker) + return; + + if (!m_panel->rootObject()) + return; + + auto waylandScreen = dynamic_cast(m_panel->window()->screen()->handle()); + if (!waylandScreen) + return; + + uint32_t anchor; + switch (m_panel->position()) { + case Top: + anchor = QtWayland::treeland_window_overlap_checker::anchor_top; + break; + case Bottom: + anchor = QtWayland::treeland_window_overlap_checker::anchor_bottom; + break; + case Left: + anchor = QtWayland::treeland_window_overlap_checker::anchor_left; + break; + case Right: + anchor = QtWayland::treeland_window_overlap_checker::anchor_right; + break; + } + + m_overlapChecker->update(m_panel->dockSize(), m_panel->dockSize(), anchor, waylandScreen->output()); } DockWakeUpArea *WaylandDockHelper::createArea(QScreen *screen) { - return new TreeLandDockWakeUpArea(screen, this, m_panel); + return new TreeLandDockWakeUpArea(screen, this); } -void WaylandDockHelper::updateDockTriggerArea() +void WaylandDockHelper::destroyArea(DockWakeUpArea *area) { + auto waylandArea = static_cast(area); + if (waylandArea) { + waylandArea->close(); + waylandArea->deleteLater(); + } } QString WaylandDockHelper::dockScreenName() @@ -52,6 +116,16 @@ QString WaylandDockHelper::dockScreenName() return {}; } +bool WaylandDockHelper::currentActiveWindowMaximized() +{ + return m_isCurrentActiveWindowMaximized; +} + +bool WaylandDockHelper::isWindowOverlap() +{ + return m_isWindowOverlap; +} + void WaylandDockHelper::setDockColorTheme(const ColorTheme &theme) { m_panel->setColorTheme(theme); @@ -82,29 +156,40 @@ TreeLandDDEShellManager::TreeLandDDEShellManager() { } -TreeLandWindowOverlapChecker::TreeLandWindowOverlapChecker(QtWaylandClient::QWaylandWindow *window, struct ::treeland_window_overlap_checker *checker) +TreeLandWindowOverlapChecker::TreeLandWindowOverlapChecker(WaylandDockHelper *helper, struct ::treeland_window_overlap_checker *checker) : QWaylandClientExtensionTemplate(treeland_dde_shell_manager_v1_interface.version) + , m_helper(helper) { + setParent(helper); init(checker); - auto waylandScreen = dynamic_cast(window->window()->screen()->handle()); - update(100, 100, anchor_right | anchor_left | anchor_bottom, waylandScreen->output()); +} + +TreeLandWindowOverlapChecker::~TreeLandWindowOverlapChecker() +{ + destroy(); } void TreeLandWindowOverlapChecker::treeland_window_overlap_checker_enter() { + m_helper->m_isWindowOverlap = true; + Q_EMIT m_helper->isWindowOverlapChanged(m_helper->m_isWindowOverlap); } void TreeLandWindowOverlapChecker::treeland_window_overlap_checker_leave() { + m_helper->m_isWindowOverlap = false; + Q_EMIT m_helper->isWindowOverlapChanged(m_helper->m_isWindowOverlap); } -TreeLandDockWakeUpArea::TreeLandDockWakeUpArea(QScreen *screen, WaylandDockHelper *helper, DockPanel *panel) +TreeLandDockWakeUpArea::TreeLandDockWakeUpArea(QScreen *screen, WaylandDockHelper *helper) : QWidget() , DockWakeUpArea(screen, helper) { + // force create windowHandle for layershell. winId(); window()->setScreen(screen); window()->resize(QSize(15, 15)); + setAttribute(Qt::WA_TranslucentBackground, true); auto window = ds::DLayerShellWindow::get(windowHandle()); window->setLayer(ds::DLayerShellWindow::LayerOverlay); @@ -150,14 +235,9 @@ void TreeLandDockWakeUpArea::updateDockWakeArea(Position pos) window->setAnchors(anchors); } -TreeLandWindowOverlapChecker::~TreeLandWindowOverlapChecker() -{ - destroy(); -} - void TreeLandDockWakeUpArea::enterEvent(QEnterEvent *event) { - m_helper->enterScreen(screen()); + m_helper->enterScreen(QWidget::screen()); } void TreeLandDockWakeUpArea::leaveEvent(QEvent *event) diff --git a/panels/dock/waylanddockhelper.h b/panels/dock/waylanddockhelper.h index 8c0613acf..a797d8d03 100644 --- a/panels/dock/waylanddockhelper.h +++ b/panels/dock/waylanddockhelper.h @@ -13,10 +13,14 @@ #include #include +#include namespace dock { class WallpaperColorManager; class TreeLandDockTriggerArea; +class TreeLandDDEShellManager; +class TreeLandWindowOverlapChecker; + class WaylandDockHelper : public DockHelper { Q_OBJECT @@ -28,14 +32,22 @@ class WaylandDockHelper : public DockHelper QString dockScreenName(); protected: + bool currentActiveWindowMaximized() override; + bool isWindowOverlap() override; [[nodiscard]] virtual DockWakeUpArea *createArea(QScreen *screen) override; + void destroyArea(DockWakeUpArea *area) override; -public Q_SLOTS: - void updateDockTriggerArea() override; +private: + void updateOverlapCheckerPos(); private: + friend class TreeLandWindowOverlapChecker; + bool m_isWindowOverlap; + bool m_isCurrentActiveWindowMaximized; DockPanel *m_panel; QScopedPointer m_wallpaperColorManager; + QScopedPointer m_overlapChecker; + QScopedPointer m_ddeShellManager; }; class WallpaperColorManager : public QWaylandClientExtensionTemplate, public QtWayland::treeland_wallpaper_color_manager_v1 @@ -67,19 +79,22 @@ class TreeLandWindowOverlapChecker : public QWaylandClientExtensionTemplate +#include #include #include -#include #include #include @@ -20,16 +22,17 @@ Q_LOGGING_CATEGORY(dockX11Log, "dde.shell.dock.x11") const uint16_t monitorSize = 15; const uint32_t allWorkspace = 0xffffffff; +// TODO: use taskmanager window data struct WindowData { QRect rect; bool isMinimized; - HideState state; + bool overlap; uint32_t workspace; WindowData() : isMinimized(false) - , state(Unknown) + , overlap(false) , workspace(0) { } @@ -39,13 +42,6 @@ XcbEventFilter::XcbEventFilter(X11DockHelper *helper) : m_helper(helper) , m_currentWorkspace(0) { - m_timer = new QTimer(this); - m_timer->setSingleShot(true); - m_timer->setInterval(200); - - connect(m_timer, &QTimer::timeout, this, [this]() { - m_helper->updateEnterState(false); - }); auto *x11Application = qGuiApp->nativeInterface(); m_connection = x11Application->connection(); xcb_ewmh_init_atoms_replies(&m_ewmh, xcb_ewmh_init_atoms(m_connection, &m_ewmh), nullptr); @@ -63,30 +59,18 @@ XcbEventFilter::XcbEventFilter(X11DockHelper *helper) bool XcbEventFilter::inTriggerArea(xcb_window_t win) const { - for (auto area: m_helper->m_areas) { - if (area->triggerWindow() == win) - return true; - } - return false; + return m_helper->m_areas.contains(win); } void XcbEventFilter::processEnterLeave(xcb_window_t win, bool enter) { - qCDebug(dockX11Log) << "process enter and leave event, isEnter:" << enter - << ", winId:" << win; - for (auto area: m_helper->m_areas) { - if (area->triggerWindow() == win) { - if (enter) { - area->mouseEnter(); - } else { - area->mouseLeave(); - } - return; + if (inTriggerArea(win)) { + if (enter) { + m_helper->enterScreen(m_helper->m_areas.value(win)->screen()); + } else { + m_helper->leaveScreen(); } } - -// dock enter/leave - m_helper->updateEnterState(enter); } bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) @@ -98,23 +82,11 @@ bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag switch (xcb_event->response_type & ~0x80) { case XCB_ENTER_NOTIFY: { auto eN = reinterpret_cast(xcb_event); - qCDebug(dockX11Log) << "enter event winId:" << eN->event; - if (m_timer->isActive()) { - if (!inTriggerArea(eN->event)) { - m_timer->stop(); - break; - } - } processEnterLeave(eN->event, true); break; } case XCB_LEAVE_NOTIFY: { auto lN = reinterpret_cast(xcb_event); - qCDebug(dockX11Log) << "leave event winId:" << lN->event; - if (!inTriggerArea(lN->event)) { - m_timer->start(); - break; - } processEnterLeave(lN->event, false); break; } @@ -346,15 +318,7 @@ void XcbEventFilter::setWindowState(const xcb_window_t& window, uint32_t list_le X11DockHelper::X11DockHelper(DockPanel* panel) : DockHelper(panel) , m_xcbHelper(new XcbEventFilter(this)) - , m_hideState(Show) - , m_smartHideState(Unknown) - , m_enter(true) -{ - connect(parent(), &DockPanel::rootObjectChanged, this, &X11DockHelper::updateWakeArea); - connect(qApp, &QGuiApplication::screenAdded, this, &X11DockHelper::updateWakeArea); - connect(qApp, &QGuiApplication::screenRemoved, this, &X11DockHelper::updateWakeArea); - connect(panel, &DockPanel::hideStateChanged, this, &X11DockHelper::updateDockTriggerArea); - connect(panel, &DockPanel::showInPrimaryChanged, this, &X11DockHelper::updateDockTriggerArea); +{ connect(panel, &DockPanel::hideModeChanged, this, &X11DockHelper::onHideModeChanged); connect(panel, &DockPanel::rootObjectChanged, this, &X11DockHelper::updateDockArea); connect(panel, &DockPanel::positionChanged, this, &X11DockHelper::updateDockArea); @@ -367,26 +331,27 @@ X11DockHelper::X11DockHelper(DockPanel* panel) onHideModeChanged(panel->hideMode()); } -void X11DockHelper::updateDockTriggerArea() +[[nodiscard]] DockWakeUpArea *X11DockHelper::createArea(QScreen *screen) { - for (auto area: m_areas) { - area->updateDockTriggerArea(); - } + auto area = new X11DockWakeUpArea(screen, this); + m_areas.insert(area->m_triggerWindow, area); + return area; } -void X11DockHelper::updateEnterState(bool enter) +void X11DockHelper::destroyArea(DockWakeUpArea *area) { - if(m_enter!= enter) { - m_enter = enter; - updateHideState(); - } + auto x11Area = static_cast(area); + if (!x11Area) + return; + + m_areas.remove(x11Area->m_triggerWindow); + x11Area->deleteLater(); } void X11DockHelper::onHideModeChanged(HideMode mode) { // 会收到重复信号,因此每次都清理下数据 disconnect(m_xcbHelper, nullptr, this, nullptr); - m_smartHideState = Unknown; for (auto &&data : m_windows) { delete data; } @@ -398,8 +363,22 @@ void X11DockHelper::onHideModeChanged(HideMode mode) connect(m_xcbHelper, &XcbEventFilter::windowClientListChanged, this, &X11DockHelper::onWindowClientListChanged); connect(m_xcbHelper, &XcbEventFilter::windowPropertyChanged, this, &X11DockHelper::onWindowPropertyChanged); connect(m_xcbHelper, &XcbEventFilter::windowGeometryChanged, this, &X11DockHelper::onWindowGeometryChanged); - connect(m_xcbHelper, &XcbEventFilter::currentWorkspaceChanged, this, &X11DockHelper::updateDockHideState, Qt::QueuedConnection); - delayedUpdateState(); + connect(m_xcbHelper, &XcbEventFilter::currentWorkspaceChanged, this, [this]() { + static bool updating = false; + if (updating) + return; + + updating = true; + int currentWorkspace = m_xcbHelper->getCurrentWorkspace(); + for (auto &&data : m_windows) { + if (data->overlap && (data->workspace == currentWorkspace || data->workspace == allWorkspace)) { + Q_EMIT isWindowOverlapChanged(isWindowOverlap()); + updating = false; + return; + } + } + updating = false; + }); } break; case KeepShowing: case KeepHidden: @@ -423,7 +402,6 @@ void X11DockHelper::onWindowClientListChanged() if (!windows.contains(it.key())) { delete it.value(); it = m_windows.erase(it); - delayedUpdateState(); } else { it++; } @@ -462,7 +440,6 @@ void X11DockHelper::onWindowWorkspaceChanged(xcb_window_t window) { if (m_windows.contains(window)) { m_windows[window]->workspace = m_xcbHelper->getWindowWorkspace(window); - delayedUpdateState(); } } @@ -472,50 +449,13 @@ void X11DockHelper::updateWindowHideState(xcb_window_t window) return; } WindowData *data = m_windows.value(window); - HideState oldHideState = data->state; - HideState newHideState = Show; - if (!data->isMinimized && data->rect.intersects(m_dockArea)) { - newHideState = Hide; - } - if (newHideState != oldHideState) { - data->state = newHideState; - delayedUpdateState(); - } -} - -void X11DockHelper::updateSmartHideState(const HideState &state) -{ - if (m_smartHideState != state) { - m_smartHideState = state; - qCDebug(dockX11Log) << "smart hide state:" << m_smartHideState; - if (parent()->hideMode() == SmartHide) { - updateHideState(); - } - } -} - -void X11DockHelper::updateDockHideState() -{ - if (!m_needUpdateState) - return; - - int currentWorkspace = m_xcbHelper->getCurrentWorkspace(); - for (auto &&data : m_windows) { - if (data->state == Hide && (data->workspace == currentWorkspace || data->workspace == allWorkspace)) { - updateSmartHideState(Hide); - m_needUpdateState = false; - return; - } + bool oldOverlap = data->overlap; + if (!data->isMinimized) { + data->overlap = data->rect.intersects(m_dockArea); } - updateSmartHideState(Show); - m_needUpdateState = false; -} -void X11DockHelper::delayedUpdateState() -{ - if (!m_needUpdateState) { - m_needUpdateState = true; - QMetaObject::invokeMethod(this, &X11DockHelper::updateDockHideState, Qt::QueuedConnection); + if (oldOverlap != data->overlap) { + Q_EMIT isWindowOverlapChanged(isWindowOverlap()); } } @@ -550,121 +490,73 @@ void X11DockHelper::updateDockArea() for (auto it = m_windows.cbegin(); it != m_windows.cend(); ++it) { updateWindowHideState(it.key()); } - delayedUpdateState(); } } -HideState X11DockHelper::hideState() -{ - return m_hideState; -} - -void X11DockHelper::updateHideState() +bool X11DockHelper::currentActiveWindowMaximized() { - auto hideState = Show; - if (m_enter) { - hideState = Show; - } else { - if (parent()->hideMode() == HideMode::SmartHide && m_smartHideState == Show) { - hideState = Show; - } else { - hideState = Hide; - } - } - if (m_hideState != hideState) { - m_hideState = hideState; - Q_EMIT hideStateChanged(); - } + return false; } -void X11DockHelper::updateWakeArea() +bool X11DockHelper::isWindowOverlap() { - auto screens = qApp->screens(); - for (auto it = m_areas.begin(); it != m_areas.end();) { - if (screens.contains((*it)->screen())) { - screens.removeOne((*it)->screen()); - ++it; - } else { - delete (*it); - it = m_areas.erase(it); - } - } - - for (auto screen : screens) { - DockTriggerArea *area = new DockTriggerArea(parent(), this, screen); - m_areas.append(area); - } + // any widnow overlap + bool overlap = false; + std::for_each(m_windows.begin(), m_windows.end(), [&overlap](const auto &window) { + return overlap |= window->overlap; + }); + return overlap; } -DockTriggerArea::DockTriggerArea(DockPanel *panel, X11DockHelper *helper, QScreen *qScreen) - : QObject(panel) - , m_panel(panel) - , m_helper(helper) - , m_screen(qScreen) - , m_enableWakeArea(false) - , m_triggerTimer(new QTimer(this)) - , m_holdingTimer(new QTimer(this)) +X11DockWakeUpArea::X11DockWakeUpArea(QScreen *screen, X11DockHelper *helper) + : QObject(helper) + , DockWakeUpArea(screen, helper) { - m_triggerTimer->setSingleShot(true); - m_triggerTimer->setInterval(1500); - m_holdingTimer->setSingleShot(true); - m_holdingTimer->setInterval(200); - - connect(m_triggerTimer, &QTimer::timeout, this, &DockTriggerArea::onTriggerTimer); - connect(m_holdingTimer, &QTimer::timeout, this, &DockTriggerArea::onHoldingTimer); - connect(panel, &DockPanel::positionChanged, this, &DockTriggerArea::updateDockTriggerArea); m_connection = qGuiApp->nativeInterface()->connection(); - xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(m_connection)).data; - m_rootWindow = screen->root; + xcb_screen_t *xcbScreen = xcb_setup_roots_iterator(xcb_get_setup(m_connection)).data; + m_rootWindow = xcbScreen->root; m_triggerWindow = xcb_generate_id(m_connection); xcb_flush(m_connection); - updateDockTriggerArea(); } -DockTriggerArea::~DockTriggerArea() +X11DockWakeUpArea::~X11DockWakeUpArea() { - disableWakeArea(); } -void DockTriggerArea::enableWakeArea() +void X11DockWakeUpArea::open() { - if (m_enableWakeArea) - return; uint32_t values_list[] = {1}; - QRect rect = matchDockTriggerArea(); - xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_triggerWindow, m_rootWindow, rect.x(), rect.y(), rect.width(), rect.height(), 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, XCB_CW_OVERRIDE_REDIRECT, values_list); + xcb_create_window(m_connection, + XCB_COPY_FROM_PARENT, + m_triggerWindow, + m_rootWindow, + 1, + 1, + 1, + 1, + 0, + XCB_WINDOW_CLASS_INPUT_ONLY, + XCB_COPY_FROM_PARENT, + XCB_CW_OVERRIDE_REDIRECT, + values_list); uint32_t values[] = {XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW}; xcb_change_window_attributes(m_connection, m_triggerWindow, XCB_CW_EVENT_MASK, values); xcb_map_window(m_connection, m_triggerWindow); - m_enableWakeArea = true; } -void DockTriggerArea::disableWakeArea() +void X11DockWakeUpArea::close() { - if (!m_enableWakeArea || m_holdingTimer->isActive()) - return; xcb_destroy_window(m_connection, m_triggerWindow); - m_enableWakeArea = false; -} - -void DockTriggerArea::mouseEnter() -{ - m_triggerTimer->start(); -} - -void DockTriggerArea::mouseLeave() -{ - m_triggerTimer->stop(); } -const QRect DockTriggerArea::matchDockTriggerArea() +void X11DockWakeUpArea::updateDockWakeArea(Position pos) { QRect triggerArea; - auto rect = m_screen->geometry(); + auto rect = screen()->geometry(); // map geometry to Native const auto factor = m_screen->devicePixelRatio(); - switch (m_panel->position()) { + switch (pos) { case Top: { triggerArea.setX(rect.left()); triggerArea.setY(rect.top()); @@ -696,49 +588,8 @@ const QRect DockTriggerArea::matchDockTriggerArea() } triggerArea = QRect(triggerArea.topLeft(), triggerArea.size() * factor); - return triggerArea; -} - -void DockTriggerArea::updateDockTriggerArea() -{ - auto isDockAllowedShownOnThisScreen = [this]() -> bool { - return (m_panel->showInPrimary() && m_screen == qApp->primaryScreen()) || !m_panel->showInPrimary(); - }; - - auto isDockShownThisScreen = [this]() -> bool { - return m_panel->dockScreen() == m_screen && m_panel->hideState() == Show; - }; - - if (isDockAllowedShownOnThisScreen() && !isDockShownThisScreen()) { - enableWakeArea(); - } else { - disableWakeArea(); - return; - } - - QRect rect = matchDockTriggerArea(); - qCDebug(dockX11Log) << "update dock trigger area" << rect; - auto connection = qGuiApp->nativeInterface()->connection(); - int values[4] = {rect.x(), rect.y(), rect.width(), rect.height()}; - - xcb_configure_window(connection, m_triggerWindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); - xcb_flush(connection); -} -void DockTriggerArea::onTriggerTimer() -{ - m_holdingTimer->start(); - if (m_panel->dockScreen() != m_screen) { - m_panel->setDockScreen(m_screen); - m_helper->updateDockTriggerArea(); - } - m_helper->updateEnterState(true); -} -void DockTriggerArea::onHoldingTimer() -{ - if (m_panel->dockScreen() == m_screen && m_panel->hideState() == Show) { - disableWakeArea(); - } else { - enableWakeArea(); - } + int values[4] = {triggerArea.x(), triggerArea.y(), triggerArea.width(), triggerArea.height()}; + xcb_configure_window(m_connection, m_triggerWindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); + xcb_flush(m_connection); } } // namespace dock diff --git a/panels/dock/x11dockhelper.h b/panels/dock/x11dockhelper.h index 883a19860..4526b64f6 100644 --- a/panels/dock/x11dockhelper.h +++ b/panels/dock/x11dockhelper.h @@ -4,11 +4,13 @@ #pragma once #include "dockhelper.h" + #include #include #include namespace dock { +class X11DockWakeUpArea; class X11DockHelper; struct WindowData; @@ -44,7 +46,6 @@ class XcbEventFilter: public QObject, public QAbstractNativeEventFilter void processEnterLeave(xcb_window_t win, bool enter); QPointer m_helper; - QTimer *m_timer; QMap m_atoms; xcb_connection_t* m_connection; xcb_window_t m_rootWindow; @@ -52,56 +53,21 @@ class XcbEventFilter: public QObject, public QAbstractNativeEventFilter uint32_t m_currentWorkspace; }; -class DockTriggerArea : public QObject -{ - Q_OBJECT - -public: - DockTriggerArea(DockPanel *panel, X11DockHelper *helper, QScreen *qScreen); - ~DockTriggerArea(); - - xcb_window_t triggerWindow() const { return m_triggerWindow; } - QScreen *screen() const { return m_screen; } - void enableWakeArea(); - void disableWakeArea(); - void mouseEnter(); - void mouseLeave(); -public Q_SLOTS: - void updateDockTriggerArea(); - void onTriggerTimer(); - void onHoldingTimer(); - -private: - const QRect matchDockTriggerArea(); - - DockPanel *m_panel; - X11DockHelper *m_helper; - QScreen *m_screen; - xcb_window_t m_triggerWindow; - xcb_window_t m_rootWindow; - xcb_connection_t *m_connection; - bool m_enableWakeArea; - - QTimer* m_triggerTimer; - QTimer* m_holdingTimer; -}; - - class X11DockHelper : public DockHelper { Q_OBJECT public: - X11DockHelper(DockPanel* panel); - HideState hideState() override; - QList triggerAreas() const { return m_areas; } + X11DockHelper(DockPanel *panel); + +protected: + bool currentActiveWindowMaximized() override; + bool isWindowOverlap() override; -public Q_SLOTS: - void updateDockTriggerArea() override; - void updateEnterState(bool enter); + [[nodiscard]] DockWakeUpArea *createArea(QScreen *screen) override; + void destroyArea(DockWakeUpArea *area) override; private Q_SLOTS: - void updateHideState(); void onHideModeChanged(HideMode mode); void onWindowClientListChanged(); @@ -111,27 +77,36 @@ private Q_SLOTS: void onWindowWorkspaceChanged(xcb_window_t window); void updateWindowHideState(xcb_window_t window); - void updateSmartHideState(const dock::HideState &state); - void updateDockHideState(); - void delayedUpdateState(); - void updateDockArea(); -private: - inline void updateWakeArea(); + void updateDockArea(); private: friend class XcbEventFilter; private: - dock::HideState m_hideState; - QString m_registerKey; - QList m_areas; + QHash m_areas; QRect m_dockArea; - bool m_needUpdateState; - bool m_enter; - dock::HideState m_smartHideState; QHash m_windows; XcbEventFilter *m_xcbHelper; }; + +class X11DockWakeUpArea : public QObject, public DockWakeUpArea +{ + Q_OBJECT + +private: + X11DockWakeUpArea(QScreen *screen, X11DockHelper *helper); + ~X11DockWakeUpArea(); + + void open() override; + void close() override; + void updateDockWakeArea(Position pos) override; + +private: + friend class X11DockHelper; + xcb_window_t m_triggerWindow; + xcb_window_t m_rootWindow; + xcb_connection_t *m_connection; +}; }