views:

2901

answers:

6

I want an app's main window to ignore mouse and keyboard events, passing them to applications underneath it in the window manager Z-order.

I see how to make child widgets ignore keyboard or mouse events, but how about the main window?

I'm trying to make a desktop widget that always sits just over the background and is totally invisible to keyboard and mouse events. (Pass through)

Qt::X11BypassWindowManagerHint gets me keyboard pass through (although sadly X11 specific, but fine for now), so how about mouse events?

Is there a OS-agnostic way to be transparent to keyboard events?

EDIT:

The key word here is transparency.

I don't want to EAT mouse and keyboard events, I want the window manager to know I don't want them at all. Those events should be directed to whatever application is under me in the zorder.

For example, I want to be able to click on desktop icons that are covered by my widget and interact with them as if the widget was not there.

A: 

I think that overriding is supposed to work:

bool YourMainWindow::event( QEvent *event )
{
   event ->accept();
   return true;
}

that's some of what the QWidget class documentation says about event() member function:

This function returns true if the event was recognized, otherwise it returns false. If the recognized event was accepted (see QEvent::accepted), any further processing such as event propagation to the parent widget stops.

Maleev
+1  A: 

Use Qt's event filters: they will allow your application to eat whichever events you specify (i.e. keyboard and mouse events) but still process other events such as paint events.

bool FilterObject::eventFilter(QObject* object, QEvent* event)
{
    QKeyEvent* pKeyEvent = qobject_cast<QKeyEvent*>(event);
    QMouseEvent* pMouseEvent = qobject_cast<QMouseEvent*>(event);

    if (pKeyEvent || pMouseEvent)
    {
        // eat all keyboard and mouse events
        return true;
    }

    return FilterObjectParent::eventFilter(object, event);
}
Krsna
+1  A: 

Maybe I'm missing something here, but have you tried subclassing the QMainWindow class and overriding the QWidget::event() method to always return false? If you need to handle some events, you could add that intelligence here as well.

This technique should allow you to inspect the events coming in to the application and ignore them if desired without having to eat them using an event filter.

If this doesn't work you could attempt to redirect the events to the desktop by calling QCoreApplication::notify() and passing the event to the desktop widget obtained by calling QApplication::desktop(). I have no idea if this would work, but it seemed like it might be worth giving a try.

Joe Corkery
+2  A: 

Maybe what you want is

widget->setAttribute(Qt::WA_TransparentForMouseEvents)

? That's what QRubberBand uses to let it's parent handle the mouse events. As for keyboard events, a QWidget doesn't get any keyboard events unless it has set itself a focusPolicy().

setFocusPolicy( Qt::NoFocus );

should therefore take care of the keyboard events.

Okay, this is doing exactly what I said I already know how to do. I don't want a widget that lets "it's parent handle the mouse events"... I want the entire APPLICATION to ignore them. I want something to tell the windowing environment (X, WinXP, etc) that a click on my app should just pass to another app sitting under it on the Z-order. That typing on the keyboard should do the same. These solutions are just passing events up from child widgets to the parent. I want events being sent from the parent widget back to the window manager, or most likely just never sent to the app at all.
darron
however, this response is useful to someone who might actually want to do what you're talking about. (pass stuff to a client). I did try it, on the off chance that the Qt framework actually recognizes you're trying to ignore events at the parent level and would try to send them back to the window manager (or set some sort of flag in the window manager to bypass)... but as expected it did not work. My app ate the events.
darron
Right, sorry. I've since also tried setMask(), which does what you want, but also clips visibility. I'm pretty sure there's no way to do what you want, without falling back to OS-specific hacks. Have you found the functionality you seek in any other application?
A: 

I am working on a similar issue where we have to embed a Java swing component into a QT widget.

One of the solutions is to have a transparent QT widget and display Java swing component beneath it and somehow have all the mouse-clicks and keyboard events pass to the Swing component.

Like dblack mentioned, if there is a way to let the Qtwidget not accept any events and pass them "as is" to the underlying object/component, that would be useful.

@dblack: Any success with it so far?

ashwin
Nope, not so far.
darron
A: 

have u ever used "WS_EX_TRANSPARENT" in MFC, i want some thing similar to this. what this(Qt::WA_TransparentForMouseEvents) does is make child transparent to mouse event and will send all child events to parent, but what if my window which i want to make mouse event transparent is top level window or say is my Main Window. this flag does not seem to work there.

when we use setWindowOpacity(0.0), all events go through it, but problem is even what ever i draw on it also becomes invisible(transparent window), but i want drawings on it to be visible and still mouse events should go through it.

Gajender