// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "mainwindowbase.h"
#include "constants.h"
#include "dragwidget.h"
#include "multiscreenworker.h"
#include "dockscreen.h"
#include "touchsignalmanager.h"
#include "displaymanager.h"
#include "menuworker.h"
#include "docksettings.h"

#include <DStyle>
#include <DWindowManagerHelper>
#include <DSysInfo>
#include <DPlatformTheme>

#include <QScreen>
#include <QX11Info>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformnativeinterface.h>

#define DRAG_AREA_SIZE (5)

// 任务栏圆角最小的时候，任务栏的高度值
#define MIN_RADIUS_WINDOWSIZE 46
// 任务栏圆角最小值和最大值的差值
#define MAX_MIN_RADIUS_DIFFVALUE 6
// 最小圆角值
#define MIN_RADIUS 12

#define DOCK_SCREEN DockScreen::instance()
#define DIS_INS DisplayManager::instance()

DGUI_USE_NAMESPACE

MainWindowBase::MainWindowBase(MultiScreenWorker *multiScreenWorker, QWidget *parent)
    : DBlurEffectWidget(parent)
    , m_platformWindowHandle(this)
    , m_displayMode(Dock::DisplayMode::Efficient)
    , m_position(Dock::Position::Bottom)
    , m_dragWidget(new DragWidget(this))
    , m_multiScreenWorker(multiScreenWorker)
    , m_updateDragAreaTimer(new QTimer(this))
    , m_shadowMaskOptimizeTimer(new QTimer(this))
    , m_isShow(false)
    , m_order(0)
{
    initUi();
    initAttribute();
    initConnection();
    initMember();
}

MainWindowBase::~MainWindowBase()
{
}

void MainWindowBase::setOrder(int order)
{
    m_order = order;
}

int MainWindowBase::order() const
{
    return m_order;
}

void MainWindowBase::initAttribute()
{
    setAttribute(Qt::WA_TranslucentBackground);
    setAttribute(Qt::WA_X11DoNotAcceptFocus);

    Qt::WindowFlags flags = Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Window;
    //1 确保这两行代码的先后顺序，否则会导致任务栏界面不再置顶
    setWindowFlags(windowFlags() | flags | Qt::WindowDoesNotAcceptFocus);

    if (Utils::IS_WAYLAND_DISPLAY) {
        setWindowFlag(Qt::FramelessWindowHint, false); // 会导致设置圆角为0时无效
        setAttribute(Qt::WA_NativeWindow);
        windowHandle()->setProperty("_d_dwayland_window-type", "dock");
    }

    if (DGuiApplicationHelper::isXWindowPlatform()) {
        const auto display = QX11Info::display();
        if (!display) {
            qWarning() << "QX11Info::display() is " << display;
        } else {
            //2 确保这两行代码的先后顺序，否则会导致任务栏界面不再置顶
            XcbMisc::instance()->set_window_type(xcb_window_t(this->winId()), XcbMisc::Dock);
        }
    }

    setMouseTracking(true);
    setAcceptDrops(true);

    m_dragWidget->setMouseTracking(true);
    m_dragWidget->setFocusPolicy(Qt::NoFocus);

    if ((Dock::Top == m_position) || (Dock::Bottom == m_position))
        m_dragWidget->setCursor(Qt::SizeVerCursor);
    else
        m_dragWidget->setCursor(Qt::SizeHorCursor);
}

