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
|
QWindow *QPlatformWindow::window() const
|
||||||
{
|
{
|
||||||
@ -78,6 +78,15 @@ QWindow *QPlatformWindow::window() const
|
|||||||
return d->window;
|
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
|
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
|
can happen programatically(from ie. user application) or by the window manager. This means that
|
||||||
|
@ -66,6 +66,8 @@ public:
|
|||||||
virtual ~QPlatformWindow();
|
virtual ~QPlatformWindow();
|
||||||
|
|
||||||
QWindow *window() const;
|
QWindow *window() const;
|
||||||
|
QPlatformWindow *parent() const;
|
||||||
|
|
||||||
virtual void setGeometry(const QRect &rect);
|
virtual void setGeometry(const QRect &rect);
|
||||||
virtual QRect geometry() const;
|
virtual QRect geometry() const;
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ void QWindow::create()
|
|||||||
QObject *object = childObjects.at(i);
|
QObject *object = childObjects.at(i);
|
||||||
if(object->isWindowType()) {
|
if(object->isWindowType()) {
|
||||||
QWindow *window = static_cast<QWindow *>(object);
|
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);
|
window->d_func()->platformWindow->setParent(d->platformWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,9 +133,9 @@ void QWindow::setParent(QWindow *parent)
|
|||||||
QObject::setParent(parent);
|
QObject::setParent(parent);
|
||||||
|
|
||||||
if (d->platformWindow) {
|
if (d->platformWindow) {
|
||||||
if (parent && parent->d_func()->platformWindow) {
|
if (parent && parent->d_func()->platformWindow && !isTopLevel()) {
|
||||||
d->platformWindow->setParent(parent->d_func()->platformWindow);
|
d->platformWindow->setParent(parent->d_func()->platformWindow);
|
||||||
} else if (!parent) {
|
} else {
|
||||||
d->platformWindow->setParent(0);
|
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
|
bool QWindow::isTopLevel() const
|
||||||
{
|
{
|
||||||
Q_D(const QWindow);
|
Q_D(const QWindow);
|
||||||
return d->parentWindow == 0;
|
return d->windowFlags & Qt::Window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWindow::setWindowFormat(const QWindowFormat &format)
|
void QWindow::setWindowFormat(const QWindowFormat &format)
|
||||||
@ -196,6 +196,12 @@ Qt::WindowFlags QWindow::windowFlags() const
|
|||||||
return d->windowFlags;
|
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)
|
void QWindow::setWindowTitle(const QString &title)
|
||||||
{
|
{
|
||||||
Q_D(QWindow);
|
Q_D(QWindow);
|
||||||
|
@ -107,6 +107,7 @@ public:
|
|||||||
|
|
||||||
void setWindowFlags(Qt::WindowFlags flags);
|
void setWindowFlags(Qt::WindowFlags flags);
|
||||||
Qt::WindowFlags windowFlags() const;
|
Qt::WindowFlags windowFlags() const;
|
||||||
|
Qt::WindowType windowType() const;
|
||||||
|
|
||||||
QString windowTitle() const;
|
QString windowTitle() const;
|
||||||
|
|
||||||
|
@ -73,20 +73,17 @@
|
|||||||
#include "../eglconvenience/qxlibeglintegration.h"
|
#include "../eglconvenience/qxlibeglintegration.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Returns true if we should set WM_TRANSIENT_FOR on \a w
|
// 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::Sheet
|
||||||
|| w->windowType() == Qt::Tool
|
|| w->windowType() == Qt::Tool
|
||||||
|| w->windowType() == Qt::SplashScreen
|
|| w->windowType() == Qt::SplashScreen
|
||||||
|| w->windowType() == Qt::ToolTip
|
|| w->windowType() == Qt::ToolTip
|
||||||
|| w->windowType() == Qt::Drawer
|
|| w->windowType() == Qt::Drawer
|
||||||
|| w->windowType() == Qt::Popup)
|
|| w->windowType() == Qt::Popup;
|
||||||
&& !w->testAttribute(Qt::WA_X11BypassTransientForHint));
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
QXcbWindow::QXcbWindow(QWindow *window)
|
QXcbWindow::QXcbWindow(QWindow *window)
|
||||||
: QPlatformWindow(window)
|
: QPlatformWindow(window)
|
||||||
@ -119,8 +116,8 @@ QXcbWindow::QXcbWindow(QWindow *window)
|
|||||||
QRect rect = window->geometry();
|
QRect rect = window->geometry();
|
||||||
|
|
||||||
xcb_window_t xcb_parent_id = m_screen->root();
|
xcb_window_t xcb_parent_id = m_screen->root();
|
||||||
if (window->parent() && window->parent()->handle())
|
if (parent() && !window->isTopLevel())
|
||||||
xcb_parent_id = static_cast<QXcbWindow *>(window->parent()->handle())->xcb_window();
|
xcb_parent_id = static_cast<QXcbWindow *>(parent())->xcb_window();
|
||||||
|
|
||||||
#if defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
|
#if defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
|
||||||
if (window->surfaceType() == QWindow::OpenGLSurface
|
if (window->surfaceType() == QWindow::OpenGLSurface
|
||||||
@ -217,18 +214,6 @@ QXcbWindow::QXcbWindow(QWindow *window)
|
|||||||
&m_syncCounter));
|
&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
|
// set the PID to let the WM kill the application if unresponsive
|
||||||
long pid = getpid();
|
long pid = getpid();
|
||||||
Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
|
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);
|
xcb_set_wm_hints(xcb_connection(), m_window, &hints);
|
||||||
|
|
||||||
|
// update WM_NORMAL_HINTS
|
||||||
propagateSizeHints();
|
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));
|
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
|
||||||
@ -598,6 +595,7 @@ void QXcbWindow::lower()
|
|||||||
|
|
||||||
void QXcbWindow::propagateSizeHints()
|
void QXcbWindow::propagateSizeHints()
|
||||||
{
|
{
|
||||||
|
// update WM_NORMAL_HINTS
|
||||||
xcb_size_hints_t hints;
|
xcb_size_hints_t hints;
|
||||||
|
|
||||||
QRect rect = geometry();
|
QRect rect = geometry();
|
||||||
|
@ -93,11 +93,9 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
|
|||||||
|
|
||||||
QWindow *win = topData()->window;
|
QWindow *win = topData()->window;
|
||||||
|
|
||||||
if (!q->isWindow()) {
|
if (QWidget *nativeParent = q->nativeParentWidget()) {
|
||||||
if (QWidget *nativeParent = q->nativeParentWidget()) {
|
if (nativeParent->windowHandle())
|
||||||
if (nativeParent->windowHandle())
|
win->setParent(nativeParent->windowHandle());
|
||||||
win->setParent(nativeParent->windowHandle());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
win->setWindowFlags(data.window_flags);
|
win->setWindowFlags(data.window_flags);
|
||||||
|
Loading…
Reference in New Issue
Block a user