diff options
author | Giulio Camuffo <giuliocamuffo@gmail.com> | 2013-03-22 18:48:53 +0100 |
---|---|---|
committer | Andy Nichols <andy.nichols@digia.com> | 2013-04-03 11:39:06 +0200 |
commit | 7a9fe97eea5f643da27344b24ecd00927c5eda80 (patch) | |
tree | e25635e52a5b5acf9b3e7edc8e79c673c6109faf /src | |
parent | 77248e2765e4db5cd7fe6e53e07a612d75b91011 (diff) | |
download | qtwayland-7a9fe97eea5f643da27344b24ecd00927c5eda80.tar.gz |
Fix the popups handling.
Use wl_shell_surface_set_popup() instead of wl_shell_surface_set_transient(),
since the latter is not supposed to make the surface follow the transient
parent movements.
Needs Weston master or 1.0.6, otherwise freezes will happen.
To have the best experience you should however use recent weston master.
The popups in QtCompositor are badly placed.
Change-Id: I3c86e5d74503514749840681b4e81c58cd73ca70
Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Diffstat (limited to 'src')
4 files changed, 63 insertions, 5 deletions
diff --git a/src/plugins/platforms/wayland_common/qwaylandshellsurface.cpp b/src/plugins/platforms/wayland_common/qwaylandshellsurface.cpp index 81392204..890552c2 100644 --- a/src/plugins/platforms/wayland_common/qwaylandshellsurface.cpp +++ b/src/plugins/platforms/wayland_common/qwaylandshellsurface.cpp @@ -141,6 +141,25 @@ void QWaylandShellSurface::updateTransientParent(QWindow *parent) flags); } +void QWaylandShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial) +{ + QWaylandWindow *parent_wayland_window = parent->topLevelWindow(); + if (!parent_wayland_window || !parent_wayland_window->shellSurface()) + return; + + // set_popup expects a position relative to the parent + QPoint transientPos = m_window->geometry().topLeft(); // this is absolute + transientPos -= parent_wayland_window->geometry().topLeft(); + if (parent_wayland_window->decoration()) { + transientPos.setX(transientPos.x() + parent_wayland_window->decoration()->margins().left()); + transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top()); + } + + wl_shell_surface_set_popup(m_shell_surface, device->wl_seat(), serial, + parent_wayland_window->wl_surface(), + transientPos.x(), transientPos.y(), 0); +} + void QWaylandShellSurface::setClassName(const char *_class) { wl_shell_surface_set_class(m_shell_surface, _class); @@ -175,6 +194,9 @@ void QWaylandShellSurface::popup_done(void *data, { Q_UNUSED(data); Q_UNUSED(wl_shell_surface); + + QWaylandShellSurface *shell_surface = static_cast<QWaylandShellSurface *>(data); + QCoreApplication::postEvent(shell_surface->m_window->window(), new QCloseEvent()); } const wl_shell_surface_listener QWaylandShellSurface::m_shell_surface_listener = { diff --git a/src/plugins/platforms/wayland_common/qwaylandshellsurface.h b/src/plugins/platforms/wayland_common/qwaylandshellsurface.h index e54a46bf..e9061f0b 100644 --- a/src/plugins/platforms/wayland_common/qwaylandshellsurface.h +++ b/src/plugins/platforms/wayland_common/qwaylandshellsurface.h @@ -69,6 +69,7 @@ private: void setTopLevel(); void updateTransientParent(QWindow *parent); + void setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial); struct wl_shell_surface *handle() const { return m_shell_surface; } diff --git a/src/plugins/platforms/wayland_common/qwaylandwindow.cpp b/src/plugins/platforms/wayland_common/qwaylandwindow.cpp index 7b0e939f..b71176d4 100644 --- a/src/plugins/platforms/wayland_common/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland_common/qwaylandwindow.cpp @@ -79,6 +79,8 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mWaitingForFrameSync(false) , mFrameCallback(0) , mSentInitialResize(false) + , mMouseDevice(0) + , mMouseSerial(0) , mState(Qt::WindowNoState) { static WId id = 1; @@ -104,7 +106,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window) if (parent() && mSubSurfaceWindow) { mSubSurfaceWindow->setParent(static_cast<const QWaylandWindow *>(parent())); } else if (window->transientParent()) { - if (window->transientParent()) { + if (window->type() != Qt::Popup) { mShellSurface->updateTransientParent(window->transientParent()); } } else { @@ -163,19 +165,23 @@ void QWaylandWindow::setGeometry(const QRect &rect) { QPlatformWindow::setGeometry(rect); - if (shellSurface() && window()->transientParent()) - shellSurface()->updateTransientParent(window()->transientParent()); - mDisplay->scheduleRedraw(this); } void QWaylandWindow::setVisible(bool visible) { - if (visible) { if (mBuffer) wl_surface_attach(mSurface, mBuffer->buffer(), 0, 0); + if (window()->type() == Qt::Popup && transientParent()) { + QWaylandWindow *parent = transientParent(); + mMouseDevice = parent->mMouseDevice; + mMouseSerial = parent->mMouseSerial; + + mShellSurface->setPopup(transientParent(), mMouseDevice, mMouseSerial); + } + if (!mSentInitialResize) { QWindowSystemInterface::handleGeometryChange(window(), geometry()); QWindowSystemInterface::flushWindowSystemEvents(); @@ -407,8 +413,32 @@ void QWaylandWindow::setDecoration(QWaylandDecoration *decoration) } } +QWaylandWindow *QWaylandWindow::topLevelWindow() +{ + QWaylandWindow *w = this; + while (w->parent()) { + w = static_cast<QWaylandWindow *>(w->parent()); + } + return w; +} + +QWaylandWindow *QWaylandWindow::transientParent() const +{ + if (window()->transientParent()) { + // Take the top level window here, since the transient parent may be some non-native + // QWindow, which cannot have the mMouseDevice and mMouseSerial + return static_cast<QWaylandWindow *>(window()->transientParent()->handle())->topLevelWindow(); + } + return 0; +} + void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { + if (b != Qt::NoButton) { + mMouseSerial = inputDevice->serial(); + mMouseDevice = inputDevice; + } + if (mWindowDecoration) { handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods); return; diff --git a/src/plugins/platforms/wayland_common/qwaylandwindow.h b/src/plugins/platforms/wayland_common/qwaylandwindow.h index 258c58b9..172728c9 100644 --- a/src/plugins/platforms/wayland_common/qwaylandwindow.h +++ b/src/plugins/platforms/wayland_common/qwaylandwindow.h @@ -129,6 +129,9 @@ public: inline bool isMaximized() const { return mState == Qt::WindowMaximized; } inline bool isFullscreen() const { return mState == Qt::WindowFullScreen; } + QWaylandWindow *topLevelWindow(); + QWaylandWindow *transientParent() const; + protected: virtual void createDecorationInstance() {} @@ -152,6 +155,8 @@ protected: QPoint mOffset; QIcon mWindowIcon; + QWaylandInputDevice *mMouseDevice; + int mMouseSerial; Qt::WindowState mState; |