Irrlicht event for mouse wheel - c++

I want to get the status for the mouse wheel or get triggered, when the user uses the mouse wheel.
I already have an event receiver like in the example(which is extending from IEventReceiver) but I cannot see / find a way for the mouse wheel.
Is there another receiver / event handler / solution?

class MyEventReceiver : public IEventReceiver {
public:
virtual bool OnEvent(const SEvent& event) {
if(event.EventType == irr::EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_MOUSE_WHEEL)
printf("%f\n", event.MouseInput.Wheel);
return false;
}
...

Check the Wheel public attribute of the SMouseInput event type
http://irrlicht.sourceforge.net/docu/structirr_1_1_s_event_1_1_s_mouse_input.html

Related

Mouse right click option using eventFilter in Qt

I have QGraphicsView, which has many QGraphicsItem. I am trying to create a right click menu on these QGraphicsItem. Right click menu has multiple options. But only 1st option works. It means, if I click on 2nd option, it does not work. If I change the sequence ( means 1st one will go to 2nd position, and 2nd one will come to 1st position ) then still 2nd one will not work.
bool myClass::eventFilter(QObject *watched, QEvent *event)
{
switch(event->type())
{
case QEvent::ContextMenu:
{
foreach(QGraphicsItem* pItem, _scene->items())
{
if(pItem->isUnderMouse())
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (event);
menu = new QMenu(this);
myMenu = menu->addMenu("Copy");
myMenu ->addAction(Name);
myMenu ->addAction(Address);
if(Name == menu->exec(mouseEvent->globalPos()))
{
// logic
}
if(Address == menu->exec(mouseEvent->globalPos()))
{
// logic
}
}
}
}
}
Always works only 1st mouse right click option. Why is so ?
The usual way to do something like this is to override the QGraphicsItem::mouseReleaseEvent() or QGraphicsItem::mousePressEvent() function of your item class.
This way, you won't have to do anything (no looping, etc...), it is already handled by the event loop.
Here you can find a simple example:
void MyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
if(event->button() == Qt::RightButton)
{
QMenu my_menu;
// Build your QMenu the way you want
my_menu.addAction(my_first_action);
my_menu.addAction(my_second_action);
//...
my_menu.exec(event->globalPos());
}
}
From the Qt documentation:
Note that all signals are emitted as usual. If you connect a QAction to a slot and call the menu's exec(), you get the result both via the signal-slot connection and in the return value of exec().
You just need to QObject::connect() the QActions you added to the context menu to the proper slots (here goes the "logic") and the job is done.
If you prefer to check the returned value by yourself, you just have to get the returned QAction* once and for all (only one call to QMenu::exec()) and branch on it.
For example:
void MyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
if(event->button() == Qt::RightButton)
{
QMenu my_menu;
// Build your QMenu the way you want
my_menu.addAction(my_first_action);
my_menu.addAction(my_second_action);
//...
QAction * triggered = my_menu.exec(event->globalPos());
if(triggered == my_first_action)
{
// Do something
}
else if(triggered == my_second_action)
{
// Do some other thing
}
//...
}
}
I would personnally prefer to stick with the signal-slot connections instead that manually handling the returned value, especially since each QAction is most likely to be already connected to its corresponding slot.

Processing mouse wheel events in Qt4.8

In Qt5 it can be done in QML like this.
MouseArea {
onWheel: {
if (wheel.modifiers & Qt.ControlModifier) {
adjustZoom(wheel.angleDelta.y / 120);
}
}
}
How to achieve the same in Qt4.8?
Looks like I'm reinventing the bicycle but here is how it works for now.
I have a new QWidget that catches the wheelEvent and sends a new signal.
void WheelEventCarrier::wheelEvent(QWheelEvent *event)
{
emit sendWheelEvent(event->delta()/120);
}
I define a new signal in QML and process it ibid.
signal wheelEvent(int delta)
onWheelEvent:
{
if(delta > 0)
tag_meas_mod.zoomIn(true);
else
tag_meas_mod.zoomOut(true);
}
I wrap my widget around all my UI and connect the two signals.
WheelEventCarrier carrier;
UI.setParent(&carrier);
QObject::connect(&carrier,
SIGNAL(sendWheelEvent(int)),
viewer.rootObject(),
SIGNAL(wheelEvent(int)));
carrier.show();
Hope you can point me to a better solution.

Qt disable touch screen detection

