summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-06-10 12:40:29 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-06-10 12:40:56 +0200
commit6b0cd62e5ecad075c4528d3a09ec903ab057680e (patch)
treedaa08ef647df36a774c5ce78738dffb9c2d154bf
parentf56a905ced02b387f6ac7f482f997629f27bcf89 (diff)
Added frameMargins() API and support in XCB plugin.
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.cpp5
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.h3
-rw-r--r--src/gui/kernel/qwindow.cpp8
-rw-r--r--src/gui/kernel/qwindow.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp92
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h5
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp47
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa.cpp15
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h2
9 files changed, 163 insertions, 17 deletions
diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp
index cba5529df4..feffd0cfed 100644
--- a/src/gui/kernel/qplatformwindow_qpa.cpp
+++ b/src/gui/kernel/qplatformwindow_qpa.cpp
@@ -108,6 +108,11 @@ QRect QPlatformWindow::geometry() const
return d->rect;
}
+QMargins QPlatformWindow::frameMargins() const
+{
+ return QMargins();
+}
+
/*!
Reimplemented in subclasses to show the surface
if \a visible is \c true, and hide it if \a visible is \c false.
diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h
index 72f63ebcef..8166344246 100644
--- a/src/gui/kernel/qplatformwindow_qpa.h
+++ b/src/gui/kernel/qplatformwindow_qpa.h
@@ -44,6 +44,7 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/qrect.h>
+#include <QtCore/qmargins.h>
#include <QtCore/qstring.h>
#include <QtGui/qwindowdefs.h>
@@ -71,6 +72,8 @@ public:
virtual void setGeometry(const QRect &rect);
virtual QRect geometry() const;
+ virtual QMargins frameMargins() const;
+
virtual void setVisible(bool visible);
virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
virtual Qt::WindowState setWindowState(Qt::WindowState state);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 97e74c5652..9ba8af2d2d 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -396,6 +396,14 @@ QRect QWindow::geometry() const
return d->geometry;
}
+QMargins QWindow::frameMargins() const
+{
+ Q_D(const QWindow);
+ if (d->platformWindow)
+ return d->platformWindow->frameMargins();
+ return QMargins();
+}
+
void QWindow::setWindowIcon(const QImage &icon) const
{
Q_UNUSED(icon);
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 4356153683..7910c3884c 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -44,6 +44,7 @@
#include <QtCore/QObject>
#include <QtCore/QEvent>
+#include <QtCore/QMargins>
#include <QtGui/qguiglformat_qpa.h>
#include <QtGui/qwindowdefs.h>
@@ -138,6 +139,8 @@ public:
void setGeometry(const QRect &rect);
QRect geometry() const;
+ QMargins frameMargins() const;
+
void setWindowIcon(const QImage &icon) const;
void destroy();
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 86a8c75878..d635ee8bcb 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -113,6 +113,7 @@ void QXcbWindow::create()
m_windowState = Qt::WindowNoState;
m_hasReceivedSyncRequest = false;
+ m_dirtyFrameMargins = true;
Qt::WindowType type = window()->windowType();
@@ -304,6 +305,93 @@ void QXcbWindow::setGeometry(const QRect &rect)
Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
}
+QMargins QXcbWindow::frameMargins() const
+{
+ if (m_dirtyFrameMargins) {
+ xcb_window_t window = m_window;
+ xcb_window_t parent = m_window;
+
+ bool foundRoot = false;
+
+ const QVector<xcb_window_t> &virtualRoots =
+ connection()->wmSupport()->virtualRoots();
+
+ while (!foundRoot) {
+ xcb_query_tree_cookie_t cookie = xcb_query_tree(xcb_connection(), parent);
+
+ xcb_generic_error_t *error;
+ xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, &error);
+ if (reply) {
+ if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1) {
+ foundRoot = true;
+ } else {
+ window = parent;
+ parent = reply->parent;
+ }
+
+ free(reply);
+ } else {
+ if (error) {
+ connection()->handleXcbError(error);
+ free(error);
+ }
+
+ m_dirtyFrameMargins = false;
+ m_frameMargins = QMargins();
+ return m_frameMargins;
+ }
+ }
+
+ QPoint offset;
+
+ xcb_generic_error_t *error;
+ xcb_translate_coordinates_reply_t *reply =
+ xcb_translate_coordinates_reply(
+ xcb_connection(),
+ xcb_translate_coordinates(xcb_connection(), window, parent, 0, 0),
+ &error);
+
+ if (reply) {
+ offset = QPoint(reply->dst_x, reply->dst_y);
+ free(reply);
+ } else if (error) {
+ free(error);
+ }
+
+ xcb_get_geometry_reply_t *geom =
+ xcb_get_geometry_reply(
+ xcb_connection(),
+ xcb_get_geometry(xcb_connection(), parent),
+ &error);
+
+ if (geom) {
+ // --
+ // add the border_width for the window managers frame... some window managers
+ // do not use a border_width of zero for their frames, and if we the left and
+ // top strut, we ensure that pos() is absolutely correct. frameGeometry()
+ // will still be incorrect though... perhaps i should have foffset as well, to
+ // indicate the frame offset (equal to the border_width on X).
+ // - Brad
+ // -- copied from qwidget_x11.cpp
+
+ int left = offset.x() + geom->border_width;
+ int top = offset.y() + geom->border_width;
+ int right = geom->width + geom->border_width - geometry().width() - offset.x();
+ int bottom = geom->height + geom->border_width - geometry().height() - offset.y();
+
+ m_frameMargins = QMargins(left, top, right, bottom);
+
+ free(geom);
+ } else if (error) {
+ free(error);
+ }
+
+ m_dirtyFrameMargins = false;
+ }
+
+ return m_frameMargins;
+}
+
void QXcbWindow::setVisible(bool visible)
{
if (visible)
@@ -327,6 +415,8 @@ void QXcbWindow::show()
free(error);
}
+ m_dirtyFrameMargins = true;
+
if (window()->windowState() & Qt::WindowMinimized)
xcb_wm_hints_set_iconic(&hints);
else
@@ -635,6 +725,8 @@ Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state)
if (state == m_windowState)
return state;
+ m_dirtyFrameMargins = true;
+
// unset old state
switch (m_windowState) {
case Qt::WindowMinimized:
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index f50a611b4e..501e9a33c4 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -61,6 +61,8 @@ public:
void setGeometry(const QRect &rect);
+ QMargins frameMargins() const;
+
void setVisible(bool visible);
Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
Qt::WindowState setWindowState(Qt::WindowState state);
@@ -139,6 +141,9 @@ private:
bool m_mapped;
xcb_window_t m_netWmUserTimeWindow;
+
+ mutable bool m_dirtyFrameMargins;
+ mutable QMargins m_frameMargins;
};
#endif
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index 3363ad7454..caaa065b64 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -641,24 +641,41 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
QPoint oldPos = q->pos();
data.crect = r;
+ bool needsShow = false;
+
+ if (w == 0 || h == 0) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ hide_sys();
+ data.crect = QRect(x, y, w, h);
+ } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+ needsShow = true;
+ }
+
if (q->isVisible()) {
- if (q->windowHandle()) {
- if (q->isWindow()) {
- q->windowHandle()->setGeometry(q->geometry());
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
+ if (q->windowHandle()) {
+ if (q->isWindow()) {
+ q->windowHandle()->setGeometry(q->geometry());
+ } else {
+ QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
+ q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size()));
+ }
+ const QWidgetBackingStore *bs = maybeBackingStore();
+ if (bs->windowSurface) {
+ if (isResize)
+ bs->windowSurface->resize(r.size());
+ }
+
+ if (needsShow)
+ show_sys();
} else {
- QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
- q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size()));
+ if (isMove && !isResize)
+ moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
+ else
+ invalidateBuffer_resizeHelper(oldPos, olds);
}
- const QWidgetBackingStore *bs = maybeBackingStore();
- if (bs->windowSurface) {
- if (isResize)
- bs->windowSurface->resize(r.size());
- }
- } else {
- if (isMove && !isResize)
- moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
- else
- invalidateBuffer_resizeHelper(oldPos, olds);
}
if (isMove) {
diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp
index 786293a716..27f9c9e2f8 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa.cpp
+++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp
@@ -266,9 +266,20 @@ void QWidgetWindow::handleKeyEvent(QKeyEvent *event)
QGuiApplication::sendSpontaneousEvent(widget, event);
}
+void QWidgetWindow::updateGeometry()
+{
+ if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
+ return;
+
+ QMargins margins = frameMargins();
+
+ m_widget->data->crect = geometry().translated(-margins.left(), -margins.top());
+ m_widget->d_func()->topData()->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
+}
+
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
- m_widget->data->crect = geometry();
+ updateGeometry();
QGuiApplication::sendSpontaneousEvent(m_widget, event);
}
@@ -276,7 +287,7 @@ void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
{
QSize oldSize = m_widget->data->crect.size();
- m_widget->data->crect = geometry();
+ updateGeometry();
QGuiApplication::sendSpontaneousEvent(m_widget, event);
if (m_widget->d_func()->paintOnScreen()) {
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h
index a217a969ca..f200839b0b 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa_p.h
+++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h
@@ -78,6 +78,8 @@ protected:
void handleExposeEvent(QExposeEvent *);
private:
+ void updateGeometry();
+
QWidget *m_widget;
QWeakPointer<QWidget> m_implicit_mouse_grabber;
QWeakPointer<QWidget> m_dragTarget;