void MainWindowBase::initConnection()
{
    connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasCompositeChanged, m_shadowMaskOptimizeTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
    connect(m_shadowMaskOptimizeTimer, &QTimer::timeout, this, &MainWindowBase::adjustShadowMask, Qt::QueuedConnection);

    connect(m_dragWidget, &DragWidget::dragFinished, this, [ = ] {
        Utils::setIsDraging(false);
    });

    // -拖拽任务栏改变高度或宽度-------------------------------------------------------------------------------
    connect(m_updateDragAreaTimer, &QTimer::timeout, this, &MainWindowBase::resetDragWindow);
    //TODO 后端考虑删除这块，目前还不能删除，调整任务栏高度的时候，任务栏外部区域有变化
    connect(m_updateDragAreaTimer, &QTimer::timeout, m_multiScreenWorker, &MultiScreenWorker::onRequestUpdateRegionMonitor);

    connect(m_dragWidget, &DragWidget::dragPointOffset, this, &MainWindowBase::onMainWindowSizeChanged);
    connect(m_dragWidget, &DragWidget::dragFinished, this, &MainWindowBase::resetDragWindow);   //　更新拖拽区域
    connect(TouchSignalManager::instance(), &TouchSignalManager::touchMove, m_dragWidget, &DragWidget::onTouchMove);
    connect(TouchSignalManager::instance(), &TouchSignalManager::middleTouchPress, this, &MainWindowBase::touchRequestResizeDock);

    connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindowBase::onThemeTypeChanged);
    connect(m_multiScreenWorker, &MultiScreenWorker::opacityChanged, this, &MainWindowBase::setMaskAlpha, Qt::QueuedConnection);

    onThemeTypeChanged(DGuiApplicationHelper::instance()->themeType());
    QMetaObject::invokeMethod(this, &MainWindowBase::onCompositeChanged);
}

void MainWindowBase::initMember()
{
    //INFO 这里要大于动画的300ms，否则可能动画过程中这个定时器就被触发了
    m_updateDragAreaTimer->setInterval(500);
    m_updateDragAreaTimer->setSingleShot(true);
    m_shadowMaskOptimizeTimer->setSingleShot(true);
    m_shadowMaskOptimizeTimer->setInterval(100);
}

int MainWindowBase::getBorderRadius() const
{
    if (!DWindowManagerHelper::instance()->hasComposite() || m_multiScreenWorker->displayMode() != DisplayMode::Fashion)
        return 0;

    int size = ((m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) ? height() : width());
    return qMin(MAX_MIN_RADIUS_DIFFVALUE, qMax(size - MIN_RADIUS_WINDOWSIZE, 0)) + MIN_RADIUS;
}

QRect MainWindowBase::getAnimationRect(const QRect &sourceRect, const Dock::Position &pos) const
{
    if (!Utils::IS_WAYLAND_DISPLAY
            || m_multiScreenWorker->hideMode() == HideMode::KeepShowing
            || m_multiScreenWorker->displayMode() == Dock::DisplayMode::Fashion)
        return sourceRect;

    // 在wayland环境下，如果任务栏状态为智能隐藏或者一直隐藏，那么在高效模式下，任务栏距离边缘的距离如果为0
    // 会导致在WindowManager类中设置窗管的_d_dwayland_dockstrut属性失效，因此，此处将动画位置距离边缘设置为1
    // 此时就不会出现_d_dwayland_dockstrut属性失效的情况（1个像素并不影响动画效果）
    // 在时尚模式下无需做这个设置，因为时尚模式下距离边缘的距离为10
    QRect animationRect = sourceRect;
    switch (pos) {
    case Dock::Position::Bottom: {
        animationRect.setTop(animationRect.top() - 1);
        animationRect.setHeight(sourceRect.height());
        break;
    }
    case Dock::Position::Left: {
        animationRect.setLeft(1);
        animationRect.setWidth(sourceRect.width());
        break;
    }
    case Dock::Position::Top: {
        animationRect.setTop(1);
        animationRect.setHeight(sourceRect.height());
        break;
    }
    case Dock::Position::Right: {
        animationRect.setLeft(animationRect.left() - 1);
        animationRect.setWidth(sourceRect.width());
        break;
    }
    }
    return animationRect;
}

/**
 * @brief MainWindow::onMainWindowSizeChanged 任务栏拖拽过程中会不停调用此方法更新自身大小
 * @param offset 拖拽时的坐标偏移量
 */
