File indexing completed on 2024-04-28 05:26:27
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, QCursor::pos(), 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 const auto windowDragWhiteList = StyleConfigData::windowDragWhiteList(); 0198 for (const QString &exception : windowDragWhiteList) { 0199 ExceptionId id(exception); 0200 if (!id.className().isEmpty()) { 0201 _whiteList.insert(ExceptionId(exception)); 0202 } 0203 } 0204 } 0205 0206 //_____________________________________________________________ 0207 void WindowManager::initializeBlackList() 0208 { 0209 _blackList = Util::makeT<ExceptionSet>( 0210 {ExceptionId(QStringLiteral("CustomTrackView@kdenlive")), ExceptionId(QStringLiteral("MuseScore")), ExceptionId(QStringLiteral("KGameCanvasWidget"))}); 0211 0212 const auto windowDragBlackList = StyleConfigData::windowDragBlackList(); 0213 for (const QString &exception : windowDragBlackList) { 0214 ExceptionId id(exception); 0215 if (!id.className().isEmpty()) { 0216 _blackList.insert(ExceptionId(exception)); 0217 } 0218 } 0219 } 0220 0221 //_____________________________________________________________ 0222 bool WindowManager::eventFilter(QObject *object, QEvent *event) 0223 { 0224 if (!enabled()) { 0225 return false; 0226 } 0227 0228 switch (event->type()) { 0229 case QEvent::MouseButtonPress: 0230 return mousePressEvent(object, event); 0231 break; 0232 0233 case QEvent::MouseMove: 0234 if (object == _target.data() 0235 #if BREEZE_HAVE_QTQUICK 0236 || object == _quickTarget.data() 0237 #endif 0238 ) { 0239 return mouseMoveEvent(object, event); 0240 } 0241 break; 0242 0243 case QEvent::MouseButtonRelease: 0244 if (_target 0245 #if BREEZE_HAVE_QTQUICK 0246 || _quickTarget 0247 #endif 0248 ) { 0249 return mouseReleaseEvent(object, event); 0250 } 0251 break; 0252 0253 default: 0254 break; 0255 } 0256 0257 return false; 0258 } 0259 0260 //_____________________________________________________________ 0261 void WindowManager::timerEvent(QTimerEvent *event) 0262 { 0263 if (event->timerId() == _dragTimer.timerId()) { 0264 _dragTimer.stop(); 0265 setLocked(false); 0266 if (_target) { 0267 startDrag(_target.data()->window()->windowHandle()); 0268 } 0269 #if BREEZE_HAVE_QTQUICK 0270 else if (_quickTarget) { 0271 _quickTarget.data()->ungrabMouse(); 0272 startDrag(_quickTarget.data()->window()); 0273 } 0274 #endif 0275 resetDrag(); 0276 } else { 0277 return QObject::timerEvent(event); 0278 } 0279 } 0280 0281 //_____________________________________________________________ 0282 bool WindowManager::mousePressEvent(QObject *object, QEvent *event) 0283 { 0284 // cast event and check buttons/modifiers 0285 auto mouseEvent = static_cast<QMouseEvent *>(event); 0286 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { 0287 return false; 0288 } 0289 if (!(mouseEvent->modifiers() == Qt::NoModifier && mouseEvent->button() == Qt::LeftButton)) { 0290 return false; 0291 } 0292 0293 // If we are in a QQuickWidget we don't want to ever do dragging from a qwidget in the 0294 // hyerarchy, but only from an internal item, if any. If any event handler will manage 0295 // the event, we don't want the drag to start 0296 if (object->inherits("QQuickWidget")) { 0297 _eventInQQuickWidget = true; 0298 event->setAccepted(false); 0299 return false; 0300 } else { 0301 _eventInQQuickWidget = false; 0302 } 0303 0304 // check lock 0305 if (isLocked()) { 0306 return false; 0307 } else { 0308 setLocked(true); 0309 } 0310 0311 #if BREEZE_HAVE_QTQUICK 0312 // check QQuickItem - we can immediately start drag, because QQuickWindow's contentItem 0313 // only receives mouse events that weren't handled by children 0314 if (auto item = qobject_cast<QQuickItem *>(object)) { 0315 _quickTarget = item; 0316 _dragPoint = mouseEvent->pos(); 0317 _globalDragPoint = 0318 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0319 mouseEvent->globalPosition().toPoint(); 0320 #else 0321 mouseEvent->globalPos(); 0322 #endif 0323 0324 if (_dragTimer.isActive()) { 0325 _dragTimer.stop(); 0326 } 0327 _dragTimer.start(_dragDelay, this); 0328 0329 return true; 0330 } 0331 #endif 0332 0333 if (_eventInQQuickWidget) { 0334 event->setAccepted(true); 0335 return false; 0336 } 0337 _eventInQQuickWidget = false; 0338 0339 // cast to widget 0340 auto widget = static_cast<QWidget *>(object); 0341 0342 // check if widget can be dragged from current position 0343 if (isBlackListed(widget) || !canDrag(widget)) { 0344 return false; 0345 } 0346 0347 // retrieve widget's child at event position 0348 auto position(mouseEvent->pos()); 0349 auto child = widget->childAt(position); 0350 if (!canDrag(widget, child, position)) { 0351 return false; 0352 } 0353 0354 // save target and drag point 0355 _target = widget; 0356 _dragPoint = position; 0357 _globalDragPoint = 0358 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0359 mouseEvent->globalPosition().toPoint(); 0360 #else 0361 mouseEvent->globalPos(); 0362 #endif 0363 _dragAboutToStart = true; 0364 0365 // send a move event to the current child with same position 0366 // if received, it is caught to actually start the drag 0367 auto localPoint(_dragPoint); 0368 if (child) { 0369 localPoint = child->mapFrom(widget, localPoint); 0370 } else { 0371 child = widget; 0372 } 0373 QMouseEvent localMouseEvent(QEvent::MouseMove, 0374 localPoint, 0375 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) 0376 QCursor::pos(), 0377 #endif 0378 Qt::NoButton, 0379 Qt::LeftButton, 0380 Qt::NoModifier); 0381 localMouseEvent.setTimestamp(mouseEvent->timestamp()); 0382 qApp->sendEvent(child, &localMouseEvent); 0383 0384 // never eat event 0385 return false; 0386 } 0387 0388 //_____________________________________________________________ 0389 bool WindowManager::mouseMoveEvent(QObject *object, QEvent *event) 0390 { 0391 Q_UNUSED(object); 0392 0393 // stop timer 0394 if (_dragTimer.isActive()) { 0395 _dragTimer.stop(); 0396 } 0397 0398 // cast event and check drag distance 0399 auto mouseEvent = static_cast<QMouseEvent *>(event); 0400 if (mouseEvent->source() != Qt::MouseEventNotSynthesized) { 0401 return false; 0402 } 0403 auto eventPos = 0404 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0405 mouseEvent->globalPosition().toPoint(); 0406 #else 0407 mouseEvent->globalPos(); 0408 #endif 0409 if (!_dragInProgress) { 0410 if (_dragAboutToStart) { 0411 if (mouseEvent->pos() == _dragPoint) { 0412 // start timer, 0413 _dragAboutToStart = false; 0414 if (_dragTimer.isActive()) { 0415 _dragTimer.stop(); 0416 } 0417 _dragTimer.start(_dragDelay, this); 0418 0419 } else { 0420 resetDrag(); 0421 } 0422 0423 } else if (QPoint(eventPos - _globalDragPoint).manhattanLength() >= _dragDistance) { 0424 _dragTimer.start(0, this); 0425 } 0426 0427 return true; 0428 0429 } else { 0430 return false; 0431 } 0432 } 0433 0434 //_____________________________________________________________ 0435 bool WindowManager::mouseReleaseEvent(QObject *object, QEvent *event) 0436 { 0437 Q_UNUSED(object); 0438 Q_UNUSED(event); 0439 resetDrag(); 0440 return false; 0441 } 0442 0443 //_____________________________________________________________ 0444 bool WindowManager::isDragable(QWidget *widget) 0445 { 0446 // check widget 0447 if (!widget) { 0448 return false; 0449 } 0450 0451 // accepted default types 0452 if ((qobject_cast<QDialog *>(widget) && widget->isWindow()) || (qobject_cast<QMainWindow *>(widget) && widget->isWindow()) 0453 || qobject_cast<QGroupBox *>(widget)) { 0454 return true; 0455 } 0456 0457 // more accepted types, provided they are not dock widget titles 0458 if ((qobject_cast<QMenuBar *>(widget) || qobject_cast<QTabBar *>(widget) || qobject_cast<QStatusBar *>(widget) || qobject_cast<QToolBar *>(widget)) 0459 && !isDockWidgetTitle(widget)) { 0460 return true; 0461 } 0462 0463 if (widget->inherits("KScreenSaver") && widget->inherits("KCModule")) { 0464 return true; 0465 } 0466 0467 if (isWhiteListed(widget)) { 0468 return true; 0469 } 0470 0471 // flat toolbuttons 0472 if (auto toolButton = qobject_cast<QToolButton *>(widget)) { 0473 if (toolButton->autoRaise()) { 0474 return true; 0475 } 0476 } 0477 0478 // viewports 0479 /* 0480 one needs to check that 0481 1/ the widget parent is a scrollarea 0482 2/ it matches its parent viewport 0483 3/ the parent is not blacklisted 0484 */ 0485 if (auto listView = qobject_cast<QListView *>(widget->parentWidget())) { 0486 if (listView->viewport() == widget && !isBlackListed(listView)) { 0487 return true; 0488 } 0489 } 0490 0491 if (auto treeView = qobject_cast<QTreeView *>(widget->parentWidget())) { 0492 if (treeView->viewport() == widget && !isBlackListed(treeView)) { 0493 return true; 0494 } 0495 } 0496 0497 /* 0498 catch labels in status bars. 0499 this is because of kstatusbar 0500 who captures buttonPress/release events 0501 */ 0502 if (auto label = qobject_cast<QLabel *>(widget)) { 0503 if (label->textInteractionFlags().testFlag(Qt::TextSelectableByMouse)) { 0504 return false; 0505 } 0506 0507 QWidget *parent = label->parentWidget(); 0508 while (parent) { 0509 if (qobject_cast<QStatusBar *>(parent)) { 0510 return true; 0511 } 0512 parent = parent->parentWidget(); 0513 } 0514 } 0515 0516 return false; 0517 } 0518 0519 //_____________________________________________________________ 0520 bool WindowManager::isBlackListed(QWidget *widget) 0521 { 0522 // check against noAnimations property 0523 const auto propertyValue(widget->property(PropertyNames::noWindowGrab)); 0524 if (propertyValue.isValid() && propertyValue.toBool()) { 0525 return true; 0526 } 0527 0528 // list-based blacklisted widgets 0529 const auto appName(qApp->applicationName()); 0530 for (const ExceptionId &id : std::as_const(_blackList)) { 0531 if (!id.appName().isEmpty() && id.appName() != appName) { 0532 continue; 0533 } 0534 if (id.className() == QStringLiteral("*") && !id.appName().isEmpty()) { 0535 // if application name matches and all classes are selected 0536 // disable the grabbing entirely 0537 setEnabled(false); 0538 return true; 0539 } 0540 if (widget->inherits(id.className().toLatin1().data())) { 0541 return true; 0542 } 0543 } 0544 0545 return false; 0546 } 0547 0548 //_____________________________________________________________ 0549 bool WindowManager::isWhiteListed(QWidget *widget) const 0550 { 0551 const auto appName(qApp->applicationName()); 0552 for (const ExceptionId &id : std::as_const(_whiteList)) { 0553 if (!(id.appName().isEmpty() || id.appName() == appName)) { 0554 continue; 0555 } 0556 if (widget->inherits(id.className().toLatin1().data())) { 0557 return true; 0558 } 0559 } 0560 0561 return false; 0562 } 0563 0564 //_____________________________________________________________ 0565 bool WindowManager::canDrag(QWidget *widget) 0566 { 0567 // check if enabled 0568 if (!enabled()) { 0569 return false; 0570 } 0571 0572 // assume isDragable widget is already passed 0573 // check some special cases where drag should not be effective 0574 0575 // check mouse grabber 0576 if (QWidget::mouseGrabber()) { 0577 return false; 0578 } 0579 0580 /* 0581 check cursor shape. 0582 Assume that a changed cursor means that some action is in progress 0583 and should prevent the drag 0584 */ 0585 if (widget->cursor().shape() != Qt::ArrowCursor) { 0586 return false; 0587 } 0588 0589 // accept 0590 return true; 0591 } 0592 0593 //_____________________________________________________________ 0594 bool WindowManager::canDrag(QWidget *widget, QWidget *child, const QPoint &position) 0595 { 0596 // retrieve child at given position and check cursor again 0597 if (child && child->cursor().shape() != Qt::ArrowCursor) { 0598 return false; 0599 } 0600 0601 /* 0602 check against children from which drag should never be enabled, 0603 even if mousePress/Move has been passed to the parent 0604 */ 0605 if (child && (qobject_cast<QComboBox *>(child) || qobject_cast<QProgressBar *>(child) || qobject_cast<QScrollBar *>(child))) { 0606 return false; 0607 } 0608 0609 // tool buttons 0610 if (auto toolButton = qobject_cast<QToolButton *>(widget)) { 0611 if (dragMode() == StyleConfigData::WD_MINIMAL && !qobject_cast<QToolBar *>(widget->parentWidget())) { 0612 return false; 0613 } 0614 return toolButton->autoRaise() && !toolButton->isEnabled(); 0615 } 0616 0617 // check menubar 0618 if (auto menuBar = qobject_cast<QMenuBar *>(widget)) { 0619 // do not drag from menubars embedded in Mdi windows 0620 if (findParent<QMdiSubWindow *>(widget)) { 0621 return false; 0622 } 0623 0624 // check if there is an active action 0625 if (menuBar->activeAction() && menuBar->activeAction()->isEnabled()) { 0626 return false; 0627 } 0628 0629 // check if action at position exists and is enabled 0630 if (auto action = menuBar->actionAt(position)) { 0631 if (action->isSeparator()) { 0632 return true; 0633 } 0634 if (action->isEnabled()) { 0635 return false; 0636 } 0637 } 0638 0639 // return true in all other cases 0640 return true; 0641 } 0642 0643 /* 0644 in MINIMAL mode, anything that has not been already accepted 0645 and does not come from a toolbar is rejected 0646 */ 0647 if (dragMode() == StyleConfigData::WD_MINIMAL) { 0648 if (qobject_cast<QToolBar *>(widget)) { 0649 return true; 0650 } else { 0651 return false; 0652 } 0653 } 0654 0655 /* following checks are relevant only for WD_FULL mode */ 0656 0657 // tabbar. Make sure no tab is under the cursor 0658 if (auto tabBar = qobject_cast<QTabBar *>(widget)) { 0659 return tabBar->tabAt(position) == -1; 0660 } 0661 0662 /* 0663 check groupboxes 0664 prevent drag if unchecking grouboxes 0665 */ 0666 if (auto groupBox = qobject_cast<QGroupBox *>(widget)) { 0667 // non checkable group boxes are always ok 0668 if (!groupBox->isCheckable()) { 0669 return true; 0670 } 0671 0672 // gather options to retrieve checkbox subcontrol rect 0673 QStyleOptionGroupBox opt; 0674 opt.initFrom(groupBox); 0675 if (groupBox->isFlat()) { 0676 opt.features |= QStyleOptionFrame::Flat; 0677 } 0678 opt.lineWidth = 1; 0679 opt.midLineWidth = 0; 0680 opt.text = groupBox->title(); 0681 opt.textAlignment = groupBox->alignment(); 0682 opt.subControls = (QStyle::SC_GroupBoxFrame | QStyle::SC_GroupBoxCheckBox); 0683 if (!groupBox->title().isEmpty()) { 0684 opt.subControls |= QStyle::SC_GroupBoxLabel; 0685 } 0686 0687 opt.state |= (groupBox->isChecked() ? QStyle::State_On : QStyle::State_Off); 0688 0689 // check against groupbox checkbox 0690 if (groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, groupBox).contains(position)) { 0691 return false; 0692 } 0693 0694 // check against groupbox label 0695 if (!groupBox->title().isEmpty() 0696 && groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, groupBox).contains(position)) { 0697 return false; 0698 } 0699 0700 return true; 0701 } 0702 0703 // labels 0704 if (auto label = qobject_cast<QLabel *>(widget)) { 0705 if (label->textInteractionFlags().testFlag(Qt::TextSelectableByMouse)) { 0706 return false; 0707 } 0708 } 0709 0710 // abstract item views 0711 QAbstractItemView *itemView(nullptr); 0712 if ((itemView = qobject_cast<QListView *>(widget->parentWidget())) || (itemView = qobject_cast<QTreeView *>(widget->parentWidget()))) { 0713 if (widget == itemView->viewport()) { 0714 // QListView 0715 if (itemView->frameShape() != QFrame::NoFrame) { 0716 return false; 0717 } else if (itemView->selectionMode() != QAbstractItemView::NoSelection && itemView->selectionMode() != QAbstractItemView::SingleSelection 0718 && itemView->model() && itemView->model()->rowCount()) { 0719 return false; 0720 } else if (itemView->model() && itemView->indexAt(position).isValid()) { 0721 return false; 0722 } 0723 } 0724 0725 } else if ((itemView = qobject_cast<QAbstractItemView *>(widget->parentWidget()))) { 0726 if (widget == itemView->viewport()) { 0727 // QAbstractItemView 0728 if (itemView->frameShape() != QFrame::NoFrame) { 0729 return false; 0730 } else if (itemView->indexAt(position).isValid()) { 0731 return false; 0732 } 0733 } 0734 0735 } else if (auto graphicsView = qobject_cast<QGraphicsView *>(widget->parentWidget())) { 0736 if (widget == graphicsView->viewport()) { 0737 // QGraphicsView 0738 if (graphicsView->frameShape() != QFrame::NoFrame) { 0739 return false; 0740 } else if (graphicsView->dragMode() != QGraphicsView::NoDrag) { 0741 return false; 0742 } else if (graphicsView->itemAt(position)) { 0743 return false; 0744 } 0745 } 0746 } 0747 0748 return true; 0749 } 0750 0751 //____________________________________________________________ 0752 void WindowManager::resetDrag() 0753 { 0754 _target.clear(); 0755 #if BREEZE_HAVE_QTQUICK 0756 _quickTarget.clear(); 0757 #endif 0758 if (_dragTimer.isActive()) { 0759 _dragTimer.stop(); 0760 } 0761 _dragPoint = QPoint(); 0762 _globalDragPoint = QPoint(); 0763 _dragAboutToStart = false; 0764 _dragInProgress = false; 0765 } 0766 0767 //____________________________________________________________ 0768 void WindowManager::startDrag(QWindow *window) 0769 { 0770 if (!(enabled() && window)) { 0771 return; 0772 } 0773 if (QWidget::mouseGrabber()) { 0774 return; 0775 } 0776 0777 #if BREEZE_HAVE_QTQUICK 0778 if (_quickTarget) { 0779 if (QQuickWindow *qw = qobject_cast<QQuickWindow *>(window)) { 0780 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(qw); 0781 if (renderWindow) { 0782 _dragInProgress = renderWindow->startSystemMove(); 0783 } else { 0784 _dragInProgress = window->startSystemMove(); 0785 } 0786 } 0787 } else 0788 #endif 0789 { 0790 _dragInProgress = window->startSystemMove(); 0791 } 0792 } 0793 0794 //____________________________________________________________ 0795 bool WindowManager::isDockWidgetTitle(const QWidget *widget) const 0796 { 0797 if (!widget) { 0798 return false; 0799 } 0800 if (auto dockWidget = qobject_cast<const QDockWidget *>(widget->parent())) { 0801 return widget == dockWidget->titleBarWidget(); 0802 0803 } else { 0804 return false; 0805 } 0806 } 0807 0808 }