summaryrefslogtreecommitdiffstats
path: root/src/gui/embedded/qscreenvfb_qws.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/embedded/qscreenvfb_qws.cpp')
-rw-r--r--src/gui/embedded/qscreenvfb_qws.cpp445
1 files changed, 445 insertions, 0 deletions
diff --git a/src/gui/embedded/qscreenvfb_qws.cpp b/src/gui/embedded/qscreenvfb_qws.cpp
new file mode 100644
index 0000000000..1c8829d500
--- /dev/null
+++ b/src/gui/embedded/qscreenvfb_qws.cpp
@@ -0,0 +1,445 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module 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 QT_NO_QWS_QVFB
+
+#define QTOPIA_QVFB_BRIGHTNESS
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <qvfbhdr.h>
+#include <qscreenvfb_qws.h>
+#include <qkbdvfb_qws.h>
+#include <qmousevfb_qws.h>
+#include <qwindowsystem_qws.h>
+#include <qsocketnotifier.h>
+#include <qapplication.h>
+#include <qscreen_qws.h>
+#include <qmousedriverfactory_qws.h>
+#include <qkbddriverfactory_qws.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVFbScreenPrivate
+{
+public:
+ QVFbScreenPrivate();
+ ~QVFbScreenPrivate();
+
+ bool success;
+ unsigned char *shmrgn;
+ int brightness;
+ bool blank;
+ QVFbHeader *hdr;
+ QWSMouseHandler *mouse;
+#ifndef QT_NO_QWS_KEYBOARD
+ QWSKeyboardHandler *keyboard;
+#endif
+};
+
+QVFbScreenPrivate::QVFbScreenPrivate()
+ : mouse(0)
+
+{
+#ifndef QT_NO_QWS_KEYBOARD
+ keyboard = 0;
+#endif
+ brightness = 255;
+ blank = false;
+}
+
+QVFbScreenPrivate::~QVFbScreenPrivate()
+{
+ delete mouse;
+#ifndef QT_NO_QWS_KEYBOARD
+ delete keyboard;
+#endif
+}
+
+/*!
+ \internal
+
+ \class QVFbScreen
+ \ingroup qws
+
+ \brief The QVFbScreen class implements a screen driver for the
+ virtual framebuffer.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+ Custom screen drivers can be added by subclassing the
+ QScreenDriverPlugin class, using the QScreenDriverFactory class to
+ dynamically load the driver into the application, but there should
+ only be one screen object per application.
+
+ The Qt for Embedded Linux platform provides a \l{The Virtual
+ Framebuffer}{virtual framebuffer} for development and debugging;
+ the virtual framebuffer allows Qt for Embedded Linux applications to be
+ developed on a desktop machine, without switching between consoles
+ and X11.
+
+ \sa QScreen, QScreenDriverPlugin, {Running Applications}
+*/
+
+/*!
+ \fn bool QVFbScreen::connect(const QString & displaySpec)
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::disconnect()
+ \reimp
+*/
+
+/*!
+ \fn bool QVFbScreen::initDevice()
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::restore()
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::save()
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::setDirty(const QRect & r)
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::setMode(int nw, int nh, int nd)
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::shutdownDevice()
+ \reimp
+*/
+
+/*!
+ \fn QVFbScreen::QVFbScreen(int displayId)
+
+ Constructs a QVNCScreen object. The \a displayId argument
+ identifies the Qt for Embedded Linux server to connect to.
+*/
+QVFbScreen::QVFbScreen(int display_id)
+ : QScreen(display_id, VFbClass), d_ptr(new QVFbScreenPrivate)
+{
+ d_ptr->shmrgn = 0;
+ d_ptr->hdr = 0;
+ data = 0;
+}
+
+/*!
+ Destroys this QVFbScreen object.
+*/
+QVFbScreen::~QVFbScreen()
+{
+ delete d_ptr;
+}
+
+static QVFbScreen *connected = 0;
+
+bool QVFbScreen::connect(const QString &displaySpec)
+{
+ QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
+ if (displayArgs.contains(QLatin1String("Gray")))
+ grayscale = true;
+
+ key_t key = ftok(QT_VFB_MOUSE_PIPE(displayId).toLocal8Bit(), 'b');
+
+ if (key == -1)
+ return false;
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
+ if (displayArgs.contains(QLatin1String("littleendian")))
+#endif
+ QScreen::setFrameBufferLittleEndian(true);
+#endif
+
+ int shmId = shmget(key, 0, 0);
+ if (shmId != -1)
+ d_ptr->shmrgn = (unsigned char *)shmat(shmId, 0, 0);
+ else
+ return false;
+
+ if ((long)d_ptr->shmrgn == -1 || d_ptr->shmrgn == 0) {
+ qDebug("No shmrgn %ld", (long)d_ptr->shmrgn);
+ return false;
+ }
+
+ d_ptr->hdr = (QVFbHeader *)d_ptr->shmrgn;
+ data = d_ptr->shmrgn + d_ptr->hdr->dataoffset;
+
+ dw = w = d_ptr->hdr->width;
+ dh = h = d_ptr->hdr->height;
+ d = d_ptr->hdr->depth;
+
+ switch (d) {
+ case 1:
+ setPixelFormat(QImage::Format_Mono);
+ break;
+ case 8:
+ setPixelFormat(QImage::Format_Indexed8);
+ break;
+ case 12:
+ setPixelFormat(QImage::Format_RGB444);
+ break;
+ case 15:
+ setPixelFormat(QImage::Format_RGB555);
+ break;
+ case 16:
+ setPixelFormat(QImage::Format_RGB16);
+ break;
+ case 18:
+ setPixelFormat(QImage::Format_RGB666);
+ break;
+ case 24:
+ setPixelFormat(QImage::Format_RGB888);
+ break;
+ case 32:
+ setPixelFormat(QImage::Format_ARGB32_Premultiplied);
+ break;
+ }
+
+ lstep = d_ptr->hdr->linestep;
+
+ // Handle display physical size spec.
+ int dimIdxW = -1;
+ int dimIdxH = -1;
+ for (int i = 0; i < displayArgs.size(); ++i) {
+ if (displayArgs.at(i).startsWith(QLatin1String("mmWidth"))) {
+ dimIdxW = i;
+ break;
+ }
+ }
+ for (int i = 0; i < displayArgs.size(); ++i) {
+ if (displayArgs.at(i).startsWith(QLatin1String("mmHeight"))) {
+ dimIdxH = i;
+ break;
+ }
+ }
+ if (dimIdxW >= 0) {
+ bool ok;
+ int pos = 7;
+ if (displayArgs.at(dimIdxW).at(pos) == QLatin1Char('='))
+ ++pos;
+ int pw = displayArgs.at(dimIdxW).mid(pos).toInt(&ok);
+ if (ok) {
+ physWidth = pw;
+ if (dimIdxH < 0)
+ physHeight = dh*physWidth/dw;
+ }
+ }
+ if (dimIdxH >= 0) {
+ bool ok;
+ int pos = 8;
+ if (displayArgs.at(dimIdxH).at(pos) == QLatin1Char('='))
+ ++pos;
+ int ph = displayArgs.at(dimIdxH).mid(pos).toInt(&ok);
+ if (ok) {
+ physHeight = ph;
+ if (dimIdxW < 0)
+ physWidth = dw*physHeight/dh;
+ }
+ }
+ if (dimIdxW < 0 && dimIdxH < 0) {
+ const int dpi = 72;
+ physWidth = qRound(dw * 25.4 / dpi);
+ physHeight = qRound(dh * 25.4 / dpi);
+ }
+
+ qDebug("Connected to VFB server %s: %d x %d x %d %dx%dmm (%dx%ddpi)", displaySpec.toLatin1().data(),
+ w, h, d, physWidth, physHeight, qRound(dw*25.4/physWidth), qRound(dh*25.4/physHeight) );
+
+ size = lstep * h;
+ mapsize = size;
+ screencols = d_ptr->hdr->numcols;
+ memcpy(screenclut, d_ptr->hdr->clut, sizeof(QRgb) * screencols);
+
+ connected = this;
+
+ if (qgetenv("QT_QVFB_BGR").toInt())
+ pixeltype = BGRPixel;
+
+ return true;
+}
+
+void QVFbScreen::disconnect()
+{
+ connected = 0;
+ if ((long)d_ptr->shmrgn != -1 && d_ptr->shmrgn) {
+ if (qApp->type() == QApplication::GuiServer && d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader)) {
+ d_ptr->hdr->serverVersion = 0;
+ }
+ shmdt((char*)d_ptr->shmrgn);
+ }
+}
+
+bool QVFbScreen::initDevice()
+{
+#ifndef QT_NO_QWS_MOUSE_QVFB
+ const QString mouseDev = QT_VFB_MOUSE_PIPE(displayId);
+ d_ptr->mouse = new QVFbMouseHandler(QLatin1String("QVFbMouse"), mouseDev);
+ qwsServer->setDefaultMouse("None");
+ if (d_ptr->mouse)
+ d_ptr->mouse->setScreen(this);
+#endif
+
+#if !defined(QT_NO_QWS_KBD_QVFB) && !defined(QT_NO_QWS_KEYBOARD)
+ const QString keyboardDev = QT_VFB_KEYBOARD_PIPE(displayId);
+ d_ptr->keyboard = new QVFbKeyboardHandler(keyboardDev);
+ qwsServer->setDefaultKeyboard("None");
+#endif
+
+ if (d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader))
+ d_ptr->hdr->serverVersion = QT_VERSION;
+
+ if(d==8) {
+ screencols=256;
+ if (grayscale) {
+ // Build grayscale palette
+ for(int loopc=0;loopc<256;loopc++) {
+ screenclut[loopc]=qRgb(loopc,loopc,loopc);
+ }
+ } else {
+ // 6x6x6 216 color cube
+ int idx = 0;
+ for(int ir = 0x0; ir <= 0xff; ir+=0x33) {
+ for(int ig = 0x0; ig <= 0xff; ig+=0x33) {
+ for(int ib = 0x0; ib <= 0xff; ib+=0x33) {
+ screenclut[idx]=qRgb(ir, ig, ib);
+ idx++;
+ }
+ }
+ }
+ screencols=idx;
+ }
+ memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
+ d_ptr->hdr->numcols = screencols;
+ } else if (d == 4) {
+ int val = 0;
+ for (int idx = 0; idx < 16; idx++, val += 17) {
+ screenclut[idx] = qRgb(val, val, val);
+ }
+ screencols = 16;
+ memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
+ d_ptr->hdr->numcols = screencols;
+ } else if (d == 1) {
+ screencols = 2;
+ screenclut[1] = qRgb(0xff, 0xff, 0xff);
+ screenclut[0] = qRgb(0, 0, 0);
+ memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
+ d_ptr->hdr->numcols = screencols;
+ }
+
+#ifndef QT_NO_QWS_CURSOR
+ QScreenCursor::initSoftwareCursor();
+#endif
+ return true;
+}
+
+void QVFbScreen::shutdownDevice()
+{
+}
+
+void QVFbScreen::setMode(int ,int ,int)
+{
+}
+
+// save the state of the graphics card
+// This is needed so that e.g. we can restore the palette when switching
+// between linux virtual consoles.
+void QVFbScreen::save()
+{
+ // nothing to do.
+}
+
+// restore the state of the graphics card.
+void QVFbScreen::restore()
+{
+}
+void QVFbScreen::setDirty(const QRect& rect)
+{
+ const QRect r = rect.translated(-offset());
+ d_ptr->hdr->dirty = true;
+ d_ptr->hdr->update = d_ptr->hdr->update.united(r);
+}
+
+void QVFbScreen::setBrightness(int b)
+{
+ if (connected) {
+ connected->d_ptr->brightness = b;
+
+ QVFbHeader *hdr = connected->d_ptr->hdr;
+ if (hdr->viewerVersion < 0x040400) // brightness not supported
+ return;
+
+ const int br = connected->d_ptr->blank ? 0 : b;
+ if (hdr->brightness != br) {
+ hdr->brightness = br;
+ connected->setDirty(connected->region().boundingRect());
+ }
+ }
+}
+
+void QVFbScreen::blank(bool on)
+{
+ d_ptr->blank = on;
+ setBrightness(connected->d_ptr->brightness);
+}
+
+#endif // QT_NO_QWS_QVFB
+
+QT_END_NAMESPACE