From 6bd8a385d6497da9390a752df4ba4a56a3f7fd5e Mon Sep 17 00:00:00 2001 From: Marius Bugge Monsen Date: Tue, 15 Sep 2009 16:14:48 +0200 Subject: Initial commit of the Qt Developer Days Window System client implementation. --- devdays.pro | 10 ++ main.cpp | 70 +++++++++++++ qgraphicssystem_dd.cpp | 268 +++++++++++++++++++++++++++++++++++++++++++++++++ qgraphicssystem_dd.h | 127 +++++++++++++++++++++++ 4 files changed, 475 insertions(+) create mode 100644 devdays.pro create mode 100644 main.cpp create mode 100644 qgraphicssystem_dd.cpp create mode 100644 qgraphicssystem_dd.h diff --git a/devdays.pro b/devdays.pro new file mode 100644 index 0000000..6837a1b --- /dev/null +++ b/devdays.pro @@ -0,0 +1,10 @@ +TARGET = qdevdaysgraphicssystem +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_dd.cpp +HEADERS = qgraphicssystem_dd.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..72e9a88 --- /dev/null +++ b/main.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "qgraphicssystem_dd.h" + +QT_BEGIN_NAMESPACE + +class QDevDaysGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString &system); +}; + +QStringList QDevDaysGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "DevDays"; + return list; +} + +QGraphicsSystem* QDevDaysGraphicsSystemPlugin::create(const QString &system) +{ + if (system.toLower() == "devdays") + return new QDevDaysGraphicsSystem; + return 0; +} + +Q_EXPORT_PLUGIN2(devdays, QDevDaysGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/qgraphicssystem_dd.cpp b/qgraphicssystem_dd.cpp new file mode 100644 index 0000000..d175a45 --- /dev/null +++ b/qgraphicssystem_dd.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicssystem_dd.h" + +#include +#include + +#include +#include + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +// +// window surface +// + +QDevDaysWindowSurface::QDevDaysWindowSurface(QWidget *window, QDevDaysGraphicsSystem *system) + : QWindowSurface(window), m_system(system) +{ + quint32 parentId = system->m_ids.value(window->parentWidget(), 0); + + Request request(Request::CreateRequest, parentId); + system->sendRequest(request); + + Response response; + system->waitForResponse(response); + m_id = response.id; + + m_system->m_surfaces.insert(m_id, this); + m_system->m_ids.insert(window, m_id); +} + +QDevDaysWindowSurface::~QDevDaysWindowSurface() +{ + Request request(Request::DestroyRequest, m_id); + m_system->sendRequest(request); + m_system->m_surfaces.remove(m_id); + m_system->m_ids.remove(window()); +} + +QPaintDevice *QDevDaysWindowSurface::paintDevice() +{ + qDebug() << "WINDOW: paint device" << m_image.size(); + return &m_image; +} + +void QDevDaysWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + qDebug() << "WINDOW: flush"; + // send an update request to the server + Request request(Request::UpdateRequest, m_id); // ### rect + m_system->sendRequest(request); + // we don't expect any response +} + +void QDevDaysWindowSurface::setGeometry(const QRect &rect) +{ + qDebug() << "WINDOW: setGeometry"; + QWindowSurface::setGeometry(rect); + + // create or resize the shared memory + qint32 byteCount = rect.width() * rect.height() * sizeof(quint32); // ### server should hold the pixel format + qDebug() << "WINDOW: byte count" << byteCount; + if (byteCount > m_shared.size()) { + if (m_shared.key().isEmpty()) + m_shared.setKey(QString::number(m_id)); + else + m_shared.detach(); + if (!m_shared.create(byteCount) && !m_shared.attach()) + qWarning() << m_shared.errorString() << m_shared.key(); + qDebug() << "WINDOW: data" << m_shared.data() << "key" << m_shared.key(); + } + + Request request(Request::SetGeometryRequest, m_id, rect); + m_system->sendRequest(request); +} + +bool QDevDaysWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + // the server doesn't have scroll + return QWindowSurface::scroll(area, dx, dy); +} + +void QDevDaysWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); + qDebug() << "WINDOW: begin paint" << m_id << geometry(); + // lock the surface shared memory before painting + if (m_shared.lock() && m_shared.data()) + m_image = QImage((uchar*)m_shared.data(), geometry().width(), geometry().height(), m_system->screens().first()->format()); + else + qDebug() << m_shared.errorString(); + qDebug() << "WINDOW: image" << m_image.size() << "geometry" << geometry() << "data" << m_shared.data() << "key" << m_shared.key(); +} + +void QDevDaysWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); + qDebug() << "WINDOW: end paint"; + // unlock the surface shared memory after painting + // also make sure that the paint device is invalid + if (m_shared.unlock()) + m_image = QImage(); + else + qDebug() << "WINDOW: failed to unlock shared memory"; +} + +void QDevDaysWindowSurface::handleMouseEvent(const Event &event) +{ + QEvent::Type type = QEvent::None; + QPoint position = event.rect.topLeft().toPoint(); + switch (event.type) { + case Event::MousePressEvent: + type = QEvent::MouseButtonPress; + break; + case Event::MouseReleaseEvent: + type = QEvent::MouseButtonPress; + break; + default: + break; + } + QMouseEvent mouseEvent(type, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + QApplicationPrivate::handleMouseEvent(window(), mouseEvent); +} + +void QDevDaysWindowSurface::handleGeometryChanged(const Event &event) +{ + QApplicationPrivate::handleGeometryChange(window(), event.rect.toRect()); +} + +// +// graphics system +// + +QDevDaysGraphicsSystem::QDevDaysGraphicsSystem() + : QObject(0) +{ + qDebug() << "SYSTEM: constructor"; + connectToServer(); +} + +QPixmapData *QDevDaysGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ + qDebug() << "SYSTEM: create pixmap data"; + // the window system has no server-side pixmap type + return new QRasterPixmapData(type); +} + +QWindowSurface *QDevDaysGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + qDebug() << "SYSTEM: create window surface"; + // send create request to the server + Q_ASSERT(widget); + if (widget->windowType() == Qt::Desktop) + return 0; + return new QDevDaysWindowSurface(widget, const_cast(this)); +} + +QList QDevDaysGraphicsSystem::screens() const +{ + qDebug() << "SYSTEM: screens"; + return QList() << &m_screen; +} + +bool QDevDaysGraphicsSystem::connectToServer() +{ + qDebug() << "SYSTEM: connect to server"; + m_connection.connectToHost(QHostAddress::LocalHost, 2048); + if (m_connection.waitForConnected()) { + QObject::connect(&m_connection, SIGNAL(readyRead()), this, SLOT(eventDispatcher())); + QObject::connect(&m_connection, SIGNAL(disconnected()), QApplication::instance(), SLOT(quit())); + qDebug() << "SYSTEM: connected to server"; + return true; + } + qDebug() << "SYSTEM: unable to connect to server"; + return false; +} + +bool QDevDaysGraphicsSystem::sendRequest(const Request &request) +{ + qDebug() << "SYSTEM: sending request"; + QDataStream stream(&m_connection); + stream << (*static_cast(&request)); + return m_connection.isValid(); +} + +bool QDevDaysGraphicsSystem::waitForResponse(Response &response) +{ + qDebug() << "SYSTEM: waiting for response"; + if (m_connection.waitForReadyRead(-1)) { + if (m_message.message == Message::ResponseMessage) { + qDebug() << "SYSTEM: received response"; + response.type = m_message.type; + response.id = m_message.id; + response.rect = m_message.rect; + // clear internal message + m_message.message = Message::InvalidMessage; + return true; + } + } + //handleConnectionError(); + return false; +} + +void QDevDaysGraphicsSystem::eventDispatcher() +{ + qDebug() << "SYSTEM: event dispatcher"; + while (m_connection.bytesAvailable()) { + QDataStream in(&m_connection); + in >> m_message; + if (m_message.message == Event::EventMessage) { + qDebug() << "SYSTEM: received event" << m_message.type; + } else if (m_message.message == Response::ResponseMessage) { + qDebug() << "SYSTEM: received response" << m_message.type << m_message.id; + } + //if (!m_connection.isValid()) + // handleConnectionError(); + } +} + +QT_END_NAMESPACE diff --git a/qgraphicssystem_dd.h b/qgraphicssystem_dd.h new file mode 100644 index 0000000..6021d47 --- /dev/null +++ b/qgraphicssystem_dd.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_DD_H +#define QGRAPHICSSYSTEM_DD_H + +#include +#include +#include + +#include +#include "/Users/mmonsen/Development/depots/display-server-client/protocol.h" + +QT_BEGIN_NAMESPACE + +class QDevDaysGraphicsSystem; +class QDevDaysGraphicsSystemScreen; + +class QDevDaysWindowSurface : public QWindowSurface +{ +public: + QDevDaysWindowSurface(QWidget *window, QDevDaysGraphicsSystem *system); + ~QDevDaysWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void setGeometry(const QRect &rect); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + + // event handlers + void handleMouseEvent(const Event &event); + void handleGeometryChanged(const Event &event); + +private: + QDevDaysGraphicsSystem *m_system; + quint32 m_id; + QSharedMemory m_shared; + QImage m_image; +}; + +class QDevDaysGraphicsSystemScreen : public QGraphicsSystemScreen +{ +public: + QDevDaysGraphicsSystemScreen() {} + ~QDevDaysGraphicsSystemScreen() {} + + QRect geometry() const { return QRect(0, 0, 640, 480); } // size in pixels + int depth() const { return 32; } + QImage::Format format() const { return QImage::Format_ARGB32; } + QSize physicalSize() const { return QSize(80, 108); } // size in milimeters +}; + +class QDevDaysGraphicsSystem : public QObject, public QGraphicsSystem +{ + Q_OBJECT +public: + QDevDaysGraphicsSystem(); + + // QGraphicsSystem interface + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + QList screens() const; + + // client interface + bool connectToServer(); + bool sendRequest(const Request &request); + bool waitForResponse(Response &response); + +public slots: + void eventDispatcher(); + +private: + QTcpSocket m_connection; + Message m_message; + +public: + mutable QHash m_surfaces; + mutable QHash m_ids; + mutable QDevDaysGraphicsSystemScreen m_screen; + //mutable Client m_client; +}; + + +QT_END_NAMESPACE + +#endif -- cgit v1.2.3