Add Qt::WindowTransparentForMouseEvents
authorLars Knoll <lars.knoll@nokia.com>
Tue, 20 Sep 2011 16:09:08 +0000 (18:09 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 21 Sep 2011 10:07:19 +0000 (12:07 +0200)
Add a flag for output only windows that are
transparent for mouse events and implement it
for the xcb backend.

Change-Id: I24afdb6b27de34bcdf0c061a5a4987ac2880e4ae
Reviewed-on: http://codereview.qt-project.org/5260
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/corelib/global/qnamespace.h
src/plugins/platforms/xcb/qxcbwindow.cpp
src/plugins/platforms/xcb/qxcbwindow.h

index 43e6176..807bed8 100644 (file)
@@ -258,6 +258,7 @@ public:
         WindowContextHelpButtonHint = 0x00010000,
         WindowShadeButtonHint = 0x00020000,
         WindowStaysOnTopHint = 0x00040000,
+        WindowTransparentForInput = 0x00080000,
 
         CustomizeWindowHint = 0x02000000,
         WindowStaysOnBottomHint = 0x04000000,
index 50be8ba..cde450e 100644 (file)
@@ -57,6 +57,7 @@
 #define class class_name
 #include <xcb/xcb_icccm.h>
 #undef class
+#include <xcb/xfixes.h>
 
 // xcb-icccm 3.8 support
 #ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
@@ -120,6 +121,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
     , m_window(0)
     , m_syncCounter(0)
     , m_mapped(false)
+    , m_transparent(false)
     , m_netWmUserTimeWindow(XCB_NONE)
 #if defined(XCB_USE_EGL)
     , m_eglSurface(0)
@@ -303,6 +305,9 @@ void QXcbWindow::create()
     setWindowTitle(window()->windowTitle());
     setWindowState(window()->windowState());
 
+    if (window()->windowFlags() & Qt::WindowTransparentForInput)
+        setTransparentForMouseEvents(true);
+
     connection()->drag()->dndEnable(this, true);
 }
 
@@ -665,9 +670,16 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
     if (type == Qt::Popup)
         flags |= Qt::X11BypassWindowManagerHint;
 
+    if (flags & Qt::WindowTransparentForInput) {
+        uint32_t mask = XCB_EVENT_MASK_NO_EVENT;
+        xcb_change_window_attributes(xcb_connection(), xcb_window(), XCB_CW_EVENT_MASK, &mask);
+    }
+
     setNetWmWindowFlags(flags);
     setMotifWindowFlags(flags);
 
+    setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput);
+
     return flags;
 }
 
@@ -974,6 +986,33 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
                         XCB_ATOM_CARDINAL, 32, 1, &timestamp);
 }
 
+void QXcbWindow::setTransparentForMouseEvents(bool transparent)
+{
+    if (transparent == m_transparent)
+        return;
+
+    xcb_rectangle_t rectangle;
+
+    xcb_rectangle_t *rect = 0;
+    int nrect = 0;
+
+    if (!transparent) {
+        rectangle.x = 0;
+        rectangle.y = 0;
+        rectangle.width = geometry().width();
+        rectangle.height = geometry().height();
+        rect = &rectangle;
+        nrect = 1;
+    }
+
+    xcb_xfixes_region_t region = xcb_generate_id(xcb_connection());
+    xcb_xfixes_create_region(xcb_connection(), region, nrect, rect);
+    xcb_xfixes_set_window_shape_region_checked(xcb_connection(), m_window, XCB_SHAPE_SK_INPUT, 0, 0, region);
+    xcb_xfixes_destroy_region(xcb_connection(), region);
+
+    m_transparent = transparent;
+}
+
 
 WId QXcbWindow::winId() const
 {
index a85760e..e864c14 100644 (file)
@@ -124,6 +124,8 @@ private:
     void updateMotifWmHintsBeforeMap();
     void updateNetWmStateBeforeMap();
 
+    void setTransparentForMouseEvents(bool transparent);
+
     void create();
     void destroy();
 
@@ -143,6 +145,7 @@ private:
     Qt::WindowState m_windowState;
 
     bool m_mapped;
+    bool m_transparent;
     xcb_window_t m_netWmUserTimeWindow;
 
     QSurfaceFormat m_requestedFormat;