~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kstyles/oxygen/oxygenwindowmanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// krazy:excludeall=qclasses
 
2
 
 
3
//////////////////////////////////////////////////////////////////////////////
 
4
// oxygenwindowmanager.cpp
 
5
// pass some window mouse press/release/move event actions to window manager
 
6
// -------------------
 
7
//
 
8
// Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
 
9
//
 
10
// Largely inspired from BeSpin style
 
11
// Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
 
12
//
 
13
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
14
// of this software and associated documentation files (the "Software"), to
 
15
// deal in the Software without restriction, including without limitation the
 
16
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 
17
// sell copies of the Software, and to permit persons to whom the Software is
 
18
// furnished to do so, subject to the following conditions:
 
19
//
 
20
// The above copyright notice and this permission notice shall be included in
 
21
// all copies or substantial portions of the Software.
 
22
//
 
23
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
24
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
25
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
26
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
27
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
28
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
29
// IN THE SOFTWARE.
 
30
//////////////////////////////////////////////////////////////////////////////
 
31
 
 
32
#include "oxygenwindowmanager.h"
 
33
#include "oxygenwindowmanager.moc"
 
34
#include "oxygenpropertynames.h"
 
35
#include "oxygenstyleconfigdata.h"
 
36
 
 
37
#include <QtGui/QApplication>
 
38
#include <QtGui/QComboBox>
 
39
#include <QtGui/QDialog>
 
40
#include <QtGui/QDockWidget>
 
41
#include <QtGui/QGroupBox>
 
42
#include <QtGui/QLabel>
 
43
#include <QtGui/QListView>
 
44
#include <QtGui/QMainWindow>
 
45
#include <QtGui/QMenuBar>
 
46
#include <QtGui/QMouseEvent>
 
47
#include <QtGui/QProgressBar>
 
48
#include <QtGui/QStatusBar>
 
49
#include <QtGui/QStyle>
 
50
#include <QtGui/QStyleOptionGroupBox>
 
51
#include <QtGui/QTabBar>
 
52
#include <QtGui/QTabWidget>
 
53
#include <QtGui/QToolBar>
 
54
#include <QtGui/QToolButton>
 
55
#include <QtGui/QTreeView>
 
56
#include <QtGui/QGraphicsView>
 
57
 
 
58
#include <QtCore/QTextStream>
 
59
#include <QtGui/QTextDocument>
 
60
 
 
61
#include <KGlobalSettings>
 
62
 
 
63
#ifdef Q_WS_X11
 
64
#include <QX11Info>
 
65
#include <NETRootInfo>
 
66
#endif
 
67
 
 
68
namespace Oxygen
 
