Reintroduce -geometry command line argument for X11/XCB.

Add parsing for the window geometry specification to
QGuiApplicationPrivate. Enable the argument under a different
name for the other platforms as well.

Task-number: QTBUG-27349
Change-Id: I973b2c69f5172f7d0bc983b8ba4b0d164649ef02
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Friedemann Kleint 2013-07-25 08:40:24 +02:00 committed by The Qt Project
parent 5ec0804583
commit d7e37537d4
3 changed files with 125 additions and 4 deletions

View File

@ -101,6 +101,8 @@
# include <QtCore/QLibraryInfo>
#endif // Q_OS_WIN && !Q_OS_WINCE
#include <ctype.h>
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT bool qt_is_gui_used = true;
@ -215,6 +217,106 @@ static inline bool isPopupWindow(const QWindow *w)
return (w->flags() & Qt::WindowType_Mask) == Qt::Popup;
}
// Geometry specification for top level windows following the convention of the
// -geometry command line arguments in X11 (see XParseGeometry).
struct QWindowGeometrySpecification
{
QWindowGeometrySpecification() : corner(Qt::TopLeftCorner), xOffset(-1), yOffset(-1), width(-1), height(-1) {}
static QWindowGeometrySpecification fromArgument(const QByteArray &a);
QRect apply(const QRect &windowGeometry, const QSize &windowMinimumSize, const QSize &windowMaximumSize, const QRect &availableGeometry) const;
inline QRect apply(const QRect &windowGeometry, const QWindow *window) const
{ return apply(windowGeometry, window->minimumSize(), window->maximumSize(), window->screen()->virtualGeometry()); }
Qt::Corner corner;
int xOffset;
int yOffset;
int width;
int height;
};
// Parse a token of a X11 geometry specification "200x100+10-20".
static inline int nextGeometryToken(const QByteArray &a, int &pos, char *op)
{
*op = 0;
const int size = a.size();
if (pos >= size)
return -1;
*op = a.at(pos);
if (*op == '+' || *op == '-' || *op == 'x')
pos++;
else if (isdigit(*op))
*op = 'x'; // If it starts with a digit, it is supposed to be a width specification.
else
return -1;
const int numberPos = pos;
for ( ; pos < size && isdigit(a.at(pos)); ++pos) ;
bool ok;
const int result = a.mid(numberPos, pos - numberPos).toInt(&ok);
return ok ? result : -1;
}
QWindowGeometrySpecification QWindowGeometrySpecification::fromArgument(const QByteArray &a)
{
QWindowGeometrySpecification result;
int pos = 0;
for (int i = 0; i < 4; ++i) {
char op;
const int value = nextGeometryToken(a, pos, &op);
if (value < 0)
break;
switch (op) {
case 'x':
(result.width >= 0 ? result.height : result.width) = value;
break;
case '+':
case '-':
if (result.xOffset >= 0) {
result.yOffset = value;
if (op == '-')
result.corner = result.corner == Qt::TopRightCorner ? Qt::BottomRightCorner : Qt::BottomLeftCorner;
} else {
result.xOffset = value;
if (op == '-')
result.corner = Qt::TopRightCorner;
}
}
}
return result;
}
QRect QWindowGeometrySpecification::apply(const QRect &windowGeometry, const QSize &windowMinimumSize, const QSize &windowMaximumSize, const QRect &availableGeometry) const
{
QRect result = windowGeometry;
if (width >= 0 || height >= 0) {
QSize size = windowGeometry.size();
if (width >= 0)
size.setWidth(qBound(windowMinimumSize.width(), width, windowMaximumSize.width()));
if (height >= 0)
size.setHeight(qBound(windowMinimumSize.height(), height, windowMaximumSize.height()));
result.setSize(size);
}
if (xOffset >= 0 || yOffset >= 0) {
QPoint topLeft = windowGeometry.topLeft();
if (xOffset >= 0) {
topLeft.setX(corner == Qt::TopLeftCorner || corner == Qt::BottomLeftCorner ?
xOffset :
qMax(availableGeometry.right() - result.width() - xOffset, availableGeometry.left()));
}
if (yOffset >= 0) {
topLeft.setY(corner == Qt::TopLeftCorner || corner == Qt::TopRightCorner ?
yOffset :
qMax(availableGeometry.bottom() - result.height() - yOffset, availableGeometry.top()));
}
result.moveTopLeft(topLeft);
}
return result;
}
static QWindowGeometrySpecification windowGeometrySpecification;
/*!
\class QGuiApplication
\brief The QGuiApplication class manages the GUI application's control
@ -910,6 +1012,9 @@ void QGuiApplicationPrivate::createPlatformIntegration()
} else if (arg == "-platform") {
if (++i < argc)
platformName = argv[i];
} else if (arg == "-qwindowgeometry" || (platformName == "xcb" && arg == "-geometry")) {
if (++i < argc)
windowGeometrySpecification = QWindowGeometrySpecification::fromArgument(argv[i]);
} else {
argv[j++] = argv[i];
}
@ -2398,6 +2503,11 @@ void QGuiApplication::setPalette(const QPalette &pal)
applicationResourceFlags |= ApplicationPaletteExplicitlySet;
}
QRect QGuiApplicationPrivate::applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window)
{
return windowGeometrySpecification.apply(windowGeometry, window);
}
/*!
Returns the default application font.

View File

@ -275,6 +275,8 @@ public:
// hook reimplemented in QApplication to apply the QStyle function on the QIcon
virtual QPixmap applyQIconStyleHelper(QIcon::Mode, const QPixmap &basePixmap) const { return basePixmap; }
static QRect applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window);
protected:
virtual void notifyThemeChanged();
#ifndef QT_NO_DRAGANDDROP

View File

@ -7268,10 +7268,19 @@ void QWidget::setVisible(bool visible)
create();
}
#if defined(Q_WS_X11)
if (windowType() == Qt::Window)
QApplicationPrivate::applyX11SpecificCommandLineArguments(this);
#endif
// Handling of the -qwindowgeometry, -geometry command line arguments
if (windowType() == Qt::Window && windowHandle()) {
static bool done = false;
if (!done) {
done = true;
const QRect oldGeometry = frameGeometry();
const QRect geometry = QGuiApplicationPrivate::applyWindowGeometrySpecification(oldGeometry, windowHandle());
if (oldGeometry.size() != geometry.size())
resize(geometry.size());
if (geometry.topLeft() != oldGeometry.topLeft())
move(geometry.topLeft());
} // done
}
bool wasResized = testAttribute(Qt::WA_Resized);
Qt::WindowStates initialWindowState = windowState();