diff --git a/src/main_window.cpp b/src/main_window.cpp index 776c9ff1..4cf51667 100755 --- a/src/main_window.cpp +++ b/src/main_window.cpp @@ -342,10 +342,7 @@ void MainWindow::initTreelandtAttributes() //initTreelandtAttributes installEventFilter(this); createWinId(); - //构建截屏工具栏和相关组件 - m_toolBar =new ToolBar(this); - m_toolBar->move(100,128); - m_toolBar->show(); + // Treeland 截图工具栏在 sourceReady(captureRegionChanged) 后由 updateCaptureRegion 创建 m_sideBar = new SideBar(this); m_sideBar->initSideBar(this); @@ -367,8 +364,6 @@ void MainWindow::initTreelandtAttributes() //initTreelandtAttributes } m_zoomIndicator->hideMagnifier(); } - // 设置窗口大小和位置 - connect(m_toolBar, &ToolBar::currentFunctionToMain, this, &MainWindow::changeFunctionButton); m_backgroundRect = rootWindowRect; m_backgroundRect = QRect(m_backgroundRect.topLeft() / m_pixelRatio, m_backgroundRect.size()); move(m_backgroundRect.topLeft() * m_pixelRatio); @@ -915,9 +910,11 @@ void MainWindow::checkIsLockScreen() qCInfo(dsrApp) << "Current Screen is LockScreen?" << isLockScreen; if (isLockScreen) { pinScreenshotsLockScreen(isLockScreen); - m_toolBar->setScrollShotDisabled(true); - m_toolBar->setOcrScreenshotsEnable(false); - m_toolBar->setButEnableOnLockScreen(false); + if (m_toolBar) { + m_toolBar->setScrollShotDisabled(true); + m_toolBar->setOcrScreenshotsEnable(false); + m_toolBar->setButEnableOnLockScreen(false); + } } // 电源界面判断接口 QDBusInterface ddeLockFront( @@ -935,9 +932,11 @@ void MainWindow::checkIsLockScreen() qCInfo(dsrApp) << "Current Screen is Powersource UI?" << isLockFront; if (isLockFront) { pinScreenshotsLockScreen(isLockScreen); - m_toolBar->setScrollShotDisabled(true); - m_toolBar->setOcrScreenshotsEnable(false); - m_toolBar->setButEnableOnLockScreen(false); + if (m_toolBar) { + m_toolBar->setScrollShotDisabled(true); + m_toolBar->setOcrScreenshotsEnable(false); + m_toolBar->setButEnableOnLockScreen(false); + } } } void MainWindow::initDynamicLibPath() @@ -1407,30 +1406,36 @@ void MainWindow::initScreenShot() // 构建截屏工具栏按钮 by zyg if (m_firstShot == 0) { qCDebug(dsrApp) << "initScreenShot m_firstShot == 0"; - m_toolBar->hide(); + if (m_toolBar) { + m_toolBar->hide(); + } m_sideBar->hide(); // m_recordButton->hide(); // m_shotButton->hide(); m_sizeTips->hide(); - } - - else { + } else { qCDebug(dsrApp) << "initScreenShot m_firstShot != 0"; - m_toolBar->show(); + if (m_toolBar) { + m_toolBar->show(); + } m_sideBar->hide(); // m_recordButton->hide(); // m_shotButton->show(); m_sizeTips->show(); - updateToolBarPos(); + if (m_toolBar) { + updateToolBarPos(); + } // updateShotButtonPos(); m_sizeTips->setRecorderTipsInfo(false); m_sizeTips->updateTips(QPoint(recordX, recordY), QSize(recordWidth, recordHeight)); } - m_toolBar->setFocus(); + if (m_toolBar) { + m_toolBar->setFocus(); + } qCDebug(dsrApp) << "initScreenShot end"; } @@ -1496,24 +1501,28 @@ void MainWindow::initScreenRecorder() // 构建截屏工具栏按钮 by zyg if (m_firstShot == 0) { qCDebug(dsrApp) << "initScreenRecorder m_firstShot == 0"; - m_toolBar->hide(); + if (m_toolBar) { + m_toolBar->hide(); + } m_sideBar->hide(); // m_recordButton->hide(); // m_shotButton->hide(); m_sizeTips->hide(); - } - - else { + } else { qCDebug(dsrApp) << "initScreenRecorder m_firstShot != 0"; - m_toolBar->show(); + if (m_toolBar) { + m_toolBar->show(); + } m_sideBar->hide(); // m_recordButton->show(); // m_shotButton->hide(); m_sizeTips->show(); - updateToolBarPos(); + if (m_toolBar) { + updateToolBarPos(); + } // updateRecordButtonPos(); m_sizeTips->setRecorderTipsInfo(true); m_sizeTips->updateTips(QPoint(recordX, recordY), QSize(recordWidth, recordHeight)); @@ -1533,7 +1542,9 @@ void MainWindow::initScreenRecorder() } } - m_toolBar->setFocus(); + if (m_toolBar) { + m_toolBar->setFocus(); + } qCDebug(dsrApp) << "initScreenRecorder end"; } @@ -2819,7 +2830,7 @@ void MainWindow::wheelEvent(QWheelEvent *event) void MainWindow::pinScreenshotsLockScreen(bool isLocked) { - if (m_toolBarInit) { + if (m_toolBar) { m_toolBar->setPinScreenshotsEnable(!isLocked); } } @@ -2915,7 +2926,10 @@ void MainWindow::compositeChanged() { // 滚动截图过程中动态切换为2D模式,直接结束 if (m_functionType == status::shot) { - m_toolBar->setScrollShotDisabled(!m_wmHelper->hasBlurWindow()); + // Treeland:工具栏在 sourceReady 后才创建,Wayland 初始化可能先触发 hasBlurWindowChanged + if (m_toolBar) { + m_toolBar->setScrollShotDisabled(!m_wmHelper->hasBlurWindow()); + } return; } if (!m_wmHelper->hasBlurWindow() && m_functionType == status::scrollshot) { @@ -2952,7 +2966,7 @@ void MainWindow::compositeChanged() void MainWindow::updateToolBarPos() { - if (m_shotflag == 1) { + if (m_shotflag == 1 || !m_toolBar) { return; } m_isToolBarInside = false; @@ -5243,16 +5257,18 @@ int MainWindow::mouseMoveEF(QMouseEvent *mouseEvent, bool &needRepaint) m_currentCursor = mouseEvent->pos(); // 没打开截图的编辑模式 if (!m_isShapesWidgetExist) { - if (m_toolBar->isVisible()) { + if (m_toolBar && m_toolBar->isVisible()) { updateToolBarPos(); - m_zoomIndicator->hideMagnifier(); + if (m_zoomIndicator) { + m_zoomIndicator->hideMagnifier(); + } } if (!isFirstMove) { isFirstMove = true; } else { if (status::shot == m_functionType) { - if (!m_toolBar->isVisible() && !isFirstReleaseButton) { + if (m_toolBar && !m_toolBar->isVisible() && !isFirstReleaseButton) { // QPoint curPos = this->cursor().pos(); 采用全局坐标,替换局部坐标 // mouseEvent->globalPos()此接口获取的光标坐标是已经缩放后的坐标,需还原 QPoint curPos = this->cursor().pos(); // 采用全局坐标,替换局部坐标 @@ -7748,7 +7764,7 @@ void MainWindow::initializeCapture() ); connect(manager->context(), &TreelandCaptureContext::captureRegionChanged, - this, &MainWindow::updateCaptureRegion); + this, &MainWindow::updateCaptureRegion, Qt::UniqueConnection); connect(manager, &TreelandCaptureManager::finishSelect, this, &MainWindow::handleCaptureFinish); @@ -7854,32 +7870,68 @@ void MainWindow::onFinishClicked() TreelandCaptureManager::instance()->finishSelect(); } +void MainWindow::destroyTreelandToolBar() +{ + if (!m_toolBar) { + return; + } + + ToolBar *toolBar = m_toolBar; + m_toolBar = nullptr; + m_toolBarInit = false; + + if (toolBar->windowHandle()) { + toolBar->windowHandle()->setParent(nullptr); + } + toolBar->blockSignals(true); + disconnect(toolBar, nullptr, nullptr, nullptr); + disconnect(nullptr, nullptr, toolBar, nullptr); + toolBar->hide(); + delete toolBar; + // 选项菜单里的边框子菜单由 ImageBorderHelper 缓存,需清理悬空指针 + ImageBorderHelper::instance()->pruneBorderMenus(); +} + void MainWindow::updateCaptureRegion() { auto context = TreelandCaptureManager::instance()->context(); - if (!context) return; - QRect region = context->captureRegion().toRect(); + if (!context) { + return; + } + + const QRect region = context->captureRegion().toRect(); + // 无效选区:只销毁旧工具栏,等下一次 sourceReady 再创建 + if (region.width() <= 0 || region.height() <= 0) { + destroyTreelandToolBar(); + return; + } + + // 每次重新选区:先析构上一块工具栏(含 Wayland subsurface),再按新选区 new + destroyTreelandToolBar(); m_toolBar = new ToolBar(this); + connect(m_toolBar, &ToolBar::currentFunctionToMain, this, &MainWindow::changeFunctionButton); m_toolBar->initToolBar(this, isHideToolBar); + m_toolBar->setRecordLaunchMode(m_functionType); + m_toolBarInit = true; m_toolBar->setAttribute(Qt::WA_TranslucentBackground); m_toolBar->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); + recordX = region.x(); + recordY = region.y(); + recordWidth = region.width(); + recordHeight = region.height(); + m_toolBar->showWidget(); - QPoint pos(region.x(), qMin(region.bottom(), height() - 2 * m_toolBar->height())); + const QPoint pos(region.x(), qMin(region.bottom(), height() - 2 * m_toolBar->height())); m_toolBar->showAt(pos); - m_toolBar->showWidget(); - - if(windowHandle()&&m_toolBar->windowHandle()) - { - if(m_toolBar->windowHandle()->parent() != windowHandle()) - { - m_toolBar->windowHandle()->setParent(windowHandle()); - m_toolBar->hide(); - m_toolBar->show(); - } + if (windowHandle() && m_toolBar->windowHandle() + && m_toolBar->windowHandle()->parent() != windowHandle()) { + m_toolBar->windowHandle()->setParent(windowHandle()); + m_toolBar->hide(); + m_toolBar->show(); } } diff --git a/src/main_window.h b/src/main_window.h index 98d8a06c..3c439124 100755 --- a/src/main_window.h +++ b/src/main_window.h @@ -470,6 +470,9 @@ public slots: */ void updateCaptureRegion(); + /** Treeland:销毁当前工具栏(含 subsurface 解绑),便于重选区后重建 */ + void destroyTreelandToolBar(); + Q_SCRIPTABLE void stopRecord(); Q_SCRIPTABLE void stopApp(); diff --git a/src/widgets/imagemenu.cpp b/src/widgets/imagemenu.cpp index 30c328bd..08d5423d 100755 --- a/src/widgets/imagemenu.cpp +++ b/src/widgets/imagemenu.cpp @@ -254,15 +254,34 @@ ImageBorderHelper *ImageBorderHelper::instance() return m_imageBorderHelper; } +void ImageBorderHelper::pruneBorderMenus() +{ + for (auto it = m_allBorderMenu.begin(); it != m_allBorderMenu.end();) { + if (it.value().isNull()) { + it = m_allBorderMenu.erase(it); + } else { + ++it; + } + } +} + ImageMenu *ImageBorderHelper::getBorderMenu(const BorderType type, const QString title, QWidget *parent) { qCDebug(dsrApp) << "ImageBorderHelper::getBorderMenu called for type:" << type << ", title:" << title; - if (!m_allBorderMenu.contains(type)) { - qCDebug(dsrApp) << "Menu for type" << type << "not found, creating new one"; - m_allBorderMenu.insert(type, new ImageMenu(type, title, parent)); + pruneBorderMenus(); + + if (ImageMenu *cached = m_allBorderMenu.value(type)) { + if (cached->parent() == parent) { + return cached; + } + m_allBorderMenu.remove(type); + delete cached; } - qCDebug(dsrApp) << "Returning menu for type:" << type; - return m_allBorderMenu[type]; + + ImageMenu *menu = new ImageMenu(type, title, parent); + m_allBorderMenu.insert(type, menu); + qCDebug(dsrApp) << "Created border menu for type:" << type; + return menu; } void ImageBorderHelper::setActionState(const BorderType type, const bool isChecked) @@ -270,10 +289,14 @@ void ImageBorderHelper::setActionState(const BorderType type, const bool isCheck qCDebug(dsrApp) << "ImageBorderHelper::setActionState called for type:" << type << ", isChecked:" << isChecked; // 选中某边框,后清空其他类型的所有边框 for (auto itr = m_allBorderMenu.begin(); itr != m_allBorderMenu.end(); ++itr) { - qCDebug(dsrApp) << "Processing menu for border type:" << itr.value()->borderType(); - if (itr.value()->borderType() != type) { - qCDebug(dsrApp) << "Clearing action state for other border type:" << itr.value()->borderType(); - itr.value()->ActionChecked(nullptr); + ImageMenu *menu = itr.value(); + if (!menu) { + continue; + } + qCDebug(dsrApp) << "Processing menu for border type:" << menu->borderType(); + if (menu->borderType() != type) { + qCDebug(dsrApp) << "Clearing action state for other border type:" << menu->borderType(); + menu->ActionChecked(nullptr); } } @@ -287,6 +310,9 @@ int ImageBorderHelper::getBorderTypeDetail() int typeDetail = 0; for (auto itr = m_allBorderMenu.begin(); itr != m_allBorderMenu.end(); ++itr) { ImageMenu *menu = itr.value(); + if (!menu) { + continue; + } qCDebug(dsrApp) << "Getting border type detail for menu of type:" << menu->borderType(); typeDetail = menu->getBorderTypeDetail(); if (typeDetail != 0) { @@ -306,9 +332,9 @@ void ImageBorderHelper::setBorderTypeDetail(const int typeDetail) int id = typeDetail & 0xFF; qCDebug(dsrApp) << "Parsed type:" << type << ", ID:" << id; - if (m_allBorderMenu.contains(type)) { + if (ImageMenu *menu = m_allBorderMenu.value(type)) { qCDebug(dsrApp) << "Menu for type" << type << "found, setting border type detail"; - m_allBorderMenu[type]->setBorderTypeDetail(id); + menu->setBorderTypeDetail(id); } } @@ -387,9 +413,12 @@ ImageBorderHelper::~ImageBorderHelper() { qCDebug(dsrApp) << "ImageBorderHelper destructor entered"; for (auto itr = m_allBorderMenu.begin(); itr != m_allBorderMenu.end(); ++itr) { - qCDebug(dsrApp) << "Deleting border menu for type:" << itr.value()->borderType(); - delete *itr; + if (ImageMenu *menu = itr.value()) { + qCDebug(dsrApp) << "Deleting border menu for type:" << menu->borderType(); + delete menu; + } } + m_allBorderMenu.clear(); if (m_borderhandle != nullptr) { qCDebug(dsrApp) << "Deleting border handler"; delete m_borderhandle; diff --git a/src/widgets/imagemenu.h b/src/widgets/imagemenu.h index 0299fb4c..23530ad4 100644 --- a/src/widgets/imagemenu.h +++ b/src/widgets/imagemenu.h @@ -9,6 +9,7 @@ #include #include #include +#include DWIDGET_USE_NAMESPACE class BorderProcessInterface; @@ -26,6 +27,8 @@ class ImageBorderHelper : public QObject static ImageBorderHelper *instance(); ImageMenu* getBorderMenu(const BorderType type, const QString title, QWidget *parent = nullptr); + /** 工具栏/选项菜单销毁后清理悬空缓存(如 Treeland 重选区重建工具栏) */ + void pruneBorderMenus(); void setActionState(const BorderType type, const bool isChecked); int getBorderTypeDetail(); void setBorderTypeDetail(const int typeDetail); @@ -41,7 +44,7 @@ class ImageBorderHelper : public QObject ~ImageBorderHelper(); private: static ImageBorderHelper *m_imageBorderHelper; - QMap m_allBorderMenu; + QMap> m_allBorderMenu; BorderProcessInterface *m_borderhandle; }; diff --git a/src/widgets/toolbar.cpp b/src/widgets/toolbar.cpp index f29ce0e1..f01087ea 100755 --- a/src/widgets/toolbar.cpp +++ b/src/widgets/toolbar.cpp @@ -323,38 +323,44 @@ void ToolBar::mouseReleaseEvent(QMouseEvent *event) void ToolBar::setScrollShotDisabled(const bool state) { + if (!m_toolbarWidget) { + return; + } m_toolbarWidget->setScrollShotDisabled(state); } void ToolBar::setPinScreenshotsEnable(const bool &state) { - m_toolbarWidget->setPinScreenshotsEnable(state); + if (m_toolbarWidget) + m_toolbarWidget->setPinScreenshotsEnable(state); } void ToolBar::setOcrScreenshotsEnable(const bool &state) { - m_toolbarWidget->setOcrScreenshotsEnable(state); + if (m_toolbarWidget) + m_toolbarWidget->setOcrScreenshotsEnable(state); } void ToolBar::setButEnableOnLockScreen(const bool &state) { - m_toolbarWidget->setButEnableOnLockScreen(state); + if (m_toolbarWidget) + m_toolbarWidget->setButEnableOnLockScreen(state); } int ToolBar::getFuncSubToolX(QString &func) { - return m_toolbarWidget->getFuncSubToolX(func); + return m_toolbarWidget ? m_toolbarWidget->getFuncSubToolX(func) : 0; } QRect ToolBar::getAiButtonGlobalRect() const { - return m_toolbarWidget->getAiButtonGlobalRect(); + return m_toolbarWidget ? m_toolbarWidget->getAiButtonGlobalRect() : QRect(); } QPoint ToolBar::getAiButtonGlobalCenter() const { - return m_toolbarWidget->getAiButtonGlobalCenter(); + return m_toolbarWidget ? m_toolbarWidget->getAiButtonGlobalCenter() : QPoint(); } bool ToolBar::isDraged() @@ -414,18 +420,21 @@ void ToolBar::hideWidget(){ void ToolBar::setRecordButtonDisable() { - m_toolbarWidget->setRecordButtonDisable(); + if (m_toolbarWidget) + m_toolbarWidget->setRecordButtonDisable(); } void ToolBar::setRecordLaunchMode(const unsigned int funType) { qCDebug(dsrApp) << "Setting record launch mode:" << funType; - m_toolbarWidget->setRecordLaunchFromMain(funType); + if (m_toolbarWidget) + m_toolbarWidget->setRecordLaunchFromMain(funType); } void ToolBar::setVideoButtonInit() { - m_toolbarWidget->setVideoInitFromMain(); + if (m_toolbarWidget) + m_toolbarWidget->setVideoInitFromMain(); } void ToolBar::shapeClickedFromMain(QString shape) @@ -442,11 +451,12 @@ void ToolBar::shapeClickedFromMain(QString shape) void ToolBar::setCameraDeviceEnable(bool status) { qCDebug(dsrApp) << "Setting camera device enable:" << status; - m_toolbarWidget->setCameraDeviceEnable(status); + if (m_toolbarWidget) + m_toolbarWidget->setCameraDeviceEnable(status); } QRect ToolBar::getShotOptionRect(){ - return m_toolbarWidget->getShotOptionRect(); + return m_toolbarWidget ? m_toolbarWidget->getShotOptionRect() : QRect(); } ToolBar::~ToolBar() {