From 25f70314e0e2aa5cb913aba108d2e9c16117004a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 16 May 2011 16:39:50 +0200 Subject: Implement QWindow minimum/maximum/base size hints and size increments. --- examples/qpa/windows/window.cpp | 8 ++- src/gui/kernel/qplatformwindow_qpa.cpp | 8 +++ src/gui/kernel/qplatformwindow_qpa.h | 2 + src/gui/kernel/qwindow.cpp | 76 ++++++++++++++++++++++++---- src/gui/kernel/qwindow.h | 11 ++++- src/gui/kernel/qwindow_p.h | 10 +++- src/plugins/platforms/xcb/qxcbwindow.cpp | 85 +++++++++++++++++++++++++------- src/plugins/platforms/xcb/qxcbwindow.h | 4 ++ src/widgets/kernel/qwidget_qpa.cpp | 17 +++++++ 9 files changed, 189 insertions(+), 32 deletions(-) diff --git a/examples/qpa/windows/window.cpp b/examples/qpa/windows/window.cpp index d08db5714b..76bc117793 100644 --- a/examples/qpa/windows/window.cpp +++ b/examples/qpa/windows/window.cpp @@ -23,9 +23,15 @@ Window::Window(QWindow *parent) if (parent) setGeometry(QRect(160, 120, 320, 240)); - else + else { setGeometry(QRect(10, 10, 640, 480)); + setSizeIncrement(QSize(10, 10)); + setBaseSize(QSize(640, 480)); + setMinimumSize(QSize(240, 160)); + setMaximumSize(QSize(800, 600)); + } + create(); QGuiApplicationPrivate::platformIntegration()->createWindowSurface(this, winId()); diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp index d7d1d96f42..afbff2ad5d 100644 --- a/src/gui/kernel/qplatformwindow_qpa.cpp +++ b/src/gui/kernel/qplatformwindow_qpa.cpp @@ -160,6 +160,14 @@ void QPlatformWindow::raise() { qWarning("This plugin does not support raise()") */ void QPlatformWindow::lower() { qWarning("This plugin does not support lower()"); } +/*! + Reimplement to propagate the size hints of the QWindow. + + The size hints include QWindow::minimumSize(), QWindow::maximumSize(), + QWindow::sizeIncrement(), and QWindow::baseSize(). +*/ +void QPlatformWindow::propagateSizeHints() {qWarning("This plugin does not support propagateSizeHints()"); } + /*! Reimplement to be able to let Qt set the opacity level of a window */ diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h index c74e96695d..de3174bde9 100644 --- a/src/gui/kernel/qplatformwindow_qpa.h +++ b/src/gui/kernel/qplatformwindow_qpa.h @@ -80,6 +80,8 @@ public: virtual void raise(); virtual void lower(); + virtual void propagateSizeHints(); + virtual void setOpacity(qreal level); virtual void requestActivateWindow(); diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 897b370cf5..5d4fd763b8 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -143,6 +143,15 @@ void QWindow::setParent(QWindow *parent) d->parentWindow = parent; } +/*! + Returns whether the window is top level, i.e. parent-less. + */ +bool QWindow::isTopLevel() const +{ + Q_D(const QWindow); + return d->parentWindow == 0; +} + void QWindow::setWindowFormat(const QWindowFormat &format) { Q_D(QWindow); @@ -256,26 +265,68 @@ void QWindow::setWindowState(Qt::WindowState state) QSize QWindow::minimumSize() const { - qDebug() << "unimplemented:" << __FILE__ << __LINE__; - return QSize(); + Q_D(const QWindow); + return d->minimumSize; } QSize QWindow::maximumSize() const { - qDebug() << "unimplemented:" << __FILE__ << __LINE__; - return QSize(); + Q_D(const QWindow); + return d->maximumSize; } -void QWindow::setMinimumSize(const QSize &size) const +QSize QWindow::baseSize() const { - Q_UNUSED(size); - qDebug() << "unimplemented:" << __FILE__ << __LINE__; + Q_D(const QWindow); + return d->baseSize; } -void QWindow::setMaximumSize(const QSize &size) const +QSize QWindow::sizeIncrement() const { - Q_UNUSED(size); - qDebug() << "unimplemented:" << __FILE__ << __LINE__; + Q_D(const QWindow); + return d->sizeIncrement; +} + +void QWindow::setMinimumSize(const QSize &size) +{ + Q_D(QWindow); + QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX)); + if (d->minimumSize == adjustedSize) + return; + d->minimumSize = adjustedSize; + if (d->platformWindow && isTopLevel()) + d->platformWindow->propagateSizeHints(); +} + +void QWindow::setMaximumSize(const QSize &size) +{ + Q_D(QWindow); + QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX)); + if (d->maximumSize == adjustedSize) + return; + d->maximumSize = adjustedSize; + if (d->platformWindow && isTopLevel()) + d->platformWindow->propagateSizeHints(); +} + +void QWindow::setBaseSize(const QSize &size) +{ + Q_D(QWindow); + if (d->baseSize == size) + return; + d->baseSize = size; + if (d->platformWindow && isTopLevel()) + d->platformWindow->propagateSizeHints(); +} + +void QWindow::setSizeIncrement(const QSize &size) +{ + Q_D(QWindow); + if (d->sizeIncrement == size) + return; + d->sizeIncrement = size; + if (d->platformWindow && isTopLevel()) + d->platformWindow->propagateSizeHints(); } void QWindow::setGeometry(const QRect &rect) @@ -464,4 +515,9 @@ void QWindow::wheelEvent(QWheelEvent *) } #endif //QT_NO_WHEELEVENT +Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window) +{ + return window->d_func(); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index 70227106b1..e0a1871ea1 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -94,6 +94,8 @@ public: QWindow *parent() const; void setParent(QWindow *parent); + bool isTopLevel() const; + QWindow *topLevelWindow() const; void setWindowFormat(const QWindowFormat &format); @@ -116,9 +118,13 @@ public: QSize minimumSize() const; QSize maximumSize() const; + QSize baseSize() const; + QSize sizeIncrement() const; - void setMinimumSize(const QSize &size) const; - void setMaximumSize(const QSize &size) const; + void setMinimumSize(const QSize &size); + void setMaximumSize(const QSize &size); + void setBaseSize(const QSize &size); + void setSizeIncrement(const QSize &size); void setGeometry(const QRect &rect); QRect geometry() const; @@ -177,6 +183,7 @@ private: friend class QGuiApplication; friend class QGuiApplicationPrivate; friend class QWindowSurface; + friend Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window); }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index b6227741ba..215a18d27e 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -52,7 +52,9 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) -class QWindowPrivate : public QObjectPrivate +#define QWINDOWSIZE_MAX ((1<<24)-1) + +class Q_GUI_EXPORT QWindowPrivate : public QObjectPrivate { public: QWindowPrivate() @@ -65,6 +67,7 @@ public: , glContext(0) , surface(0) , windowState(Qt::WindowNoState) + , maximumSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX) { isWindow = true; } @@ -84,6 +87,11 @@ public: QWindowContext *glContext; QWindowSurface *surface; Qt::WindowState windowState; + + QSize minimumSize; + QSize maximumSize; + QSize baseSize; + QSize sizeIncrement; }; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index dd28d13eb5..709efb2bc6 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -52,6 +52,7 @@ #include #include +#include #include #include @@ -256,31 +257,49 @@ void QXcbWindow::setGeometry(const QRect &rect) void QXcbWindow::setVisible(bool visible) { - xcb_wm_hints_t hints; - if (visible) { - // TODO: QWindow::isMinimized() or similar + if (visible) + show(); + else + hide(); +} + +void QXcbWindow::show() +{ + if (window()->isTopLevel()) { + xcb_get_property_cookie_t cookie = xcb_get_wm_hints(xcb_connection(), m_window); + + xcb_wm_hints_t hints; + xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, 0); + if (window()->windowState() & Qt::WindowMinimized) xcb_wm_hints_set_iconic(&hints); else xcb_wm_hints_set_normal(&hints); + xcb_set_wm_hints(xcb_connection(), m_window, &hints); - Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); - connection()->sync(); - } else { - Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); - - // send synthetic UnmapNotify event according to icccm 4.1.4 - xcb_unmap_notify_event_t event; - event.response_type = XCB_UNMAP_NOTIFY; - event.sequence = 0; // does this matter? - event.event = m_screen->root(); - event.window = m_window; - event.from_configure = false; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(), - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); - xcb_flush(xcb_connection()); + propagateSizeHints(); } + + Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + connection()->sync(); +} + +void QXcbWindow::hide() +{ + Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); + + // send synthetic UnmapNotify event according to icccm 4.1.4 + xcb_unmap_notify_event_t event; + event.response_type = XCB_UNMAP_NOTIFY; + event.sequence = 0; // does this matter? + event.event = m_screen->root(); + event.window = m_window; + event.from_configure = false; + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + + xcb_flush(xcb_connection()); } struct QtMWMHints { @@ -577,6 +596,36 @@ void QXcbWindow::lower() Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); } +void QXcbWindow::propagateSizeHints() +{ + xcb_size_hints_t hints; + + QRect rect = geometry(); + + xcb_size_hints_set_position(&hints, true, rect.x(), rect.y()); + xcb_size_hints_set_size(&hints, true, rect.width(), rect.height()); + + QWindow *win = window(); + + QSize minimumSize = win->minimumSize(); + QSize maximumSize = win->maximumSize(); + QSize baseSize = win->baseSize(); + QSize sizeIncrement = win->sizeIncrement(); + + if (minimumSize.width() > 0 || minimumSize.height() > 0) + xcb_size_hints_set_min_size(&hints, minimumSize.width(), minimumSize.height()); + + if (maximumSize.width() < QWINDOWSIZE_MAX || maximumSize.height() < QWINDOWSIZE_MAX) + xcb_size_hints_set_max_size(&hints, maximumSize.width(), maximumSize.height()); + + if (sizeIncrement.width() > 0 || sizeIncrement.height() > 0) { + xcb_size_hints_set_base_size(&hints, baseSize.width(), baseSize.height()); + xcb_size_hints_set_resize_inc(&hints, sizeIncrement.width(), sizeIncrement.height()); + } + + xcb_set_wm_normal_hints(xcb_connection(), m_window, &hints); +} + void QXcbWindow::requestActivateWindow() { Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, XCB_TIME_CURRENT_TIME)); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 831c25bdfb..accb32b36e 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -69,6 +69,7 @@ public: void setWindowTitle(const QString &title); void raise(); void lower(); + void propagateSizeHints(); void requestActivateWindow(); @@ -96,6 +97,9 @@ private: void setNetWmWindowTypes(Qt::WindowFlags flags); void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0); + void show(); + void hide(); + QXcbScreen *m_screen; xcb_window_t m_window; diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index b7b502a35f..533cc0a47c 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -49,6 +49,7 @@ #include "QtWidgets/qdesktopwidget.h" #include "QtGui/qplatformwindow_qpa.h" #include "QtGui/qplatformglcontext_qpa.h" +#include "QtGui/private/qwindow_p.h" #include @@ -628,6 +629,22 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) void QWidgetPrivate::setConstraints_sys() { + Q_Q(QWidget); + if (extra && q->windowHandle()) { + QWindow *win = q->windowHandle(); + QWindowPrivate *winp = qt_window_private(win); + + winp->minimumSize = QSize(extra->minw, extra->minh); + winp->maximumSize = QSize(extra->maxw, extra->maxh); + + if (extra->topextra) { + winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh); + winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch); + } + + if (winp->platformWindow) + winp->platformWindow->propagateSizeHints(); + } } void QWidgetPrivate::scroll_sys(int dx, int dy) -- cgit v1.2.3