void MainWindowBase::onMainWindowSizeChanged(QPoint offset)
{
    QScreen *screen = DIS_INS->screen(DOCK_SCREEN->current());
    if (!screen)
        return;

    const QRect rect = getDockGeometry(screen, position(), displayMode(), Dock::HideState::Show);
    QRect newRect;
    switch (m_multiScreenWorker->position()) {
    case Top: {
        newRect.setX(rect.x());
        newRect.setY(rect.y());
        newRect.setWidth(rect.width());
        newRect.setHeight(qBound(DOCK_MIN_SIZE, rect.height() + offset.y(), DOCK_MAX_SIZE));
    }
        break;
    case Bottom: {
        newRect.setX(rect.x());
        newRect.setY(rect.y() + rect.height() - qBound(DOCK_MIN_SIZE, rect.height() - offset.y(), DOCK_MAX_SIZE));
        newRect.setWidth(rect.width());
        newRect.setHeight(qBound(DOCK_MIN_SIZE, rect.height() - offset.y(), DOCK_MAX_SIZE));
    }
        break;
    case Left: {
        newRect.setX(rect.x());
        newRect.setY(rect.y());
        newRect.setWidth(qBound(DOCK_MIN_SIZE, rect.width() + offset.x(), DOCK_MAX_SIZE));
        newRect.setHeight(rect.height());
    }
        break;
    case Right: {
        newRect.setX(rect.x() + rect.width() - qBound(DOCK_MIN_SIZE, rect.width() - offset.x(), DOCK_MAX_SIZE));
        newRect.setY(rect.y());
        newRect.setWidth(qBound(DOCK_MIN_SIZE, rect.width() - offset.x(), DOCK_MAX_SIZE));
        newRect.setHeight(rect.height());
    }
        break;
    }

    Utils::setIsDraging(true);

    setFixedSize(newRect.size());
    move(newRect.topLeft());
    resetPanelGeometry();

    Q_EMIT requestUpdate();
}

void MainWindowBase::updateDragGeometry()
{
    switch (position()) {
    case Dock::Top:
        m_dragWidget->setGeometry(0, height() - DRAG_AREA_SIZE, width(), DRAG_AREA_SIZE);
        break;
    case Dock::Bottom:
        m_dragWidget->setGeometry(0, 0, width(), DRAG_AREA_SIZE);
        break;
    case Dock::Left:
        m_dragWidget->setGeometry(width() - DRAG_AREA_SIZE, 0, DRAG_AREA_SIZE, height());
        break;
    case Dock::Right:
        m_dragWidget->setGeometry(0, 0, DRAG_AREA_SIZE, height());
        break;
    }

    m_dragWidget->raise();
    if ((Top == position()) || (Bottom == position())) {
        m_dragWidget->setCursor(Qt::SizeVerCursor);
    } else {
        m_dragWidget->setCursor(Qt::SizeHorCursor);
    }
}

void MainWindowBase::resetDragWindow()
{
    updateDragGeometry();
    QScreen *screen = DIS_INS->screen(DOCK_SCREEN->current());
    if (!screen)
        return;

    if (m_multiScreenWorker->hideState() == Dock::HideState::Show) {
        QRect currentRect = getDockGeometry(screen, position(), displayMode(), Dock::HideState::Show);

        // 这个时候屏幕有可能是隐藏的，不能直接使用this->width()这种去设置任务栏的高度，而应该保证原值
        int dockSize = 0;
        if (m_multiScreenWorker->position() == Position::Left
                || m_multiScreenWorker->position() == Position::Right) {
            dockSize = this->width() == 0 ? currentRect.width() : this->width();
        } else {
            dockSize = this->height() == 0 ? currentRect.height() : this->height();
        }

        /** FIX ME
        * 作用：限制dockSize的值在40～100之间。
        * 问题1：如果dockSize为39，会导致dock的mainwindow高度变成99，显示的内容高度却是39。
        * 问题2：dockSize的值在这里不应该为39，但在高分屏上开启缩放后，拉高任务栏操作会概率出现。
        * 暂时未分析出原因，后面再修改。
        */
        dockSize = qBound(DOCK_MIN_SIZE, dockSize, DOCK_MAX_SIZE);

        // 通知窗管和后端更新数据
        m_multiScreenWorker->updateDaemonDockSize(dockSize);                                // 1.先更新任务栏高度
    }

    m_multiScreenWorker->requestUpdateFrontendGeometry();                               // 2.再更新任务栏位置,保证先1再2
    m_multiScreenWorker->requestNotifyWindowManager();
    m_multiScreenWorker->requestUpdateRegionMonitor();                                  // 界面发生变化，应更新监控区域
}

void MainWindowBase::touchRequestResizeDock()
{
    const QPoint touchPos(QCursor::pos());
    QRect dockRect = geometry();
    // 隐藏状态返回
    if (width() == 0 || height() == 0)
        return;

    int resizeHeight = Utils::SettingValue("com.deepin.dde.dock.touch", QByteArray(), "resizeHeight", 7).toInt();

    QRect touchRect;
    // 任务栏屏幕 内侧边线 内外resizeHeight距离矩形区域内长按可拖动任务栏高度
    switch (position()) {
    case Position::Top:
        touchRect = QRect(dockRect.x(), dockRect.y() + dockRect.height() - resizeHeight, dockRect.width(), resizeHeight * 2);
        break;
    case Position::Bottom:
        touchRect = QRect(dockRect.x(), dockRect.y() - resizeHeight, dockRect.width(), resizeHeight * 2);
        break;
    case Position::Left:
        touchRect = QRect(dockRect.x() + dockRect.width() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height());
        break;
    case Position::Right:
        touchRect = QRect(dockRect.x() - resizeHeight, dockRect.y(), resizeHeight * 2, dockRect.height());
        break;
    }

    if (!touchRect.contains(touchPos))
        return;

    qApp->postEvent(m_dragWidget, new QMouseEvent(QEvent::MouseButtonPress, m_dragWidget->mapFromGlobal(touchPos)
                                                  , QPoint(), touchPos, Qt::LeftButton, Qt::NoButton
                                                  , Qt::NoModifier, Qt::MouseEventSynthesizedByApplication));
}

void MainWindowBase::adjustShadowMask()
{
    if (!m_isShow || m_shadowMaskOptimizeTimer->isActive())
        return;

    m_platformWindowHandle.setWindowRadius(getBorderRadius());
}

void MainWindowBase::onCompositeChanged()
{
    setMaskColor(AutoColor);

    setMaskAlpha(m_multiScreenWorker->opacity());
    m_platformWindowHandle.setBorderWidth(0);

    m_shadowMaskOptimizeTimer->start();
}

void MainWindowBase::onThemeTypeChanged(DGuiApplicationHelper::ColorType themeType)
{
    if (DWindowManagerHelper::instance()->hasComposite()) {
        if (themeType == DGuiApplicationHelper::DarkType) {
            QColor color = Qt::black;
            color.setAlpha(255 * 0.3);
            m_platformWindowHandle.setBorderColor(color);
        } else {
            m_platformWindowHandle.setBorderColor(QColor(QColor::Invalid));
        }
    }
}

void MainWindowBase::setDisplayMode(const Dock::DisplayMode &displayMode)
{
    m_displayMode = displayMode;
    adjustShadowMask();
    m_platformWindowHandle.setShadowOffset(QPoint(0, (displayMode == Dock::DisplayMode::Fashion ? 5 : 0)));
}

void MainWindowBase::setPosition(const Dock::Position &position)
{
    m_position = position;
}

