/**************************************************************************** ** ** Implementation of the TQWidgetResizeHandler class ** ** Created : 001010 ** ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. ** ** This file is part of the workspace module of the TQt GUI Toolkit. ** ** This file may be used under the terms of the GNU General ** Public License versions 2.0 or 3.0 as published by the Free ** Software Foundation and appearing in the files LICENSE.GPL2 ** and LICENSE.GPL3 included in the packaging of this file. ** Alternatively you may (at your option) use any later version ** of the GNU General Public License if such license has been ** publicly approved by Trolltech ASA (or its successors, if any) ** and the KDE Free TQt Foundation. ** ** Please review the following information to ensure GNU General ** Public Licensing requirements will be met: ** http://trolltech.com/products/qt/licenses/licensing/opensource/. ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview ** or contact the sales department at sales@trolltech.com. ** ** This file may be used under the terms of the Q Public License as ** defined by Trolltech ASA and appearing in the file LICENSE.TQPL ** included in the packaging of this file. Licensees holding valid TQt ** Commercial licenses may use this file in accordance with the TQt ** Commercial License Agreement provided with the Software. ** ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted ** herein. ** **********************************************************************/ #include "tqwidgetresizehandler_p.h" #ifndef TQT_NO_RESIZEHANDLER #include "tqframe.h" #include "ntqapplication.h" #include "ntqcursor.h" #include "tqsizegrip.h" #if defined(TQ_WS_WIN) #include "qt_windows.h" #endif #define RANGE 4 static bool resizeHorizontalDirectionFixed = FALSE; static bool resizeVerticalDirectionFixed = FALSE; TQWidgetResizeHandler::TQWidgetResizeHandler( TQWidget *parent, TQWidget *cw, const char *name ) : TQObject( parent, name ), widget( parent ), childWidget( cw ? cw : parent ), extrahei( 0 ), buttonDown( FALSE ), moveResizeMode( FALSE ), sizeprotect( TRUE ), moving( TRUE ) { mode = Nowhere; widget->setMouseTracking( TRUE ); TQFrame *frame = ::tqt_cast(widget); range = frame ? frame->frameWidth() : RANGE; range = TQMAX( RANGE, range ); activeForMove = activeForResize = TRUE; tqApp->installEventFilter( this ); } void TQWidgetResizeHandler::setActive( Action ac, bool b ) { if ( ac & Move ) activeForMove = b; if ( ac & Resize ) activeForResize = b; if ( !isActive() ) setMouseCursor( Nowhere ); } bool TQWidgetResizeHandler::isActive( Action ac ) const { bool b = FALSE; if ( ac & Move ) b = activeForMove; if ( ac & Resize ) b |= activeForResize; return b; } static TQWidget *childOf( TQWidget *w, TQWidget *child ) { while ( child ) { if ( child == w ) return child; if ( child->isTopLevel() ) break; child = child->parentWidget(); } return 0; } bool TQWidgetResizeHandler::eventFilter( TQObject *o, TQEvent *ee ) { if ( !isActive() || !o->isWidgetType() || !ee->spontaneous()) return FALSE; if ( ee->type() != TQEvent::MouseButtonPress && ee->type() != TQEvent::MouseButtonRelease && ee->type() != TQEvent::MouseMove && ee->type() != TQEvent::KeyPress && ee->type() != TQEvent::AccelOverride ) return FALSE; TQWidget *w = childOf( widget, (TQWidget*)o ); if ( !w #ifndef TQT_NO_SIZEGRIP || ::tqt_cast(o) #endif || tqApp->activePopupWidget() ) { if ( buttonDown && ee->type() == TQEvent::MouseButtonRelease ) buttonDown = FALSE; return FALSE; } TQMouseEvent *e = (TQMouseEvent*)ee; switch ( e->type() ) { case TQEvent::MouseButtonPress: { if ( w->isMaximized() ) break; if ( !widget->rect().contains( widget->mapFromGlobal( e->globalPos() ) ) ) return FALSE; if ( e->button() == LeftButton ) { emit activate(); bool me = isMovingEnabled(); setMovingEnabled( me && o == widget ); mouseMoveEvent( e ); setMovingEnabled( me ); buttonDown = TRUE; moveOffset = widget->mapFromGlobal( e->globalPos() ); invertedMoveOffset = widget->rect().bottomRight() - moveOffset; } } break; case TQEvent::MouseButtonRelease: if ( w->isMaximized() ) break; if ( e->button() == LeftButton ) { moveResizeMode = FALSE; buttonDown = FALSE; widget->releaseMouse(); widget->releaseKeyboard(); } break; case TQEvent::MouseMove: { if ( w->isMaximized() ) break; bool me = isMovingEnabled(); setMovingEnabled( me && o == widget ); mouseMoveEvent( e ); setMovingEnabled( me ); if ( buttonDown && mode != Center ) return TRUE; } break; case TQEvent::KeyPress: keyPressEvent( (TQKeyEvent*)e ); break; case TQEvent::AccelOverride: if ( buttonDown ) { ((TQKeyEvent*)ee)->accept(); return TRUE; } break; default: break; } return FALSE; } void TQWidgetResizeHandler::mouseMoveEvent( TQMouseEvent *e ) { TQPoint pos = widget->mapFromGlobal( e->globalPos() ); if ( !moveResizeMode && ( !buttonDown || ( e->state() & LeftButton ) == 0 ) ) { if ( pos.y() <= range && pos.x() <= range) mode = TopLeft; else if ( pos.y() >= widget->height()-range && pos.x() >= widget->width()-range) mode = BottomRight; else if ( pos.y() >= widget->height()-range && pos.x() <= range) mode = BottomLeft; else if ( pos.y() <= range && pos.x() >= widget->width()-range) mode = TopRight; else if ( pos.y() <= range ) mode = Top; else if ( pos.y() >= widget->height()-range ) mode = Bottom; else if ( pos.x() <= range ) mode = Left; else if ( pos.x() >= widget->width()-range ) mode = Right; else mode = Center; if ( widget->isMinimized() || !isActive(Resize) ) mode = Center; #ifndef TQT_NO_CURSOR setMouseCursor( mode ); #endif return; } if ( buttonDown && !isMovingEnabled() && mode == Center && !moveResizeMode ) return; if ( widget->testWState( WState_ConfigPending ) ) return; TQPoint globalPos = widget->parentWidget( TRUE ) ? widget->parentWidget( TRUE )->mapFromGlobal( e->globalPos() ) : e->globalPos(); if ( widget->parentWidget( TRUE ) && !widget->parentWidget( TRUE )->rect().contains( globalPos ) ) { if ( globalPos.x() < 0 ) globalPos.rx() = 0; if ( globalPos.y() < 0 ) globalPos.ry() = 0; if ( sizeprotect && globalPos.x() > widget->parentWidget()->width() ) globalPos.rx() = widget->parentWidget()->width(); if ( sizeprotect && globalPos.y() > widget->parentWidget()->height() ) globalPos.ry() = widget->parentWidget()->height(); } TQPoint p = globalPos + invertedMoveOffset; TQPoint pp = globalPos - moveOffset; int fw = 0; int mw = TQMAX( childWidget->minimumSizeHint().width(), childWidget->minimumWidth() ); int mh = TQMAX( childWidget->minimumSizeHint().height(), childWidget->minimumHeight() ); if ( childWidget != widget ) { TQFrame *frame = ::tqt_cast(widget); if ( frame ) fw = frame->frameWidth(); mw += 2 * fw; mh += 2 * fw + extrahei; } TQSize mpsize( widget->geometry().right() - pp.x() + 1, widget->geometry().bottom() - pp.y() + 1 ); mpsize = mpsize.expandedTo( widget->minimumSize() ).expandedTo( TQSize(mw, mh) ); TQPoint mp( widget->geometry().right() - mpsize.width() + 1, widget->geometry().bottom() - mpsize.height() + 1 ); TQRect geom = widget->geometry(); switch ( mode ) { case TopLeft: geom = TQRect( mp, widget->geometry().bottomRight() ) ; break; case BottomRight: geom = TQRect( widget->geometry().topLeft(), p ) ; break; case BottomLeft: geom = TQRect( TQPoint(mp.x(), widget->geometry().y() ), TQPoint( widget->geometry().right(), p.y()) ) ; break; case TopRight: geom = TQRect( TQPoint( widget->geometry().x(), mp.y() ), TQPoint( p.x(), widget->geometry().bottom()) ) ; break; case Top: geom = TQRect( TQPoint( widget->geometry().left(), mp.y() ), widget->geometry().bottomRight() ) ; break; case Bottom: geom = TQRect( widget->geometry().topLeft(), TQPoint( widget->geometry().right(), p.y() ) ) ; break; case Left: geom = TQRect( TQPoint( mp.x(), widget->geometry().top() ), widget->geometry().bottomRight() ) ; break; case Right: geom = TQRect( widget->geometry().topLeft(), TQPoint( p.x(), widget->geometry().bottom() ) ) ; break; case Center: if ( isMovingEnabled() || moveResizeMode ) geom.moveTopLeft( pp ); break; default: break; } TQSize maxsize( childWidget->maximumSize() ); if ( childWidget != widget ) maxsize += TQSize( 2 * fw, 2 * fw + extrahei ); geom = TQRect( geom.topLeft(), geom.size().expandedTo( widget->minimumSize() ) .expandedTo( TQSize(mw, mh) ) .boundedTo( maxsize ) ); if ( geom != widget->geometry() && ( widget->isTopLevel() || widget->parentWidget()->rect().intersects( geom ) ) ) { if ( widget->isMinimized() ) widget->move( geom.topLeft() ); else widget->setGeometry( geom ); } #if defined(TQ_WS_WIN) MSG msg; QT_WA( { while(PeekMessageW( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE )) ; } , { while(PeekMessageA( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE )) ; } ); #endif TQApplication::syncX(); } void TQWidgetResizeHandler::setMouseCursor( MousePosition m ) { #ifndef TQT_NO_CURSOR switch ( m ) { case TopLeft: case BottomRight: widget->setCursor( sizeFDiagCursor ); break; case BottomLeft: case TopRight: widget->setCursor( sizeBDiagCursor ); break; case Top: case Bottom: widget->setCursor( sizeVerCursor ); break; case Left: case Right: widget->setCursor( sizeHorCursor ); break; default: widget->setCursor( arrowCursor ); break; } #endif } void TQWidgetResizeHandler::keyPressEvent( TQKeyEvent * e ) { if ( !isMove() && !isResize() ) return; bool is_control = e->state() & ControlButton; int delta = is_control?1:8; TQPoint pos = TQCursor::pos(); switch ( e->key() ) { case Key_Left: pos.rx() -= delta; if ( pos.x() <= TQApplication::desktop()->geometry().left() ) { if ( mode == TopLeft || mode == BottomLeft ) { moveOffset.rx() += delta; invertedMoveOffset.rx() += delta; } else { moveOffset.rx() -= delta; invertedMoveOffset.rx() -= delta; } } if ( isResize() && !resizeHorizontalDirectionFixed ) { resizeHorizontalDirectionFixed = TRUE; if ( mode == BottomRight ) mode = BottomLeft; else if ( mode == TopRight ) mode = TopLeft; #ifndef TQT_NO_CURSOR setMouseCursor( mode ); widget->grabMouse( widget->cursor() ); #else widget->grabMouse(); #endif } break; case Key_Right: pos.rx() += delta; if ( pos.x() >= TQApplication::desktop()->geometry().right() ) { if ( mode == TopRight || mode == BottomRight ) { moveOffset.rx() += delta; invertedMoveOffset.rx() += delta; } else { moveOffset.rx() -= delta; invertedMoveOffset.rx() -= delta; } } if ( isResize() && !resizeHorizontalDirectionFixed ) { resizeHorizontalDirectionFixed = TRUE; if ( mode == BottomLeft ) mode = BottomRight; else if ( mode == TopLeft ) mode = TopRight; #ifndef TQT_NO_CURSOR setMouseCursor( mode ); widget->grabMouse( widget->cursor() ); #else widget->grabMouse(); #endif } break; case Key_Up: pos.ry() -= delta; if ( pos.y() <= TQApplication::desktop()->geometry().top() ) { if ( mode == TopLeft || mode == TopRight ) { moveOffset.ry() += delta; invertedMoveOffset.ry() += delta; } else { moveOffset.ry() -= delta; invertedMoveOffset.ry() -= delta; } } if ( isResize() && !resizeVerticalDirectionFixed ) { resizeVerticalDirectionFixed = TRUE; if ( mode == BottomLeft ) mode = TopLeft; else if ( mode == BottomRight ) mode = TopRight; #ifndef TQT_NO_CURSOR setMouseCursor( mode ); widget->grabMouse( widget->cursor() ); #else widget->grabMouse(); #endif } break; case Key_Down: pos.ry() += delta; if ( pos.y() >= TQApplication::desktop()->geometry().bottom() ) { if ( mode == BottomLeft || mode == BottomRight ) { moveOffset.ry() += delta; invertedMoveOffset.ry() += delta; } else { moveOffset.ry() -= delta; invertedMoveOffset.ry() -= delta; } } if ( isResize() && !resizeVerticalDirectionFixed ) { resizeVerticalDirectionFixed = TRUE; if ( mode == TopLeft ) mode = BottomLeft; else if ( mode == TopRight ) mode = BottomRight; #ifndef TQT_NO_CURSOR setMouseCursor( mode ); widget->grabMouse( widget->cursor() ); #else widget->grabMouse(); #endif } break; case Key_Space: case Key_Return: case Key_Enter: case Key_Escape: moveResizeMode = FALSE; widget->releaseMouse(); widget->releaseKeyboard(); buttonDown = FALSE; break; default: return; } TQCursor::setPos( pos ); } void TQWidgetResizeHandler::doResize() { if ( !activeForResize ) return; moveResizeMode = TRUE; buttonDown = TRUE; moveOffset = widget->mapFromGlobal( TQCursor::pos() ); if ( moveOffset.x() < widget->width()/2) { if ( moveOffset.y() < widget->height()/2) mode = TopLeft; else mode = BottomLeft; } else { if ( moveOffset.y() < widget->height()/2) mode = TopRight; else mode = BottomRight; } invertedMoveOffset = widget->rect().bottomRight() - moveOffset; #ifndef TQT_NO_CURSOR setMouseCursor( mode ); widget->grabMouse( widget->cursor() ); #else widget->grabMouse(); #endif widget->grabKeyboard(); resizeHorizontalDirectionFixed = FALSE; resizeVerticalDirectionFixed = FALSE; } void TQWidgetResizeHandler::doMove() { if ( !activeForMove ) return; mode = Center; moveResizeMode = TRUE; buttonDown = TRUE; moveOffset = widget->mapFromGlobal( TQCursor::pos() ); invertedMoveOffset = widget->rect().bottomRight() - moveOffset; #ifndef TQT_NO_CURSOR widget->grabMouse( SizeAllCursor ); #else widget->grabMouse(); #endif widget->grabKeyboard(); } #endif //TQT_NO_RESIZEHANDLER