File indexing completed on 2024-04-28 05:47:26
0001 /***************************************************************************** 0002 * Copyright 2010 Craig Drummond <craig.p.drummond@gmail.com> * 0003 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU Lesser General Public License as * 0007 * published by the Free Software Foundation; either version 2.1 of the * 0008 * License, or (at your option) version 3, or any later version accepted * 0009 * by the membership of KDE e.V. (or its successor approved by the * 0010 * membership of KDE e.V.), which shall act as a proxy defined in * 0011 * Section 6 of version 3 of the license. * 0012 * * 0013 * This program is distributed in the hope that it will be useful, * 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0016 * Lesser General Public License for more details. * 0017 * * 0018 * You should have received a copy of the GNU Lesser General Public * 0019 * License along with this library. If not, * 0020 * see <http://www.gnu.org/licenses/>. * 0021 *****************************************************************************/ 0022 0023 // Copied from oxygenwindowmanager.cpp svnversion: 1139230 0024 0025 ////////////////////////////////////////////////////////////////////////////// 0026 // windowmanager.cpp 0027 // pass some window mouse press/release/move event actions to window manager 0028 // ------------------- 0029 // 0030 // Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org> 0031 // 0032 // Largely inspired from BeSpin style 0033 // Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de> 0034 // 0035 // Permission is hereby granted, free of charge, to any person obtaining a copy 0036 // of this software and associated documentation files (the "Software"), to 0037 // deal in the Software without restriction, including without limitation the 0038 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 0039 // sell copies of the Software, and to permit persons to whom the Software is 0040 // furnished to do so, subject to the following conditions: 0041 // 0042 // The above copyright notice and this permission notice shall be included in 0043 // all copies or substantial portions of the Software. 0044 // 0045 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0046 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0047 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0048 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0049 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 0050 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 0051 // IN THE SOFTWARE. 0052 ////////////////////////////////////////////////////////////////////////////// 0053 0054 #include "config.h" 0055 #include "windowmanager.h" 0056 #include "qtcurve.h" 0057 #include <common/common.h> 0058 #include "utils.h" 0059 0060 #include <QProgressBar> 0061 #include <QApplication> 0062 #include <QComboBox> 0063 #include <QDialog> 0064 #include <QDockWidget> 0065 #include <QGroupBox> 0066 #include <QLabel> 0067 #include <QListView> 0068 #include <QMainWindow> 0069 #include <QMenuBar> 0070 #include <QMouseEvent> 0071 #include <QStatusBar> 0072 #include <QStyle> 0073 #include <QStyleOptionGroupBox> 0074 #include <QTabBar> 0075 #include <QTabWidget> 0076 #include <QToolBar> 0077 #include <QToolButton> 0078 #include <QTreeView> 0079 #include <QGraphicsView> 0080 0081 #include <QTextStream> 0082 #include <QTextDocument> 0083 0084 #include <qtcurve-utils/x11wmmove.h> 0085 0086 namespace QtCurve { 0087 //_____________________________________________________________ 0088 WindowManager::WindowManager( QObject* parent ): 0089 QObject(parent), 0090 _enabled(true), 0091 _useWMMoveResize(qtcX11Enabled()), 0092 _dragMode(WM_DRAG_NONE), 0093 _dragDistance(QApplication::startDragDistance()), 0094 _dragDelay(QApplication::startDragTime()), 0095 _dragAboutToStart(false), 0096 _dragInProgress(false), 0097 _locked(false), 0098 _cursorOverride(false) 0099 { 0100 // install application wise event filter 0101 _appEventFilter = new AppEventFilter(this); 0102 qApp->installEventFilter(_appEventFilter); 0103 } 0104 0105 //_____________________________________________________________ 0106 void WindowManager::initialize( int windowDrag, const QStringList &whiteList, const QStringList &blackList ) 0107 { 0108 setEnabled( windowDrag ); 0109 setDragMode( windowDrag ); 0110 //CPD: Why??? setUseWMMoveResize( OxygenStyleConfigData::useWMMoveResize() ); 0111 0112 #ifdef QTC_QT5_ENABLE_KDE 0113 setDragDistance(QApplication::startDragDistance()); 0114 #endif 0115 setDragDelay(QApplication::startDragTime()); 0116 0117 initializeWhiteList(whiteList); 0118 initializeBlackList(blackList); 0119 } 0120 0121 void 0122 WindowManager::registerWidget(QWidget *widget) 0123 { 0124 0125 if (isBlackListed(widget)) { 0126 /* 0127 also install filter for blacklisted widgets 0128 to be able to catch the relevant events and prevent 0129 the drag to happen 0130 */ 0131 widget->installEventFilter(this); 0132 } else if (isDragable(widget)) { 0133 widget->installEventFilter(this); 0134 } 0135 } 0136 0137 void 0138 WindowManager::unregisterWidget(QWidget *widget) 0139 { 0140 if (widget) { 0141 widget->removeEventFilter(this); 0142 } 0143 } 0144 0145 //_____________________________________________________________ 0146 void WindowManager::initializeWhiteList( const QStringList &list ) 0147 { 0148 0149 _whiteList.clear(); 0150 0151 // add user specified whitelisted classnames 0152 _whiteList.insert( ExceptionId( "MplayerWindow" ) ); 0153 _whiteList.insert( ExceptionId( "ViewSliders@kmix" ) ); 0154 _whiteList.insert( ExceptionId( "Sidebar_Widget@konqueror" ) ); 0155 0156 for (const QString& exception: list) { 0157 ExceptionId id(exception); 0158 if (!id.className().isEmpty()) { 0159 _whiteList.insert(exception); 0160 } 0161 } 0162 } 0163 0164 void 0165 WindowManager::initializeBlackList(const QStringList &list) 0166 { 0167 _blackList.clear(); 0168 _blackList.insert(ExceptionId("CustomTrackView@kdenlive")); 0169 _blackList.insert(ExceptionId("MuseScore")); 0170 for (const QString &exception: list) { 0171 ExceptionId id(exception); 0172 if (!id.className().isEmpty()) { 0173 _blackList.insert(exception); 0174 } 0175 } 0176 } 0177 0178 //_____________________________________________________________ 0179 bool WindowManager::eventFilter( QObject* object, QEvent* event ) 0180 { 0181 if( !enabled() ) return false; 0182 0183 switch ( event->type() ) 0184 { 0185 case QEvent::MouseButtonPress: 0186 return mousePressEvent( object, event ); 0187 break; 0188 0189 case QEvent::MouseMove: 0190 if ( object == _target.data() ) return mouseMoveEvent( object, event ); 0191 break; 0192 0193 case QEvent::MouseButtonRelease: 0194 if ( _target ) return mouseReleaseEvent( object, event ); 0195 break; 0196 0197 default: 0198 break; 0199 0200 } 0201 0202 return false; 0203 0204 } 0205 0206 //_____________________________________________________________ 0207 void WindowManager::timerEvent( QTimerEvent* event ) 0208 { 0209 0210 if( event->timerId() == _dragTimer.timerId() ) 0211 { 0212 _dragTimer.stop(); 0213 if( _target ) 0214 { startDrag( _target.data(), _globalDragPoint ); } 0215 0216 } else { 0217 0218 return QObject::timerEvent( event ); 0219 0220 } 0221 0222 } 0223 0224 //_____________________________________________________________ 0225 bool WindowManager::mousePressEvent( QObject* object, QEvent* event ) 0226 { 0227 0228 // cast event and check buttons/modifiers 0229 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event ); 0230 if( !( mouseEvent->modifiers() == Qt::NoModifier && mouseEvent->button() == Qt::LeftButton ) ) 0231 { return false; } 0232 0233 // check lock 0234 if( isLocked() ) return false; 0235 else setLocked( true ); 0236 0237 // cast to widget 0238 QWidget *widget = static_cast<QWidget*>( object ); 0239 0240 // check if widget can be dragged from current position 0241 if( isBlackListed( widget ) || !canDrag( widget ) ) return false; 0242 0243 // retrieve widget's child at event position 0244 QPoint position( mouseEvent->pos() ); 0245 QWidget* child = widget->childAt( position ); 0246 if( !canDrag( widget, child, position ) ) return false; 0247 0248 // save target and drag point 0249 _target = widget; 0250 _dragPoint = position; 0251 _globalDragPoint = mouseEvent->globalPos(); 0252 _dragAboutToStart = true; 0253 0254 // send a move event to the current child with same position 0255 // if received, it is caught to actually start the drag 0256 QPoint localPoint( _dragPoint ); 0257 if( child ) localPoint = child->mapFrom( widget, localPoint ); 0258 else child = widget; 0259 QMouseEvent localMouseEvent( QEvent::MouseMove, localPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier ); 0260 qApp->sendEvent( child, &localMouseEvent ); 0261 0262 // never eat event 0263 return false; 0264 0265 } 0266 0267 //_____________________________________________________________ 0268 bool WindowManager::mouseMoveEvent( QObject* object, QEvent* event ) 0269 { 0270 0271 Q_UNUSED( object ); 0272 0273 // stop timer 0274 if( _dragTimer.isActive() ) _dragTimer.stop(); 0275 0276 // cast event and check drag distance 0277 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event ); 0278 if( !_dragInProgress ) 0279 { 0280 0281 if( _dragAboutToStart ) 0282 { 0283 if( mouseEvent->globalPos() == _globalDragPoint ) 0284 { 0285 // start timer, 0286 _dragAboutToStart = false; 0287 if( _dragTimer.isActive() ) _dragTimer.stop(); 0288 _dragTimer.start( _dragDelay, this ); 0289 0290 } else resetDrag(); 0291 0292 } else if( QPoint( mouseEvent->globalPos() - _globalDragPoint ).manhattanLength() >= _dragDistance ) 0293 { _dragTimer.start( 0, this ); } 0294 return true; 0295 0296 } else if( !useWMMoveResize() ) { 0297 0298 // use QWidget::move for the grabbing 0299 /* this works only if the sending object and the target are identical */ 0300 QWidget* window( _target.data()->window() ); 0301 window->move( window->pos() + mouseEvent->pos() - _dragPoint ); 0302 return true; 0303 0304 } else return false; 0305 0306 } 0307 0308 //_____________________________________________________________ 0309 bool WindowManager::mouseReleaseEvent( QObject* object, QEvent* event ) 0310 { 0311 Q_UNUSED( object ); 0312 Q_UNUSED( event ); 0313 resetDrag(); 0314 return false; 0315 } 0316 0317 //_____________________________________________________________ 0318 bool WindowManager::isDragable( QWidget* widget ) 0319 { 0320 0321 // check widget 0322 if( !widget ) return false; 0323 0324 // accepted default types 0325 if( 0326 ( qobject_cast<QDialog*>( widget ) && widget->isWindow() ) || 0327 ( qobject_cast<QMainWindow*>( widget ) && widget->isWindow() ) || 0328 qobject_cast<QGroupBox*>( widget ) ) 0329 { return true; } 0330 0331 // more accepted types, provided they are not dock widget titles 0332 if( ( qobject_cast<QMenuBar*>( widget ) || 0333 qobject_cast<QTabBar*>( widget ) || 0334 qobject_cast<QStatusBar*>( widget ) || 0335 qobject_cast<QToolBar*>( widget ) ) && 0336 !isDockWidgetTitle( widget ) ) 0337 { return true; } 0338 0339 if( widget->inherits( "KScreenSaver" ) && widget->inherits( "KCModule" ) ) 0340 { return true; } 0341 0342 if( isWhiteListed( widget ) ) 0343 { return true; } 0344 0345 // flat toolbuttons 0346 if( QToolButton* toolButton = qobject_cast<QToolButton*>( widget ) ) 0347 { if( toolButton->autoRaise() ) return true; } 0348 0349 // viewports 0350 /* 0351 one needs to check that 0352 1/ the widget parent is a scrollarea 0353 2/ it matches its parent viewport 0354 3/ the parent is not blacklisted 0355 */ 0356 if( QListView* listView = qobject_cast<QListView*>( widget->parentWidget() ) ) 0357 { if( listView->viewport() == widget && !isBlackListed( listView ) ) return true; } 0358 0359 if( QTreeView* treeView = qobject_cast<QTreeView*>( widget->parentWidget() ) ) 0360 { if( treeView->viewport() == widget && !isBlackListed( treeView ) ) return true; } 0361 0362 //if( QGraphicsView* graphicsView = qobject_cast<QGraphicsView*>( widget->parentWidget() ) ) 0363 //{ if( graphicsView->viewport() == widget && !isBlackListed( graphicsView ) ) return true; } 0364 0365 /* 0366 catch labels in status bars. 0367 this is because of kstatusbar 0368 who captures buttonPress/release events 0369 */ 0370 if( QLabel* label = qobject_cast<QLabel*>( widget ) ) 0371 { 0372 if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false; 0373 0374 QWidget* parent = label->parentWidget(); 0375 while( parent ) 0376 { 0377 if( qobject_cast<QStatusBar*>( parent ) ) return true; 0378 parent = parent->parentWidget(); 0379 } 0380 } 0381 0382 return false; 0383 0384 } 0385 0386 //_____________________________________________________________ 0387 bool WindowManager::isBlackListed( QWidget* widget ) 0388 { 0389 0390 // check against noAnimations propery 0391 QVariant propertyValue( widget->property( "_kde_no_window_grab" ) ); 0392 if( propertyValue.isValid() && propertyValue.toBool() ) return true; 0393 0394 // list-based blacklisted widgets 0395 QString appName( qApp->applicationName() ); 0396 for (const ExceptionId &id: const_(_blackList)) { 0397 if (!id.appName().isEmpty() && id.appName() != appName) 0398 continue; 0399 if (id.className() == "*" && !id.appName().isEmpty()) { 0400 // if application name matches and all classes are selected 0401 // disable the grabbing entirely 0402 setEnabled(false); 0403 return true; 0404 } 0405 if (widget->inherits(id.className().toLatin1())) { 0406 return true; 0407 } 0408 } 0409 return false; 0410 } 0411 0412 //_____________________________________________________________ 0413 bool WindowManager::isWhiteListed( QWidget* widget ) const 0414 { 0415 0416 QString appName( qApp->applicationName() ); 0417 for (const ExceptionId &id: _whiteList) { 0418 if (!id.appName().isEmpty() && id.appName() != appName) 0419 continue; 0420 if (widget->inherits(id.className().toLatin1())) { 0421 return true; 0422 } 0423 } 0424 0425 return false; 0426 } 0427 0428 //_____________________________________________________________ 0429 bool WindowManager::canDrag( QWidget* widget ) 0430 { 0431 0432 // check if enabled 0433 if( !enabled() ) return false; 0434 0435 // assume isDragable widget is already passed 0436 // check some special cases where drag should not be effective 0437 0438 // check mouse grabber 0439 if( QWidget::mouseGrabber() ) return false; 0440 0441 /* 0442 check cursor shape. 0443 Assume that a changed cursor means that some action is in progress 0444 and should prevent the drag 0445 */ 0446 if( widget->cursor().shape() != Qt::ArrowCursor ) return false; 0447 0448 // accept 0449 return true; 0450 0451 } 0452 0453 //_____________________________________________________________ 0454 bool WindowManager::canDrag( QWidget* widget, QWidget* child, const QPoint& position ) 0455 { 0456 0457 // retrieve child at given position and check cursor again 0458 if( child && child->cursor().shape() != Qt::ArrowCursor ) return false; 0459 0460 /* 0461 check against children from which drag should never be enabled, 0462 even if mousePress/Move has been passed to the parent 0463 */ 0464 if( child && ( 0465 qobject_cast<QComboBox*>(child ) || 0466 qobject_cast<QProgressBar*>( child ) ) ) 0467 { return false; } 0468 0469 // tool buttons 0470 if( QToolButton* toolButton = qobject_cast<QToolButton*>( widget ) ) 0471 { 0472 if( dragMode() < WM_DRAG_ALL && !qobject_cast<QToolBar*>(widget->parentWidget() ) ) return false; 0473 return toolButton->autoRaise() && !toolButton->isEnabled(); 0474 } 0475 0476 // check menubar 0477 if( QMenuBar* menuBar = qobject_cast<QMenuBar*>( widget ) ) 0478 { 0479 0480 // check if there is an active action 0481 if( menuBar->activeAction() && menuBar->activeAction()->isEnabled() ) return false; 0482 0483 // check if action at position exists and is enabled 0484 if( QAction* action = menuBar->actionAt( position ) ) 0485 { 0486 if( action->isSeparator() ) return true; 0487 if( action->isEnabled() ) return false; 0488 } 0489 0490 // return true in all other cases 0491 return true; 0492 0493 } 0494 0495 if(dragMode() < WM_DRAG_MENU_AND_TOOLBAR && qobject_cast<QToolBar*>( widget )) 0496 return false; 0497 0498 /* 0499 in MINIMAL mode, anything that has not been already accepted 0500 and does not come from a toolbar is rejected 0501 */ 0502 if( dragMode() < WM_DRAG_ALL ) 0503 { 0504 if( qobject_cast<QToolBar*>( widget ) ) return true; 0505 else return false; 0506 } 0507 0508 /* following checks are relevant only for WD_FULL mode */ 0509 0510 // tabbar. Make sure no tab is under the cursor 0511 if( QTabBar* tabBar = qobject_cast<QTabBar*>( widget ) ) 0512 { return tabBar->tabAt( position ) == -1; } 0513 0514 /* 0515 check groupboxes 0516 prevent drag if unchecking grouboxes 0517 */ 0518 if( QGroupBox *groupBox = qobject_cast<QGroupBox*>( widget ) ) 0519 { 0520 // non checkable group boxes are always ok 0521 if( !groupBox->isCheckable() ) return true; 0522 0523 // gather options to retrieve checkbox subcontrol rect 0524 QStyleOptionGroupBox opt; 0525 opt.initFrom( groupBox ); 0526 if( groupBox->isFlat() ) opt.features |= QStyleOptionFrame::Flat; 0527 opt.lineWidth = 1; 0528 opt.midLineWidth = 0; 0529 opt.text = groupBox->title(); 0530 opt.textAlignment = groupBox->alignment(); 0531 opt.subControls = (QStyle::SC_GroupBoxFrame | QStyle::SC_GroupBoxCheckBox); 0532 if (!groupBox->title().isEmpty()) opt.subControls |= QStyle::SC_GroupBoxLabel; 0533 0534 opt.state |= (groupBox->isChecked() ? QStyle::State_On : QStyle::State_Off); 0535 0536 // check against groupbox checkbox 0537 if( groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, groupBox ).contains( position ) ) 0538 { return false; } 0539 0540 // check against groupbox label 0541 if( !groupBox->title().isEmpty() && groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, groupBox ).contains( position ) ) 0542 { return false; } 0543 0544 return true; 0545 0546 } 0547 0548 // labels 0549 if( QLabel* label = qobject_cast<QLabel*>( widget ) ) 0550 { if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false; } 0551 0552 // abstract item views 0553 QAbstractItemView* itemView(nullptr); 0554 if( 0555 ( itemView = qobject_cast<QListView*>( widget->parentWidget() ) ) || 0556 ( itemView = qobject_cast<QTreeView*>( widget->parentWidget() ) ) ) 0557 { 0558 if( widget == itemView->viewport() ) 0559 { 0560 // QListView 0561 if( itemView->frameShape() != QFrame::NoFrame ) return false; 0562 else if( 0563 itemView->selectionMode() != QAbstractItemView::NoSelection && 0564 itemView->selectionMode() != QAbstractItemView::SingleSelection && 0565 itemView->model() && itemView->model()->rowCount() ) return false; 0566 else if( itemView->model() && itemView->indexAt( position ).isValid() ) return false; 0567 } 0568 0569 } else if( ( itemView = qobject_cast<QAbstractItemView*>( widget->parentWidget() ) ) ) { 0570 0571 0572 if( widget == itemView->viewport() ) 0573 { 0574 // QAbstractItemView 0575 if( itemView->frameShape() != QFrame::NoFrame ) return false; 0576 else if( itemView->indexAt( position ).isValid() ) return false; 0577 } 0578 0579 } else if( QGraphicsView* graphicsView = qobject_cast<QGraphicsView*>( widget->parentWidget() ) ) { 0580 0581 if( widget == graphicsView->viewport() ) 0582 { 0583 // QGraphicsView 0584 if( graphicsView->frameShape() != QFrame::NoFrame ) return false; 0585 else if( graphicsView->dragMode() != QGraphicsView::NoDrag ) return false; 0586 else if( graphicsView->itemAt( position ) ) return false; 0587 } 0588 0589 } 0590 0591 return true; 0592 0593 } 0594 0595 //____________________________________________________________ 0596 void WindowManager::resetDrag( void ) 0597 { 0598 0599 if( (!useWMMoveResize() ) && _target && _cursorOverride ) { 0600 0601 qApp->restoreOverrideCursor(); 0602 _cursorOverride = false; 0603 0604 } 0605 0606 _target.clear(); 0607 if( _dragTimer.isActive() ) _dragTimer.stop(); 0608 _dragPoint = QPoint(); 0609 _globalDragPoint = QPoint(); 0610 _dragAboutToStart = false; 0611 _dragInProgress = false; 0612 0613 } 0614 0615 //____________________________________________________________ 0616 void WindowManager::startDrag(QWidget* widget, const QPoint &position) 0617 { 0618 Q_UNUSED(position); 0619 if (!(enabled() && widget) || QWidget::mouseGrabber()) 0620 return; 0621 0622 // ungrab pointer 0623 // DO NOT condition compile on QTC_ENABLE_X11. 0624 // There's no direct linkage on X11 and the following code will just do 0625 // nothing if X11 is not enabled (either at compile time or at run time). 0626 if (useWMMoveResize()) { 0627 qtcX11MoveTrigger(widget->window()->internalWinId(), 0628 position.x(), position.y()); 0629 } 0630 0631 if(!useWMMoveResize()) { 0632 if (!_cursorOverride) { 0633 qApp->setOverrideCursor(Qt::SizeAllCursor); 0634 _cursorOverride = true; 0635 } 0636 } 0637 0638 _dragInProgress = true; 0639 return; 0640 } 0641 0642 //____________________________________________________________ 0643 bool WindowManager::isDockWidgetTitle( const QWidget* widget ) const 0644 { 0645 0646 if( !widget ) return false; 0647 if( const QDockWidget* dockWidget = qobject_cast<const QDockWidget*>( widget->parent() ) ) 0648 { 0649 0650 return widget == dockWidget->titleBarWidget(); 0651 0652 } else return false; 0653 0654 } 0655 0656 //____________________________________________________________ 0657 bool WindowManager::AppEventFilter::eventFilter( QObject* object, QEvent* event ) 0658 { 0659 0660 if( event->type() == QEvent::MouseButtonRelease ) 0661 { 0662 0663 // stop drag timer 0664 if( _parent->_dragTimer.isActive() ) 0665 { _parent->resetDrag(); } 0666 0667 // unlock 0668 if( _parent->isLocked() ) 0669 { _parent->setLocked( false ); } 0670 0671 } 0672 0673 if( !_parent->enabled() ) return false; 0674 0675 /* 0676 if a drag is in progress, the widget will not receive any event 0677 we trigger on the first MouseMove or MousePress events that are received 0678 by any widget in the application to detect that the drag is finished 0679 */ 0680 if( _parent->useWMMoveResize() && _parent->_dragInProgress && _parent->_target && ( event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress ) ) 0681 { return appMouseEvent( object, event ); } 0682 0683 return false; 0684 0685 } 0686 0687 //_____________________________________________________________ 0688 bool WindowManager::AppEventFilter::appMouseEvent( QObject* object, QEvent* event ) 0689 { 0690 0691 Q_UNUSED( object ); 0692 0693 // store target window (see later) 0694 QWidget* window( _parent->_target.data()->window() ); 0695 0696 /* 0697 post some mouseRelease event to the target, in order to counter balance 0698 the mouse press that triggered the drag. Note that it triggers a resetDrag 0699 */ 0700 QMouseEvent mouseEvent( QEvent::MouseButtonRelease, _parent->_dragPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier ); 0701 qApp->sendEvent( _parent->_target.data(), &mouseEvent ); 0702 0703 if( event->type() == QEvent::MouseMove ) 0704 { 0705 /* 0706 HACK: quickly move the main cursor out of the window and back 0707 this is needed to get the focus right for the window children 0708 the origin of this issue is unknown at the moment 0709 */ 0710 const QPoint cursor = QCursor::pos(); 0711 QCursor::setPos(window->mapToGlobal( window->rect().topRight() ) + QPoint(1, 0) ); 0712 QCursor::setPos(cursor); 0713 0714 } 0715 0716 return true; 0717 0718 } 0719 0720 0721 }