FocusIndicator improved
This commit is contained in:
parent
c3c9405b65
commit
1dee82c29e
@ -7,27 +7,46 @@
|
||||
#include <QskBoxBorderColors.h>
|
||||
#include <QskRgbValue.h>
|
||||
|
||||
#include <QQuickWindow>
|
||||
#include <qquickwindow.h>
|
||||
#include <qbasictimer.h>
|
||||
|
||||
|
||||
QSK_STATE( FocusIndicator, Concealed, QskAspect::FirstUserState )
|
||||
|
||||
static inline bool qskIsExposingKeyPress( const QKeyEvent* event )
|
||||
{
|
||||
// what keys do we want have here ???
|
||||
return qskIsButtonPressKey( event ) || qskFocusChainIncrement( event );
|
||||
}
|
||||
|
||||
static void qskMaybeExpose( FocusIndicator* indicator, bool on )
|
||||
{
|
||||
Q_UNUSED( indicator );
|
||||
Q_UNUSED( on );
|
||||
|
||||
#if 0
|
||||
if ( on )
|
||||
{
|
||||
if ( auto w = indicator->window() )
|
||||
{
|
||||
if ( w->isExposed() && w->isActive() )
|
||||
indicator->setExposed( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indicator->setExposed( false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
class FocusIndicator::PrivateData
|
||||
{
|
||||
public:
|
||||
void restartTimer( FocusIndicator* indicator, int ms )
|
||||
{
|
||||
if( timerId > 0 )
|
||||
{
|
||||
indicator->killTimer( timerId );
|
||||
timerId = 0;
|
||||
}
|
||||
inline bool isAutoConcealing() const { return timeout > 0; }
|
||||
|
||||
if ( ms > 0 )
|
||||
timerId = indicator->startTimer( ms );
|
||||
}
|
||||
|
||||
const int timeout = 4500;
|
||||
int timerId = 0;
|
||||
int timeout = 0;
|
||||
QBasicTimer concealTimer;
|
||||
|
||||
bool blockAutoRepeatKeyEvents = false;
|
||||
};
|
||||
@ -36,8 +55,6 @@ FocusIndicator::FocusIndicator( QQuickItem* parent )
|
||||
: Inherited( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
if( window() )
|
||||
window()->installEventFilter( this );
|
||||
#if 1
|
||||
auto colors = boxBorderColorsHint( Panel );
|
||||
|
||||
@ -47,34 +64,91 @@ FocusIndicator::FocusIndicator( QQuickItem* parent )
|
||||
setAnimationHint( Panel | QskAspect::Color | Concealed, 500 );
|
||||
#endif
|
||||
|
||||
m_data->restartTimer( this, m_data->timeout );
|
||||
setExposedTimeout( 4500 );
|
||||
}
|
||||
|
||||
FocusIndicator::~FocusIndicator()
|
||||
{
|
||||
}
|
||||
|
||||
void FocusIndicator::setConcealed( bool on )
|
||||
void FocusIndicator::setExposedTimeout( int ms )
|
||||
{
|
||||
if ( on == isConcealed() )
|
||||
ms = std::max( ms, 0 );
|
||||
if ( ms == m_data->timeout )
|
||||
return;
|
||||
|
||||
setSkinStateFlag( Concealed, on );
|
||||
m_data->timeout = ms;
|
||||
|
||||
int timeout = 0;
|
||||
if ( !on )
|
||||
timeout = m_data->timeout + animationHint( Panel | QskAspect::Color ).duration;
|
||||
if ( m_data->isAutoConcealing() )
|
||||
{
|
||||
if ( auto w = window() )
|
||||
w->installEventFilter( this );
|
||||
|
||||
m_data->restartTimer( this, timeout );
|
||||
if ( isExposed() )
|
||||
{
|
||||
if ( isInitiallyPainted() )
|
||||
m_data->concealTimer.start( m_data->timeout, this );
|
||||
else
|
||||
setExposed( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( auto w = window() )
|
||||
w->removeEventFilter( this );
|
||||
|
||||
Q_EMIT concealedChanged( on );
|
||||
setExposed( true );
|
||||
}
|
||||
|
||||
Q_EMIT exposedTimeoutChanged( ms );
|
||||
}
|
||||
|
||||
int FocusIndicator::exposedTimeout() const
|
||||
{
|
||||
return m_data->timeout;
|
||||
}
|
||||
|
||||
void FocusIndicator::setExposed( bool on )
|
||||
{
|
||||
if ( on == isExposed() )
|
||||
return;
|
||||
|
||||
setSkinStateFlag( Concealed, !on );
|
||||
|
||||
if ( m_data->isAutoConcealing() )
|
||||
{
|
||||
if ( on )
|
||||
{
|
||||
const auto hint = animationHint( Panel | QskAspect::Color );
|
||||
m_data->concealTimer.start( m_data->timeout + hint.duration, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data->concealTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Q_EMIT exposedChanged( on );
|
||||
}
|
||||
|
||||
bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
|
||||
{
|
||||
if( object != window() )
|
||||
if( ( object != window() ) || !m_data->isAutoConcealing() )
|
||||
return Inherited::eventFilter( object, event );
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
case QEvent::ShortcutOverride:
|
||||
if ( m_data->concealTimer.isActive() )
|
||||
{
|
||||
// renew the exposed period
|
||||
m_data->concealTimer.start( m_data->timeout, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
@ -82,37 +156,22 @@ bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
|
||||
const auto keyEvent = static_cast< QKeyEvent* >( event );
|
||||
|
||||
if( keyEvent->isAutoRepeat() && m_data->blockAutoRepeatKeyEvents )
|
||||
return true;
|
||||
|
||||
if ( qskIsButtonPressKey( keyEvent ) )
|
||||
{
|
||||
if ( isConcealed() )
|
||||
{
|
||||
setConcealed( false );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
/*
|
||||
We swallow all auto repeated events to avoid running along
|
||||
the tab chain by accident.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if( qskFocusChainIncrement( keyEvent ) != 0 )
|
||||
if ( !isExposed() && qskIsExposingKeyPress( keyEvent ) )
|
||||
{
|
||||
if ( isConcealed() )
|
||||
{
|
||||
setConcealed( false );
|
||||
m_data->blockAutoRepeatKeyEvents = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// extending the timer
|
||||
m_data->restartTimer( this, m_data->timeout );
|
||||
return false;
|
||||
}
|
||||
setExposed( true );
|
||||
m_data->blockAutoRepeatKeyEvents = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_data->blockAutoRepeatKeyEvents = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -129,15 +188,11 @@ bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
|
||||
break;
|
||||
}
|
||||
|
||||
case QEvent::Expose:
|
||||
case QEvent::FocusIn:
|
||||
case QEvent::FocusOut:
|
||||
{
|
||||
setConcealed( true );
|
||||
break;
|
||||
}
|
||||
|
||||
case QEvent::FocusIn:
|
||||
{
|
||||
setConcealed( false );
|
||||
qskMaybeExpose( this, event->type() != QEvent::FocusOut );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -149,34 +204,36 @@ void FocusIndicator::windowChangeEvent( QskWindowChangeEvent* event )
|
||||
{
|
||||
Inherited::windowChangeEvent( event );
|
||||
|
||||
if( event->oldWindow() )
|
||||
event->oldWindow()->removeEventFilter( this );
|
||||
if ( m_data->isAutoConcealing() )
|
||||
{
|
||||
if ( auto w = event->oldWindow() )
|
||||
w->removeEventFilter( this );
|
||||
|
||||
if( event->window() )
|
||||
event->window()->installEventFilter( this );
|
||||
if( auto w = event->window() )
|
||||
{
|
||||
w->installEventFilter( this );
|
||||
qskMaybeExpose( this, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FocusIndicator::timerEvent( QTimerEvent* event )
|
||||
{
|
||||
if( event->timerId() == m_data->timerId )
|
||||
if ( m_data->isAutoConcealing() )
|
||||
{
|
||||
m_data->restartTimer( this, 0 );
|
||||
|
||||
if ( !isConcealed() )
|
||||
if( event->timerId() == m_data->concealTimer.timerId() )
|
||||
{
|
||||
setSkinStateFlag( Concealed, true );
|
||||
Q_EMIT concealedChanged( true );
|
||||
setExposed( false );
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Inherited::timerEvent( event );
|
||||
}
|
||||
|
||||
bool FocusIndicator::isConcealed() const
|
||||
bool FocusIndicator::isExposed() const
|
||||
{
|
||||
return hasSkinState( Concealed );
|
||||
return !hasSkinState( Concealed );
|
||||
}
|
||||
|
||||
#include "moc_FocusIndicator.cpp"
|
||||
|
@ -10,8 +10,11 @@ class FocusIndicator : public QskFocusIndicator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( bool concealed READ isConcealed
|
||||
WRITE setConcealed NOTIFY concealedChanged )
|
||||
Q_PROPERTY( bool exposed READ isExposed
|
||||
WRITE setExposed NOTIFY exposedChanged )
|
||||
|
||||
Q_PROPERTY( int exposedTimeout READ exposedTimeout
|
||||
WRITE setExposedTimeout NOTIFY exposedTimeoutChanged )
|
||||
|
||||
using Inherited = QskFocusIndicator;
|
||||
|
||||
@ -21,15 +24,21 @@ class FocusIndicator : public QskFocusIndicator
|
||||
FocusIndicator( QQuickItem* parent = nullptr );
|
||||
~FocusIndicator() override;
|
||||
|
||||
bool isExposed() const;
|
||||
bool isConcealed() const;
|
||||
|
||||
bool eventFilter( QObject*, QEvent* ) override;
|
||||
|
||||
void setExposedTimeout( int ms );
|
||||
int exposedTimeout() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setConcealed( bool );
|
||||
void setExposed( bool = true );
|
||||
void setConcealed( bool = true );
|
||||
|
||||
Q_SIGNALS:
|
||||
void concealedChanged( bool );
|
||||
void exposedChanged( bool );
|
||||
void exposedTimeoutChanged( int );
|
||||
|
||||
protected:
|
||||
void windowChangeEvent( QskWindowChangeEvent* ) override;
|
||||
@ -39,3 +48,13 @@ class FocusIndicator : public QskFocusIndicator
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
inline void FocusIndicator::setConcealed( bool on )
|
||||
{
|
||||
setExposed( !on );
|
||||
}
|
||||
|
||||
inline bool FocusIndicator::isConcealed() const
|
||||
{
|
||||
return !isExposed();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user