Skip to content

Commit

Permalink
feat: treeland weak area implement
Browse files Browse the repository at this point in the history
log: as title
  • Loading branch information
tsic404 authored and deepin-bot[bot] committed Nov 7, 2024
1 parent 3fd3c0e commit 2a8f8a2
Show file tree
Hide file tree
Showing 8 changed files with 430 additions and 55 deletions.
3 changes: 3 additions & 0 deletions panels/dock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down
216 changes: 210 additions & 6 deletions panels/dock/dockhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <QGuiApplication>

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<QWindow *>(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<DockPanel *>(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;
}
}
48 changes: 41 additions & 7 deletions panels/dock/dockhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,69 @@

#pragma once

#include "constants.h"
#include "dockpanel.h"
#include "dsglobal.h"

#include <QObject>


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<QScreen *, DockWakeUpArea *> m_areas;
QHash<QWindow *, bool> 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;
};
}

14 changes: 8 additions & 6 deletions panels/dock/dockpanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand All @@ -126,14 +126,17 @@ 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);
connect(window(), &QQuickWindow::heightChanged, this, &DockPanel::onWindowGeometryChanged);
QMetaObject::invokeMethod(this, &DockPanel::onWindowGeometryChanged);
if (showInPrimary())
updateDockScreen();
else {
m_dockScreen = window()->screen();
}
}
});

Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 2a8f8a2

Please sign in to comment.