diff --git a/client.cpp b/client.cpp index 01d06c1547..f19548c2d3 100644 --- a/client.cpp +++ b/client.cpp @@ -77,6 +77,9 @@ Client::Client( Workspace *ws ) transient_for( NULL ), transient_for_id( None ), original_transient_for_id( None ), + autoRaiseTimer( NULL ), + shadeHoverTimer( NULL ), + delayedMoveResizeTimer( NULL ), in_group( NULL ), window_group( None ), in_layer( UnknownLayer ), @@ -95,8 +98,6 @@ Client::Client( Workspace *ws ) demandAttentionKNotifyTimer( NULL ) // SELI do all as initialization { - autoRaiseTimer = 0; - shadeHoverTimer = 0; // set the initial mapping state mapping_state = WithdrawnState; @@ -1450,48 +1451,47 @@ bool Client::isSpecialWindow() const Sets an appropriate cursor shape for the logical mouse position \a m */ -void Client::setCursor( Position m ) +void Client::updateCursor() { + Position m = mode; if( !isResizable() || isShade()) - { m = PositionCenter; - } - switch ( m ) + QCursor c; + switch( m ) { case PositionTopLeft: case PositionBottomRight: - setCursor( Qt::SizeFDiagCursor ); + c = Qt::SizeFDiagCursor; break; case PositionBottomLeft: case PositionTopRight: - setCursor( Qt::SizeBDiagCursor ); + c = Qt::SizeBDiagCursor; break; case PositionTop: case PositionBottom: - setCursor( Qt::SizeVerCursor ); + c = Qt::SizeVerCursor; break; case PositionLeft: case PositionRight: - setCursor( Qt::SizeHorCursor ); + c = Qt::SizeHorCursor; break; default: - if( buttonDown && isMovable()) - setCursor( Qt::SizeAllCursor ); + if( moveResizeMode ) + c = Qt::SizeAllCursor; else - setCursor( Qt::ArrowCursor ); + c = Qt::ArrowCursor; break; } - } - -// TODO mit nejake checkCursor(), ktere se zavola v manage() a pri vecech, kdy by se kurzor mohl zmenit? -void Client::setCursor( const QCursor& c ) - { if( c.handle() == cursor.handle()) return; cursor = c; if( decoration != NULL ) decoration->widget()->setCursor( cursor ); XDefineCursor( display(), frameId(), cursor.handle()); + if( moveResizeMode ) // XDefineCursor doesn't change cursor if there's pointer grab active + XChangeActivePointerGrab( display(), + ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask, + cursor.handle(), xTime()); } Client::Position Client::mousePosition( const QPoint& p ) const diff --git a/client.h b/client.h index 20d71f28e9..84fc9b35f3 100644 --- a/client.h +++ b/client.h @@ -265,6 +265,7 @@ class Client void autoRaise(); void shadeHover(); void shortcutActivated(); + void delayedMoveResize(); private: friend class Bridge; // FRAME @@ -275,8 +276,7 @@ class Client virtual ~Client(); // use destroyClient() or releaseWindow() Position mousePosition( const QPoint& ) const; - void setCursor( Position m ); - void setCursor( const QCursor& c ); + void updateCursor(); // transparent stuff void drawbound( const QRect& geom ); @@ -346,6 +346,8 @@ class Client void leaveMoveResize(); void checkUnrestrictedMoveResize(); void handleMoveResize( int x, int y, int x_root, int y_root ); + void startDelayedMoveResize(); + void stopDelayedMoveResize(); void positionGeometryTip(); void grabButton( int mod ); void ungrabButton( int mod ); @@ -447,6 +449,7 @@ class Client int workarea_diff_x, workarea_diff_y; QTimer* autoRaiseTimer; QTimer* shadeHoverTimer; + QTimer* delayedMoveResizeTimer; Colormap cmap; QString cap_normal, cap_iconic, cap_suffix; Group* in_group; diff --git a/events.cpp b/events.cpp index b8c5ca9b6e..4392583549 100644 --- a/events.cpp +++ b/events.cpp @@ -988,7 +988,7 @@ void Client::leaveNotifyEvent( XCrossingEvent* e ) if ( !buttonDown ) { mode = PositionCenter; - setCursor( Qt::ArrowCursor ); + updateCursor(); } bool lostMouse = !rect().contains( QPoint( e->x, e->y ) ); // 'lostMouse' wouldn't work with e.g. B2 or Keramik, which have non-rectangular decorations @@ -1281,7 +1281,8 @@ void Client::processDecorationButtonPress( int button, int /*state*/, int x, int moveOffset = QPoint( x, y ); invertedMoveOffset = rect().bottomRight() - moveOffset; unrestrictedMoveResize = false; - setCursor( mode ); // update to sizeAllCursor if about to move + startDelayedMoveResize(); + updateCursor(); } performMouseCommand( com, QPoint( x_root, y_root )); } @@ -1297,13 +1298,13 @@ void Client::processMousePressEvent( QMouseEvent* e ) int button; switch( e->button()) { - case Qt::LeftButton: + case Qt::LeftButton: button = Button1; break; - case Qt::MidButton: + case Qt::MidButton: button = Button2; break; - case Qt::RightButton: + case Qt::RightButton: button = Button3; break; default: @@ -1329,6 +1330,7 @@ bool Client::buttonReleaseEvent( Window w, int /*button*/, int state, int x, int if ( (state & ( Button1Mask & Button2Mask & Button3Mask )) == 0 ) { buttonDown = false; + stopDelayedMoveResize(); if ( moveResizeMode ) { finishMoveResize( false ); @@ -1336,7 +1338,7 @@ bool Client::buttonReleaseEvent( Window w, int /*button*/, int state, int x, int QPoint mousepos( x_root - x, y_root - y ); mode = mousePosition( mousepos ); } - setCursor( mode ); + updateCursor(); } return true; } @@ -1384,8 +1386,10 @@ bool Client::motionNotifyEvent( Window w, int /*state*/, int x, int y, int x_roo { Position newmode = mousePosition( QPoint( x, y )); if( newmode != mode ) - setCursor( newmode ); - mode = newmode; + { + mode = newmode; + updateCursor(); + } // reset the timestamp for the optimization, otherwise with long passivity // the option in waitingMotionEvent() may be always true next_motion_time = CurrentTime; @@ -1496,7 +1500,7 @@ void Client::NETMoveResize( int x_root, int y_root, NET::Direction direction ) { finishMoveResize( true ); buttonDown = false; - setCursor( mode ); + updateCursor(); } else if( direction >= NET::TopLeft && direction <= NET::Left ) { @@ -1520,12 +1524,9 @@ void Client::NETMoveResize( int x_root, int y_root, NET::Direction direction ) invertedMoveOffset = rect().bottomRight() - moveOffset; unrestrictedMoveResize = false; mode = convert[ direction ]; - setCursor( mode ); if( !startMoveResize()) - { buttonDown = false; - setCursor( mode ); - } + updateCursor(); } else if( direction == NET::KeyboardMove ) { // ignore mouse coordinates given in the message, mouse position is used by the moving algorithm @@ -1568,12 +1569,12 @@ void Client::keyPressEvent( uint key_code ) case Qt::Key_Enter: finishMoveResize( false ); buttonDown = false; - setCursor( mode ); + updateCursor(); break; case Qt::Key_Escape: finishMoveResize( true ); buttonDown = false; - setCursor( mode ); + updateCursor(); break; default: return; diff --git a/geometry.cpp b/geometry.cpp index c5204708d2..8777ae3927 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2260,6 +2260,7 @@ bool Client::startMoveResize() assert( !moveResizeMode ); assert( QWidget::keyboardGrabber() == NULL ); assert( QWidget::mouseGrabber() == NULL ); + stopDelayedMoveResize(); if( QApplication::activePopupWidget() != NULL ) return false; // popups have grab bool has_grab = false; @@ -2398,6 +2399,33 @@ void Client::checkUnrestrictedMoveResize() } } +// When the user pressed mouse on the titlebar, don't activate move immediatelly, +// since it may be just a click. Activate instead after a delay. Move used to be +// activated only after moving by several pixels, but that looks bad. +void Client::startDelayedMoveResize() + { + delete delayedMoveResizeTimer; + delayedMoveResizeTimer = new QTimer( this ); + connect( delayedMoveResizeTimer, SIGNAL( timeout()), this, SLOT( delayedMoveResize())); + delayedMoveResizeTimer->setSingleShot( true ); + delayedMoveResizeTimer->start( QApplication::doubleClickInterval()); + } + +void Client::stopDelayedMoveResize() + { + delete delayedMoveResizeTimer; + delayedMoveResizeTimer = NULL; + } + +void Client::delayedMoveResize() + { + assert( buttonDown ); + if( !startMoveResize()) + buttonDown = false; + updateCursor(); + stopDelayedMoveResize(); + } + void Client::handleMoveResize( int x, int y, int x_root, int y_root ) { if(( mode == PositionCenter && !isMovable()) @@ -2412,9 +2440,10 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root ) if( !startMoveResize()) { buttonDown = false; - setCursor( mode ); + updateCursor(); return; } + updateCursor(); } else return; diff --git a/useractions.cpp b/useractions.cpp index 197cec0400..2664541ed0 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -608,12 +608,9 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo invertedMoveOffset = rect().bottomRight() - moveOffset; unrestrictedMoveResize = ( command == Options::MouseActivateRaiseAndUnrestrictedMove || command == Options::MouseUnrestrictedMove ); - setCursor( mode ); if( !startMoveResize()) - { buttonDown = false; - setCursor( mode ); - } + updateCursor(); break; } case Options::MouseResize: @@ -638,12 +635,9 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo mode = (x < width() / 2) ? PositionLeft : PositionRight; invertedMoveOffset = rect().bottomRight() - moveOffset; unrestrictedMoveResize = ( command == Options::MouseUnrestrictedResize ); - setCursor( mode ); if( !startMoveResize()) - { buttonDown = false; - setCursor( mode ); - } + updateCursor(); break; } case Options::MouseMaximize: