Fix broken handling of inactive transient surfaces
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Mon, 18 Jun 2012 13:57:31 +0000 (16:57 +0300)
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>
Mon, 18 Jun 2012 19:52:07 +0000 (21:52 +0200)
Makes tooltips and tooltip-like components like Create's locator show
up properly. These should never get keyboard focus even though they
are regular surfaces like any other.

Change-Id: I0ade61845d9785cad19040683362a5532a04e6f6
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/compositor/compositor_api/waylandinput.cpp
src/compositor/compositor_api/waylandinput.h
src/compositor/compositor_api/waylandsurface.cpp
src/compositor/compositor_api/waylandsurface.h
src/compositor/wayland_wrapper/wlinputdevice.cpp
src/compositor/wayland_wrapper/wlinputdevice.h
src/compositor/wayland_wrapper/wlshellsurface.cpp
src/compositor/wayland_wrapper/wlsurface.cpp
src/compositor/wayland_wrapper/wlsurface.h
src/plugins/platforms/wayland/qwaylandshellsurface.cpp

index 2a5cb6b..290bfed 100644 (file)
@@ -127,10 +127,10 @@ WaylandSurface *WaylandInputDevice::keyboardFocus() const
     return 0;
 }
 
-void WaylandInputDevice::setKeyboardFocus(WaylandSurface *surface)
+bool WaylandInputDevice::setKeyboardFocus(WaylandSurface *surface)
 {
     Wayland::Surface *wlsurface = surface?surface->handle():0;
-    d->setKeyboardFocus(wlsurface);
+    return d->setKeyboardFocus(wlsurface);
 }
 
 WaylandSurface *WaylandInputDevice::mouseFocus() const
index be38511..90985ed 100644 (file)
@@ -79,7 +79,7 @@ public:
     void sendFullTouchEvent(QTouchEvent *event);
 
     WaylandSurface *keyboardFocus() const;
-    void setKeyboardFocus(WaylandSurface *surface);
+    bool setKeyboardFocus(WaylandSurface *surface);
 
     WaylandSurface *mouseFocus() const;
     void setMouseFocus(WaylandSurface *surface, const QPointF &local_pos, const QPointF &global_pos = QPointF());
index 08b9291..69eb9d6 100644 (file)
@@ -336,3 +336,12 @@ QString WaylandSurface::title() const
     Q_D(const WaylandSurface);
     return d->surface->title();
 }
+
+/*!
+ * \return True if WL_SHELL_SURFACE_TRANSIENT_INACTIVE was set for this surface, meaning it should not receive keyboard focus.
+ */
+bool WaylandSurface::transientInactive() const
+{
+    Q_D(const WaylandSurface);
+    return d->surface->transientInactive();
+}
index c271e2e..76e0840 100644 (file)
@@ -151,6 +151,8 @@ public:
 
     QString title() const;
 
+    bool transientInactive() const;
+
 signals:
     void mapped();
     void unmapped();
index 29bfb57..0625fa6 100644 (file)
@@ -385,10 +385,17 @@ Surface *InputDevice::keyboardFocus() const
     return wayland_cast<Surface>(keyboardDevice()->focus);
 }
 
-void InputDevice::setKeyboardFocus(Surface *surface)
+/*!
+ * \return True if the keyboard focus is changed successfully. False for inactive transient surfaces.
+ */
+bool InputDevice::setKeyboardFocus(Surface *surface)
 {
+    if (surface && surface->transientInactive())
+        return false;
+
     sendSelectionFocus(surface);
     wl_keyboard_set_focus(keyboardDevice(), surface ? surface->base() : 0);
+    return true;
 }
 
 Surface *InputDevice::mouseFocus() const
index 9bfb423..58f4502 100644 (file)
@@ -82,7 +82,7 @@ public:
     void sendFullTouchEvent(QTouchEvent *event);
 
     Surface *keyboardFocus() const;
-    void setKeyboardFocus(Surface *surface);
+    bool setKeyboardFocus(Surface *surface);
 
     Surface *mouseFocus() const;
     void setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos);
index 12adf82..a0d3e93 100644 (file)
@@ -223,7 +223,8 @@ void ShellSurface::set_transient(struct wl_client *client,
     shell_surface->m_transientParent = parent_shell_surface;
     shell_surface->m_xOffset = x;
     shell_surface->m_yOffset = y;
-
+    if (flags & WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
+        shell_surface->surface()->setTransientInactive(true);
 }
 
 void ShellSurface::set_fullscreen(struct wl_client *client,
index 70ebe07..87f7eae 100644 (file)
@@ -85,6 +85,7 @@ Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor)
     , m_extendedSurface(0)
     , m_subSurface(0)
     , m_shellSurface(0)
+    , m_transientInactive(false)
 {
     wl_list_init(&m_frame_callback_list);
     addClientResource(client, &base()->resource, id, &wl_surface_interface,
index 0716172..9ab5cb0 100644 (file)
@@ -126,6 +126,9 @@ public:
     QString title() const { return m_title; }
     void setTitle(const QString &title);
 
+    bool transientInactive() const { return m_transientInactive; }
+    void setTransientInactive(bool v) { m_transientInactive = v; }
+
 private:
     Q_DISABLE_COPY(Surface)
 
@@ -155,6 +158,7 @@ private:
     QPointF m_position;
     QSize m_size;
     QString m_title;
+    bool m_transientInactive;
 
     inline SurfaceBuffer *currentSurfaceBuffer() const;
     bool advanceBufferQueue();
index 3a85a19..05e415b 100644 (file)
@@ -88,11 +88,18 @@ void QWaylandShellSurface::updateTransientParent(QWindow *parent)
         transientPos.setX(transientPos.x() + parent_wayland_window->decoration()->margins().left());
         transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
     }
+
+    uint32_t flags = 0;
+    Qt::WindowFlags wf = m_window->window()->windowFlags();
+    if (wf.testFlag(Qt::ToolTip)
+            || wf.testFlag(Qt::WindowTransparentForInput))
+        flags |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
+
     wl_shell_surface_set_transient(m_shell_surface,
                                    parent_wayland_window->shellSurface()->m_shell_surface,
                                    transientPos.x(),
                                    transientPos.y(),
-                                   0);
+                                   flags);
 }
 
 void QWaylandShellSurface::setTitle(const char *title)