Offscreen testing platform plugin

Useful for running auto-tests without popping up a bunch of windows in
the windowing system. Thus they can be run in the background and even in
parallel without focus issues.

Change-Id: I8b14c6de258b41225480a0af5a2a9553663bc2b7
Reviewed-by: Jason McDonald <macadder1@gmail.com>
This commit is contained in:
Samuel Rødal 2012-12-05 14:27:41 +01:00 committed by The Qt Project
parent 00ad768f10
commit d78bd439dc
15 changed files with 1384 additions and 3 deletions

View File

@ -1070,6 +1070,8 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
delete platform_integration;
platform_integration = 0;
delete m_gammaTables.load();
window_list.clear();
}
#if 0

View File

@ -196,7 +196,13 @@ bool QPlatformWindow::isEmbedded(const QPlatformWindow *parentWindow) const
*/
QPoint QPlatformWindow::mapToGlobal(const QPoint &pos) const
{
return pos;
const QPlatformWindow *p = this;
QPoint result = pos;
while (p) {
result += p->geometry().topLeft();
p = p->parent();
}
return result;
}
/*!
@ -208,7 +214,13 @@ QPoint QPlatformWindow::mapToGlobal(const QPoint &pos) const
*/
QPoint QPlatformWindow::mapFromGlobal(const QPoint &pos) const
{
return pos;
const QPlatformWindow *p = this;
QPoint result = pos;
while (p) {
result -= p->geometry().topLeft();
p = p->parent();
}
return result;
}
/*!

View File

@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qpa/qplatformintegrationplugin.h>
#include "qoffscreenintegration.h"
QT_BEGIN_NAMESPACE
class QOffscreenIntegrationPlugin : public QPlatformIntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE "offscreen.json")
public:
QPlatformIntegration *create(const QString&, const QStringList&);
};
QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, const QStringList& paramList)
{
Q_UNUSED(paramList);
if (system.toLower() == "offscreen")
return QOffscreenIntegration::createOffscreenIntegration();
return 0;
}
QT_END_NAMESPACE
#include "main.moc"

View File

@ -0,0 +1,3 @@
{
"Keys": [ "offscreen" ]
}

View File

@ -0,0 +1,25 @@
TARGET = qoffscreen
PLUGIN_TYPE = platforms
load(qt_plugin)
QT += core-private gui-private platformsupport-private
SOURCES = main.cpp \
qoffscreenintegration.cpp \
qoffscreenwindow.cpp \
qoffscreencommon.cpp
HEADERS = qoffscreenintegration.h \
qoffscreenwindow.h \
qoffscreencommon.h
OTHER_FILES += offscreen.json
contains(QT_CONFIG, xcb):contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles2) {
SOURCES += qoffscreenintegration_x11.cpp
HEADERS += qoffscreenintegration_x11.h
system(echo "Using X11 offscreen integration with GLX")
} else {
SOURCES += qoffscreenintegration_dummy.cpp
}

View File

@ -0,0 +1,229 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qoffscreencommon.h"
#include "qoffscreenwindow.h"
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformcursor.h>
#include <qpa/qplatformwindow.h>
QT_BEGIN_NAMESPACE
QPlatformWindow *QOffscreenScreen::windowContainingCursor = 0;
class QOffscreenCursor : public QPlatformCursor
{
public:
QOffscreenCursor() : m_pos(10, 10) {}
QPoint pos() const { return m_pos; }
void setPos(const QPoint &pos)
{
m_pos = pos;
QWindowList wl = QGuiApplication::topLevelWindows();
QWindow *containing = 0;
foreach (QWindow *w, wl) {
if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(pos)) {
containing = w;
break;
}
}
QPoint local = pos;
if (containing)
local -= containing->position();
QWindow *previous = QOffscreenScreen::windowContainingCursor ? QOffscreenScreen::windowContainingCursor->window() : 0;
if (containing != previous)
QWindowSystemInterface::handleEnterLeaveEvent(containing, previous, local, pos);
QWindowSystemInterface::handleMouseEvent(containing, local, pos, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
QOffscreenScreen::windowContainingCursor = containing ? containing->handle() : 0;
}
void changeCursor(QCursor *windowCursor, QWindow *window)
{
Q_UNUSED(windowCursor);
Q_UNUSED(window);
}
private:
QPoint m_pos;
};
QOffscreenScreen::QOffscreenScreen()
: m_geometry(0, 0, 800, 600)
, m_cursor(new QOffscreenCursor)
{
}
QPixmap QOffscreenScreen::grabWindow(WId id, int x, int y, int width, int height) const
{
QRect rect(x, y, width, height);
QOffscreenWindow *window = QOffscreenWindow::windowForWinId(id);
if (!window || window->window()->type() == Qt::Desktop) {
QWindowList wl = QGuiApplication::topLevelWindows();
QWindow *containing = 0;
foreach (QWindow *w, wl) {
if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(rect)) {
containing = w;
break;
}
}
if (!containing)
return QPixmap();
id = containing->winId();
rect = rect.translated(-containing->geometry().topLeft());
}
QOffscreenBackingStore *store = QOffscreenBackingStore::backingStoreForWinId(id);
if (store)
return store->grabWindow(id, rect);
return QPixmap();
}
QOffscreenBackingStore::QOffscreenBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
}
QOffscreenBackingStore::~QOffscreenBackingStore()
{
clearHash();
}
QPaintDevice *QOffscreenBackingStore::paintDevice()
{
return &m_image;
}
void QOffscreenBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(region);
if (m_image.size().isEmpty())
return;
QSize imageSize = m_image.size();
QRegion clipped = QRect(0, 0, window->width(), window->height());
clipped &= QRect(0, 0, imageSize.width(), imageSize.height()).translated(-offset);
QRect bounds = clipped.boundingRect().translated(offset);
if (bounds.isNull())
return;
WId id = window->winId();
m_windowAreaHash[id] = bounds;
m_backingStoreForWinIdHash[id] = this;
}
void QOffscreenBackingStore::resize(const QSize &size, const QRegion &)
{
QImage::Format format = QGuiApplication::primaryScreen()->handle()->format();
if (m_image.size() != size)
m_image = QImage(size, format);
clearHash();
}
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
bool QOffscreenBackingStore::scroll(const QRegion &area, int dx, int dy)
{
if (m_image.isNull())
return false;
const QVector<QRect> rects = area.rects();
for (int i = 0; i < rects.size(); ++i)
qt_scrollRectInImage(m_image, rects.at(i), QPoint(dx, dy));
return true;
}
QPixmap QOffscreenBackingStore::grabWindow(WId window, const QRect &rect) const
{
QRect area = m_windowAreaHash.value(window, QRect());
if (area.isNull())
return QPixmap();
QRect adjusted = rect;
if (adjusted.width() <= 0)
adjusted.setWidth(area.width());
if (adjusted.height() <= 0)
adjusted.setHeight(area.height());
adjusted = adjusted.translated(area.topLeft()) & area;
if (adjusted.isEmpty())
return QPixmap();
return QPixmap::fromImage(m_image.copy(adjusted));
}
QOffscreenBackingStore *QOffscreenBackingStore::backingStoreForWinId(WId id)
{
return m_backingStoreForWinIdHash.value(id, 0);
}
void QOffscreenBackingStore::clearHash()
{
QList<WId> ids = m_windowAreaHash.keys();
foreach (WId id, ids) {
QHash<WId, QOffscreenBackingStore *>::iterator it = m_backingStoreForWinIdHash.find(id);
if (it.value() == this)
m_backingStoreForWinIdHash.remove(id);
}
m_windowAreaHash.clear();
}
QHash<WId, QOffscreenBackingStore *> QOffscreenBackingStore::m_backingStoreForWinIdHash;
QT_END_NAMESPACE

View File

@ -0,0 +1,109 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOFFSCREENCOMMON_H
#define QOFFSCREENCOMMON_H
#include <qpa/qplatformbackingstore.h>
#include <qpa/qplatformdrag.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformwindow.h>
#include <qscopedpointer.h>
#include <qimage.h>
#include <qhash.h>
QT_BEGIN_NAMESPACE
class QOffscreenScreen : public QPlatformScreen
{
public:
QOffscreenScreen();
QRect geometry() const { return m_geometry; }
int depth() const { return 32; }
QImage::Format format() const { return QImage::Format_RGB32; }
QPlatformCursor *cursor() const { return m_cursor.data(); }
QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
static QPlatformWindow *windowContainingCursor;
public:
QRect m_geometry;
QScopedPointer<QPlatformCursor> m_cursor;
};
class QOffscreenDrag : public QPlatformDrag
{
public:
QMimeData *platformDropData() { return 0; }
Qt::DropAction drag(QDrag *) { return Qt::IgnoreAction; }
};
class QOffscreenBackingStore : public QPlatformBackingStore
{
public:
QOffscreenBackingStore(QWindow *window);
~QOffscreenBackingStore();
QPaintDevice *paintDevice();
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
void resize(const QSize &size, const QRegion &staticContents);
bool scroll(const QRegion &area, int dx, int dy);
QPixmap grabWindow(WId window, const QRect &rect) const;
static QOffscreenBackingStore *backingStoreForWinId(WId id);
private:
void clearHash();
QImage m_image;
QHash<WId, QRect> m_windowAreaHash;
static QHash<WId, QOffscreenBackingStore *> m_backingStoreForWinIdHash;
};
QT_END_NAMESPACE
#endif

View File

@ -0,0 +1,162 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qoffscreenintegration.h"
#include "qoffscreenwindow.h"
#include "qoffscreencommon.h"
#if defined(Q_OS_UNIX)
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#if defined(Q_OS_MAC)
#include <qpa/qplatformfontdatabase.h>
#else
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
#endif
#elif defined(Q_OS_WIN)
#include <QtPlatformSupport/private/qbasicfontdatabase_p.h>
#include <QtCore/private/qeventdispatcher_win_p.h>
#endif
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformservices.h>
QT_BEGIN_NAMESPACE
template <typename BaseEventDispatcher>
class QOffscreenEventDispatcher : public BaseEventDispatcher
{
public:
explicit QOffscreenEventDispatcher(QObject *parent = 0)
: BaseEventDispatcher(parent)
{
}
bool processEvents(QEventLoop::ProcessEventsFlags flags)
{
bool didSendEvents = QWindowSystemInterface::sendWindowSystemEvents(flags);
return BaseEventDispatcher::processEvents(flags) || didSendEvents;
}
bool hasPendingEvents()
{
return BaseEventDispatcher::hasPendingEvents()
|| QWindowSystemInterface::windowSystemEventsQueued();
}
void flush()
{
if (qApp)
qApp->sendPostedEvents();
BaseEventDispatcher::flush();
}
};
QOffscreenIntegration::QOffscreenIntegration()
{
#if defined(Q_OS_UNIX)
m_eventDispatcher = createUnixEventDispatcher();
#if defined(Q_OS_MAC)
m_fontDatabase.reset(new QPlatformFontDatabase());
#else
m_fontDatabase.reset(new QGenericUnixFontDatabase());
#endif
#elif defined(Q_OS_WIN)
m_eventDispatcher = new QOffscreenEventDispatcher<QEventDispatcherWin32>();
m_fontDatabase.reset(new QBasicFontDatabase());
#endif
m_drag.reset(new QOffscreenDrag);
m_services.reset(new QPlatformServices);
QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher);
screenAdded(new QOffscreenScreen);
}
QOffscreenIntegration::~QOffscreenIntegration()
{
}
bool QOffscreenIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
case ThreadedPixmaps: return true;
case MultipleWindows: return true;
default: return QPlatformIntegration::hasCapability(cap);
}
}
QPlatformWindow *QOffscreenIntegration::createPlatformWindow(QWindow *window) const
{
Q_UNUSED(window);
QPlatformWindow *w = new QOffscreenWindow(window);
w->requestActivateWindow();
return w;
}
QPlatformBackingStore *QOffscreenIntegration::createPlatformBackingStore(QWindow *window) const
{
return new QOffscreenBackingStore(window);
}
QAbstractEventDispatcher *QOffscreenIntegration::guiThreadEventDispatcher() const
{
return m_eventDispatcher;
}
QPlatformFontDatabase *QOffscreenIntegration::fontDatabase() const
{
return m_fontDatabase.data();
}
QPlatformDrag *QOffscreenIntegration::drag() const
{
return m_drag.data();
}
QPlatformServices *QOffscreenIntegration::services() const
{
return m_services.data();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOFFSCREENINTEGRATION_H
#define QOFFSCREENINTEGRATION_H
#include <qpa/qplatformintegration.h>
#include <qscopedpointer.h>
QT_BEGIN_NAMESPACE
class QOffscreenBackendData;
class QOffscreenIntegration : public QPlatformIntegration
{
public:
QOffscreenIntegration();
~QOffscreenIntegration();
bool hasCapability(QPlatformIntegration::Capability cap) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
QPlatformDrag *drag() const;
QPlatformServices *services() const;
QPlatformFontDatabase *fontDatabase() const;
QAbstractEventDispatcher *guiThreadEventDispatcher() const;
static QOffscreenIntegration *createOffscreenIntegration();
private:
QAbstractEventDispatcher *m_eventDispatcher;
QScopedPointer<QPlatformFontDatabase> m_fontDatabase;
QScopedPointer<QPlatformDrag> m_drag;
QScopedPointer<QPlatformServices> m_services;
};
QT_END_NAMESPACE
#endif

View File

@ -0,0 +1,47 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qoffscreenintegration.h"
QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration()
{
return new QOffscreenIntegration;
}

View File

@ -0,0 +1,252 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qoffscreenintegration_x11.h"
#include <QByteArray>
#include <QOpenGLContext>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <QtPlatformSupport/private/qglxconvenience_p.h>
#include <qpa/qplatformsurface.h>
#include <qsurface.h>
QT_BEGIN_NAMESPACE
QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration()
{
return new QOffscreenX11Integration;
}
bool QOffscreenX11Integration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
case OpenGL: return true;
case ThreadedOpenGL: return true;
default: return QOffscreenIntegration::hasCapability(cap);
}
}
QPlatformOpenGLContext *QOffscreenX11Integration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
if (!m_connection)
m_connection.reset(new QOffscreenX11Connection);
return new QOffscreenX11GLXContext(m_connection->x11Info(), context);
}
QOffscreenX11Connection::QOffscreenX11Connection()
{
XInitThreads();
QByteArray displayName = qgetenv("DISPLAY");
Display *display = XOpenDisplay(displayName.constData());
m_display = display;
m_screenNumber = DefaultScreen(display);
}
QOffscreenX11Connection::~QOffscreenX11Connection()
{
XCloseDisplay((Display *)m_display);
}
class QOffscreenX11Info
{
public:
QOffscreenX11Info(QOffscreenX11Connection *connection)
: m_connection(connection)
{
}
Display *display() const {
return (Display *)m_connection->display();
}
Window root() const {
return DefaultRootWindow(display());
}
int screenNumber() const {
return m_connection->screenNumber();
}
private:
QOffscreenX11Connection *m_connection;
};
QOffscreenX11Info *QOffscreenX11Connection::x11Info()
{
if (!m_x11Info)
m_x11Info.reset(new QOffscreenX11Info(this));
return m_x11Info.data();
}
class QOffscreenX11GLXContextData
{
public:
QOffscreenX11Info *x11;
QSurfaceFormat format;
GLXContext context;
GLXContext shareContext;
Window window;
};
static Window createDummyWindow(QOffscreenX11Info *x11, XVisualInfo *visualInfo)
{
Colormap cmap = XCreateColormap(x11->display(), x11->root(), visualInfo->visual, AllocNone);
XSetWindowAttributes a;
a.background_pixel = WhitePixel(x11->display(), x11->screenNumber());
a.border_pixel = BlackPixel(x11->display(), x11->screenNumber());
a.colormap = cmap;
Window window = XCreateWindow(x11->display(), x11->root(),
0, 0, 100, 100,
0, visualInfo->depth, InputOutput, visualInfo->visual,
CWBackPixel|CWBorderPixel|CWColormap, &a);
XFreeColormap(x11->display(), cmap);
return window;
}
static Window createDummyWindow(QOffscreenX11Info *x11, GLXFBConfig config)
{
XVisualInfo *visualInfo = glXGetVisualFromFBConfig(x11->display(), config);
if (!visualInfo)
qFatal("Could not initialize GLX");
Window window = createDummyWindow(x11, visualInfo);
XFree(visualInfo);
return window;
}
QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context)
: d(new QOffscreenX11GLXContextData)
{
d->x11 = x11;
d->format = context->format();
d->shareContext = 0;
if (context->shareHandle())
d->shareContext = static_cast<QOffscreenX11GLXContext *>(context->shareHandle())->d->context;
GLXFBConfig config = qglx_findConfig(x11->display(), x11->screenNumber(), d->format);
if (config) {
d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, d->shareContext, true);
if (!d->context && d->shareContext) {
d->shareContext = 0;
// re-try without a shared glx context
d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, 0, true);
}
// Get the basic surface format details
if (d->context)
d->format = qglx_surfaceFormatFromGLXFBConfig(x11->display(), config, d->context);
// Create a temporary window so that we can make the new context current
d->window = createDummyWindow(x11, config);
} else {
XVisualInfo *visualInfo = qglx_findVisualInfo(x11->display(), 0, &d->format);
if (!visualInfo)
qFatal("Could not initialize GLX");
d->context = glXCreateContext(x11->display(), visualInfo, d->shareContext, true);
if (!d->context && d->shareContext) {
// re-try without a shared glx context
d->shareContext = 0;
d->context = glXCreateContext(x11->display(), visualInfo, 0, true);
}
d->window = createDummyWindow(x11, visualInfo);
XFree(visualInfo);
}
}
QOffscreenX11GLXContext::~QOffscreenX11GLXContext()
{
glXDestroyContext(d->x11->display(), d->context);
XDestroyWindow(d->x11->display(), d->window);
}
bool QOffscreenX11GLXContext::makeCurrent(QPlatformSurface *surface)
{
QSize size = surface->surface()->size();
XResizeWindow(d->x11->display(), d->window, size.width(), size.height());
XSync(d->x11->display(), true);
if (glXMakeCurrent(d->x11->display(), d->window, d->context)) {
glViewport(0, 0, size.width(), size.height());
return true;
}
return false;
}
void QOffscreenX11GLXContext::doneCurrent()
{
glXMakeCurrent(d->x11->display(), 0, 0);
}
void QOffscreenX11GLXContext::swapBuffers(QPlatformSurface *)
{
}
void (*QOffscreenX11GLXContext::getProcAddress(const QByteArray &procName)) ()
{
return (void (*)())glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.constData()));
}
QSurfaceFormat QOffscreenX11GLXContext::format() const
{
return d->format;
}
bool QOffscreenX11GLXContext::isSharing() const
{
return d->shareContext;
}
bool QOffscreenX11GLXContext::isValid() const
{
return d->context && d->window;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,108 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOFFSCREENINTEGRATION_X11_H
#define QOFFSCREENINTEGRATION_X11_H
#include "qoffscreenintegration.h"
#include <qglobal.h>
#include <qscopedpointer.h>
#include <qpa/qplatformopenglcontext.h>
QT_BEGIN_NAMESPACE
class QOffscreenX11Connection;
class QOffscreenX11Info;
class QOffscreenX11Integration : public QOffscreenIntegration
{
public:
bool hasCapability(QPlatformIntegration::Capability cap) const;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
private:
mutable QScopedPointer<QOffscreenX11Connection> m_connection;
};
class QOffscreenX11Connection {
public:
QOffscreenX11Connection();
~QOffscreenX11Connection();
QOffscreenX11Info *x11Info();
void *display() const { return m_display; }
int screenNumber() const { return m_screenNumber; }
private:
void *m_display;
int m_screenNumber;
QScopedPointer<QOffscreenX11Info> m_x11Info;
};
class QOffscreenX11GLXContextData;
class QOffscreenX11GLXContext : public QPlatformOpenGLContext
{
public:
QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context);
~QOffscreenX11GLXContext();
bool makeCurrent(QPlatformSurface *surface);
void doneCurrent();
void swapBuffers(QPlatformSurface *surface);
void (*getProcAddress(const QByteArray &procName)) ();
QSurfaceFormat format() const;
bool isSharing() const;
bool isValid() const;
private:
QScopedPointer<QOffscreenX11GLXContextData> d;
};
QT_END_NAMESPACE
#endif

View File

@ -0,0 +1,199 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qoffscreenwindow.h"
#include "qoffscreencommon.h"
#include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
#include <private/qwindow_p.h>
QT_BEGIN_NAMESPACE
QOffscreenWindow::QOffscreenWindow(QWindow *window)
: QPlatformWindow(window)
, m_positionIncludesFrame(false)
, m_visible(false)
, m_pendingGeometryChangeOnShow(true)
{
if (window->windowState() == Qt::WindowNoState)
setGeometry(window->geometry());
else
setWindowState(window->windowState());
QWindowSystemInterface::flushWindowSystemEvents();
static WId counter = 0;
m_winId = ++counter;
m_windowForWinIdHash[m_winId] = this;
}
QOffscreenWindow::~QOffscreenWindow()
{
if (QOffscreenScreen::windowContainingCursor == this)
QOffscreenScreen::windowContainingCursor = 0;
m_windowForWinIdHash.remove(m_winId);
}
void QOffscreenWindow::setGeometry(const QRect &rect)
{
if (window()->windowState() != Qt::WindowNoState)
return;
m_positionIncludesFrame = qt_window_private(window())->positionPolicy == QWindowPrivate::WindowFrameInclusive;
setFrameMarginsEnabled(true);
setGeometryImpl(rect);
m_normalGeometry = geometry();
}
void QOffscreenWindow::setGeometryImpl(const QRect &rect)
{
QRect adjusted = rect;
if (adjusted.width() <= 0)
adjusted.setWidth(1);
if (adjusted.height() <= 0)
adjusted.setHeight(1);
if (m_positionIncludesFrame) {
adjusted.translate(m_margins.left(), m_margins.top());
} else {
// make sure we're not placed off-screen
if (adjusted.left() < m_margins.left())
adjusted.translate(m_margins.left(), 0);
if (adjusted.top() < m_margins.top())
adjusted.translate(0, m_margins.top());
}
QPlatformWindow::setGeometry(adjusted);
if (m_visible) {
QWindowSystemInterface::handleGeometryChange(window(), adjusted);
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), adjusted.size()));
} else {
m_pendingGeometryChangeOnShow = true;
}
}
void QOffscreenWindow::setVisible(bool visible)
{
if (visible == m_visible)
return;
if (visible) {
if (window()->type() != Qt::ToolTip)
QWindowSystemInterface::handleWindowActivated(window());
if (m_pendingGeometryChangeOnShow) {
m_pendingGeometryChangeOnShow = false;
QWindowSystemInterface::handleGeometryChange(window(), geometry());
}
}
if (visible) {
QRect rect(QPoint(), geometry().size());
QWindowSystemInterface::handleExposeEvent(window(), rect);
} else {
QWindowSystemInterface::handleExposeEvent(window(), QRegion());
}
m_visible = visible;
}
void QOffscreenWindow::requestActivateWindow()
{
if (m_visible)
QWindowSystemInterface::handleWindowActivated(window());
}
WId QOffscreenWindow::winId() const
{
return m_winId;
}
QMargins QOffscreenWindow::frameMargins() const
{
return m_margins;
}
void QOffscreenWindow::setFrameMarginsEnabled(bool enabled)
{
if (enabled && !(window()->flags() & Qt::FramelessWindowHint))
m_margins = QMargins(2, 2, 2, 2);
else
m_margins = QMargins(0, 0, 0, 0);
}
void QOffscreenWindow::setWindowState(Qt::WindowState state)
{
setFrameMarginsEnabled(state != Qt::WindowFullScreen);
m_positionIncludesFrame = false;
switch (state) {
case Qt::WindowFullScreen:
setGeometryImpl(screen()->geometry());
break;
case Qt::WindowMaximized:
setGeometryImpl(screen()->availableGeometry().adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom()));
break;
case Qt::WindowMinimized:
break;
case Qt::WindowNoState:
setGeometryImpl(m_normalGeometry);
break;
default:
break;
}
QWindowSystemInterface::handleWindowStateChanged(window(), state);
}
QOffscreenWindow *QOffscreenWindow::windowForWinId(WId id)
{
return m_windowForWinIdHash.value(id, 0);
}
QHash<WId, QOffscreenWindow *> QOffscreenWindow::m_windowForWinIdHash;
QT_END_NAMESPACE

View File

@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOFFSCREENWINDOW_H
#define QOFFSCREENWINDOW_H
#include <qpa/qplatformbackingstore.h>
#include <qpa/qplatformwindow.h>
#include <qhash.h>
QT_BEGIN_NAMESPACE
class QOffscreenWindow : public QPlatformWindow
{
public:
QOffscreenWindow(QWindow *window);
~QOffscreenWindow();
void setGeometry(const QRect &rect);
void setWindowState(Qt::WindowState state);
QMargins frameMargins() const;
void setVisible(bool visible);
void requestActivateWindow();
WId winId() const;
static QOffscreenWindow *windowForWinId(WId id);
private:
void setFrameMarginsEnabled(bool enabled);
void setGeometryImpl(const QRect &rect);
QRect m_normalGeometry;
QMargins m_margins;
bool m_positionIncludesFrame;
bool m_visible;
bool m_pendingGeometryChangeOnShow;
WId m_winId;
static QHash<WId, QOffscreenWindow *> m_windowForWinIdHash;
};
QT_END_NAMESPACE
#endif

View File

@ -1,6 +1,6 @@
TEMPLATE = subdirs
SUBDIRS += minimal
SUBDIRS += minimal offscreen
contains(QT_CONFIG, xcb) {
SUBDIRS += xcb