Is there a way to configure a Qt application to not detect the touch screen to keep the behavior of a normal screen?
It depends. If your operating system differentiates between touch events and mouse presses, you could create a touchEvent filter to ignore the events like so:
#include <QObject>
#include <QTouchEvent> // to get rid of "error: invalid use of incomplete type 'class QEvent'"
class QTouchEventFilter: public QObject
{
Q_OBJECT
public:
QTouchEventFilter(QObject *parent = 0) : QObject(parent)
{
}
protected:
bool eventFilter(QObject * p_obj, QEvent * p_event)
{
if (p_event->type() == QEvent::TouchBegin ||
p_event->type() == QEvent::TouchUpdate ||
p_event->type() == QEvent::TouchEnd ||
p_event->type() == QEvent::TouchCancel)
{
p_event->ignore();
return true;
}
return false;
}
};
Then install it on the widget you want to ignore the touch events:
myWidget->installEventFilter(new QTouchEventFilter);
However, my instinct is that on most OS's the 'touches' you're talking about are going to come in as mouse press events, and you won't be able to filter them out unless you are willing to give up all mouse input for that widget. If you are willing, use the same concept but replace the QEvent's with the once associated with the mouse.

How to get the released button inside MouseReleaseEvent in Qt

In MouseReleaseEvent(QMouseEvent *e), is there a way to know which button was released without using a new variable ? I mean something like in the MousePressEvent(QMouseEvent *e) with e.buttons().
I tried e.buttons() in the releaseEvent it's not working (which is logical).
e is already a variable. Just use:
void mouseReleaseEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton) // Left button...
{
// Do something related to the left button
}
else if (e->button() == Qt::RightButton) // Right button...
{
// Do something related to the right button
}
else if (e->button() == Qt::MidButton) // Middle button...
{
// Do something related to the middle button
}
}
A switch statement also works. I prefer the series of if -- else if because they make it easier to handle evente modifiers, i.e., e->modifiers() in order to check for alt or control clicks. The series of if's is short enough not to create any burden on the program.
EDIT: Note that you should use the button() function, not its plural buttons() version. See the explanation in #Merlin069 answer.
The problem in the posted code is this: -
if(e->buttons() & Qt::LeftButton)
As the Qt documentation states for the release event: -
... For mouse release events this excludes the button that caused the event.
The buttons() function will return the current state of the buttons, so since this is a release event, the code will return false, as it's no longer pressed.
However, the documentation for the button() function states:-
Returns the button that caused the event.
So you can use the button() function here.

X11: how to implement a global hotkey without focusloss

I have a Qt app which grabs a key with XGrabKey. I want my app to show and hide, if I press the hotkey. Additionally it has to hide if it loses focus. This works well with one drawback: The XGrabKeyboard which is used by XGrabKey, generates a FocusIn ans FocusOut event. This implies that, if I press the hotkey when the app is visible, the app receives the FocusOut event, hides and immendiately after that receives the hotkeyevent and shows again.
Can I somehow avoid the X server to generate these focus events?
Diggin deeper for about a few hours I tinkered a solution that feels nice. It uses Qt QWidget::nativeEvent and libxcb. libxcb seems to be the next gen libX11 wrapper. But it is horribly undocumented. Uncool that Qt does not provide the mode of a QFocusEvent. But I guess thats the bane in everything wanting to be platform agnostic.
Note: This is Qt5, Qt4 had stuff like QWidget::x11info()
.h
class Class : public QWidget
{
Q_OBJECT
public:
Class(QWidget *parent = 0);
~Class();
protected:
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *) override;
};
.cpp
/**************************************************************************//**
* #brief Class::nativeEvent
* This special event handler can be reimplemented in a subclass to receive
* native platform events identified by eventType which are passed in the
* message parameter. In your reimplementation of this function, if you want to
* stop the event being handled by Qt, return true and set result. If you
* return false, this native event is passed back to Qt, which translates the
* event into a Qt event and sends it to the widget.
*
* This method is called for every native event. On X11, eventType is set to
* "xcb_generic_event_t", and the message can be casted to a
* xcb_generic_event_t pointer.
*
* #param eventType
* #param message
* #return Indicator if this event shall be stoped being handled further.
*/
bool Class::nativeEvent(const QByteArray &eventType, void *message, long *)
{
if (eventType == "xcb_generic_event_t")
{
xcb_generic_event_t* event = static_cast<xcb_generic_event_t *>(message);
switch (event->response_type & ~0x80)
{
case XCB_FOCUS_IN: {
xcb_focus_in_event_t *fe = (xcb_focus_in_event_t *)event;
if (fe->mode & (XCB_NOTIFY_MODE_GRAB|XCB_NOTIFY_MODE_UNGRAB)){
return true; // Ignore this events
}
break;
}
case XCB_FOCUS_OUT: {
xcb_focus_out_event_t *fe = (xcb_focus_out_event_t *)event;
if (fe->mode & (XCB_NOTIFY_MODE_GRAB|XCB_NOTIFY_MODE_UNGRAB)){
return true; // Ignore this events
}
break;
}
}
}
return false;
}
I don't think so, but you can check the "mode" field in the XFocusChangeEvent. It can be NotifyNormal, NotifyWhileGrabbed, NotifyGrab, or NotifyUngrab. Grabbing keys should generate events with the last two modes, and so you may choose to ignore events with these modes, though I'm not sure how you would do that with Qt.