From 10a3b10726d2f46b2a284ecb7533bb9226f8c7c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 16 May 2011 17:28:56 +0200 Subject: Re-implement transient window support in XCB backend. If a QWindow has a parent but is top-level the corresponding QPlatformWindow should not be re-parented but instead be made transient for the parent window if possible. --- src/gui/kernel/qplatformwindow_qpa.cpp | 11 +++++++- src/gui/kernel/qplatformwindow_qpa.h | 2 ++ src/gui/kernel/qwindow.cpp | 16 +++++++---- src/gui/kernel/qwindow.h | 1 + src/plugins/platforms/xcb/qxcbwindow.cpp | 48 +++++++++++++++----------------- src/widgets/kernel/qwidget_qpa.cpp | 8 ++---- 6 files changed, 50 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp index afbff2ad5d..f6a1260d9d 100644 --- a/src/gui/kernel/qplatformwindow_qpa.cpp +++ b/src/gui/kernel/qplatformwindow_qpa.cpp @@ -70,7 +70,7 @@ QPlatformWindow::~QPlatformWindow() } /*! - Returnes the window which belongs to the QPlatformWindow + Returns the window which belongs to the QPlatformWindow */ QWindow *QPlatformWindow::window() const { @@ -78,6 +78,15 @@ QWindow *QPlatformWindow::window() const return d->window; } +/*! + Returns the parent platform window (or 0 if orphan). +*/ +QPlatformWindow *QPlatformWindow::parent() const +{ + Q_D(const QPlatformWindow); + return d->window->parent() ? d->window->parent()->handle() : 0; +} + /*! This function is called by Qt whenever a window is moved or the window is resized. The resize can happen programatically(from ie. user application) or by the window manager. This means that diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h index de3174bde9..6bfdc5bc75 100644 --- a/src/gui/kernel/qplatformwindow_qpa.h +++ b/src/gui/kernel/qplatformwindow_qpa.h @@ -66,6 +66,8 @@ public: virtual ~QPlatformWindow(); QWindow *window() const; + QPlatformWindow *parent() const; + virtual void setGeometry(const QRect &rect); virtual QRect geometry() const; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 5d4fd763b8..3b01a0d352 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -97,7 +97,7 @@ void QWindow::create() QObject *object = childObjects.at(i); if(object->isWindowType()) { QWindow *window = static_cast(object); - if (window->d_func()->platformWindow) + if (window->d_func()->platformWindow && !window->isTopLevel()) window->d_func()->platformWindow->setParent(d->platformWindow); } } @@ -133,9 +133,9 @@ void QWindow::setParent(QWindow *parent) QObject::setParent(parent); if (d->platformWindow) { - if (parent && parent->d_func()->platformWindow) { + if (parent && parent->d_func()->platformWindow && !isTopLevel()) { d->platformWindow->setParent(parent->d_func()->platformWindow); - } else if (!parent) { + } else { d->platformWindow->setParent(0); } } @@ -144,12 +144,12 @@ void QWindow::setParent(QWindow *parent) } /*! - Returns whether the window is top level, i.e. parent-less. + Returns whether the window is top level. */ bool QWindow::isTopLevel() const { Q_D(const QWindow); - return d->parentWindow == 0; + return d->windowFlags & Qt::Window; } void QWindow::setWindowFormat(const QWindowFormat &format) @@ -196,6 +196,12 @@ Qt::WindowFlags QWindow::windowFlags() const return d->windowFlags; } +Qt::WindowType QWindow::windowType() const +{ + Q_D(const QWindow); + return static_cast(int(d->windowFlags & Qt::WindowType_Mask)); +} + void QWindow::setWindowTitle(const QString &title) { Q_D(QWindow); diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index e0a1871ea1..22dbf48538 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -107,6 +107,7 @@ public: void setWindowFlags(Qt::WindowFlags flags); Qt::WindowFlags windowFlags() const; + Qt::WindowType windowType() const; QString windowTitle() const; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 709efb2bc6..7942e46c1d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -73,20 +73,17 @@ #include "../eglconvenience/qxlibeglintegration.h" #endif -#if 0 // Returns true if we should set WM_TRANSIENT_FOR on \a w -static inline bool isTransient(const QWidget *w) +static inline bool isTransient(const QWindow *w) { - return ((w->windowType() == Qt::Dialog - || w->windowType() == Qt::Sheet - || w->windowType() == Qt::Tool - || w->windowType() == Qt::SplashScreen - || w->windowType() == Qt::ToolTip - || w->windowType() == Qt::Drawer - || w->windowType() == Qt::Popup) - && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); + return w->windowType() == Qt::Dialog + || w->windowType() == Qt::Sheet + || w->windowType() == Qt::Tool + || w->windowType() == Qt::SplashScreen + || w->windowType() == Qt::ToolTip + || w->windowType() == Qt::Drawer + || w->windowType() == Qt::Popup; } -#endif QXcbWindow::QXcbWindow(QWindow *window) : QPlatformWindow(window) @@ -119,8 +116,8 @@ QXcbWindow::QXcbWindow(QWindow *window) QRect rect = window->geometry(); xcb_window_t xcb_parent_id = m_screen->root(); - if (window->parent() && window->parent()->handle()) - xcb_parent_id = static_cast(window->parent()->handle())->xcb_window(); + if (parent() && !window->isTopLevel()) + xcb_parent_id = static_cast(parent())->xcb_window(); #if defined(XCB_USE_GLX) || defined(XCB_USE_EGL) if (window->surfaceType() == QWindow::OpenGLSurface @@ -217,18 +214,6 @@ QXcbWindow::QXcbWindow(QWindow *window) &m_syncCounter)); } -#if 0 - if (tlw && isTransient(tlw) && tlw->parentWidget()) { - // ICCCM 4.1.2.6 - QWidget *p = tlw->parentWidget()->window(); - xcb_window_t parentWindow = p->winId(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, - 1, &parentWindow)); - - } -#endif - // set the PID to let the WM kill the application if unresponsive long pid = getpid(); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, @@ -278,7 +263,19 @@ void QXcbWindow::show() xcb_set_wm_hints(xcb_connection(), m_window, &hints); + // update WM_NORMAL_HINTS propagateSizeHints(); + + // update WM_TRANSIENT_FOR + if (isTransient(window()) && parent()) { + // ICCCM 4.1.2.6 + xcb_window_t parentWindow = static_cast(parent())->xcb_window(); + + // todo: set transient for group (wm_client_leader) if no parent, a la qwidget_x11.cpp + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, + 1, &parentWindow)); + } } Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); @@ -598,6 +595,7 @@ void QXcbWindow::lower() void QXcbWindow::propagateSizeHints() { + // update WM_NORMAL_HINTS xcb_size_hints_t hints; QRect rect = geometry(); diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 533cc0a47c..e6a55968f9 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -93,11 +93,9 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO QWindow *win = topData()->window; - if (!q->isWindow()) { - if (QWidget *nativeParent = q->nativeParentWidget()) { - if (nativeParent->windowHandle()) - win->setParent(nativeParent->windowHandle()); - } + if (QWidget *nativeParent = q->nativeParentWidget()) { + if (nativeParent->windowHandle()) + win->setParent(nativeParent->windowHandle()); } win->setWindowFlags(data.window_flags); -- cgit v1.2.3