69
{
 
70
 
 
71
    //_____________________________________________________________
 
72
    WindowManager::WindowManager( QObject* parent ):
 
73
        QObject( parent ),
 
74
        _enabled( true ),
 
75
        _useWMMoveResize( true ),
 
76
        _dragMode( StyleConfigData::WD_FULL ),
 
77
        _dragDistance( KGlobalSettings::dndEventDelay() ),
 
78
        _dragDelay( QApplication::startDragTime() ),
 
79
        _dragAboutToStart( false ),
 
80
        _dragInProgress( false ),
 
81
        _locked( false ),
 
82
        _cursorOverride( false )
 
83
    {
 
84
 
 
85
        // install application wise event filter
 
86
        _appEventFilter = new AppEventFilter( this );
 
87
        qApp->installEventFilter( _appEventFilter );
 
88
 
 
89
    }
 
90
 
 
91
    //_____________________________________________________________
 
92
    void WindowManager::initialize( void )
 
93
    {
 
94
 
 
95
        setEnabled( StyleConfigData::windowDragEnabled() );
 
96
        setDragMode( StyleConfigData::windowDragMode() );
 
97
        setUseWMMoveResize( StyleConfigData::useWMMoveResize() );
 
98
 
 
99
        setDragDistance( KGlobalSettings::dndEventDelay() );
 
100
        setDragDelay( QApplication::startDragTime() );
 
101
 
 
102
        initializeWhiteList();
 
103
        initializeBlackList();
 
104
 
 
105
    }
 
106
 
 
107
    //_____________________________________________________________
 
108
    void WindowManager::registerWidget( QWidget* widget )
 
109
    {
 
110
 
 
111
        if( isBlackListed( widget ) )
 
112
        {
 
113
 
 
114
            /*
 
115
            also install filter for blacklisted widgets
 
116
            to be able to catch the relevant events and prevent
 
117
            the drag to happen
 
118
            */
 
119
            widget->removeEventFilter( this );
 
120
            widget->installEventFilter( this );
 
121
 
 
122
        } else if( isDragable( widget ) ) {
 
123
 
 
124
            widget->removeEventFilter( this );
 
125
            widget->installEventFilter( this );
 
126
 
 
127
        }
 
128
 
 
129
    }
 
130
 
 
131
    //_____________________________________________________________
 
132
    void WindowManager::unregisterWidget( QWidget* widget )
 
133
    {
 
134
        if( widget )
 
135
        { widget->removeEventFilter( this ); }
 
136
    }
 
137
 
 
138
    //_____________________________________________________________
 
139
    void WindowManager::initializeWhiteList( void )
 
140
    {
 
141
 
 
142
        _whiteList.clear();
 
143
 
 
144
        // add user specified whitelisted classnames
 
145
        _whiteList.insert( ExceptionId( "MplayerWindow" ) );
 
146
        _whiteList.insert( ExceptionId( "ViewSliders@kmix" ) );
 
147
        _whiteList.insert( ExceptionId( "Sidebar_Widget@konqueror" ) );
 
148
 
 
149
        foreach( const QString& exception, StyleConfigData::windowDragWhiteList() )
 
150
        {
 
151
            ExceptionId id( exception );
 
152
            if( !id.className().isEmpty() )
 
153
            { _whiteList.insert( exception ); }
 
154
        }
 
155
    }
 
156
 
 
157
    //_____________________________________________________________
 
158
    void WindowManager::initializeBlackList( void )
 
159
    {
 
160
 
 
161
        _blackList.clear();
 
162
        _blackList.insert( ExceptionId( "CustomTrackView@kdenlive" ) );
 
163
        _blackList.insert( ExceptionId( "MuseScore" ) );
 
164
        _blackList.insert( ExceptionId( "KGameCanvasWidget" ) );
 
165
        foreach( const QString& exception, StyleConfigData::windowDragBlackList() )
 
166
        {
 
167
            ExceptionId id( exception );
 
168
            if( !id.className().isEmpty() )
 
169
            { _blackList.insert( exception ); }
 
170
        }
 
171
 
 
172
    }
 
173
 
 
174
    //_____________________________________________________________
 
175
    bool WindowManager::eventFilter( QObject* object, QEvent* event )
 
176
    {
 
177
        if( !enabled() ) return false;
 
178
 
 
179
        switch ( event->type() )
 
180
        {
 
181
            case QEvent::MouseButtonPress:
 
182
                return mousePressEvent( object, event );
 
183
            break;
 
184
 
 
185
            case QEvent::MouseMove:
 
186
                if ( object == _target.data() ) return mouseMoveEvent( object, event );
 
187
            break;
 
188
 
 
189
            case QEvent::MouseButtonRelease:
 
190
                if ( _target ) return mouseReleaseEvent( object, event );
 
191
            break;
 
192
 
 
193
            default:
 
194
            break;
 
195
 
 
196
        }
 
197
 
 
198
        return false;
 
199
 
 
200
    }
 
201
 
 
202
    //_____________________________________________________________
 
203
    void WindowManager::timerEvent( QTimerEvent* event )
 
204
    {
 
205
 
 
206
        if( event->timerId() == _dragTimer.timerId() )
 
207
        {
 
208
            _dragTimer.stop();
 
209
            if( _target )
 
210
            { startDrag( _target.data(), _globalDragPoint ); }
 
211
 
 
212
        } else {
 
213
 
 
214
            return QObject::timerEvent( event );
 
215
 
 
216
        }
 
217
 
 
218
    }
 
219
 
 
220
    //_____________________________________________________________
 
221
    bool WindowManager::mousePressEvent( QObject* object, QEvent* event )
 
222
    {
 
223
 
 
224
        // cast event and check buttons/modifiers
 
225
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );
 
226
        if( !( mouseEvent->modifiers() == Qt::NoModifier && mouseEvent->button() == Qt::LeftButton ) )
 
227
        { return false; }
 
228
 
 
229
        // check lock
 
230
        if( isLocked() ) return false;
 
231
        else setLocked( true );
 
232
 
 
233
        // cast to widget
 
234
        QWidget *widget = static_cast<QWidget*>( object );
 
235
 
 
236
        // check if widget can be dragged from current position
 
237
        if( isBlackListed( widget ) || !canDrag( widget ) ) return false;
 
238
 
 
239
        // retrieve widget's child at event position
 
240
        QPoint position( mouseEvent->pos() );
 
241
        QWidget* child = widget->childAt( position );
 
242
        if( !canDrag( widget, child, position ) ) return false;
 
243
 
 
244
        // save target and drag point
 
245
        _target = widget;
 
246
        _dragPoint = position;
 
247
        _globalDragPoint = mouseEvent->globalPos();
 
248
        _dragAboutToStart = true;
 
249
 
 
250
        // send a move event to the current child with same position
 
251
        // if received, it is caught to actually start the drag
 
252
        QPoint localPoint( _dragPoint );
 
253
        if( child ) localPoint = child->mapFrom( widget, localPoint );
 
254
        else child = widget;
 
255
        QMouseEvent localMouseEvent( QEvent::MouseMove, localPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier );
 
256
        qApp->sendEvent( child, &localMouseEvent );
 
257
 
 
258
        // never eat event
 
259
        return false;
 
260
 
 
261
    }
 
