summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-05-18 09:32:17 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-05-18 09:32:17 +0200
commit516f4e283ba4626d7239630397ef867ab0366071 (patch)
tree094e1a5347f26fe147323d74ce70080d110f96d3 /src
parent10a3b10726d2f46b2a284ecb7533bb9226f8c7c8 (diff)
Add QWindow::setWindowModality().
Also set corresponding window manager hints in xcb plugin.
Diffstat (limited to 'src')
-rw-r--r--src/gui/kernel/qwindow.cpp18
-rw-r--r--src/gui/kernel/qwindow.h4
-rw-r--r--src/gui/kernel/qwindow_p.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp136
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp6
-rw-r--r--src/widgets/platforms/x11/qwidget_x11.cpp2
7 files changed, 151 insertions, 19 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 3b01a0d352..121791d2f3 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -152,6 +152,24 @@ bool QWindow::isTopLevel() const
return d->windowFlags & Qt::Window;
}
+bool QWindow::isModal() const
+{
+ Q_D(const QWindow);
+ return d->modality != Qt::NonModal;
+}
+
+Qt::WindowModality QWindow::windowModality() const
+{
+ Q_D(const QWindow);
+ return d->modality;
+}
+
+void QWindow::setWindowModality(Qt::WindowModality windowModality)
+{
+ Q_D(QWindow);
+ d->modality = windowModality;
+}
+
void QWindow::setWindowFormat(const QWindowFormat &format)
{
Q_D(QWindow);
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 22dbf48538..de4e414703 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -96,7 +96,9 @@ public:
bool isTopLevel() const;
- QWindow *topLevelWindow() const;
+ bool isModal() const;
+ Qt::WindowModality windowModality() const;
+ void setWindowModality(Qt::WindowModality windowModality);
void setWindowFormat(const QWindowFormat &format);
QWindowFormat requestedWindowFormat() const;
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 215a18d27e..f52dd559f1 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -92,6 +92,8 @@ public:
QSize maximumSize;
QSize baseSize;
QSize sizeIncrement;
+
+ Qt::WindowModality modality;
};
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 7942e46c1d..eeec59c868 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -253,8 +253,15 @@ void QXcbWindow::show()
if (window()->isTopLevel()) {
xcb_get_property_cookie_t cookie = xcb_get_wm_hints(xcb_connection(), m_window);
+ xcb_generic_error_t *error;
+
xcb_wm_hints_t hints;
- xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, 0);
+ xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, &error);
+
+ if (error) {
+ connection()->handleXcbError(error);
+ free(error);
+ }
if (window()->windowState() & Qt::WindowMinimized)
xcb_wm_hints_set_iconic(&hints);
@@ -276,6 +283,9 @@ void QXcbWindow::show()
XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
1, &parentWindow));
}
+
+ // update _MOTIF_WM_HINTS
+ updateMotifWmHintsBeforeShow();
}
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
@@ -299,7 +309,7 @@ void QXcbWindow::hide()
xcb_flush(xcb_connection());
}
-struct QtMWMHints {
+struct QtMotifWmHints {
quint32 flags, functions, decorations;
qint32 input_mode;
quint32 status;
@@ -332,6 +342,53 @@ enum {
MWM_INPUT_FULL_APPLICATION_MODAL = 3L
};
+static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window)
+{
+ QtMotifWmHints hints;
+
+ xcb_get_property_cookie_t get_cookie =
+ xcb_get_property(c->xcb_connection(), 0, window, c->atom(QXcbAtom::_MOTIF_WM_HINTS),
+ c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20);
+
+ xcb_generic_error_t *error;
+
+ xcb_get_property_reply_t *reply =
+ xcb_get_property_reply(c->xcb_connection(), get_cookie, &error);
+
+ if (reply && reply->format == 32 && reply->type == c->atom(QXcbAtom::_MOTIF_WM_HINTS)) {
+ hints = *((QtMotifWmHints *)xcb_get_property_value(reply));
+ } else if (error) {
+ c->handleXcbError(error);
+ free(error);
+
+ hints.flags = 0L;
+ hints.functions = MWM_FUNC_ALL;
+ hints.decorations = MWM_DECOR_ALL;
+ hints.input_mode = 0L;
+ hints.status = 0L;
+ }
+
+ free(reply);
+
+ return hints;
+}
+
+static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMotifWmHints &hints)
+{
+ if (hints.flags != 0l) {
+ Q_XCB_CALL2(xcb_change_property(c->xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ window,
+ c->atom(QXcbAtom::_MOTIF_WM_HINTS),
+ c->atom(QXcbAtom::_MOTIF_WM_HINTS),
+ 32,
+ 5,
+ &hints), c);
+ } else {
+ Q_XCB_CALL2(xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)), c);
+ }
+}
+
Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
@@ -358,7 +415,7 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
bool tooltip = (type == Qt::ToolTip);
- QtMWMHints mwmhints;
+ QtMotifWmHints mwmhints;
mwmhints.flags = 0L;
mwmhints.functions = 0L;
mwmhints.decorations = 0;
@@ -418,18 +475,7 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
mwmhints.decorations = 0;
}
- if (mwmhints.flags != 0l) {
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_MOTIF_WM_HINTS),
- atom(QXcbAtom::_MOTIF_WM_HINTS),
- 32,
- 5,
- &mwmhints));
- } else {
- Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS)));
- }
+ setMotifWmHints(connection(), m_window, mwmhints);
if (popup || tooltip) {
const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER;
@@ -555,6 +601,62 @@ void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
windowTypes.count(), windowTypes.constData()));
}
+void QXcbWindow::updateMotifWmHintsBeforeShow()
+{
+ QtMotifWmHints mwmhints = getMotifWmHints(connection(), m_window);
+
+ if (window()->windowModality() != Qt::NonModal) {
+ switch (window()->windowModality()) {
+ case Qt::WindowModal:
+ mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
+ break;
+ case Qt::ApplicationModal:
+ default:
+ mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
+ break;
+ }
+ mwmhints.flags |= MWM_HINTS_INPUT_MODE;
+ } else {
+ mwmhints.input_mode = MWM_INPUT_MODELESS;
+ mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
+ }
+
+ if (window()->minimumSize() == window()->maximumSize()) {
+ // fixed size, remove the resize handle (since mwm/dtwm
+ // isn't smart enough to do it itself)
+ mwmhints.flags |= MWM_HINTS_FUNCTIONS;
+ if (mwmhints.functions == MWM_FUNC_ALL) {
+ mwmhints.functions = MWM_FUNC_MOVE;
+ } else {
+ mwmhints.functions &= ~MWM_FUNC_RESIZE;
+ }
+
+ if (mwmhints.decorations == MWM_DECOR_ALL) {
+ mwmhints.flags |= MWM_HINTS_DECORATIONS;
+ mwmhints.decorations = (MWM_DECOR_BORDER
+ | MWM_DECOR_TITLE
+ | MWM_DECOR_MENU);
+ } else {
+ mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
+ }
+ }
+
+ if (window()->windowFlags() & Qt::WindowMinimizeButtonHint) {
+ mwmhints.flags |= MWM_HINTS_DECORATIONS;
+ mwmhints.decorations |= MWM_DECOR_MINIMIZE;
+ mwmhints.functions |= MWM_FUNC_MINIMIZE;
+ }
+ if (window()->windowFlags() & Qt::WindowMaximizeButtonHint) {
+ mwmhints.flags |= MWM_HINTS_DECORATIONS;
+ mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
+ mwmhints.functions |= MWM_FUNC_MAXIMIZE;
+ }
+ if (window()->windowFlags() & Qt::WindowCloseButtonHint)
+ mwmhints.functions |= MWM_FUNC_CLOSE;
+
+ setMotifWmHints(connection(), m_window, mwmhints);
+}
+
WId QXcbWindow::winId() const
{
return m_window;
@@ -563,7 +665,9 @@ WId QXcbWindow::winId() const
void QXcbWindow::setParent(const QPlatformWindow *parent)
{
QPoint topLeft = geometry().topLeft();
- Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), static_cast<const QXcbWindow *>(parent)->xcb_window(), topLeft.x(), topLeft.y()));
+
+ xcb_window_t xcb_parent_id = parent ? static_cast<const QXcbWindow *>(parent)->xcb_window() : m_screen->root();
+ Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y()));
}
void QXcbWindow::setWindowTitle(const QString &title)
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index accb32b36e..9827a808cc 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -97,6 +97,8 @@ private:
void setNetWmWindowTypes(Qt::WindowFlags flags);
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
+ void updateMotifWmHintsBeforeShow();
+
void show();
void hide();
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index e6a55968f9..a4c68c16a5 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -763,7 +763,8 @@ void QWidgetPrivate::updateFrameStrut()
void QWidgetPrivate::setWindowOpacity_sys(qreal level)
{
Q_Q(QWidget);
- q->windowHandle()->setOpacity(level);
+ if (q->windowHandle())
+ q->windowHandle()->setOpacity(level);
}
void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
@@ -788,6 +789,9 @@ QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
void QWidgetPrivate::setModal_sys()
{
+ Q_Q(QWidget);
+ if (q->windowHandle())
+ q->windowHandle()->setWindowModality(q->windowModality());
}
#ifndef QT_NO_CURSOR
diff --git a/src/widgets/platforms/x11/qwidget_x11.cpp b/src/widgets/platforms/x11/qwidget_x11.cpp
index 3eec5c7331..12f4e2f856 100644
--- a/src/widgets/platforms/x11/qwidget_x11.cpp
+++ b/src/widgets/platforms/x11/qwidget_x11.cpp
@@ -134,7 +134,7 @@ enum {
};
-static QtMWMHints GetMWMHints(Display *display, Window window)
+static QtMWMHints getMWMHints(Display *display, Window window)
{
QtMWMHints mwmhints;