[Qt-interest] Off-screen render with QGraphicsView; focus issues?

Girish Ramakrishnan girish at forwardbias.in
Mon Dec 14 18:30:35 CET 2009


Hi Penn,

Penn Taylor wrote:
> Summary: Hidden instances of QGraphicsView cannot be treated as focused
> and active in Qt 4.6 but (apparently) could be in Qt 4.5.3. How can this
> behavior be mimicked in Qt 4.6?
> 
> Detailed explanation:
> I'm using a hidden QGraphicsView that contains a QGraphicsProxyWidget to
> render to texture and use this directly in an OpenGL app. This is done
> with a hidden QGraphicsView because user interaction takes place through
> a GL context (and window) owned and managed by another library.
> 
> I can get keyboard focus and tab events to propagate correctly, but some
> aspects aren't quite right. For example, clicking on a slider in my app
> allows the slider to be moved, but does not place the little "selected"
> border around the widget as it should. Ditto for tab traversal. This
> makes keyboard navigation difficult, because you can never tell which
> widget is selected.
> 
> I noticed that scene->hasFocus() and view->hasFocus() always return
> false, even if I explicitly call setFocus() just before hasFocus().  It
> appears calls to setFocus() and activateWindow() do nothing as long as
> the window is hidden. I suspect this to be the root of my problem.
> So...how can I make the QGraphicsView, scene, etc. act as though they
> are visible, active, and focused even when technically they are not?
> 

Indeed, I have been facing the exact same problems as yours (very
similar use case too). 4.6 QGV seems to have changed lots of it's
existing behavior.

After lots of QGV code grokking, here's how I solved my problems:

0. Things work differently when you have a (hidden) QGraphicsView and
when you have _no_ view (i.e just a scene). When you are using a hidden
QGraphicsView, the code seems to rely on the screen pos to locate items
under the cursor.

1. Send QEvent::WindowActivate and QEvent::ActivationChange to the scene
to make it believe that the view is now activated.

2. Call QGraphicsItem::setActive(true) for your proxy widget to make the
scene understand the item is now active.

3. Call QGraphicsScene::setFocusItem() to make the scene understand that
the item now gets keyboard focus.

4. The focus code seems to rely on events being spontaneous. This was
the toughest part to fix because QCoreApplication::sendSpontaneousEvent
is internal. But I found a super hack :-) qt_sendSpontaneousEvent is a
non-exported function which is a friend of QCoreApplication. This means
that you can add your own qt_sendSpontaneousEvent and call
QCoreApplication::sendSpontaneousEvent. I could not figure a way to make
mouse handling work correctly without this hack.

There is some hard to understand but working code at
http://git.forwardbias.in/?p=hacks/qtwebkitgl.git;a=summary (gvcapture
branch). It captures the contents of a QGraphicsWebView. On a page that
requries http auth, a dialog is displayed which is where I faced the
issues above.

Girish



More information about the Qt-interest-old mailing list