summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-05-19 10:51:34 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-05-19 10:53:30 +0200
commitea7277690d9f4a7c4e10f3d3b7a2bef46d6878c2 (patch)
tree620b3d1acc7f8d5855f84248635d9a43f5e57476 /src
parente0e696dd05fbe329044879cf560fe26330edf7bd (diff)
Better setWindowFlags() support in XCB window.
We need to re-create the native window in setParent, as used to be done in QWidgetPrivate::setParent_sys in qwidget_x11.cpp.
Diffstat (limited to 'src')
-rw-r--r--src/gui/kernel/qwindow.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp20
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp100
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h7
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp16
6 files changed, 100 insertions, 49 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 121791d2f3..3ff7d6c998 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -127,9 +127,6 @@ void QWindow::setParent(QWindow *parent)
{
Q_D(QWindow);
- if (d->parentWindow == parent)
- return;
-
QObject::setParent(parent);
if (d->platformWindow) {
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 1c12ee3059..851a781d6c 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -102,6 +102,26 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
free(reply);
m_syncRequestSupported = m_windowManagerName != QLatin1String("KWin");
+
+ m_clientLeader = xcb_generate_id(xcb_connection());
+ Q_XCB_CALL2(xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT,
+ m_clientLeader,
+ m_screen->root,
+ 0, 0, 1, 1,
+ 0,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ m_screen->root_visual,
+ 0, 0), connection);
+
+ Q_XCB_CALL2(xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_clientLeader,
+ atom(QXcbAtom::WM_CLIENT_LEADER),
+ XCB_ATOM_WINDOW,
+ 32,
+ 1,
+ &m_clientLeader), connection);
}
QXcbScreen::~QXcbScreen()
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 9547d016b7..8efafb35bc 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -67,6 +67,8 @@ public:
xcb_screen_t *screen() const { return m_screen; }
xcb_window_t root() const { return m_screen->root; }
+ xcb_window_t clientLeader() const { return m_clientLeader; }
+
QString windowManagerName() const { return m_windowManagerName; }
bool syncRequestSupported() const { return m_syncRequestSupported; }
@@ -75,6 +77,7 @@ private:
int m_number;
QString m_windowManagerName;
bool m_syncRequestSupported;
+ xcb_window_t m_clientLeader;
};
#endif
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 35c9efc1d9..074fdafe87 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -89,17 +89,35 @@ static inline bool isTransient(const QWindow *w)
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
+ , m_window(0)
, m_context(0)
- , m_windowState(Qt::WindowNoState)
+ , m_syncCounter(0)
{
m_screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens().at(0));
setConnection(m_screen->connection());
- const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_EVENT_MASK;
+ create();
+}
+
+void QXcbWindow::create()
+{
+ bool wasCreated = (m_window != 0);
+ destroy();
+
+ m_windowState = Qt::WindowNoState;
+ m_hasReceivedSyncRequest = false;
+
+ Qt::WindowType type = window()->windowType();
+
+ const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK;
const quint32 values[] = {
// XCB_CW_BACK_PIXMAP
XCB_NONE,
+ // XCB_CW_OVERRIDE_REDIRECT
+ type == Qt::Popup,
+ // XCB_CW_SAVE_UNDER
+ type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer,
// XCB_CW_EVENT_MASK
XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_STRUCTURE_NOTIFY
@@ -115,21 +133,21 @@ QXcbWindow::QXcbWindow(QWindow *window)
| XCB_EVENT_MASK_FOCUS_CHANGE
};
- QRect rect = window->geometry();
+ QRect rect = window()->geometry();
xcb_window_t xcb_parent_id = m_screen->root();
- if (parent() && !window->isTopLevel())
+ 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
+ if (window()->surfaceType() == QWindow::OpenGLSurface
&& QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
{
#if defined(XCB_USE_GLX)
- XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), window->requestedWindowFormat());
+ XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), window()->requestedWindowFormat());
#elif defined(XCB_USE_EGL)
EGLDisplay eglDisplay = connection()->egl_display();
- EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,window->requestedWindowFormat(),true);
+ EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,window()->requestedWindowFormat(),true);
VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig);
XVisualInfo visualInfoTemplate;
@@ -149,7 +167,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
0, visualInfo->depth, InputOutput, visualInfo->visual,
CWColormap, &a);
- printf("created GL window: %d\n", m_window);
+ printf("created GL window: %x\n", m_window);
} else {
qFatal("no window!");
}
@@ -172,7 +190,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
0, // value mask
0)); // value list
- printf("created regular window: %d\n", m_window);
+ printf("created regular window: %x\n", m_window);
}
connection()->addWindow(m_window, this);
@@ -188,7 +206,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
if (m_screen->syncRequestSupported())
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
- if (window->windowFlags() & Qt::WindowContextHelpButtonHint)
+ if (window()->windowFlags() & Qt::WindowContextHelpButtonHint)
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);
Q_XCB_CALL(xcb_change_property(xcb_connection(),
@@ -221,15 +239,36 @@ QXcbWindow::QXcbWindow(QWindow *window)
Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
1, &pid));
+
+ xcb_wm_hints_t hints;
+ memset(&hints, 0, sizeof(hints));
+ xcb_wm_hints_set_normal(&hints);
+
+ xcb_set_wm_hints(xcb_connection(), m_window, &hints);
+
+ xcb_window_t leader = m_screen->clientLeader();
+ Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
+ 1, &leader));
+
+ if (wasCreated)
+ setWindowFlags(window()->windowFlags());
}
QXcbWindow::~QXcbWindow()
{
+ destroy();
+}
+
+void QXcbWindow::destroy()
+{
delete m_context;
- if (m_screen->syncRequestSupported())
+ if (m_syncCounter && m_screen->syncRequestSupported())
Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
- connection()->removeWindow(m_window);
- Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
+ if (m_window) {
+ connection()->removeWindow(m_window);
+ Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
+ }
}
void QXcbWindow::setGeometry(const QRect &rect)
@@ -468,27 +507,20 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
- setNetWmWindowTypes(flags);
-
if (type == Qt::ToolTip)
flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
if (type == Qt::Popup)
flags |= Qt::X11BypassWindowManagerHint;
- bool topLevel = (flags & Qt::Window);
- bool popup = (type == Qt::Popup);
- bool dialog = (type == Qt::Dialog
- || type == Qt::Sheet);
- bool desktop = (type == Qt::Desktop);
- bool tool = (type == Qt::Tool || type == Qt::SplashScreen
- || type == Qt::ToolTip || type == Qt::Drawer);
+ setNetWmWindowFlags(flags);
+ setMotifWindowFlags(flags);
- Q_UNUSED(topLevel);
- Q_UNUSED(dialog);
- Q_UNUSED(desktop);
- Q_UNUSED(tool);
+ return flags;
+}
- bool tooltip = (type == Qt::ToolTip);
+void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags)
+{
+ Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
QtMotifWmHints mwmhints;
mwmhints.flags = 0L;
@@ -551,15 +583,6 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
}
setMotifWmHints(connection(), m_window, mwmhints);
-
- if (popup || tooltip) {
- const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER;
- const quint32 values[] = { true, true };
-
- Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
- }
-
- return flags;
}
void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
@@ -640,7 +663,7 @@ Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state)
return m_windowState;
}
-void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
+void QXcbWindow::setNetWmWindowFlags(Qt::WindowFlags flags)
{
// in order of decreasing priority
QVector<uint> windowTypes;
@@ -767,6 +790,9 @@ WId QXcbWindow::winId() const
void QXcbWindow::setParent(const QPlatformWindow *parent)
{
+ // re-create for compatibility
+ create();
+
QPoint topLeft = geometry().topLeft();
xcb_window_t xcb_parent_id = parent ? static_cast<const QXcbWindow *>(parent)->xcb_window() : m_screen->root();
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 9996188714..a6ca3de565 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -94,15 +94,20 @@ public:
void updateSyncRequestCounter();
private:
- void setNetWmWindowTypes(Qt::WindowFlags flags);
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
QVector<xcb_atom_t> getNetWmState();
void setNetWmState(const QVector<xcb_atom_t> &atoms);
void printNetWmState(const QVector<xcb_atom_t> &state);
+ void setNetWmWindowFlags(Qt::WindowFlags flags);
+ void setMotifWindowFlags(Qt::WindowFlags flags);
+
void updateMotifWmHintsBeforeMap();
void updateNetWmStateBeforeMap();
+ void create();
+ void destroy();
+
void show();
void hide();
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index a4c68c16a5..6721fdbb6a 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -93,13 +93,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
QWindow *win = topData()->window;
+ win->setWindowFlags(data.window_flags);
+ win->setGeometry(q->geometry());
+
if (QWidget *nativeParent = q->nativeParentWidget()) {
if (nativeParent->windowHandle())
win->setParent(nativeParent->windowHandle());
}
- win->setWindowFlags(data.window_flags);
- win->setGeometry(q->geometry());
win->create();
data.window_flags = win->windowFlags();
@@ -174,13 +175,12 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
if (parent != newparent) {
QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
- if (q->windowHandle() && newparent) {
- QWidget * parentWithWindow = newparent->windowHandle()? newparent : newparent->nativeParentWidget();
- if (parentWithWindow && parentWithWindow->windowHandle()) {
- q->windowHandle()->setParent(parentWithWindow->windowHandle());
- }
+ if (q->windowHandle()) {
+ q->windowHandle()->setWindowFlags(f);
+ QWidget *parentWithWindow =
+ newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
+ q->windowHandle()->setParent(parentWithWindow ? parentWithWindow->windowHandle() : 0);
}
-
}
if (!newparent) {