Implement QWindow minimum/maximum/base size hints and size increments.

This commit is contained in:
Samuel Rødal 2011-05-16 16:39:50 +02:00
parent 276d60a4d6
commit 25f70314e0
9 changed files with 189 additions and 32 deletions

View File

@ -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());

View File

@ -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
*/

View File

@ -80,6 +80,8 @@ public:
virtual void raise();
virtual void lower();
virtual void propagateSizeHints();
virtual void setOpacity(qreal level);
virtual void requestActivateWindow();

View File

@ -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

View File

@ -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

View File

@ -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;
};

View File

@ -52,6 +52,7 @@
#include <xcb/xcb_icccm.h>
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
#include <private/qwindowsurface_p.h>
#include <QtGui/QWindowSystemInterface>
@ -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));

View File

@ -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;

View File

@ -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 <QtGui/QPlatformCursor>
@ -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)