262
 
 
263
    //_____________________________________________________________
 
264
    bool WindowManager::mouseMoveEvent( QObject* object, QEvent* event )
 
265
    {
 
266
 
 
267
        Q_UNUSED( object );
 
268
 
 
269
        // stop timer
 
270
        if( _dragTimer.isActive() ) _dragTimer.stop();
 
271
 
 
272
        // cast event and check drag distance
 
273
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );
 
274
        if( !_dragInProgress )
 
275
        {
 
276
 
 
277
            if( _dragAboutToStart )
 
278
            {
 
279
                if( mouseEvent->globalPos() == _globalDragPoint )
 
280
                {
 
281
                    // start timer,
 
282
                    _dragAboutToStart = false;
 
283
                    if( _dragTimer.isActive() ) _dragTimer.stop();
 
284
                    _dragTimer.start( _dragDelay, this );
 
285
 
 
286
                } else resetDrag();
 
287
 
 
288
            } else if( QPoint( mouseEvent->globalPos() - _globalDragPoint ).manhattanLength() >= _dragDistance )
 
289
            { _dragTimer.start( 0, this ); }
 
290
            return true;
 
291
 
 
292
        } else if( !useWMMoveResize() ) {
 
293
 
 
294
            // use QWidget::move for the grabbing
 
295
            /* this works only if the sending object and the target are identical */
 
296
            QWidget* window( _target.data()->window() );
 
297
            window->move( window->pos() + mouseEvent->pos() - _dragPoint );
 
298
            return true;
 
299
 
 
300
        } else return false;
 
301
 
 
302
    }
 
303
 
 
304
    //_____________________________________________________________
 
305
    bool WindowManager::mouseReleaseEvent( QObject* object, QEvent* event )
 
306
    {
 
307
        Q_UNUSED( object );
 
308
        Q_UNUSED( event );
 
309
        resetDrag();
 
310
        return false;
 
311
    }
 
312
 
 
313
    //_____________________________________________________________
 
314
    bool WindowManager::isDragable( QWidget* widget )
 
