PDA

View Full Version : Qt5 native messages not propogated?



ComServant
27th December 2012, 16:48
I use Qt 4.8 with SFML 2.0, but I just migrated to Qt 5.0. I'm programming on Windows 7, 32 bit, and I use MinGW (4.7.2) as my compiler.

The basic layout of my application is a QWidget as the "main window", with several QWidget side panels, and in the center, a QWidget mixed with SFML ("sfml window"), that SFML draws and handles events for.

In Qt 4.8, SFML keyboard events for that central SFML window worked just fine, but in Qt 5.0, the keyboard events aren't reaching SFML. The keyboard events are reaching the QWidget that SFML is attached to (I breakpointed on keyPressEvent() to test), but SFML's keyboard events stopped working in Qt 5. Not all events, mouse events work fine, but the keyboard events don't get forwarded to SFML by Qt.

I even tried to grabKeyboard() on the QWidget/SFML window to check. Didn't help.

class AreaWindow : public QWidget, public sf::RenderWindow
{
Q_OBJECT
public:
AreaWindow();
~AreaWindow();

//...other functions...
}




AreaWindow::AreaWindow()
: QWidget(nullptr), isInitialized(false)
{
//Setup some states to allow direct rendering into the widget
QWidget::setAttribute(Qt::WA_PaintOnScreen);
QWidget::setAttribute(Qt::WA_OpaquePaintEvent);
QWidget::setAttribute(Qt::WA_NoSystemBackground);
QWidget::setAttribute(Qt::WA_PaintUnclipped);

//Set strong focus to enable keyboard events to be received
QWidget::setFocusPolicy(Qt::StrongFocus);
}

void AreaWindow::showEvent(QShowEvent*)
{
if(!this->isInitialized)
{
//Under X11, we need to flush the commands sent to the server to ensure that
//SFML will get an updated view of the windows
#ifdef Q_WS_X11
XFlush(QX11Info::display());
#endif

//Create the SFML window with the widget handle
sf::RenderWindow::create((HWND)this->winId());

this->isInitialized = true;
}
}

QPaintEngine *AreaWindow::paintEngine() const
{
//We make the paintEvent function return a null paint engine. This functions works together with
//the WA_PaintOnScreen flag to tell Qt that we're not using any of its built-in paint engines.
return nullptr;
}

void AreaWindow::paintEvent(QPaintEvent *event)
{
//Clear the window (using SFML).
sf::RenderWindow::clear(Global::Window::ClearColor .ToSfmlColor());

//Start the camera off on World mode.
this->SetCameraMode(CameraMode::World);

//...draw code goes here...

//Display on screen (using SFML).
sf::RenderWindow::display();
}


To be clear, this worked in Qt 4.8 - some change between Qt 4.8 and Qt 5.0 stopped native Win32 keyboard events from being forwarded to SFML. Any ideas?

[Edit:] SFML also isn't receiving the focus/unfocus events (sf::Event::GainedFocus and sf::Event::LostFocus), even though the QWidget is (QWidget::focusInEvent(), QWidget::focusOutEvent()).
This is not an SFML-related problem, the QWidget is stopping the Win32 events (it seems to me).

wysota
28th December 2012, 22:10
Qt doesn't "forward" any events to third party libraries. If you want that, you have to explicitly do it by overriding proper event handlers or installing event filters and doing whatever needs to be done for the events to reach wanted destination.

If you don't override a specific event handler, that event gets ignored and propagates (in case of input events) to the parent. That's the default event handling in Qt both in Qt4 and Qt5.

ComServant
29th December 2012, 03:39
I'm not suggesting Qt intentionally interacts with third party APIs. All I'm saying is that Win32 messages that previously reached a third party library in Qt 4.8 (and in Qt 4.7, and I think 4.6 also), now are not reaching it in Qt 5, even though it's still reaching the QWidget. I'm not asking for Qt to forward anything. I'm asking why it's blocking what it previously wasn't.

I don't understand how the QWidgets are implemented in Win32, but I'm wondering if a perhaps in the promotion of QWidgets to their own module, as well as any possible QPA code changes, Qt 5 might be accidentally blocking certain Win32 messages. Again, not knowing how it works under the hood, I wonder if perhaps it's failing to call DefWndProc() on a few messages that used to call it on. If so, why the change? If the change is accidental, what other side-effects might this cause in compatibility?

Why does it forward some Win32 messages but not others? Why not forward them all? Why not block them all? A change was made that affects the Win32 events that reach the window. The question is, why? What purpose does it serve, and was it accidental?

wysota
29th December 2012, 08:54
I'm not suggesting Qt intentionally interacts with third party APIs. All I'm saying is that Win32 messages that previously reached a third party library in Qt 4.8 (and in Qt 4.7, and I think 4.6 also), now are not reaching it in Qt 5, even though it's still reaching the QWidget. I'm not asking for Qt to forward anything. I'm asking why it's blocking what it previously wasn't.
How were they "reaching" the library?


Why does it forward some Win32 messages but not others? Why not forward them all? Why not block them all? A change was made that affects the Win32 events that reach the window. The question is, why? What purpose does it serve, and was it accidental?
If you want to handle windows events then install a native event filter on the application object.

ComServant
29th December 2012, 15:59
I'm not sure. I'll just looked at the source of SFML, and this is what it looks like:

Qt creates the window
Qt gives me the HWND (http://www.qtcentre.org/threads/52445-Converting-from-Qt-s-WId-to-Windows-HWND?p=234769#post234769)
I give SFML the HWND
SFML attaches it's own WndProc callback function to it, but saves the previous (Qt's) WndProc.
SFML receives the messages, processes them, then forwards them to the previous (Qt's) WndProc.


So it looks like SFML gets to process the Win32 events before Qt. I don't know why SFML is not processing the key presses (but is receiving mouse messages) then, but why it was previously with Qt 4.8.

It looks like I was investigating the wrong API - thanks for the help.

neosettler
7th February 2014, 20:06
Greetings,

I've been on this case for awhile now and I still couldn't figure why SFML does not process mouse wheel and keyboard inputs anymore.

Could you tell us how you fixed it?

Note: It is clearly a QT modification from 4.8 to 5.x that brought this issue.

Thank you!

ComServant
10th February 2014, 04:28
It's definitely a Qt issue, and I haven't gotten it working. I'm using Qt 5.0.1 - maybe someone has fixed it in a more recent update, but I can't check anytime soon.

I receive events for: Mouse movement and mouse button presses (include the middle button, which is the scroll wheel), but I don't receive events for mouse wheel movement or keypresses, even though the QWidget is clearly getting them.

I wonder if Qt treats mouse wheel in the same way as keypresses, and whether it is failing to call the Win32 DefWindowProc on them, or something.

wysota
10th February 2014, 21:43
Please provide a minimal compilable example demonstrating the problem.