/**************************************************************************** ** ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the Itemviews NG project on Trolltech Labs. ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 or 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 GNU ** General Public Licensing requirements will be met: ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and ** http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #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::CreateWindowRequest, 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::DestroyWindowRequest, 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::UpdateWindowRequest, 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); qDebug() << "WINDOW: geometry" << geometry(); // 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()); // detach m_shared.setKey(QString::number(m_id)); 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(); Q_ASSERT(m_shared.data()); } Request request(Request::SetWindowGeometryRequest, m_id, 0, 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::setVisible(bool visible) { qDebug() << "WINDOW: setVisible()" << visible; Request request(visible ? Request::ShowWindowRequest : Request::HideWindowRequest, m_id); m_system->sendRequest(request); } Qt::WindowFlags QDevDaysWindowSurface::setWindowFlags(Qt::WindowFlags type) { return window_flags = type; } Qt::WindowFlags QDevDaysWindowSurface::windowFlags() const { return window_flags; } void QDevDaysWindowSurface::raise() { qDebug() << "WINDOW: raise()"; Request request(Request::RaiseWindowRequest, m_id); m_system->sendRequest(request); } void QDevDaysWindowSurface::lower() { qDebug() << "WINDOW: lower()"; Request request(Request::LowerWindowRequest, m_id); m_system->sendRequest(request); } // // 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; switch (m_message.message) { case Event::EventMessage: { QDevDaysWindowSurface *surface = m_surfaces.value(m_message.id); QWidget *window = surface ? surface->window() : 0; qDebug() << "SYSTEM: received event" << m_message.type << window; switch (m_message.type) { case Event::GeometryChangeEvent: { QWindowSystemInterface::handleGeometryChange(window, m_message.rect.toRect()); break; } case Event::MouseMoveEvent: case Event::MousePressEvent: { // ### we don't support multiple buttons or any keyboard modifiers // ### and we don't support mouse tracking QPoint pos = m_message.rect.topLeft().toPoint(); qDebug() << "=====> Mouse press/move event" << pos << window; Qt::MouseButtons b = Qt::LeftButton; QWindowSystemInterface::handleMouseEvent(window, pos, pos+window->pos(), b); break; } case Event::MouseReleaseEvent: { // ### we don't support multiple buttons or any keyboard modifiers QPoint pos = m_message.rect.topLeft().toPoint(); qDebug() << "======> Mouse release event" << pos << window; Qt::MouseButtons b = Qt::NoButton; QWindowSystemInterface::handleMouseEvent(window, pos, pos + window->pos(), b); break; } case Event::KeyPressEvent: { QString s; if ( m_message.rect.x()) s = QChar(int(m_message.rect.x())); Qt::KeyboardModifiers mods = static_cast(m_message.rect.y()); QWindowSystemInterface::handleKeyEvent(window, QEvent::KeyPress, m_message.value, mods, s); break; } case Event::KeyReleaseEvent: { Qt::KeyboardModifiers mods = static_cast(m_message.rect.y()); QWindowSystemInterface::handleKeyEvent(window, QEvent::KeyRelease, m_message.value, mods); break; } } break; } case Response::ResponseMessage: case Request::RequestMessage: default: qDebug() << "SYSTEM: received wrong message type" << m_message.type << m_message.id; break; } //if (!m_connection.isValid()) // handleConnectionError(); } } QT_END_NAMESPACE