[kwin] Do not allow Qt to raise decoration widget above the Client

If the user actions menu is closed Qt looks for a QWidget at the mouse
position. If it finds one it tries to activate and raise it. If the
QWidget at the mouse position is a window decoration, it gets raised
above the Client. This makes the window unfortunately unusable.

To prevent this from happening we listen for the ZOrderChange event
in our event filter on the decoration widget and unconditionally lower
the decoration widget again - we never want the decoration widget to
be above our Client, so we can just always lower it. We have to use
the low level functionality and cannot use QWidget::lower as that would
result in a loop.
icc-effect-5.14.5
Martin Gräßlin 2013-10-27 09:52:45 +01:00
parent 96691036f6
commit 4bd28e90af
2 changed files with 16 additions and 2 deletions

View File

@ -1014,6 +1014,14 @@ bool Client::eventFilter(QObject* o, QEvent* e)
decoration->widget()->update();
return false;
}
if (e->type() == QEvent::ZOrderChange) {
// when the user actions menu is closed by clicking on the window decoration (which is not unlikely)
// Qt will raise the decoration window and thus the decoration window is above the actual Client
// see QWidgetWindow::handleMouseEvent (qtbase/src/widgets/kernel/qwidgetwindow.cpp)
// when this happens also a ZOrderChange event is sent, we intercept all of them and make sure that
// the window is lowest in stack again.
Xcb::lowerWindow(decorationId());
}
return false;
}

View File

@ -42,6 +42,7 @@ static void defineCursor(xcb_window_t window, xcb_cursor_t cursor);
static void setInputFocus(xcb_window_t window, uint8_t revertTo = XCB_INPUT_FOCUS_POINTER_ROOT, xcb_timestamp_t time = xTime());
static void moveWindow(xcb_window_t window, const QPoint &pos);
static void moveWindow(xcb_window_t window, uint32_t x, uint32_t y);
static void lowerWindow(xcb_window_t window);
static void selectInput(xcb_window_t window, uint32_t events);
template <typename Reply,
@ -649,8 +650,7 @@ void Window::raise()
inline
void Window::lower()
{
const uint32_t values[] = { XCB_STACK_MODE_BELOW };
xcb_configure_window(connection(), m_window, XCB_CONFIG_WINDOW_STACK_MODE, values);
lowerWindow(m_window);
}
inline
@ -796,6 +796,12 @@ static inline void moveWindow(xcb_window_t window, uint32_t x, uint32_t y)
xcb_configure_window(connection(), window, mask, values);
}
static inline void lowerWindow(xcb_window_t window)
{
const uint32_t values[] = { XCB_STACK_MODE_BELOW };
xcb_configure_window(connection(), window, XCB_CONFIG_WINDOW_STACK_MODE, values);
}
static inline WindowId createInputWindow(const QRect &geometry, uint32_t mask, const uint32_t *values)
{
WindowId window = xcb_generate_id(connection());