QRect MainWindowBase::getDockGeometry(QScreen *screen, const Dock::Position &pos, const Dock::DisplayMode &displaymode, const Dock::HideState &hideState, bool withoutScale) const
{
    QList<MainWindowBase const *> topMainWindows;           // 所有的顶层主窗口列表
    QList<MainWindowBase const *> lessOrderMainWindows;     // 所有在当前窗口之前的主窗口
    QWidgetList topWidgets = qApp->topLevelWidgets();
    for (QWidget *widget : topWidgets) {
        MainWindowBase *currentWindow = qobject_cast<MainWindowBase *>(widget);
        if (!currentWindow || !currentWindow->isVisible())
            continue;

        topMainWindows << currentWindow;
        if (currentWindow->order() < order())
            lessOrderMainWindows << currentWindow;
    }

    if (!topMainWindows.contains(this))
        return QRect();

    // 对当前窗口前面的所有窗口按照order进行排序
    std::sort(lessOrderMainWindows.begin(), lessOrderMainWindows.end(), [](MainWindowBase const *window1, MainWindowBase const *window2) {
        return window1->order() < window2->order();
    });
    QRect rect;
    const double ratio = withoutScale ? 1 : qApp->devicePixelRatio();
    const int margin = static_cast<int>((displaymode == DisplayMode::Fashion ? 10 : 0) * (withoutScale ? qApp->devicePixelRatio() : 1));
    int dockSize = 0;
    if (hideState == Dock::HideState::Show)
        dockSize = windowSize() * (withoutScale ? qApp->devicePixelRatio() : 1);

    // 拿到当前显示器缩放之前的分辨率
    QRect screenRect = screen->handle()->geometry();
    // 计算所有的窗口的总尺寸
    int totalSize = 0;
    switch (pos) {
    case Dock::Position::Top:
    case Dock::Position::Bottom: {
        // 计算任务栏的总的尺寸
        int width = 0;
        for (MainWindowBase const *mainWindow : topMainWindows) {
            QSize windowSize = mainWindow->suitableSize(pos, screenRect.width(), ratio);
            totalSize += windowSize.width() + mainWindow->dockSpace();
            if (mainWindow == this)
                width = windowSize.width();
        }

        // 计算第一个窗口的X坐标
        int x = screenRect.x() + (static_cast<int>((screenRect.width() / ratio) - totalSize) / 2);
        // 计算当前的X坐标
        for (MainWindowBase const *mainWindow : lessOrderMainWindows) {
            x += mainWindow->suitableSize(pos, screenRect.width(), ratio).width() + mainWindow->dockSpace();
        }
        int y = 0;
        if (pos == Dock::Position::Top)
            y = (screenRect.y() + static_cast<int>(margin));
        else
            y = (screenRect.y() + static_cast<int>(screenRect.height() / ratio - margin)) - dockSize;
        rect.setX(x);
        rect.setY(y);
        rect.setWidth(width);
        rect.setHeight(dockSize);
        break;
    }
    case Dock::Position::Left:
    case Dock::Position::Right: {
        int height = 0;
        for (MainWindowBase const *mainWindow : topMainWindows) {
            QSize windowSize = mainWindow->suitableSize(pos, screenRect.height(), ratio);
            totalSize += windowSize.height() + mainWindow->dockSpace();
            if (mainWindow == this)
                height = windowSize.height();
        }
        int x = 0;
        if (pos == Dock::Position::Left)
            x = screenRect.x() + static_cast<int>(margin);
        else
            x = screenRect.x() + static_cast<int>(screenRect.width() /ratio - margin) - dockSize;

        int y = screenRect.y() + static_cast<int>(((screenRect.height() / ratio) - totalSize) / 2);
        // 计算y坐标
        for (MainWindowBase const *mainWindow : lessOrderMainWindows)
            y += mainWindow->suitableSize(pos, screenRect.height(), ratio).height() + mainWindow->dockSpace();

        rect.setX(x);
        rect.setY(y);
        rect.setWidth(dockSize);
        rect.setHeight(height);
        break;
    }
    }
    return rect;
}

