File indexing completed on 2024-05-19 16:30:44
0001 /* 0002 * breezewindowmanager.cpp 0003 * pass some window mouse press/release/move event actions to window manager 0004 * Largely inspired from BeSpin style 0005 * 0006 * SPDX-FileCopyrightText: 2007 Thomas Luebking <thomas.luebking@web.de> 0007 * SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0008 * 0009 * SPDX-License-Identifier: GPL-2.0-or-later OR MIT 0010 */ 0011 0012 #include "breezewindowmanager.h" 0013 #include "breezehelper.h" 0014 #include "breezepropertynames.h" 0015 0016 #include <QComboBox> 0017 #include <QDialog> 0018 #include <QDockWidget> 0019 #include <QGraphicsView> 0020 #include <QGroupBox> 0021 #include <QLabel> 0022 #include <QListView> 0023 #include <QMainWindow> 0024 #include <QMdiSubWindow> 0025 #include <QMenuBar> 0026 #include <QMouseEvent> 0027 #include <QProgressBar> 0028 #include <QScreen> 0029 #include <QScrollBar> 0030 #include <QStatusBar> 0031 #include <QStyle> 0032 #include <QStyleOptionGroupBox> 0033 #include <QTabBar> 0034 #include <QTabWidget> 0035 #include <QToolBar> 0036 #include <QToolButton> 0037 #include <QTreeView> 0038 0039 #include <QTextStream> 0040 0041 // needed to deal with device pixel ratio 0042 #include <QWindow> 0043 0044 #if BREEZE_HAVE_QTQUICK 0045 // needed to enable dragging from QQuickWindows 0046 #include <QQuickRenderControl> 0047 #include <QQuickWindow> 0048 #endif 0049 0050 namespace Util 0051 { 0052 template<class T> 0053 inline T makeT(std::initializer_list<typename T::key_type> &&reference) 0054 { 0055 return T(std::move(reference)); 0056 } 0057 } 0058 0059 namespace Breeze 0060 { 0061 //* provide application-wise event filter 0062 /** 0063 it us used to unlock dragging and make sure event look is properly restored 0064 after a drag has occurred 0065 */ 0066 class AppEventFilter : public QObject 0067 { 0068 public: 0069 //* constructor 0070 explicit AppEventFilter(WindowManager *parent) 0071 : QObject(parent) 0072 , _parent(parent) 0073 { 0074 } 0075 0076 //* event filter 0077 bool eventFilter(QObject *object, QEvent *event) override 0078 { 0079 if (event->type() == QEvent::MouseButtonRelease) { 0080 // stop drag timer 0081 if (_parent->_dragTimer.isActive()) { 0082 _parent->resetDrag(); 0083 } 0084 0085 // unlock 0086 if (_parent->isLocked()) { 0087 _parent->setLocked(false); 0088 } 0089 } 0090 0091 if (!_parent->enabled()) { 0092 return false; 0093 } 0094 0095 /* 0096 if a drag is in progress, the widget will not receive any event 0097 we trigger on the first MouseMove or MousePress events that are received 0098 by any widget in the application to detect that the drag is finished 0099 */ 0100 if (_parent->_dragInProgress && _parent->_target && (event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress)) { 0101 return appMouseEvent(object, event); 0102 } 0103 0104 return false; 0105 } 0106 0107 protected: 0108 //* application-wise event. 0109 /** needed to catch end of XMoveResize events */ 0110 bool appMouseEvent(QObject *, QEvent *event) 0111 { 0112 Q_UNUSED(event); 0113 0114 /* 0115 post some mouseRelease event to the target, in order to counter balance 0116 the mouse press that triggered the drag. Note that it triggers a resetDrag 0117 */ 0118 QMouseEvent mouseEvent(QEvent::MouseButtonRelease, _parent->_dragPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); 0119 qApp->sendEvent(_parent->_target.data(), &mouseEvent); 0120 0121 return false; 0122 } 0123 0124 private: 0125 //* parent 0126 WindowManager *_parent = nullptr; 0127 }; 0128 0129 //_____________________________________________________________ 0130 WindowManager::WindowManager(QObject *parent) 0131 : QObject(parent) 0132 { 0133 // install application wise event filter 0134 _appEventFilter = new AppEventFilter(this); 0135 qApp->installEventFilter(_appEventFilter); 0136 } 0137 0138 //_____________________________________________________________ 0139 void WindowManager::initialize() 0140 { 0141 setEnabled(StyleConfigData::windowDragMode() != StyleConfigData::WD_NONE); 0142 setDragMode(StyleConfigData::windowDragMode()); 0143 setDragDistance(QApplication::startDragDistance()); 0144 setDragDelay(QApplication::startDragTime()); 0145 0146 initializeWhiteList(); 0147 initializeBlackList(); 0148 } 0149 0150 //_____________________________________________________________ 0151 void WindowManager::registerWidget(QWidget *widget) 0152 { 0153 if (isBlackListed(widget) || isDragable(widget) || widget->inherits("QQuickWidget")) { 0154 /* 0155 install filter for dragable widgets. 0156 also install filter for blacklisted widgets 0157 to be able to catch the relevant events and prevent 0158 the drag to happen 0159 */ 0160 widget->removeEventFilter(this); 0161 widget->installEventFilter(this); 0162 } 0163 } 0164 0165 #if BREEZE_HAVE_QTQUICK 0166 //_____________________________________________________________ 0167 void WindowManager::registerQuickItem(QQuickItem *item) 0168 { 0169 if (!item) { 0170 return; 0171 } 0172 0173 if (auto window = item->window()) { 0174 auto contentItem = window->contentItem(); 0175 contentItem->setAcceptedMouseButtons(Qt::LeftButton); 0176 contentItem->removeEventFilter(this); 0177 contentItem->installEventFilter(this); 0178 } 0179 } 0180 #endif 0181 0182 //_____________________________________________________________ 0183 void WindowManager::unregisterWidget(QWidget *widget) 0184 { 0185 if (widget) { 0186 widget->removeEventFilter(this); 0187 } 0188 } 0189 0190 //_____________________________________________________________ 0191 void WindowManager::initializeWhiteList() 0192 { 0193 _whiteList = Util::makeT<ExceptionSet>({ExceptionId(QStringLiteral("MplayerWindow")), 0194 ExceptionId(QStringLiteral("ViewSliders@kmix")), 0195 ExceptionId(QStringLiteral("Sidebar_Widget@konqueror"))}); 0196 0197 foreach (const QString &exception, StyleConfigData::windowDragWhiteList()) { 0198 ExceptionId id(exception); 0199 if (!id.className().isEmpty()) { 0200 _whiteList.insert(ExceptionId(exception)); 0201 } 0202 } 0203 } 0204 0205 //_____________________________________________________________ 0206 void WindowManager::initializeBlackList() 0207 { 0208 _blackList = Util::makeT<ExceptionSet>( 0209 {ExceptionId(QStringLiteral("CustomTrackView@kdenlive")), ExceptionId(QStringLiteral("MuseScore")), ExceptionId(QStringLiteral("KGameCanvasWidget"))}); 0210 0211 foreach (const QString &exception, StyleConfigData::windowDragBlackList()) { 0212 ExceptionId id(exception); 0213 if (!id.className().isEmpty()) { 0214 _blackList.insert(ExceptionId(exception)); 0215 } 0216 } 0217 } 0218 0219 //_____________________________________________________________ 0220 bool WindowManager::eventFilter(QObject *object, QEvent *event) 0221 { 0222 if (!enabled()) { 0223 return false; 0224 } 0225 0226 switch (event->type()) { 0227 case QEvent::MouseButtonPress: 0228 return mousePressEvent(object, event); 0229 break; 0230 0231 case QEvent::MouseMove: 0232 if (object == _target.data() 0233 #if BREEZE_HAVE_QTQUICK 0234 || object == _quickTarget.data() 0235 #endif 0236 ) { 0237 return mouseMoveEvent(object, event); 0238 } 0239 break; 0240 0241 case QEvent::MouseButtonRelease: 0242 if (_target 0243 #if BREEZE_HAVE_QTQUICK 0244 || _quickTarget 0245 #endif 0246 ) { 0247 return mouseReleaseEvent(object, event); 0248 } 0249 break; 0250 0251 default: 0252 break; 0253 } 0254 0255 return false; 0256 } 0257 0258 //_____________________________________________________________ 0259 void WindowManager::timerEvent(QTimerEvent *event) 0260 { 0261 if (event->timerId() == _dragTimer.timerId()) { 0262 _dragTimer.stop(); 0263 setLocked(false); 0264 if (_target) { 0265 startDrag(_target.data()->window()->windowHandle()); 0266 } 0267 #if BREEZE_HAVE_QTQUICK 0268 else if (_quickTarget) { 0269 _quickTarget.data()->ungrabMouse(); 0270 startDrag(_quickTarget.data()->window()); 0271 } 0272 #endif 0273 resetDrag(); 0274 } else { 0275 return QObject::timerEvent(event); 0276 } 0277 } 0278 0279 //_____________________________________________________________ 0280 bool WindowManager::mousePressEvent(QObject *object, QEvent *event) 0281 { 0282 // cast event and check buttons/modifiers 0283 auto mouseEvent = static_cast<QMouseEvent *>(event); 0284 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { 0285 return false; 0286 } 0287 if (!(mouseEvent->modifiers() == Qt::NoModifier && mouseEvent->button() == Qt::LeftButton)) { 0288 return false; 0289 } 0290 0291 // If we are in a QQuickWidget we don't want to ever do dragging from a qwidget in the 0292 // hyerarchy, but only from an internal item, if any. If any event handler will manage 0293 // the event, we don't want the drag to start 0294 if (object->inherits("QQuickWidget")) { 0295 _eventInQQuickWidget = true; 0296 event->setAccepted(false); 0297 return false; 0298 } else { 0299 _eventInQQuickWidget = false; 0300 } 0301 0302 // check lock 0303 if (isLocked()) { 0304 return false; 0305 } else { 0306 setLocked(true); 0307 } 0308 0309 #if BREEZE_HAVE_QTQUICK 0310 // check QQuickItem - we can immediately start drag, because QQuickWindow's contentItem 0311 // only receives mouse events that weren't handled by children 0312 if (auto item = qobject_cast<QQuickItem *>(object)) { 0313 _quickTarget = item; 0314 _dragPoint = mouseEvent->pos(); 0315 _globalDragPoint = mouseEvent->globalPos(); 0316 0317 if (_dragTimer.isActive()) { 0318 _dragTimer.stop(); 0319 } 0320 _dragTimer.start(_dragDelay, this); 0321 0322 return true; 0323 } 0324 #endif 0325 0326 if (_eventInQQuickWidget) { 0327 event->setAccepted(true); 0328 return false; 0329 } 0330 _eventInQQuickWidget = false; 0331 0332 // cast to widget 0333 auto widget = static_cast<QWidget *>(object); 0334 0335 // check if widget can be dragged from current position 0336 if (isBlackListed(widget) || !canDrag(widget)) { 0337 return false; 0338 } 0339 0340 // retrieve widget's child at event position 0341 auto position(mouseEvent->pos()); 0342 auto child = widget->childAt(position); 0343 if (!canDrag(widget, child, position)) { 0344 return false; 0345 } 0346 0347 // save target and drag point 0348 _target = widget; 0349 _dragPoint = position; 0350 _globalDragPoint = mouseEvent->globalPos(); 0351 _dragAboutToStart = true; 0352 0353 // send a move event to the current child with same position 0354 // if received, it is caught to actually start the drag 0355 auto localPoint(_dragPoint); 0356 if (child) { 0357 localPoint = child->mapFrom(widget, localPoint); 0358 } else { 0359 child = widget; 0360 } 0361 QMouseEvent localMouseEvent(QEvent::MouseMove, localPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); 0362 qApp->sendEvent(child, &localMouseEvent); 0363 0364 // never eat event 0365 return false; 0366 } 0367 0368 //_____________________________________________________________ 0369 bool WindowManager::mouseMoveEvent(QObject *object, QEvent *event) 0370 { 0371 Q_UNUSED(object); 0372 0373 // stop timer 0374 if (_dragTimer.isActive()) { 0375 _dragTimer.stop(); 0376 } 0377 0378 // cast event and check drag distance 0379 auto mouseEvent = static_cast<QMouseEvent *>(event); 0380 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { 0381 return false; 0382 } 0383 if (!_dragInProgress) { 0384 if (_dragAboutToStart) { 0385 if (mouseEvent->pos() == _dragPoint) { 0386 // start timer, 0387 _dragAboutToStart = false; 0388 if (_dragTimer.isActive()) { 0389 _dragTimer.stop(); 0390 } 0391 _dragTimer.start(_dragDelay, this); 0392 0393 } else { 0394 resetDrag(); 0395 } 0396 0397 } else if (QPoint(mouseEvent->globalPos() - _globalDragPoint).manhattanLength() >= _dragDistance) { 0398 _dragTimer.start(0, this); 0399 } 0400 0401 return true; 0402 0403 } else { 0404 return false; 0405 } 0406 } 0407 0408 //_____________________________________________________________ 0409 bool WindowManager::mouseReleaseEvent(QObject *object, QEvent *event) 0410 { 0411 Q_UNUSED(object); 0412 Q_UNUSED(event); 0413 resetDrag(); 0414 return false; 0415 } 0416 0417 //_____________________________________________________________ 0418 bool WindowManager::isDragable(QWidget *widget) 0419 { 0420 // check widget 0421 if (!widget) { 0422 return false; 0423 } 0424 0425 // accepted default types 0426 if ((qobject_cast<QDialog *>(widget) && widget->isWindow()) || (qobject_cast<QMainWindow *>(widget) && widget->isWindow()) 0427 || qobject_cast<QGroupBox *>(widget)) { 0428 return true; 0429 } 0430 0431 // more accepted types, provided they are not dock widget titles 0432 if ((qobject_cast<QMenuBar *>(widget) || qobject_cast<QTabBar *>(widget) || qobject_cast<QStatusBar *>(widget) || qobject_cast<QToolBar *>(widget)) 0433 && !isDockWidgetTitle(widget)) { 0434 return true; 0435 } 0436 0437 if (widget->inherits("KScreenSaver") && widget->inherits("KCModule")) { 0438 return true; 0439 } 0440 0441 if (isWhiteListed(widget)) { 0442 return true; 0443 } 0444 0445 // flat toolbuttons 0446 if (auto toolButton = qobject_cast<QToolButton *>(widget)) { 0447 if (toolButton->autoRaise()) { 0448 return true; 0449 } 0450 } 0451 0452 // viewports 0453 /* 0454 one needs to check that 0455 1/ the widget parent is a scrollarea 0456 2/ it matches its parent viewport 0457 3/ the parent is not blacklisted 0458 */ 0459 if (auto listView = qobject_cast<QListView *>(widget->parentWidget())) { 0460 if (listView->viewport() == widget && !isBlackListed(listView)) { 0461 return true; 0462 } 0463 } 0464 0465 if (auto treeView = qobject_cast<QTreeView *>(widget->parentWidget())) { 0466 if (treeView->viewport() == widget && !isBlackListed(treeView)) { 0467 return true; 0468 } 0469 } 0470 0471 /* 0472 catch labels in status bars. 0473 this is because of kstatusbar 0474 who captures buttonPress/release events 0475 */ 0476 if (auto label = qobject_cast<QLabel *>(widget)) { 0477 if (label->textInteractionFlags().testFlag(Qt::TextSelectableByMouse)) { 0478 return false; 0479 } 0480 0481 QWidget *parent = label->parentWidget(); 0482 while (parent) { 0483 if (qobject_cast<QStatusBar *>(parent)) { 0484 return true; 0485 } 0486 parent = parent->parentWidget(); 0487 } 0488 } 0489 0490 return false; 0491 } 0492 0493 //_____________________________________________________________ 0494 bool WindowManager::isBlackListed(QWidget *widget) 0495 { 0496 // check against noAnimations property 0497 const auto propertyValue(widget->property(PropertyNames::noWindowGrab)); 0498 if (propertyValue.isValid() && propertyValue.toBool()) { 0499 return true; 0500 } 0501 0502 // list-based blacklisted widgets 0503 const auto appName(qApp->applicationName()); 0504 foreach (const ExceptionId &id, _blackList) { 0505 if (!id.appName().isEmpty() && id.appName() != appName) { 0506 continue; 0507 } 0508 if (id.className() == QStringLiteral("*") && !id.appName().isEmpty()) { 0509 // if application name matches and all classes are selected 0510 // disable the grabbing entirely 0511 setEnabled(false); 0512 return true; 0513 } 0514 if (widget->inherits(id.className().toLatin1().data())) { 0515 return true; 0516 } 0517 } 0518 0519 return false; 0520 } 0521 0522 //_____________________________________________________________ 0523 bool WindowManager::isWhiteListed(QWidget *widget) const 0524 { 0525 const auto appName(qApp->applicationName()); 0526 foreach (const ExceptionId &id, _whiteList) { 0527 if (!(id.appName().isEmpty() || id.appName() == appName)) { 0528 continue; 0529 } 0530 if (widget->inherits(id.className().toLatin1().data())) { 0531 return true; 0532 } 0533 } 0534 0535 return false; 0536 } 0537 0538 //_____________________________________________________________ 0539 bool WindowManager::canDrag(QWidget *widget) 0540 { 0541 // check if enabled 0542 if (!enabled()) { 0543 return false; 0544 } 0545 0546 // assume isDragable widget is already passed 0547 // check some special cases where drag should not be effective 0548 0549 // check mouse grabber 0550 if (QWidget::mouseGrabber()) { 0551 return false; 0552 } 0553 0554 /* 0555 check cursor shape. 0556 Assume that a changed cursor means that some action is in progress 0557 and should prevent the drag 0558 */ 0559 if (widget->cursor().shape() != Qt::ArrowCursor) { 0560 return false; 0561 } 0562 0563 // accept 0564 return true; 0565 } 0566 0567 //_____________________________________________________________ 0568 bool WindowManager::canDrag(QWidget *widget, QWidget *child, const QPoint &position) 0569 { 0570 // retrieve child at given position and check cursor again 0571 if (child && child->cursor().shape() != Qt::ArrowCursor) { 0572 return false; 0573 } 0574 0575 /* 0576 check against children from which drag should never be enabled, 0577 even if mousePress/Move has been passed to the parent 0578 */ 0579 if (child && (qobject_cast<QComboBox *>(child) || qobject_cast<QProgressBar *>(child) || qobject_cast<QScrollBar *>(child))) { 0580 return false; 0581 } 0582 0583 // tool buttons 0584 if (auto toolButton = qobject_cast<QToolButton *>(widget)) { 0585 if (dragMode() == StyleConfigData::WD_MINIMAL && !qobject_cast<QToolBar *>(widget->parentWidget())) { 0586 return false; 0587 } 0588 return toolButton->autoRaise() && !toolButton->isEnabled(); 0589 } 0590 0591 // check menubar 0592 if (auto menuBar = qobject_cast<QMenuBar *>(widget)) { 0593 // do not drag from menubars embedded in Mdi windows 0594 if (findParent<QMdiSubWindow *>(widget)) { 0595 return false; 0596 } 0597 0598 // check if there is an active action 0599 if (menuBar->activeAction() && menuBar->activeAction()->isEnabled()) { 0600 return false; 0601 } 0602 0603 // check if action at position exists and is enabled 0604 if (auto action = menuBar->actionAt(position)) { 0605 if (action->isSeparator()) { 0606 return true; 0607 } 0608 if (action->isEnabled()) { 0609 return false; 0610 } 0611 } 0612 0613 // return true in all other cases 0614 return true; 0615 } 0616 0617 /* 0618 in MINIMAL mode, anything that has not been already accepted 0619 and does not come from a toolbar is rejected 0620 */ 0621 if (dragMode() == StyleConfigData::WD_MINIMAL) { 0622 if (qobject_cast<QToolBar *>(widget)) { 0623 return true; 0624 } else { 0625 return false; 0626 } 0627 } 0628 0629 /* following checks are relevant only for WD_FULL mode */ 0630 0631 // tabbar. Make sure no tab is under the cursor 0632 if (auto tabBar = qobject_cast<QTabBar *>(widget)) { 0633 return tabBar->tabAt(position) == -1; 0634 } 0635 0636 /* 0637 check groupboxes 0638 prevent drag if unchecking grouboxes 0639 */ 0640 if (auto groupBox = qobject_cast<QGroupBox *>(widget)) { 0641 // non checkable group boxes are always ok 0642 if (!groupBox->isCheckable()) { 0643 return true; 0644 } 0645 0646 // gather options to retrieve checkbox subcontrol rect 0647 QStyleOptionGroupBox opt; 0648 opt.initFrom(groupBox); 0649 if (groupBox->isFlat()) { 0650 opt.features |= QStyleOptionFrame::Flat; 0651 } 0652 opt.lineWidth = 1; 0653 opt.midLineWidth = 0; 0654 opt.text = groupBox->title(); 0655 opt.textAlignment = groupBox->alignment(); 0656 opt.subControls = (QStyle::SC_GroupBoxFrame | QStyle::SC_GroupBoxCheckBox); 0657 if (!groupBox->title().isEmpty()) { 0658 opt.subControls |= QStyle::SC_GroupBoxLabel; 0659 } 0660 0661 opt.state |= (groupBox->isChecked() ? QStyle::State_On : QStyle::State_Off); 0662 0663 // check against groupbox checkbox 0664 if (groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, groupBox).contains(position)) { 0665 return false; 0666 } 0667 0668 // check against groupbox label 0669 if (!groupBox->title().isEmpty() 0670 && groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, groupBox).contains(position)) { 0671 return false; 0672 } 0673 0674 return true; 0675 } 0676 0677 // labels 0678 if (auto label = qobject_cast<QLabel *>(widget)) { 0679 if (label->textInteractionFlags().testFlag(Qt::TextSelectableByMouse)) { 0680 return false; 0681 } 0682 } 0683 0684 // abstract item views 0685 QAbstractItemView *itemView(nullptr); 0686 if ((itemView = qobject_cast<QListView *>(widget->parentWidget())) || (itemView = qobject_cast<QTreeView *>(widget->parentWidget()))) { 0687 if (widget == itemView->viewport()) { 0688 // QListView 0689 if (itemView->frameShape() != QFrame::NoFrame) { 0690 return false; 0691 } else if (itemView->selectionMode() != QAbstractItemView::NoSelection && itemView->selectionMode() != QAbstractItemView::SingleSelection 0692 && itemView->model() && itemView->model()->rowCount()) { 0693 return false; 0694 } else if (itemView->model() && itemView->indexAt(position).isValid()) { 0695 return false; 0696 } 0697 } 0698 0699 } else if ((itemView = qobject_cast<QAbstractItemView *>(widget->parentWidget()))) { 0700 if (widget == itemView->viewport()) { 0701 // QAbstractItemView 0702 if (itemView->frameShape() != QFrame::NoFrame) { 0703 return false; 0704 } else if (itemView->indexAt(position).isValid()) { 0705 return false; 0706 } 0707 } 0708 0709 } else if (auto graphicsView = qobject_cast<QGraphicsView *>(widget->parentWidget())) { 0710 if (widget == graphicsView->viewport()) { 0711 // QGraphicsView 0712 if (graphicsView->frameShape() != QFrame::NoFrame) { 0713 return false; 0714 } else if (graphicsView->dragMode() != QGraphicsView::NoDrag) { 0715 return false; 0716 } else if (graphicsView->itemAt(position)) { 0717 return false; 0718 } 0719 } 0720 } 0721 0722 return true; 0723 } 0724 0725 //____________________________________________________________ 0726 void WindowManager::resetDrag() 0727 { 0728 _target.clear(); 0729 #if BREEZE_HAVE_QTQUICK 0730 _quickTarget.clear(); 0731 #endif 0732 if (_dragTimer.isActive()) { 0733 _dragTimer.stop(); 0734 } 0735 _dragPoint = QPoint(); 0736 _globalDragPoint = QPoint(); 0737 _dragAboutToStart = false; 0738 _dragInProgress = false; 0739 } 0740 0741 //____________________________________________________________ 0742 void WindowManager::startDrag(QWindow *window) 0743 { 0744 if (!(enabled() && window)) { 0745 return; 0746 } 0747 if (QWidget::mouseGrabber()) { 0748 return; 0749 } 0750 0751 #if BREEZE_HAVE_QTQUICK 0752 if (_quickTarget) { 0753 if (QQuickWindow *qw = qobject_cast<QQuickWindow *>(window)) { 0754 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(qw); 0755 if (renderWindow) { 0756 _dragInProgress = renderWindow->startSystemMove(); 0757 } else { 0758 _dragInProgress = window->startSystemMove(); 0759 } 0760 } 0761 } else 0762 #endif 0763 { 0764 _dragInProgress = window->startSystemMove(); 0765 } 0766 } 0767 0768 //____________________________________________________________ 0769 bool WindowManager::isDockWidgetTitle(const QWidget *widget) const 0770 { 0771 if (!widget) { 0772 return false; 0773 } 0774 if (auto dockWidget = qobject_cast<const QDockWidget *>(widget->parent())) { 0775 return widget == dockWidget->titleBarWidget(); 0776 0777 } else { 0778 return false; 0779 } 0780 } 0781 0782 }