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.
This commit is contained in:
parent
25f70314e0
commit
10a3b10726
@ -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
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
virtual ~QPlatformWindow();
|
||||
|
||||
QWindow *window() const;
|
||||
QPlatformWindow *parent() const;
|
||||
|
||||
virtual void setGeometry(const QRect &rect);
|
||||
virtual QRect geometry() const;
|
||||
|
||||
|
@ -97,7 +97,7 @@ void QWindow::create()
|
||||
QObject *object = childObjects.at(i);
|
||||
if(object->isWindowType()) {
|
||||
QWindow *window = static_cast<QWindow *>(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<Qt::WindowType>(int(d->windowFlags & Qt::WindowType_Mask));
|
||||
}
|
||||
|
||||
void QWindow::setWindowTitle(const QString &title)
|
||||
{
|
||||
Q_D(QWindow);
|
||||
|
@ -107,6 +107,7 @@ public:
|
||||
|
||||
void setWindowFlags(Qt::WindowFlags flags);
|
||||
Qt::WindowFlags windowFlags() const;
|
||||
Qt::WindowType windowType() const;
|
||||
|
||||
QString windowTitle() const;
|
||||
|
||||
|
@ -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
|
||||
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));
|
||||
|| 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<QXcbWindow *>(window->parent()->handle())->xcb_window();
|
||||
if (parent() && !window->isTopLevel())
|
||||
xcb_parent_id = static_cast<QXcbWindow *>(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<QXcbWindow *>(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();
|
||||
|
@ -93,12 +93,10 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
win->setWindowFlags(data.window_flags);
|
||||
win->setGeometry(q->geometry());
|
||||
|
Loading…
Reference in New Issue
Block a user