Use polling instead of mouse grab for scan popup. This should fix problems with Windows 7 and such.

This commit is contained in:
Konstantin Isakov 2010-07-03 20:24:30 +04:00
parent 1624afafc4
commit 621d842394
2 changed files with 75 additions and 41 deletions

View file

@ -136,6 +136,11 @@ ScanPopup::ScanPopup( QWidget * parent,
altModePollingTimer.setInterval( 50 ); altModePollingTimer.setInterval( 50 );
connect( &altModePollingTimer, SIGNAL( timeout() ), connect( &altModePollingTimer, SIGNAL( timeout() ),
this, SLOT( altModePoll() ) ); this, SLOT( altModePoll() ) );
mouseGrabPollTimer.setSingleShot( false );
mouseGrabPollTimer.setInterval( 10 );
connect( &mouseGrabPollTimer, SIGNAL( timeout() ),
this, SLOT(mouseGrabPoll()) );
} }
ScanPopup::~ScanPopup() ScanPopup::~ScanPopup()
@ -407,52 +412,55 @@ bool ScanPopup::eventFilter( QObject * watched, QEvent * event )
if ( event->type() == QEvent::MouseMove ) if ( event->type() == QEvent::MouseMove )
{ {
// printf( "Object: %s\n", watched->objectName().toUtf8().data() );
QMouseEvent * mouseEvent = ( QMouseEvent * ) event; QMouseEvent * mouseEvent = ( QMouseEvent * ) event;
reactOnMouseMove( mouseEvent->globalPos() );
// printf( "Object: %s\n", watched->objectName().toUtf8().data() );
if ( geometry().contains( mouseEvent->globalPos() ) )
{
// printf( "got inside\n" );
hideTimer.stop();
mouseEnteredOnce = true;
uninterceptMouse();
}
else
{
// printf( "outside\n" );
// We're in grab mode and outside the window - calculate the
// distance from it. We might want to hide it.
// When the mouse has entered once, we don't allow it stayng outside,
// but we give a grace period for it to return.
int proximity = mouseEnteredOnce ? 0 : 60;
// Note: watched == this ensures no other child objects popping out are
// receiving this event, meaning there's basically nothing under the
// cursor.
if ( watched == this &&
!frameGeometry().adjusted( -proximity, -proximity, proximity, proximity ).
contains( mouseEvent->globalPos() ) )
{
// We've way too far from the window -- hide the popup
// If the mouse never entered the popup, hide the window instantly --
// the user just moved the cursor further away from the window.
if ( !mouseEnteredOnce )
hideWindow();
else
hideTimer.start();
}
}
} }
} }
return QMainWindow::eventFilter( watched, event ); return QMainWindow::eventFilter( watched, event );
} }
void ScanPopup::reactOnMouseMove( QPoint const & p )
{
if ( geometry().contains( p ) )
{
// printf( "got inside\n" );
hideTimer.stop();
mouseEnteredOnce = true;
uninterceptMouse();
}
else
{
// printf( "outside\n" );
// We're in grab mode and outside the window - calculate the
// distance from it. We might want to hide it.
// When the mouse has entered once, we don't allow it stayng outside,
// but we give a grace period for it to return.
int proximity = mouseEnteredOnce ? 0 : 60;
// Note: watched == this ensures no other child objects popping out are
// receiving this event, meaning there's basically nothing under the
// cursor.
if ( /*watched == this &&*/
!frameGeometry().adjusted( -proximity, -proximity, proximity, proximity ).
contains( p ) )
{
// We've way too far from the window -- hide the popup
// If the mouse never entered the popup, hide the window instantly --
// the user just moved the cursor further away from the window.
if ( !mouseEnteredOnce )
hideWindow();
else
hideTimer.start();
}
}
}
void ScanPopup::mousePressEvent( QMouseEvent * ev ) void ScanPopup::mousePressEvent( QMouseEvent * ev )
{ {
// With mouse grabs, the press can occur anywhere on the screen, which // With mouse grabs, the press can occur anywhere on the screen, which
@ -687,19 +695,32 @@ void ScanPopup::interceptMouse()
{ {
if ( !mouseIntercepted ) if ( !mouseIntercepted )
{ {
grabMouse(); // We used to grab the mouse -- but this doesn't always work reliably
// (e.g. doesn't work at all in Windows 7 for some reason). Therefore
// we use a polling timer now.
// grabMouse();
mouseGrabPollTimer.start();
qApp->installEventFilter( this ); qApp->installEventFilter( this );
mouseIntercepted = true; mouseIntercepted = true;
} }
} }
void ScanPopup::mouseGrabPoll()
{
if ( mouseIntercepted )
reactOnMouseMove( QCursor::pos() );
}
void ScanPopup::uninterceptMouse() void ScanPopup::uninterceptMouse()
{ {
if ( mouseIntercepted ) if ( mouseIntercepted )
{ {
qApp->removeEventFilter( this ); qApp->removeEventFilter( this );
releaseMouse(); mouseGrabPollTimer.stop();
// releaseMouse();
mouseIntercepted = false; mouseIntercepted = false;
} }

View file

@ -95,6 +95,8 @@ private:
// this timer expires, the window gets hidden. // this timer expires, the window gets hidden.
QTimer altModeExpirationTimer, altModePollingTimer; // Timers for alt mode QTimer altModeExpirationTimer, altModePollingTimer; // Timers for alt mode
QTimer mouseGrabPollTimer;
void handleInputWord( QString const & ); void handleInputWord( QString const & );
void engagePopup( bool giveFocus = false ); void engagePopup( bool giveFocus = false );
void initiateTranslation(); void initiateTranslation();
@ -102,6 +104,11 @@ private:
vector< sptr< Dictionary::Class > > const & getActiveDicts(); vector< sptr< Dictionary::Class > > const & getActiveDicts();
virtual bool eventFilter( QObject * watched, QEvent * event ); virtual bool eventFilter( QObject * watched, QEvent * event );
/// Called from event filter or from mouseGrabPoll to handle mouse event
/// while it is being intercepted.
void reactOnMouseMove( QPoint const & p );
virtual void mousePressEvent( QMouseEvent * ); virtual void mousePressEvent( QMouseEvent * );
virtual void mouseMoveEvent( QMouseEvent * ); virtual void mouseMoveEvent( QMouseEvent * );
virtual void mouseReleaseEvent( QMouseEvent * ); virtual void mouseReleaseEvent( QMouseEvent * );
@ -127,6 +134,12 @@ private slots:
void altModeExpired(); void altModeExpired();
void altModePoll(); void altModePoll();
/// Called repeatedly once the popup is initially engaged and we monitor the
/// mouse as it may move away from the window. This simulates mouse grab, in
/// essense, but seems more reliable. Once the mouse enters the window, the
/// polling stops.
void mouseGrabPoll();
void pageLoaded( ArticleView * ); void pageLoaded( ArticleView * );
void escapePressed(); void escapePressed();