QVariantAnimation *MainWindowBase::createAnimation(QScreen *screen, const Dock::Position &pos, const Dock::AniAction &act)
{
    /** FIXME
     * 在高分屏2.75倍缩放的情况下，mainWindowGeometry返回的任务栏高度有问题（实际是40,返回是39）
     * 在这里增加判断，当返回值在范围（38，42）开区间内，均认为任务栏显示位置正确，直接返回，不执行动画
     * 也就是在实际值基础上下浮动1像素的误差范围
     * 正常屏幕情况下是没有这个问题的
     */
    QRect mainwindowRect = geometry();
    const QRect dockShowRect = getAnimationRect(getDockGeometry(screen, pos, m_multiScreenWorker->displayMode(), Dock::HideState::Show), pos);
    const QRect &dockHideRect = getAnimationRect(getDockGeometry(screen, pos, m_multiScreenWorker->displayMode(), Dock::HideState::Hide), pos);
    if (act == Dock::AniAction::Show) {
        if (pos == Position::Top || pos == Position::Bottom) {
            if (qAbs(dockShowRect.height() - mainwindowRect.height()) <= 1
                    && mainwindowRect.contains(dockShowRect.center()))
                return nullptr;
        } else if (pos == Position::Left || pos == Position::Right) {
            if (qAbs(dockShowRect.width() - mainwindowRect.width()) <= 1
                    && mainwindowRect.contains(dockShowRect.center()))
                return nullptr;
        }
    }
    if (act == Dock::AniAction::Hide && dockHideRect.size() == mainwindowRect.size())
        return nullptr;

    // 开始播放动画
    QVariantAnimation *ani = new QVariantAnimation(nullptr);
    ani->setEasingCurve(QEasingCurve::InOutCubic);
#ifndef DISABLE_SHOW_ANIMATION
    const bool composite = DWindowManagerHelper::instance()->hasComposite(); // 判断是否开启特效模式
    const int duration = composite ? ANIMATIONTIME : 0;
#else
    const int duration = 0;
#endif
    ani->setDuration(duration);

    connect(ani, &QVariantAnimation::valueChanged, this, [ = ](const QVariant &value) {
        if ((!m_multiScreenWorker->testState(MultiScreenWorker::ShowAnimationStart)
                && !m_multiScreenWorker->testState(MultiScreenWorker::HideAnimationStart)
                && !m_multiScreenWorker->testState(MultiScreenWorker::ChangePositionAnimationStart))
                || ani->state() != QVariantAnimation::State::Running)
            return;

        updateParentGeometry(pos, value.value<QRect>());
    });

    switch (act) {
    case Dock::AniAction::Show: {
        ani->setStartValue(dockHideRect);
        ani->setEndValue(dockShowRect);
        connect(ani, &QVariantAnimation::finished, this, [ = ]{
            updateParentGeometry(pos, dockShowRect);
        });
        break;
    }
    case Dock::AniAction::Hide: {
        ani->setStartValue(dockShowRect);
        ani->setEndValue(dockHideRect);
        connect(ani, &QVariantAnimation::finished, this, [ = ]{
            updateParentGeometry(pos, dockHideRect);
        });
        break;
    }
    }

    return ani;
}

Dock::DisplayMode MainWindowBase::displayMode() const
{
    return m_displayMode;
}

Dock::Position MainWindowBase::position() const
{
    return m_position;
}

int MainWindowBase::windowSize() const
{
    if (m_displayMode == Dock::DisplayMode::Efficient)
        return DockSettings::instance()->getWindowSizeEfficient();

    return DockSettings::instance()->getWindowSizeFashion();
}

bool MainWindowBase::isDraging() const
{
    return m_dragWidget->isDraging();
}

int MainWindowBase::dockSpace() const
{
    return DOCKSPACE;
}

void MainWindowBase::initUi()
{
    DPlatformWindowHandle::enableDXcbForWindow(this, true);
    m_platformWindowHandle.setEnableBlurWindow(true);
    m_platformWindowHandle.setTranslucentBackground(true);
    m_platformWindowHandle.setShadowOffset(QPoint(0, 0));
    QColor shadorColor = Qt::black;
    shadorColor.setAlpha(static_cast<int>(0.3 * 255));
    m_platformWindowHandle.setShadowColor(shadorColor);
}

void MainWindowBase::resizeEvent(QResizeEvent *event)
{
    updateDragGeometry();

    m_shadowMaskOptimizeTimer->start();

    if (!isDraging())
        m_updateDragAreaTimer->start();
}

void MainWindowBase::moveEvent(QMoveEvent *)
{
    updateDragGeometry();

    if (!isDraging())
        m_updateDragAreaTimer->start();
}

void MainWindowBase::enterEvent(QEvent *e)
{
    QWidget::enterEvent(e);

    if (QApplication::overrideCursor() && QApplication::overrideCursor()->shape() != Qt::ArrowCursor)
        QApplication::restoreOverrideCursor();
}

void MainWindowBase::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton && geometry().contains(QCursor::pos())) {
        m_multiScreenWorker->onAutoHideChanged(false);
        MenuWorker menuWorker;
        menuWorker.exec();
        m_multiScreenWorker->onAutoHideChanged(true);
    }

    DBlurEffectWidget::mousePressEvent(event);
}

void MainWindowBase::showEvent(QShowEvent *event)
{
    if (!m_isShow) {
        m_isShow = true;
        m_shadowMaskOptimizeTimer->start();
    }

    DBlurEffectWidget::showEvent(event);
}