315
    {
 
316
 
 
317
        // check widget
 
318
        if( !widget ) return false;
 
319
 
 
320
        // accepted default types
 
321
        if(
 
322
            ( qobject_cast<QDialog*>( widget ) && widget->isWindow() ) ||
 
323
            ( qobject_cast<QMainWindow*>( widget ) && widget->isWindow() ) ||
 
324
            qobject_cast<QGroupBox*>( widget ) )
 
325
        { return true; }
 
326
 
 
327
        // more accepted types, provided they are not dock widget titles
 
328
        if( ( qobject_cast<QMenuBar*>( widget ) ||
 
329
            qobject_cast<QTabBar*>( widget ) ||
 
330
            qobject_cast<QStatusBar*>( widget ) ||
 
331
            qobject_cast<QToolBar*>( widget ) ) &&
 
332
            !isDockWidgetTitle( widget ) )
 
333
        { return true; }
 
334
 
 
335
        if( widget->inherits( "KScreenSaver" ) && widget->inherits( "KCModule" ) )
 
336
        { return true; }
 
337
 
 
338
        if( isWhiteListed( widget ) )
 
339
        { return true; }
 
340
 
 
341
        // flat toolbuttons
 
342
        if( QToolButton* toolButton = qobject_cast<QToolButton*>( widget ) )
 
343
        { if( toolButton->autoRaise() ) return true; }
 
344
 
 
345
        // viewports
 
346
        /*
 
347
        one needs to check that
 
348
        1/ the widget parent is a scrollarea
 
349
        2/ it matches its parent viewport
 
350
        3/ the parent is not blacklisted
 
351
        */
 
352
        if( QListView* listView = qobject_cast<QListView*>( widget->parentWidget() ) )
 
353
        { if( listView->viewport() == widget && !isBlackListed( listView ) ) return true; }
 
354
 
 
355
        if( QTreeView* treeView = qobject_cast<QTreeView*>( widget->parentWidget() ) )
 
356
        { if( treeView->viewport() == widget && !isBlackListed( treeView ) ) return true; }
 
357
 
 
358
        //if( QGraphicsView* graphicsView = qobject_cast<QGraphicsView*>( widget->parentWidget() ) )
 
359
        //{ if( graphicsView->viewport() == widget && !isBlackListed( graphicsView ) ) return true; }
 
360
 
 
361
        /*
 
362
        catch labels in status bars.
 
363
        this is because of kstatusbar
 
364
        who captures buttonPress/release events
 
365
        */
 
366
        if( QLabel* label = qobject_cast<QLabel*>( widget ) )
 
367
        {
 
368
            if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false;
 
369
 
 
370
            QWidget* parent = label->parentWidget();
 
371
            while( parent )
 
372
            {
 
373
                if( qobject_cast<QStatusBar*>( parent ) ) return true;
 
374
                parent = parent->parentWidget();
 
375
            }
 
376
        }
 
377
 
 
378
        return false;
 
379
 
 
380
    }
 
381
 
 
382
    //_____________________________________________________________
 
383
    bool WindowManager::isBlackListed( QWidget* widget )
 
384
    {
 
385
 
 
386
        // check against noAnimations propery
 
387
        QVariant propertyValue( widget->property( PropertyNames::noWindowGrab ) );
 
388
        if( propertyValue.isValid() && propertyValue.toBool() ) return true;
 
389
 
 
390
        // list-based blacklisted widgets
 
391
        QString appName( qApp->applicationName() );
 
392
        foreach( const ExceptionId& id, _blackList )
 
393
        {
 
394
            if( !id.appName().isEmpty() && id.appName() != appName ) continue;
 
395
            if( id.className() == "*" && !id.appName().isEmpty() )
 
396
            {
 
397
                // if application name matches and all classes are selected
 
398
                // disable the grabbing entirely
 
399
                setEnabled( false );
 
400
                return true;
 
401
            }
 
402
            if( widget->inherits( id.className().toLatin1() ) ) return true;
 
403
        }
 
404
 
 
405
        return false;
 
406
    }
 
407
 
 
408
    //_____________________________________________________________
 
409
    bool WindowManager::isWhiteListed( QWidget* widget ) const
 
410
    {
 
411
 
 
412
        QString appName( qApp->applicationName() );
 
413
        foreach( const ExceptionId& id, _whiteList )
 
414
        {
 
415
            if( !id.appName().isEmpty() && id.appName() != appName ) continue;
 
416
            if( widget->inherits( id.className().toLatin1() ) ) return true;
 
417
        }
 
418
 
 
419
        return false;
 
420
    }
 
421
 
 
422
    //_____________________________________________________________
 
423
    bool WindowManager::canDrag( QWidget* widget )
 
