Qt or any other lang. Event Loop - c++

I'm a c++ programmer on Qt platform.
I'm wondering, how does the event loop "knows" to which widget to send an event, mainly mouse/keyboard events?
Is it done based on mouse coordinates and z-order?
What about events from keyboard?
Thanks

The event loop doesn't know. This is done in other bits of code.
The term you're looking for with the keyboard is "focus". Exactly one window has focus, systemwide (or at least one window per keyboard on multi-user systems). The OS delivers the keystrokes to that window. Qt just finds the Qt object from the native window handle. Similarly, mouse clicks are mostly handled by the OS.

It doesn't know.
When you want to capture an event, you must create an event filter that either captures the event, or allows it to be passed down.
Here's a very simple event filter that I created some time ago:
bool OGL_widget::eventFilter(QObject *obj, QEvent *event) {
switch (event->type()) {
case QEvent::KeyRelease:
case QEvent::KeyPress: {
QKeyEvent *key = static_cast<QKeyEvent*> (event);
if (!key->isAutoRepeat())
key_event_queue << *key;
}
break;
case 1001:
case 1002: {
Savestate_event *save = static_cast<Savestate_event*> (event);
save_event_queue << *save;
}
break;
}
return QObject::eventFilter(obj, event);
}
Take a look at this well written article of events at Qt docs.

Related

Emulate a global keypress in Qt

I am building a Qt Application for a raspberry pi, which is connected to a rotary encoder. When the user presses the rotary encoder button, the application registers the hardware interrupt from the button and emits a signal which the application can intercept.
The challenge is that the application has multiple windows that can be displayed, and I would like to simply have a function which translates the button press signal into a global key press that can be registered by any active window in the application, without having to add extra logic to determine which window is active to send the key press directly to it. Is there a way to simulate a system-wide key press so that whatever window is in focus will get it?
So far, I have the following snippet of code, though it requires a reference to a specific QObject to direct the keypress to:
QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter);
QCoreApplication::postEvent (receiver, event);
where receiver is the object to direct the keypress too. Any ideas?
To broadcast a key event to all top-level widgets (i.e. windows):
for(auto w : qApp->allWidgets())
{
if(w->isTopLevel())
{
qApp->postEvent(w, new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier));
}
}
To directly send the event to the active window (the foremost one):
qApp->postEvent(qApp->activeWindow(), new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier));

QT/c++ How to check globaly is mouse press or release?

void MainWindow::mousePressEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
timer->start(timer_time);
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
timer->stop();
}
}
This code works when i use it inside my appliacation, but if I want use it outside it won't be working. How can I do this?
It should start timer when LeftButton is pressed and stop when LeftButton release.
SOLUTION: understanding-the-low-level-mouse-and-keyboard-hook-win32
It sounds like hooks are what you're looking for.
Basically, hooks let you interact with the activity within your system, and can be used alter its behavior.
The event listeners in your code will only catch the mouse events that your OS delegates to your QT application. This is why your code only works when you use it inside your application. Using hooks, you can intercept mouse events at a system level and have them handled them in your app instead of letting the OS decide where they should be handled.
Here's what to use to set them up, and here's a little guide on the implementation details.

Output Keyboard/Mouse Presses?

In my program, I want to replicate the user pressing a key on the keyboard and mouse clicks.
Think about it like an auto-typer where the program types something in a word document over and over at various delays.
Any ideas on how to do this?
Thanks for your time.
I would suggest QTest namespace key and mouse simulation functions, e.g.
QTest::keyClick()
QTest::mouseClick()
You'll find documentation here
For simulating key presses you can use the QKeyEvent class which describes a key event and post that using QCoreApplication::postEvent.
QKeyEvent *event = new QKeyEvent ( QEvent::KeyPress, Qt::Key_Enter);
qApp->postEvent (receiver, event)
You can set the global position of the mouse by
QCursor::setPos(100,100);
Simulating the mouse events are like:
QMouseEvent * event = new QMouseEvent ((QEvent::MouseButtonPress), QPoint(500,500),
Qt::LeftButton,
Qt::LeftButton,
Qt::NoModifier );
qApp->postEvent((QObject*)this,(QEvent *)event);
Look at my answer in the next topic. Answer has a link to OS depended implementation of Keyboard / Mouse event generation. It can be helpful for you.

Error when trying to build a Global Keyboard Hook in Ubuntu Linux

I'm developing a code to get keyboard input in KeyPress and KeyRelease events, but when i run the program nothing happens, what is wrong with my code? And how to get the pressed key value?
void hook()
{
forever
{
XEvent event;
Display *dpy = XOpenDisplay(NULL);
XNextEvent(dpy, &event);
switch (event.type)
{
case KeyPress:
qDebug() << "keypress";
break;
case KeyRelease:
qDebug() << "keyrelease";
break;
}
}
}
Read more about keyboard X11 events. You will get them only from some X11 windows, if that window has set some of KeyPressMask or KeyReleaseMask bits in its event mask. And that window should be created InputOnly or InputOutput
You are apparently using Qt (which is a good idea). Then, stick to Qt key events.
(if you want to catch all X11 key events, use the root window of the display. But then you are interfering with your window manager, which is a bad idea; learn more about ICCCM and EWMH)
Also, run xev -in a terminal- to understand more about X11 events

Qt Application: Simulating modal behaviour (enable/disable user input)

I am currently working on an application that launches separate processes which display additional dialogs. The feature I am trying to implement is simulating modal behavior of these dialogs. More specifically, I need the application to stop processing all input, both mouse and keyboard, when the dialog is launched, and resume when it's closed.
It is not so important for the dialog to remain on top of the application, although if you can suggest how to do that without resorting to Always-On-Top behavior, that would be nice as well.
To note, the application is compiled under both Windows and Linux. Also, it is not an option to launch the dialogs directly. They are in separate executables. Also the application is a pretty complex piece of software, so disabling widgets individually is not an option, or at least a not very viable one.
I found lock() and unlock() functions in QApplication class in Qt 3.3. We are currently using Qt 4.5, which doesn't seem to have that API. As a matter of fact, Qt 4.5 QApplication class doesn't seem to provide access to the Event Loop either.
To summarize: How do I disable/enable user input in a Qt Application, both mouse and keyboard shortcuts?
gj already proposed this solution but I thought I'd paste my implementation just for reference:
Implement a filter class that will absorb user input actions.
class BusyAppFilter : public QObject
{
protected:
bool eventFilter( QObject *obj, QEvent *event );
};
bool BusyAppFilter::eventFilter(QObject *obj, QEvent *event)
{
switch ( event->type() )
{
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::HoverMove:
case QEvent::DragEnter:
case QEvent::DragLeave:
case QEvent::DragMove:
case QEvent::Drop:
return true;
default:
return QObject::eventFilter( obj, event );
}
}
Then place this code your QApplication class:
QCursor busyCursor( Qt::WaitCursor );
setOverrideCursor( busyCursor );
BusyAppFilter filter;
installEventFilter( &filter ) ;
//... do the process stuff ...
removeEventFilter( &filter );
restoreOverrideCursor();
To get full access to the application wide events, use QObject::installEventFilter() or QCoreApplication::setEventFilter() on your application object.
If your filter function returns true, Qt stops further processing of the event.
To not get too platform specific with the forwarding of the events to your other applications, i'd go for a suitable IPC mechanism.
As an alternative answer, you can create your own event loop and start running it if necessary. You would need to create a QEventLoop object, connect a signal from another process to its quit() slot (such as from a QProcess that you are running your other program in), then exec() the loop. If I read things correctly, nothing will be handled by your main event loop while that loop is running.