summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGiulio Camuffo <giuliocamuffo@gmail.com>2013-03-22 18:48:53 +0100
committerAndy Nichols <andy.nichols@digia.com>2013-04-03 11:39:06 +0200
commit7a9fe97eea5f643da27344b24ecd00927c5eda80 (patch)
treee25635e52a5b5acf9b3e7edc8e79c673c6109faf /src
parent77248e2765e4db5cd7fe6e53e07a612d75b91011 (diff)
downloadqtwayland-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')
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandshellsurface.cpp22
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandshellsurface.h1
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandwindow.cpp40
-rw-r--r--src/plugins/platforms/wayland_common/qwaylandwindow.h5
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;