424
    {
 
425
 
 
426
        // check if enabled
 
427
        if( !enabled() ) return false;
 
428
 
 
429
        // assume isDragable widget is already passed
 
430
        // check some special cases where drag should not be effective
 
431
 
 
432
        // check mouse grabber
 
433
        if( QWidget::mouseGrabber() ) return false;
 
434
 
 
435
        /*
 
436
        check cursor shape.
 
437
        Assume that a changed cursor means that some action is in progress
 
438
        and should prevent the drag
 
439
        */
 
440
        if( widget->cursor().shape() != Qt::ArrowCursor ) return false;
 
441
 
 
442
        // accept
 
443
        return true;
 
444
 
 
445
    }
 
446
 
 
447
    //_____________________________________________________________
 
448
    bool WindowManager::canDrag( QWidget* widget, QWidget* child, const QPoint& position )
 
449
    {
 
450
 
 
451
        // retrieve child at given position and check cursor again
 
452
        if( child && child->cursor().shape() != Qt::ArrowCursor ) return false;
 
453
 
 
454
        /*
 
455
        check against children from which drag should never be enabled,
 
456
        even if mousePress/Move has been passed to the parent
 
457
        */
 
458
        if( child && (
 
459
          qobject_cast<QComboBox*>(child ) ||
 
460
          qobject_cast<QProgressBar*>( child ) ) )
 
461
        { return false; }
 
462
 
 
463
        // tool buttons
 
464
        if( QToolButton* toolButton = qobject_cast<QToolButton*>( widget ) )
 
465
        {
 
466
            if( dragMode() == StyleConfigData::WD_MINIMAL && !qobject_cast<QToolBar*>(widget->parentWidget() ) ) return false;
 
467
            return toolButton->autoRaise() && !toolButton->isEnabled();
 
468
        }
 
469
 
 
470
        // check menubar
 
471
        if( QMenuBar* menuBar = qobject_cast<QMenuBar*>( widget ) )
 
472
        {
 
473
 
 
474
            // check if there is an active action
 
475
            if( menuBar->activeAction() && menuBar->activeAction()->isEnabled() ) return false;
 
476
 
 
477
            // check if action at position exists and is enabled
 
478
            if( QAction* action = menuBar->actionAt( position ) )
 
479
            {
 
480
                if( action->isSeparator() ) return true;
 
481
                if( action->isEnabled() ) return false;
 
482
            }
 
483
 
 
484
            // return true in all other cases
 
485
            return true;
 
486
 
 
487
        }
 
488
 
 
489
        /*
 
490
        in MINIMAL mode, anything that has not been already accepted
 
491
        and does not come from a toolbar is rejected
 
492
        */
 
493
        if( dragMode() == StyleConfigData::WD_MINIMAL )
 
494
        {
 
495
            if( qobject_cast<QToolBar*>( widget ) ) return true;
 
496
            else return false;
 
497
        }
 
498
 
 
499
        /* following checks are relevant only for WD_FULL mode */
 
500
 
 
501
        // tabbar. Make sure no tab is under the cursor
 
502
        if( QTabBar* tabBar = qobject_cast<QTabBar*>( widget ) )
 
503
        { return tabBar->tabAt( position ) == -1; }
 
504
 
 
505
        /*
 
506
        check groupboxes
 
507
        prevent drag if unchecking grouboxes
 
508
        */
 
509
        if( QGroupBox *groupBox = qobject_cast<QGroupBox*>( widget ) )
 
510
        {
 
511
            // non checkable group boxes are always ok
 
512
            if( !groupBox->isCheckable() ) return true;
 
513
 
 
514
            // gather options to retrieve checkbox subcontrol rect
 
515
            QStyleOptionGroupBox opt;
 
516
            opt.initFrom( groupBox );
 
517
            if( groupBox->isFlat() ) opt.features |= QStyleOptionFrameV2::Flat;
 
518
            opt.lineWidth = 1;
 
519
            opt.midLineWidth = 0;
 
520
            opt.text = groupBox->title();
 
521
            opt.textAlignment = groupBox->alignment();
 
522
            opt.subControls = (QStyle::SC_GroupBoxFrame | QStyle::SC_GroupBoxCheckBox);
 
523
            if (!groupBox->title().isEmpty()) opt.subControls |= QStyle::SC_GroupBoxLabel;
 
524
 
 
525
            opt.state |= (groupBox->isChecked() ? QStyle::State_On : QStyle::State_Off);
 
526
 
 
527
            // check against groupbox checkbox
 
528
            if( groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxCheckBox, groupBox ).contains( position ) )
 
529
            { return false; }
 
530
 
 
531
            // check against groupbox label
 
532
            if( !groupBox->title().isEmpty() && groupBox->style()->subControlRect(QStyle::CC_GroupBox, &opt, QStyle::SC_GroupBoxLabel, groupBox ).contains( position ) )
 
533
            { return false; }
 
534
 
 
535
            return true;
 
536
 
 
537
        }
 
