/**************************************************************************** ** ** Copyright (C) 2013 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 "qvncintegration.h" #include "../fb_base/fb_base.h" #include #include #include #include #include #include #include "qgenericunixfontdatabase.h" QVNCScreen::QVNCScreen(QRect screenSize, int screenId) : QFbScreen::QFbScreen() { setGeometry(screenSize); setDepth(32); setFormat(QImage::Format_RGB32); setPhysicalSize((geometry().size()*254)/720); d_ptr = new QVNCScreenPrivate(this, screenId); cursor = new QVNCCursor(d_ptr->vncServer, this); d_ptr->vncServer->setCursor(static_cast(cursor)); } QVNCDirtyMap *QVNCScreen::dirtyMap() { return d_ptr->dirty; } QRegion QVNCScreen::doRedraw() { QRegion touched; touched = QFbScreen::doRedraw(); QVector rects = touched.rects(); for (int i = 0; i < rects.size(); i++) d_ptr->setDirty(rects[i]); return touched; } static inline int defaultWidth() { return 800; } static inline int defaultHeight() { return 600; } static inline int defaultDisplay() { return 0; } static void usage() { qWarning() << "VNC Platform Integration options:"; qWarning() << " size=x - set the display width and height"; qWarning() << " defaults to" << defaultWidth() << "x" << defaultHeight(); qWarning() << " display= - set the VNC display port to ID + 5900"; qWarning() << " defaults to" << defaultDisplay(); qWarning() << " offset=x - set the current screens offset"; qWarning() << " vnc - start configuration of a new screen"; qWarning() << " size and offset are inherited from the previous screen if not set"; qWarning() << " display id is incremented from the previous screen if not set"; qWarning() << " virtual - manage the set of screens as a virtual desktop"; } QVNCIntegration::QVNCIntegration(const QStringList& paramList) : virtualDesktop(false), fontDb(new QGenericUnixFontDatabase()) { int sizeX = defaultWidth(); int sizeY = defaultHeight(); int offsetX = 0; int offsetY = 0; int display = defaultDisplay(); bool showUsage = false; foreach(QString confString, paramList) { if (confString.startsWith(QLatin1String("size="))) { QString val = confString.section(QLatin1Char('='), 1, 1); sizeX = val.section(QLatin1Char('x'), 0, 0).toInt(); sizeY = val.section(QLatin1Char('x'), 1, 1).toInt(); } else if (confString.startsWith(QLatin1String("display="))) { display = confString.section(QLatin1Char('='), 1, 1).toInt(); } else if (confString.startsWith(QLatin1String("offset="))) { QString val = confString.section(QLatin1Char('='), 1, 1); offsetX = val.section(QLatin1Char('x'), 0, 0).toInt(); offsetY = val.section(QLatin1Char('x'), 1, 1).toInt(); } else if (confString == QLatin1String("vnc")) { QRect screenRect(offsetX, offsetY, sizeX, sizeY); QVNCScreen *screen = new QVNCScreen(screenRect, display); mScreens.append(screen); screen->setObjectName(QString("screen %1").arg(display)); screen->setDirty(screenRect); ++display; } else if (confString == QLatin1String("virtual")) { virtualDesktop = true; } else { qWarning() << "Unknown VNC option:" << confString; showUsage = true; } } if (showUsage) usage(); QRect screenRect(offsetX, offsetY, sizeX, sizeY); QVNCScreen *screen = new QVNCScreen(screenRect, display); mScreens.append(screen); mPrimaryScreen = qobject_cast(mScreens.first()); screen->setObjectName(QString("screen %1").arg(display)); screen->setDirty(screenRect); } bool QVNCIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { case ThreadedPixmaps: return true; default: return QPlatformIntegration::hasCapability(cap); } } QPixmapData *QVNCIntegration::createPixmapData(QPixmapData::PixelType type) const { return new QRasterPixmapData(type); } QWindowSurface *QVNCIntegration::createWindowSurface(QWidget *widget, WId) const { QFbWindowSurface * surface; surface = new QFbWindowSurface(mPrimaryScreen, widget); return surface; } QPlatformWindow *QVNCIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const { QFbWindow *w = new QFbWindow(widget); if (virtualDesktop) { QList::const_iterator i = mScreens.constBegin(); QList::const_iterator end = mScreens.constEnd(); QFbScreen *screen; while (i != end) { screen = static_cast(*i); screen->addWindow(w); ++i; } } else mPrimaryScreen->addWindow(w); return w; } QPixmap QVNCIntegration::grabWindow(WId window, int x, int y, int width, int height) const { // qDebug() << "QVNCIntegration::grabWindow" << window << x << y << width << height; if (window == 0) { //desktop QImage *desktopImage = mPrimaryScreen->image(); if (x==0 && y == 0 && width < 0 && height < 0) { return QPixmap::fromImage(*desktopImage); } if (width < 0) width = desktopImage->width() - x; if (height < 0) height = desktopImage->height() - y; int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp QImage img(desktopImage->scanLine(y) + bytesPerPixel*x, width, height, desktopImage->bytesPerLine(), desktopImage->format()); return QPixmap::fromImage(img); } QWidget *win = QWidget::find(window); if (win) { QRect r = win->geometry(); if (width < 0) width = r.width() - x; if (height < 0) height = r.height() - y; QImage *desktopImage = mPrimaryScreen->image(); int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp QImage img(desktopImage->scanLine(r.top() + y) + bytesPerPixel*(r.left()+x), width, height, desktopImage->bytesPerLine(), desktopImage->format()); return QPixmap::fromImage(img); } return QPixmap(); } void QVNCIntegration::moveToScreen(QWidget *window, int screen) { if (virtualDesktop) { // all windows exist on all screens in virtual desktop mode return; } if (screen < 0 || screen > mScreens.size()) return; QVNCScreen * newScreen = qobject_cast(mScreens.at(screen)); for(int i = 0; i < mScreens.size(); i++) { QVNCScreen *oldScreen = qobject_cast(mScreens.at(i)); if (oldScreen->windowStack.contains(static_cast(window->platformWindow()))) { oldScreen->removeWindow(static_cast(window->platformWindow())); break; } } window->platformWindow()->setGeometry(window->geometry()); // this should be unified elsewhere newScreen->addWindow(static_cast(window->platformWindow())); } QPlatformFontDatabase *QVNCIntegration::fontDatabase() const { return fontDb; }