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 }