538
 
 
539
        // labels
 
540
        if( QLabel* label = qobject_cast<QLabel*>( widget ) )
 
541
        { if( label->textInteractionFlags().testFlag( Qt::TextSelectableByMouse ) ) return false; }
 
542
 
 
543
        // abstract item views
 
544
        QAbstractItemView* itemView( NULL );
 
545
        if(
 
546
            ( itemView = qobject_cast<QListView*>( widget->parentWidget() ) ) ||
 
547
            ( itemView = qobject_cast<QTreeView*>( widget->parentWidget() ) ) )
 
548
        {
 
549
            if( widget == itemView->viewport() )
 
550
            {
 
551
                // QListView
 
552
                if( itemView->frameShape() != QFrame::NoFrame ) return false;
 
553
                else if(
 
554
                    itemView->selectionMode() != QAbstractItemView::NoSelection &&
 
555
                    itemView->selectionMode() != QAbstractItemView::SingleSelection &&
 
556
                    itemView->model() && itemView->model()->rowCount() ) return false;
 
557
                else if( itemView->model() && itemView->indexAt( position ).isValid() ) return false;
 
558
            }
 
559
 
 
560
        } else if( ( itemView = qobject_cast<QAbstractItemView*>( widget->parentWidget() ) ) ) {
 
561
 
 
562
 
 
563
            if( widget == itemView->viewport() )
 
564
            {
 
565
                // QAbstractItemView
 
566
                if( itemView->frameShape() != QFrame::NoFrame ) return false;
 
567
                else if( itemView->indexAt( position ).isValid() ) return false;
 
568
            }
 
569
 
 
570
        } else if( QGraphicsView* graphicsView =  qobject_cast<QGraphicsView*>( widget->parentWidget() ) )  {
 
571
 
 
572
            if( widget == graphicsView->viewport() )
 
573
            {
 
574
                // QGraphicsView
 
575
                if( graphicsView->frameShape() != QFrame::NoFrame ) return false;
 
576
                else if( graphicsView->dragMode() != QGraphicsView::NoDrag ) return false;
 
577
                else if( graphicsView->itemAt( position ) ) return false;
 
578
            }
 
579
 
 
580
        }
 
581
 
 
582
        return true;
 
583
 
 
584
    }
 
585
 
 
586
    //____________________________________________________________
 
587
    void WindowManager::resetDrag( void )
 
588
    {
 
589
 
 
590
        if( (!useWMMoveResize() ) && _target && _cursorOverride ) {
 
591
 
 
592
          qApp->restoreOverrideCursor();
 
593
          _cursorOverride = false;
 
594
 
 
595
        }
 
596
 
 
597
        _target.clear();
 
598
        if( _dragTimer.isActive() ) _dragTimer.stop();
 
599
        _dragPoint = QPoint();
 
600
        _globalDragPoint = QPoint();
 
601
        _dragAboutToStart = false;
 
602
        _dragInProgress = false;
 
603
 
 
604
    }
 
605
 
 
606
    //____________________________________________________________
 
607
    void WindowManager::startDrag( QWidget* widget, const QPoint& position )
 
608
    {
 
609
 
 
610
        if( !( enabled() && widget ) ) return;
 
611
        if( QWidget::mouseGrabber() ) return;
 
612
 
 
613
        // ungrab pointer
 
614
        if( useWMMoveResize() )
 
615
        {
 
616
 
 
617
            #ifdef Q_WS_X11
 
618
            XUngrabPointer(QX11Info::display(), QX11Info::appTime());
 
619
            NETRootInfo rootInfo(QX11Info::display(), NET::WMMoveResize);
 
620
            rootInfo.moveResizeRequest( widget->window()->winId(), position.x(), position.y(), NET::Move);
 
621
            #endif
 
622
 
 
623
        }
 
624
 
 
625
        if( !useWMMoveResize() )
 
626
        {
 
627
            if( !_cursorOverride )
 
628
            {
 
629
                qApp->setOverrideCursor( Qt::SizeAllCursor );
 
630
                _cursorOverride = true;
 
631
            }
 
632
        }
 
633
 
 
634
        _dragInProgress = true;
 
635
 
 
636
        return;
 
637
 
 
638
    }
 
639
 
 
640
    //____________________________________________________________
 
641
    bool WindowManager::supportWMMoveResize( void ) const
 
642
    {
 
643
 
 
644
        #ifdef Q_WS_X11
 
645
        return true;
 
646
        #endif
 
647
 
 
648
        return false;
 
649
 
 
650
    }
 
651
 
 
652
    //____________________________________________________________
 
653
    bool WindowManager::isDockWidgetTitle( const QWidget* widget ) const
 
654
    {
 
655
 
 
656
        if( !widget ) return false;
 
657
        if( const QDockWidget* dockWidget = qobject_cast<const QDockWidget*>( widget->parent() ) )
 
658
        {
 
659
 
 
660
            return widget == dockWidget->titleBarWidget();
 
661
 
 
662
        } else return false;
 
663
 
 
664
    }
 
665
 
 
666
    //____________________________________________________________
 
667
    bool WindowManager::AppEventFilter::eventFilter( QObject* object, QEvent* event )
 
668
    {
 
669
 
 
670
        if( event->type() == QEvent::MouseButtonRelease )
 
671
        {
 
672
 
 
673
            // stop drag timer
 
674
            if( _parent->_dragTimer.isActive() )
 
675
            { _parent->resetDrag(); }
 
676
 
 
677
            // unlock
 
678
            if( _parent->isLocked() )
 
679
            { _parent->setLocked( false ); }
 
680
 
 
681
        }
 
682
 
 
683
        if( !_parent->enabled() ) return false;
 
684
 
 
685
        /*
 
686
        if a drag is in progress, the widget will not receive any event
 
687
        we trigger on the first MouseMove or MousePress events that are received
 
688
        by any widget in the application to detect that the drag is finished
 
689
        */
 
690
        if( _parent->useWMMoveResize() && _parent->_dragInProgress && _parent->_target && ( event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonPress ) )
 
691
        { return appMouseEvent( object, event ); }
 
692
 
 
693
        return false;
 
694
 
 
695
    }
 
696
 
 
697
    //_____________________________________________________________
 
698
    bool WindowManager::AppEventFilter::appMouseEvent( QObject* object, QEvent* event )
 
699
    {
 
700
 
 
701
        Q_UNUSED( object );
 
702
 
 
703
        // store target window (see later)
 
704
        QWidget* window( _parent->_target.data()->window() );
 
705
 
 
706
        /*
 
707
        post some mouseRelease event to the target, in order to counter balance
 
708
        the mouse press that triggered the drag. Note that it triggers a resetDrag
 
709
        */
 
710
        QMouseEvent mouseEvent( QEvent::MouseButtonRelease, _parent->_dragPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier );
 
711
        qApp->sendEvent( _parent->_target.data(), &mouseEvent );
 
712
 
 
713
        if( event->type() == QEvent::MouseMove )
 
714
        {
 
715
            /*
 
716
            HACK: quickly move the main cursor out of the window and back
 
717
            this is needed to get the focus right for the window children
 
718
            the origin of this issue is unknown at the moment
 
719
            */
 
720
            const QPoint cursor = QCursor::pos();
 
721
            QCursor::setPos(window->mapToGlobal( window->rect().topRight() ) + QPoint(1, 0) );
 
722
            QCursor::setPos(cursor);
 
723
 
 
724
        }
 
725
 
 
726
        return false;
 
727
 
 
728
    }
 
729
 
 
730
 
 
731
}