diff options
author | Paul Olav Tvete <paul.tvete@nokia.com> | 2009-09-07 08:12:47 (GMT) |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@nokia.com> | 2009-09-07 08:12:47 (GMT) |
commit | 2ff6c9e8d89590c8180769bd54e545f40ca9a56f (patch) | |
tree | 4c218c06f99ee31be79fb19a089d7506f29b373f /src | |
parent | bd4771a8a135bf2307c6fb2e27ccdac64637992d (diff) | |
download | Qt-2ff6c9e8d89590c8180769bd54e545f40ca9a56f.zip Qt-2ff6c9e8d89590c8180769bd54e545f40ca9a56f.tar.gz Qt-2ff6c9e8d89590c8180769bd54e545f40ca9a56f.tar.bz2 |
Please welcome the Lighthouse Research Project!
Lighthouse is a lighter, nimbler version of Qt/Embedded, which does not
contain a window system. Instead, it uses graphics system plugins to
provide the necessary functionality or interface with existing window
systems.
The first version was written by Rhys.
Squashed commit.
Diffstat (limited to 'src')
99 files changed, 10228 insertions, 72 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 787eba7..d29cd5f 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1227,7 +1227,16 @@ bool qSharedBuild() Defined on Qt for Embedded Linux. - \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11 + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_LITE +*/ + +/*! + \macro Q_WS_LITE + \relates <QtGlobal> + + Defined on Qt for Embedded Linux, Lite version. + + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS */ /*! diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a2c532f..158fa53 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -284,7 +284,7 @@ namespace QT_NAMESPACE {} # endif #endif -#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) +#if defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) #error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration." #endif @@ -799,7 +799,7 @@ namespace QT_NAMESPACE {} # define Q_WS_PM # error "Qt does not work with OS/2 Presentation Manager or Workplace Shell" #elif defined(Q_OS_UNIX) -# if defined(Q_OS_MAC) && !defined(__USE_WS_X11__) && !defined(Q_WS_QWS) +# if defined(Q_OS_MAC) && !defined(__USE_WS_X11__) && !defined(Q_WS_QWS) && !defined(Q_WS_LITE) # define Q_WS_MAC # define Q_WS_MACX # if defined(Q_OS_MAC64) @@ -811,7 +811,7 @@ namespace QT_NAMESPACE {} # if (defined(__SERIES60_31__) || defined(__S60_32__) || defined(__S60_50__)) && !defined(QT_NO_S60) # define Q_WS_S60 # endif -# elif !defined(Q_WS_QWS) +# elif !defined(Q_WS_QWS) && !defined(Q_WS_LITE) # define Q_WS_X11 # endif #endif @@ -1056,7 +1056,7 @@ redefine to built-in booleans to make autotests work properly */ typedef int QNoImplicitBoolCast; -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) +#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) #define QT_NO_FPU #endif diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 8f34e30..c37122c 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1537,7 +1537,7 @@ public: typedef void *HANDLE; #elif defined(Q_WS_X11) typedef unsigned long HANDLE; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_LITE) typedef void * HANDLE; #elif defined(Q_OS_SYMBIAN) typedef unsigned long int HANDLE; // equivalent to TUint32 diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 48671ba..94aad7a 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1133,7 +1133,7 @@ static QString getPath(QSettings::Format format, QSettings::Scope scope) if (env == 0) { userPath = homePath; userPath += QLatin1Char('/'); -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) userPath += QLatin1String("Settings"); #else userPath += QLatin1String(".config"); diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index dc1beb3..3dff0e3 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) #define QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER #endif diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri index ad2fb4c..afa5ecd 100644 --- a/src/gui/accessible/accessible.pri +++ b/src/gui/accessible/accessible.pri @@ -12,7 +12,7 @@ contains(QT_CONFIG, accessibility) { accessible/qaccessiblewidget.cpp \ accessible/qaccessibleplugin.cpp - mac:!embedded { + mac:!embedded:!embedded_lite { HEADERS += accessible/qaccessible_mac_p.h OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm \ accessible/qaccessible_mac_cocoa.mm diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri index b9fad41..08584a9 100644 --- a/src/gui/dialogs/dialogs.pri +++ b/src/gui/dialogs/dialogs.pri @@ -27,7 +27,7 @@ HEADERS += \ dialogs/qwizard.h \ dialogs/qprintpreviewdialog.h -!embedded:mac { +!embedded:!embedded_lite:mac { OBJECTIVE_SOURCES += dialogs/qcolordialog_mac.mm \ dialogs/qfiledialog_mac.mm \ dialogs/qfontdialog_mac.mm \ @@ -46,7 +46,7 @@ win32 { !win32-borland:!wince*: LIBS += -lshell32 # the filedialog needs this library } -!mac:!embedded:!symbian:unix { +!mac:!embedded:!symbian:unix|embedded_lite { HEADERS += dialogs/qpagesetupdialog_unix_p.h SOURCES += dialogs/qprintdialog_unix.cpp \ dialogs/qpagesetupdialog_unix.cpp diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri index 75a3d91..9ba7017 100644 --- a/src/gui/egl/egl.pri +++ b/src/gui/egl/egl.pri @@ -12,10 +12,14 @@ unix { embedded { SOURCES += egl/qegl_qws.cpp } else { - symbian { - SOURCES += egl/qegl_symbian.cpp + embedded_lite { + SOURCES += egl/qegl_lite.cpp } else { - SOURCES += egl/qegl_x11.cpp + symbian { + SOURCES += egl/qegl_symbian.cpp + } else { + SOURCES += egl/qegl_x11.cpp + } } } } diff --git a/src/gui/egl/qegl_lite.cpp b/src/gui/egl/qegl_lite.cpp new file mode 100644 index 0000000..784b252 --- /dev/null +++ b/src/gui/egl/qegl_lite.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include <QtGui/qpaintdevice.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qwidget.h> +#include "qegl_p.h" + +#if !defined(QT_NO_EGL) + +#include <QtGui/private/qgraphicssystem_p.h> +#include <QtGui/private/qapplication_p.h> +#include <QtGui/qdesktopwidget.h> + +QT_BEGIN_NAMESPACE + +bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +{ + Q_UNUSED(device); + Q_UNUSED(properties); + return false; +} + +EGLDisplay QEglContext::getDisplay(QPaintDevice *device) +{ + Q_UNUSED(device); + return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); +} + +static QGraphicsSystemScreen *screenForDevice(QPaintDevice *device) +{ + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) + return 0; + + QList<QGraphicsSystemScreen *> screens = gs->screens(); + + int screenNumber; + if (device && device->devType() == QInternal::Widget) + screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device)); + else + screenNumber = 0; + if (screenNumber < 0 || screenNumber >= screens.size()) + return 0; + return screens[screenNumber]; +} + +// Set pixel format and other properties based on a paint device. +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + if (!dev) + return; + + // Find the QGLScreen for this paint device. + QGraphicsSystemScreen *screen = screenForDevice(dev); + if (!screen) + return; + int devType = dev->devType(); + if (devType == QInternal::Image) + setPixelFormat(static_cast<QImage *>(dev)->format()); + else + setPixelFormat(screen->format()); +} + +QT_END_NAMESPACE + +#endif // !QT_NO_EGL diff --git a/src/gui/embedded/qkbd_qws.cpp b/src/gui/embedded/qkbd_qws.cpp index 4d97ba7..9a496ac 100644 --- a/src/gui/embedded/qkbd_qws.cpp +++ b/src/gui/embedded/qkbd_qws.cpp @@ -48,8 +48,16 @@ #include <QDataStream> #include <QStringList> +#ifdef Q_WS_QWS #include "qwindowsystem_qws.h" #include "qscreen_qws.h" +#endif + +#ifdef Q_WS_LITE +#include <private/qapplication_p.h> +#include <QKeyEvent> +#endif + #include "qtimer.h" #include <stdlib.h> @@ -352,7 +360,16 @@ QWSKeyboardHandler::~QWSKeyboardHandler() void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat) { +#if defined(Q_WS_QWS) qwsServer->processKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat); +#elif defined(Q_WS_LITE) + QEvent::Type type = isPress ? QEvent::KeyPress : QEvent::KeyRelease; + QString str; + if (unicode != 0xffff) + str = QString(unicode); + QKeyEvent ke(type, keycode, modifiers, str); + QApplicationPrivate::handleKeyEvent(0, &ke); +#endif } /*! @@ -375,6 +392,7 @@ void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardM */ int QWSKeyboardHandler::transformDirKey(int key) { +#ifdef Q_WS_QWS static int dir_keyrot = -1; if (dir_keyrot < 0) { // get the rotation @@ -387,6 +405,9 @@ int QWSKeyboardHandler::transformDirKey(int key) } int xf = qt_screen->transformOrientation() + dir_keyrot; return (key-Qt::Key_Left+xf)%4+Qt::Key_Left; +#else + return 0; +#endif } /*! @@ -452,7 +473,7 @@ void QWSKeyboardHandler::endAutoRepeat() Maps \a keycode according to a keymap and sends that key event to the \l{Qt for Embedded Linux} server application. - + Please see the \l{Qt for Embedded Linux Character Input} and the \l {kmap2qmap} documentations for a description on how to create and use keymap files. diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 7c24002..6949e39 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -4,7 +4,7 @@ QT = core DEFINES += QT_BUILD_GUI_LIB QT_NO_USING_NAMESPACE win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000 -!win32:!embedded:!mac:!symbian:CONFIG += x11 +!win32:!embedded:!embedded_lite:!mac:!symbian:CONFIG += x11 unix:QMAKE_PKGCONFIG_REQUIRES = QtCore diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 0970385..67f0699 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -61,11 +61,14 @@ win32 { embedded { SOURCES += image/qpixmap_qws.cpp } +embedded_lite { + SOURCES += image/qpixmap_lite.cpp +} x11 { HEADERS += image/qpixmap_x11_p.h SOURCES += image/qpixmap_x11.cpp } -mac { +!embedded:!embedded_lite:mac { HEADERS += image/qpixmap_mac_p.h SOURCES += image/qpixmap_mac.cpp } diff --git a/src/gui/image/qpixmap_lite.cpp b/src/gui/image/qpixmap_lite.cpp new file mode 100644 index 0000000..4ba69fa --- /dev/null +++ b/src/gui/image/qpixmap_lite.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include <qpixmap.h> + +QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) +{ + Q_UNUSED(window); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(w); + Q_UNUSED(h); + return QPixmap(); +} diff --git a/src/gui/image/qpixmapdatafactory.cpp b/src/gui/image/qpixmapdatafactory.cpp index 53c93ad..fab6af8 100644 --- a/src/gui/image/qpixmapdatafactory.cpp +++ b/src/gui/image/qpixmapdatafactory.cpp @@ -53,6 +53,9 @@ #ifdef Q_WS_MAC # include <private/qpixmap_mac_p.h> #endif +#ifdef Q_WS_LITE +# include <private/qpixmap_raster_p.h> +#endif #include "private/qapplication_p.h" #include "private/qgraphicssystem_p.h" @@ -79,6 +82,8 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type) return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); +#elif defined(Q_WS_LITE) + return new QRasterPixmapData(type); #else #error QSimplePixmapDataFactory::create() not implemented #endif diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri index 6d9f748..b3b7a3a 100644 --- a/src/gui/inputmethod/inputmethod.pri +++ b/src/gui/inputmethod/inputmethod.pri @@ -19,7 +19,7 @@ embedded { HEADERS += inputmethod/qwsinputcontext_p.h SOURCES += inputmethod/qwsinputcontext_qws.cpp } -mac:!embedded { +mac:!embedded:!embedded_lite { HEADERS += inputmethod/qmacinputcontext_p.h SOURCES += inputmethod/qmacinputcontext_mac.cpp } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 8489817..85c838b 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -181,7 +181,25 @@ embedded { } -!embedded:!x11:mac { +embedded_lite { + HEADERS += \ + kernel/qgenericpluginfactory_lite.h \ + kernel/qgenericplugin_lite.h + + SOURCES += \ + kernel/qapplication_lite.cpp \ + kernel/qclipboard_lite.cpp \ + kernel/qcursor_lite.cpp \ + kernel/qdnd_qws.cpp \ + kernel/qdesktopwidget_lite.cpp \ + kernel/qgenericpluginfactory_lite.cpp \ + kernel/qgenericplugin_lite.cpp \ + kernel/qkeymapper_qws.cpp \ + kernel/qsound_lite.cpp \ + kernel/qwidget_lite.cpp +} + +!embedded:!embedded_lite:!x11:mac { SOURCES += \ kernel/qclipboard_mac.cpp \ kernel/qmime_mac.cpp \ diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 511c797..2bcaa68 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -741,6 +741,8 @@ void QApplicationPrivate::construct( { initResources(); + graphics_system_name = qgetenv("QT_DEFAULT_GRAPHICS_SYSTEM"); + qt_is_gui_used = (qt_appType != QApplication::Tty); process_cmdline(); // Must be called before initialize() diff --git a/src/gui/kernel/qapplication_lite.cpp b/src/gui/kernel/qapplication_lite.cpp new file mode 100644 index 0000000..eec3e6c --- /dev/null +++ b/src/gui/kernel/qapplication_lite.cpp @@ -0,0 +1,624 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qapplication_p.h" +#include "qcolormap.h" +#include "qpixmapcache.h" +#if !defined(QT_NO_GLIB) +#include "private/qeventdispatcher_glib_p.h" +#endif +#include "private/qeventdispatcher_unix_p.h" +#ifndef QT_NO_CURSOR +#include "private/qcursor_p.h" +#endif + +#include "qgenericpluginfactory_lite.h" +#include <qdesktopwidget.h> + +#include <qinputcontext.h> + +#include <qdebug.h> + + +QT_BEGIN_NAMESPACE + +static QString appName; +static const char *appFont = 0; // application font + +QWidget *qt_button_down = 0; // widget got last button-down + +static bool app_do_modal = false; +extern QWidgetList *qt_modal_stack; // stack of modal widgets + +int qt_last_x = 0; +int qt_last_y = 0; + +QString QApplicationPrivate::appName() const +{ + return QT_PREPEND_NAMESPACE(appName); +} + +void QApplicationPrivate::createEventDispatcher() +{ + Q_Q(QApplication); +#if !defined(QT_NO_GLIB) + if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported()) + eventDispatcher = new QEventDispatcherGlib(q); + else +#endif + eventDispatcher = new QEventDispatcherUNIX(q); +} + +static bool qt_try_modal(QWidget *widget, const QEvent *event) +{ + QWidget * top = 0; + + if (QApplicationPrivate::tryModalHelper(widget, &top)) + return true; + + bool block_event = false; + bool paint_event = false; + + switch (event->type()) { +#if 0 + case QEvent::Focus: + if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus) + break; + // drop through +#endif + case QEvent::MouseButtonPress: // disallow mouse/key events + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + case QEvent::KeyPress: + case QEvent::KeyRelease: + block_event = true; + break; + default: + break; + } + + if ((block_event || paint_event) && top->parentWidget() == 0) + top->raise(); + + return !block_event; +} + + + +void QApplicationPrivate::enterModal_sys(QWidget *widget) +{ + qDebug() << ">>>>>>>> enterModal_sys" << app_do_modal << widget; + if (!qt_modal_stack) + qt_modal_stack = new QWidgetList; + qt_modal_stack->insert(0, widget); + app_do_modal = true; +} + +void QApplicationPrivate::leaveModal_sys(QWidget *widget ) +{ + qDebug() << "<<<<<<<<< leaveModal_sys" << app_do_modal << widget; + if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { + if (qt_modal_stack->isEmpty()) { + delete qt_modal_stack; + qt_modal_stack = 0; + } + } + app_do_modal = qt_modal_stack != 0; +} + +bool QApplicationPrivate::modalState() +{ + return app_do_modal; +} + +void QApplicationPrivate::closePopup(QWidget *popup) +{ + Q_Q(QApplication); + if (!popupWidgets) + return; + popupWidgets->removeAll(popup); + +//### +// if (popup == qt_popup_down) { +// qt_button_down = 0; +// qt_popup_down = 0; +// } + + if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup + delete QApplicationPrivate::popupWidgets; + QApplicationPrivate::popupWidgets = 0; + + //### replay mouse event? + + //### transfer/release mouse grab + + //### transfer/release keyboard grab + + //give back focus + + if (active_window) { + if (QWidget *fw = active_window->focusWidget()) { + if (fw != QApplication::focusWidget()) { + fw->setFocus(Qt::PopupFocusReason); + } else { + QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); + q->sendEvent(fw, &e); + } + } + } + + } else { + // A popup was closed, so the previous popup gets the focus. + + QWidget* aw = QApplicationPrivate::popupWidgets->last(); + if (QWidget *fw = aw->focusWidget()) + fw->setFocus(Qt::PopupFocusReason); + + //### regrab the keyboard and mouse in case 'popup' lost the grab + + + } + +} + +static int openPopupCount = 0; +void QApplicationPrivate::openPopup(QWidget *popup) +{ + openPopupCount++; + if (!popupWidgets) { // create list + popupWidgets = new QWidgetList; + + /* only grab if you are the first/parent popup */ + //#### ->grabMouse(popup,true); + //#### ->grabKeyboard(popup,true); + //### popupGrabOk = true; + } + popupWidgets->append(popup); // add to end of list + + // popups are not focus-handled by the window system (the first + // popup grabbed the keyboard), so we have to do that manually: A + // new popup gets the focus + if (popup->focusWidget()) { + popup->focusWidget()->setFocus(Qt::PopupFocusReason); + } else if (popupWidgets->count() == 1) { // this was the first popup + if (QWidget *fw = QApplication::focusWidget()) { + QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); + QApplication::sendEvent(fw, &e); + } + } +} + +void QApplicationPrivate::initializeMultitouch_sys() +{ +} + +void QApplicationPrivate::cleanupMultitouch_sys() +{ +} + +void QApplicationPrivate::initializeWidgetPaletteHash() +{ +} + +void QApplication::setCursorFlashTime(int msecs) +{ + QApplicationPrivate::cursor_flash_time = msecs; +} + +int QApplication::cursorFlashTime() +{ + return QApplicationPrivate::cursor_flash_time; +} + +void QApplication::setDoubleClickInterval(int ms) +{ + QApplicationPrivate::mouse_double_click_time = ms; +} + +int QApplication::doubleClickInterval() +{ + return QApplicationPrivate::mouse_double_click_time; +} + +void QApplication::setKeyboardInputInterval(int ms) +{ + QApplicationPrivate::keyboard_input_time = ms; +} + +int QApplication::keyboardInputInterval() +{ + return QApplicationPrivate::keyboard_input_time; +} + +#ifndef QT_NO_WHEELEVENT +void QApplication::setWheelScrollLines(int lines) +{ + QApplicationPrivate::wheel_scroll_lines = lines; +} + +int QApplication::wheelScrollLines() +{ + return QApplicationPrivate::wheel_scroll_lines; +} +#endif + +void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) +{ + switch (effect) { + case Qt::UI_AnimateMenu: + QApplicationPrivate::animate_menu = enable; + break; + case Qt::UI_FadeMenu: + if (enable) + QApplicationPrivate::animate_menu = true; + QApplicationPrivate::fade_menu = enable; + break; + case Qt::UI_AnimateCombo: + QApplicationPrivate::animate_combo = enable; + break; + case Qt::UI_AnimateTooltip: + QApplicationPrivate::animate_tooltip = enable; + break; + case Qt::UI_FadeTooltip: + if (enable) + QApplicationPrivate::animate_tooltip = true; + QApplicationPrivate::fade_tooltip = enable; + break; + case Qt::UI_AnimateToolBox: + QApplicationPrivate::animate_toolbox = enable; + break; + default: + QApplicationPrivate::animate_ui = enable; + break; + } +} + +bool QApplication::isEffectEnabled(Qt::UIEffect effect) +{ + if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui) + return false; + + switch(effect) { + case Qt::UI_AnimateMenu: + return QApplicationPrivate::animate_menu; + case Qt::UI_FadeMenu: + return QApplicationPrivate::fade_menu; + case Qt::UI_AnimateCombo: + return QApplicationPrivate::animate_combo; + case Qt::UI_AnimateTooltip: + return QApplicationPrivate::animate_tooltip; + case Qt::UI_FadeTooltip: + return QApplicationPrivate::fade_tooltip; + case Qt::UI_AnimateToolBox: + return QApplicationPrivate::animate_toolbox; + default: + return QApplicationPrivate::animate_ui; + } +} + +#ifndef QT_NO_CURSOR +void QApplication::setOverrideCursor(const QCursor &) +{ + // XXX +} + +void QApplication::restoreOverrideCursor() +{ + // XXX +} + +#endif// QT_NO_CURSOR + +QWidget *QApplication::topLevelAt(const QPoint &pos) +{ +//### We have to implement a windowsystem-aware way to do this + + //fallback implementation assuming widgets are in stacking order + + QWidgetList list = topLevelWidgets(); + for (int i = list.size()-1; i >= 0; --i) { + QWidget *w = list[i]; + //### mask is ignored + if (w != QApplication::desktop() && w->isVisible() && w->geometry().contains(pos)) + return w; + } + + return 0; +} + +void QApplication::beep() +{ +} + +void QApplication::alert(QWidget *, int) +{ +} + +static void init_plugins(const QList<QByteArray> pluginList) +{ + for (int i = 0; i < pluginList.count(); ++i) { + QByteArray pluginSpec = pluginList.at(i); + qDebug() << "init_plugins" << i << pluginSpec; + int colonPos = pluginSpec.indexOf(':'); + QObject *plugin; + if (colonPos < 0) + plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec), QString()); + else + plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec.mid(0, colonPos)), + QLatin1String(pluginSpec.mid(colonPos+1))); + qDebug() << " created" << plugin; + } +} + +class QDummyInputContext : public QInputContext +{ +public: + explicit QDummyInputContext(QObject* parent = 0) : QInputContext(parent) {} + ~QDummyInputContext() {} + QString identifierName() { return QString(); } + QString language() { return QString(); } + + void reset() {} + bool isComposing() const { return false; } + +}; + +void qt_init(QApplicationPrivate *priv, int type) +{ + Q_UNUSED(type); + + char *p; + char **argv = priv->argv; + int argc = priv->argc; + + if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms + p = strrchr(argv[0], '/'); + appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); + } + + QList<QByteArray> pluginList; + + // Get command line params + + int j = argc ? 1 : 0; + for (int i=1; i<argc; i++) { + if (argv[i] && *argv[i] != '-') { + argv[j++] = argv[i]; + continue; + } + QByteArray arg = argv[i]; + if (arg == "-fn" || arg == "-font") { + if (++i < argc) + appFont = argv[i]; + } else if (arg == "-plugin") { + if (++i < argc) + pluginList << argv[i]; + } else { + argv[j++] = argv[i]; + } + } + + if (j < priv->argc) { + priv->argv[j] = 0; + priv->argc = j; + } + + + + +#if 0 + QByteArray pluginEnv = qgetenv("QT_LITE_PLUGINS"); + if (!pluginEnv.isEmpty()) { + pluginList.append(pluginEnv.split(';')); + } +#endif + + + qDebug() << pluginList; + + init_plugins(pluginList); + + QColormap::initialize(); + QFont::initialize(); +#ifndef QT_NO_CURSOR +// QCursorData::initialize(); +#endif + + qApp->setObjectName(appName); + +#ifndef QT_NO_QWS_INPUTMETHODS + qApp->setInputContext(new QDummyInputContext(qApp)); +#endif +} + +void qt_cleanup() +{ + QPixmapCache::clear(); +#ifndef QT_NO_CURSOR + QCursorData::cleanup(); +#endif + QFont::cleanup(); + QColormap::cleanup(); +} + + +/*! + +\a tlw == 0 means that \a ev is in global coords only + + +*/ + +void QApplicationPrivate::handleMouseEvent(QWidget *tlw, const QMouseEvent &ev) +{ +// qDebug() << "handleMouseEvent" << tlw << ev.pos() << hex << ev.buttons(); + + static QWidget *implicit_mouse_grabber=0; + + QPoint localPoint = ev.pos(); + QPoint globalPoint = ev.globalPos(); + bool trustLocalPoint = !!tlw; //is there something the local point can be local to? + QWidget *mouseWidget = tlw; + + qt_last_x = globalPoint.x(); + qt_last_y = globalPoint.y(); + + if (self->inPopupMode()) { + //popup mouse handling is magical... + mouseWidget = qApp->activePopupWidget(); + trustLocalPoint = (mouseWidget == tlw); + + //### how should popup mode and implicit mouse grab interact? + + } else if (tlw && app_do_modal && !qt_try_modal(tlw, &ev) ) { + //even if we're blocked by modality, we should deliver the mouse release event.. + //### this code is not completely correct: multiple buttons can be pressed simultaneously + if (!(implicit_mouse_grabber && ev.buttons() == Qt::NoButton)) { + //qDebug() << "modal blocked mouse event to" << tlw; + return; + } + } else { + QWidget *mouseWindow = tlw; + + // find the tlw if we didn't get it from the plugin + if (!mouseWindow) { + mouseWindow = QApplication::topLevelAt(globalPoint); + } + + if (!mouseWindow && !implicit_mouse_grabber) + return; //nowhere to send it + + // which child should have it? + mouseWidget = mouseWindow; + if (mouseWindow) { + QWidget *w = mouseWindow->childAt(ev.pos()); + if (w) { + mouseWidget = w; + } + } + + //handle implicit mouse grab + if (ev.type() == QEvent::MouseButtonPress && !implicit_mouse_grabber) { + implicit_mouse_grabber = mouseWidget; + + Q_ASSERT(mouseWindow); + mouseWindow->activateWindow(); //focus + } else if (implicit_mouse_grabber) { + mouseWidget = implicit_mouse_grabber; + mouseWindow = mouseWidget->window(); + trustLocalPoint = (mouseWindow == tlw); + } + } + Q_ASSERT(mouseWidget); + + if (trustLocalPoint) { + // we have a sensible localPoint, so we prefer that, since the + // window system may know more than we do + localPoint = mouseWidget->mapFrom(tlw, localPoint); + } else { + // we don't want to map a local point from a different toplevel + // and we definitely don't want to map from the null pointer + localPoint = mouseWidget->mapFromGlobal(globalPoint); + } + + if (ev.buttons() == Qt::NoButton) { + //qDebug() << "resetting mouse grabber"; + implicit_mouse_grabber = 0; + } + + // Remember, we might enter a modal event loop when sending the event, + // so think carefully before adding code below this point. + + // qDebug() << "sending mouse ev." << ev.type() << localPoint << globalPoint << ev.button() << ev.buttons() << mouseWidget << "mouse grabber" << implicit_mouse_grabber; + + QMouseEvent e(ev.type(), localPoint, globalPoint, ev.button(), ev.buttons(), ev.modifiers()); + QApplication::sendSpontaneousEvent(mouseWidget, &e); + +} + + + +// Remember, Qt convention is: keyboard state is state *before* + +void QApplicationPrivate::handleKeyEvent(QWidget *tlw, QKeyEvent *e) +{ + QWidget *focusW = 0; + if (self->inPopupMode()) { + QWidget *popupW = qApp->activePopupWidget(); + focusW = popupW->focusWidget() ? popupW->focusWidget() : popupW; + } + if (!focusW) + focusW = QApplication::focusWidget(); + if (!focusW) + focusW = tlw; + if (!focusW) + focusW = QApplication::activeWindow(); + + //qDebug() << "handleKeyEvent" << hex << e->key() << e->modifiers() << e->text() << "widget" << focusW; + + if (!focusW) + return; + if (app_do_modal && !qt_try_modal(focusW, e)) + return; + + QApplication::sendSpontaneousEvent(focusW, e); +} + + +void QApplicationPrivate::handleGeometryChange(QWidget *tlw, const QRect &newRect) +{ + QRect cr(tlw->geometry()); + + bool isResize = cr.size() != newRect.size(); + bool isMove = cr.topLeft() != newRect.topLeft(); + tlw->data->crect = newRect; + if (isResize) { + QResizeEvent e(tlw->data->crect.size(), cr.size()); + QApplication::sendSpontaneousEvent(tlw, &e); + } + + if (isMove) { + //### frame geometry + QMoveEvent e(tlw->data->crect.topLeft(), cr.topLeft()); + QApplication::sendSpontaneousEvent(tlw, &e); + } +} +QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 3b6cd43..84182cb 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -571,6 +571,12 @@ public: void _q_readRX71MultiTouchEvents(); #endif +#ifdef Q_WS_LITE + static void handleMouseEvent(QWidget *tlw, const QMouseEvent &ev); + static void handleKeyEvent(QWidget *tlw, QKeyEvent *e); + static void handleGeometryChange(QWidget *tlw, const QRect &newRect); +#endif + private: #ifdef Q_WS_QWS QMap<const QScreen*, QRect> maxWindowRects; diff --git a/src/gui/kernel/qclipboard_lite.cpp b/src/gui/kernel/qclipboard_lite.cpp new file mode 100644 index 0000000..0d9268f --- /dev/null +++ b/src/gui/kernel/qclipboard_lite.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qclipboard.h" + +#ifndef QT_NO_CLIPBOARD + +#include "qmimedata.h" +#include "qapplication.h" + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + + +class QClipboardData +{ +public: + QClipboardData(); + ~QClipboardData(); + + void setSource(QMimeData* s) + { + if (s == src) + return; + delete src; + src = s; + } + QMimeData* source() + { return src; } + + void clear(); + +private: + QMimeData* src; +}; + +QClipboardData::QClipboardData() +{ + src = 0; +} + +QClipboardData::~QClipboardData() +{ + delete src; +} + +void QClipboardData::clear() +{ + delete src; + src = 0; +} + + +static QClipboardData *internalCbData = 0; + +static void cleanupClipboardData() +{ + delete internalCbData; + internalCbData = 0; +} + +static QClipboardData *clipboardData() +{ + if (internalCbData == 0) { + internalCbData = new QClipboardData; + qAddPostRoutine(cleanupClipboardData); + } + return internalCbData; +} + + +void QClipboard::clear(Mode mode) +{ + setText(QString(), mode); +} + + +bool QClipboard::event(QEvent *e) +{ + return QObject::event(e); +} + +const QMimeData* QClipboard::mimeData(Mode mode) const +{ + if (mode != Clipboard) return 0; + + QClipboardData *d = clipboardData(); + return d->source(); +} + +void QClipboard::setMimeData(QMimeData* src, Mode mode) +{ + if (mode != Clipboard) return; + + QClipboardData *d = clipboardData(); + + d->setSource(src); + + emitChanged(QClipboard::Clipboard); +} + +bool QClipboard::supportsMode(Mode mode) const +{ + return (mode == Clipboard); +} + +bool QClipboard::ownsMode(Mode mode) const +{ + if (mode == Clipboard) + qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!"); + return false; +} + +void QClipboard::connectNotify( const char * ) +{ +} + +void QClipboard::ownerDestroyed() +{ +} + +#endif // QT_NO_CLIPBOARD + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index 2a919b3..115a4cc 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -120,7 +120,7 @@ public: static int x11Screen(); #elif defined(Q_WS_MAC) Qt::HANDLE handle() const; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_LITE) int handle() const; #endif #endif diff --git a/src/gui/kernel/qcursor_lite.cpp b/src/gui/kernel/qcursor_lite.cpp new file mode 100644 index 0000000..5af03fc --- /dev/null +++ b/src/gui/kernel/qcursor_lite.cpp @@ -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 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$ +** +****************************************************************************/ + +#include <qcursor.h> +#include <private/qcursor_p.h> +#include <qbitmap.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +#ifndef QT_NO_CURSOR + +static int nextCursorId = Qt::BitmapCursor; + +/***************************************************************************** + Internal QCursorData class + *****************************************************************************/ + +QCursorData::QCursorData(Qt::CursorShape s) + : cshape(s), bm(0), bmm(0), hx(0), hy(0), id(s) +{ + ref = 1; +} + +QCursorData::~QCursorData() +{ + delete bm; + delete bmm; +} + + +/***************************************************************************** + Global cursors + *****************************************************************************/ + +extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp + +int QCursor::handle() const +{ + return d->id; +} + + +QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) +{ + if (!QCursorData::initialized) + QCursorData::initialize(); + if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { + qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); + QCursorData *c = qt_cursorTable[0]; + c->ref.ref(); + return c; + } + QCursorData *d = new QCursorData; + d->bm = new QBitmap(bitmap); + d->bmm = new QBitmap(mask); + d->cshape = Qt::BitmapCursor; + d->id = ++nextCursorId; + d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; + d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; + + return d; +} + +void QCursorData::update() +{ +} + +#endif //QT_NO_CURSOR + +extern int qt_last_x,qt_last_y; + +QPoint QCursor::pos() +{ + return QPoint(qt_last_x, qt_last_y); +} + +void QCursor::setPos(int x, int y) +{ + // Need to check, since some X servers generate null mouse move + // events, causing looping in applications which call setPos() on + // every mouse move event. + // + if (pos() == QPoint(x, y)) + return; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h index 94b751a..17164e7 100644 --- a/src/gui/kernel/qcursor_p.h +++ b/src/gui/kernel/qcursor_p.h @@ -88,7 +88,7 @@ struct QCursorData { short hx, hy; #if defined (Q_WS_MAC) int mId; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_LITE) int id; #endif #if defined (Q_WS_WIN) diff --git a/src/gui/kernel/qdesktopwidget_lite.cpp b/src/gui/kernel/qdesktopwidget_lite.cpp new file mode 100644 index 0000000..7aea787 --- /dev/null +++ b/src/gui/kernel/qdesktopwidget_lite.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qdesktopwidget.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +QDesktopWidget::QDesktopWidget() + : QWidget(0, Qt::Desktop) +{ + setObjectName(QLatin1String("desktop")); +} + +QDesktopWidget::~QDesktopWidget() +{ +} + +bool QDesktopWidget::isVirtualDesktop() const +{ + return true; +} + +int QDesktopWidget::primaryScreen() const +{ + return 0; +} + +int QDesktopWidget::numScreens() const +{ + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) + return 0; + return qMax(gs->screens().size(), 1); +} + +QWidget *QDesktopWidget::screen(int) +{ + return this; +} + +const QRect QDesktopWidget::availableGeometry(int screenNo) const +{ + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) + return QRect(); + QList<QGraphicsSystemScreen *> screens = gs->screens(); + if (screenNo == -1) + screenNo = 0; + if (screenNo < 0 || screenNo >= screens.size()) + return QRect(); + else + return screens[screenNo]->availableGeometry(); +} + +const QRect QDesktopWidget::screenGeometry(int screenNo) const +{ + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) + return QRect(); + QList<QGraphicsSystemScreen *> screens = gs->screens(); + if (screenNo == -1) + screenNo = 0; + if (screenNo < 0 || screenNo >= screens.size()) + return QRect(); + else + return screens[screenNo]->geometry(); +} + +int QDesktopWidget::screenNumber(const QWidget *w) const +{ + if (!w) + return 0; + + QRect frame = w->frameGeometry(); + if (!w->isWindow()) + frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); + const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2; + return screenNumber(midpoint); +} + +int QDesktopWidget::screenNumber(const QPoint &p) const +{ + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) + return -1; + QList<QGraphicsSystemScreen *> screens = gs->screens(); + + for (int i = 0; i < screens.size(); ++i) + if (screens[i]->geometry().contains(p)) + return i; + + return -1; +} + +void QDesktopWidget::resizeEvent(QResizeEvent *) +{ +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 1f64015..a9d5056 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -262,7 +262,7 @@ public: private: QPixmap *pm_cursor; int n_cursor; -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) Qt::DropAction currentActionForOverrideCursor; #endif diff --git a/src/gui/kernel/qgenericplugin_lite.cpp b/src/gui/kernel/qgenericplugin_lite.cpp new file mode 100644 index 0000000..29d7728 --- /dev/null +++ b/src/gui/kernel/qgenericplugin_lite.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qgenericplugin_lite.h" + +#ifndef QT_NO_LIBRARY + +QT_BEGIN_NAMESPACE + +/*! + \class QGenericPlugin + \ingroup plugins + \ingroup lite + + \brief The QGenericPlugin class is an abstract base class for + window-system related plugins in Qt for Embedded Linux LITE. + + Note that this class is only available in \l{Qt for Embedded Linux LITE}. + + A mouse plugin can be created by subclassing + QGenericPlugin and reimplementing the pure virtual keys() and + create() functions. By exporting the derived class using the + Q_EXPORT_PLUGIN2() macro, The default implementation of the + QGenericPluginFactory class will automatically detect the plugin and + load the driver into the server application at run-time. See \l + {How to Create Qt Plugins} for details. + + \sa QGenericPluginFactory +*/ + +/*! + \fn QStringList QGenericPlugin::keys() const + + Implement this function to return the list of valid keys, i.e. the + drivers supported by this plugin. + + \sa create() +*/ + +/*! + Constructs a plugin with the given \a parent. + + Note that this constructor is invoked automatically by the + Q_EXPORT_PLUGIN2() macro, so there is no need for calling it + explicitly. +*/ +QGenericPlugin::QGenericPlugin(QObject *parent) + : QObject(parent) +{ +} + +/*! + Destroys the plugin. + + Note that Qt destroys a plugin automatically when it is no longer + used, so there is no need for calling the destructor explicitly. +*/ +QGenericPlugin::~QGenericPlugin() +{ +} + +/*! + \fn QObject* QGenericPlugin::create(const QString &key, const QString& specification) + + Implement this function to create a driver matching the type + specified by the given \a key and \a specification parameters. Note that + keys are case-insensitive. + + \sa keys() +*/ + +QT_END_NAMESPACE + +#endif // QT_NO_LIBRARY diff --git a/src/gui/kernel/qgenericplugin_lite.h b/src/gui/kernel/qgenericplugin_lite.h new file mode 100644 index 0000000..2c0ee7a --- /dev/null +++ b/src/gui/kernel/qgenericplugin_lite.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QGENERICPLUGIN_LITE_H +#define QGENERICPLUGIN_LITE_H + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_LIBRARY + +//class QGenericObject; ????? + + struct Q_GUI_EXPORT QGenericPluginFactoryInterface : public QFactoryInterface +{ + virtual QObject* create(const QString &name, const QString &spec) = 0; +}; + +#define QGenericPluginFactoryInterface_iid "com.trolltech.Qt.QGenericPluginFactoryInterface" +Q_DECLARE_INTERFACE(QGenericPluginFactoryInterface, QGenericPluginFactoryInterface_iid) + +class Q_GUI_EXPORT QGenericPlugin : public QObject, public QGenericPluginFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QGenericPluginFactoryInterface:QFactoryInterface) +public: + explicit QGenericPlugin(QObject *parent = 0); + ~QGenericPlugin(); + + virtual QStringList keys() const = 0; + virtual QObject* create(const QString& name, const QString &spec) = 0; +}; + +#endif // QT_NO_LIBRARY + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMOUSEDRIVERPLUGIN_QWS_H diff --git a/src/gui/kernel/qgenericpluginfactory_lite.cpp b/src/gui/kernel/qgenericpluginfactory_lite.cpp new file mode 100644 index 0000000..4e5b12b --- /dev/null +++ b/src/gui/kernel/qgenericpluginfactory_lite.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qgenericpluginfactory_lite.h" + +#include "qapplication.h" +#include "private/qfactoryloader_p.h" +#include "qgenericplugin_lite.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QGenericPluginFactoryInterface_iid, + QLatin1String("/generic"), Qt::CaseInsensitive)) + +#endif //QT_NO_LIBRARY +#endif //QT_MAKEDLL + +/*! + \class QGenericPluginFactory + \ingroup qws + + \brief The QGenericPluginFactory class creates window-system + related plugin drivers in Qt for Embedded Linux LITE. + + Note that this class is only available in \l{Qt for Embedded Linux LITE}. + + + \sa QGenericPlugin +*/ + +/*! + Creates the driver specified by \a key, using the given \a specification. + + Note that the keys are case-insensitive. + + \sa keys() +*/ +QObject *QGenericPluginFactory::create(const QString& key, const QString &specification) +{ + QString driver = key.toLower(); + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + if (QGenericPluginFactoryInterface *factory = qobject_cast<QGenericPluginFactoryInterface*>(loader()->instance(driver))) + return factory->create(driver, specification); +#endif +#endif + return 0; +} + +/*! + Returns the list of valid keys, i.e. the available mouse drivers. + + \sa create() +*/ +QStringList QGenericPluginFactory::keys() +{ + QStringList list; + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + QStringList plugins = loader()->keys(); + for (int i = 0; i < plugins.size(); ++i) { + if (!list.contains(plugins.at(i))) + list += plugins.at(i); + } +#endif //QT_NO_LIBRARY +#endif //QT_MAKEDLL + return list; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgenericpluginfactory_lite.h b/src/gui/kernel/qgenericpluginfactory_lite.h new file mode 100644 index 0000000..3be4614 --- /dev/null +++ b/src/gui/kernel/qgenericpluginfactory_lite.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QGENERICPLUGINFACTORY_LITE_H +#define QGENERICPLUGINFACTORY_LITE_H + +#include <QtCore/qstringlist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QString; +class QObject; + +class Q_GUI_EXPORT QGenericPluginFactory +{ +public: + static QStringList keys(); + static QObject *create(const QString&, const QString &); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGENERICPLUGINFACTORY_QWS_H diff --git a/src/gui/kernel/qsound_lite.cpp b/src/gui/kernel/qsound_lite.cpp new file mode 100644 index 0000000..2e2c1e8 --- /dev/null +++ b/src/gui/kernel/qsound_lite.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qapplication.h" + +#ifndef QT_NO_SOUND + +#include "qsound.h" +#include "qsound_p.h" + +class QAuServerLite : public QAuServer +{ + Q_OBJECT +public: + QAuServerLite( QObject* parent ); + + void play( QSound* s ) {} + void stop( QSound* s ) {} + bool okay() { return false; } +}; + +QAuServerLite::QAuServerLite(QObject* parent) : + QAuServer(parent) +{ +} + +QAuServer* qt_new_audio_server() +{ + return new QAuServerLite(qApp); +} + +#include "qsound_lite.moc" + +#endif // QT_NO_SOUND + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 44f9db1..a3b861e 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -5266,7 +5266,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP //actually send the paint event QPaintEvent e(toBePainted); QCoreApplication::sendSpontaneousEvent(q, &e); -#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS) +#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS) && !defined(Q_WS_LITE) if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow())) backingStore->markDirtyOnScreen(toBePainted, q, offset); #endif diff --git a/src/gui/kernel/qwidget_lite.cpp b/src/gui/kernel/qwidget_lite.cpp new file mode 100644 index 0000000..bbc7766 --- /dev/null +++ b/src/gui/kernel/qwidget_lite.cpp @@ -0,0 +1,616 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qwidget.h" +#include "qevent.h" +#include "qapplication.h" +#include "private/qbackingstore_p.h" +#include "private/qwidget_p.h" +#include "private/qgraphicssystem_p.h" +#include "private/qapplication_p.h" + +QT_BEGIN_NAMESPACE + +void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destroyOldWindow*/) +{ + Q_Q(QWidget); + + Q_UNUSED(window); + Q_UNUSED(initializeWindow); + // XXX + + + Qt::WindowFlags flags = data.window_flags; + +#if 1 + QWindowSurface *surface = q->windowSurface(); + if (surface && (flags & Qt::Window)) + data.window_flags = surface->setWindowFlags(data.window_flags); +#endif +// qDebug() << "create_sys" << q; +} + +void QWidget::destroy(bool destroyWindow, bool destroySubWindows) +{ + Q_UNUSED(destroyWindow); + Q_UNUSED(destroySubWindows); + // XXX + + + if ((windowType() == Qt::Popup)) + qApp->d_func()->closePopup(this); + +} + +void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) +{ + Q_Q(QWidget); + + QWidget *oldParent = q->parentWidget(); + Qt::WindowFlags oldFlags = data.window_flags; + if (parent != newparent) { + QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function??? + + } + if (!newparent) { + f |= Qt::Window; + } + data.window_flags = f; + if (f & Qt::Window) { + //qDebug() << "setParent_sys" << q << newparent << hex << f; + if (QWindowSurface *surface = q->windowSurface()) + data.window_flags = surface->setWindowFlags(data.window_flags); + } + // XXX Reparenting child to toplevel or vice versa ### + if ((f&Qt::Window) && !(oldFlags&Qt::Window)) { + qDebug() << "setParent_sys() change to toplevel"; + q->create(); //### this cannot be right + } else if ((f&Qt::Window) && !(oldFlags&Qt::Window)) { + qDebug() << "######## setParent_sys() change from toplevel not implemented ########"; + } +} + +QPoint QWidget::mapToGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x += w->data->crect.x(); + y += w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +QPoint QWidget::mapFromGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x -= w->data->crect.x(); + y -= w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +void QWidgetPrivate::updateSystemBackground() {} + +#ifndef QT_NO_CURSOR +void QWidgetPrivate::setCursor_sys(const QCursor &cursor) +{ + Q_UNUSED(cursor); + Q_Q(QWidget); + if (q->isVisible()) + updateCursor(); +} + +void QWidgetPrivate::unsetCursor_sys() +{ + Q_Q(QWidget); + if (q->isVisible()) + updateCursor(); +} + +void QWidgetPrivate::updateCursor() const +{ + // XXX +} + +#endif //QT_NO_CURSOR + +void QWidgetPrivate::setWindowTitle_sys(const QString &caption) +{ + Q_UNUSED(caption); + // XXX +} + +void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/) +{ +} + +void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) +{ + Q_UNUSED(iconText); +} + +QWidget *qt_pressGrab = 0; +QWidget *qt_mouseGrb = 0; +static QWidget *keyboardGrb = 0; + +void QWidget::grabMouse() +{ + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + // XXX + //qwsDisplay()->grabMouse(this,true); + + qt_mouseGrb = this; + qt_pressGrab = 0; +} + +#ifndef QT_NO_CURSOR +void QWidget::grabMouse(const QCursor &cursor) +{ + Q_UNUSED(cursor); + + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + // XXX + //qwsDisplay()->grabMouse(this,true); + //qwsDisplay()->selectCursor(this, cursor.handle()); + qt_mouseGrb = this; + qt_pressGrab = 0; +} +#endif + +void QWidget::releaseMouse() +{ + if (qt_mouseGrb == this) { + // XXX + //qwsDisplay()->grabMouse(this,false); + qt_mouseGrb = 0; + } +} + +void QWidget::grabKeyboard() +{ + if (keyboardGrb) + keyboardGrb->releaseKeyboard(); + // XXX + //qwsDisplay()->grabKeyboard(this, true); + keyboardGrb = this; +} + +void QWidget::releaseKeyboard() +{ + if (keyboardGrb == this) { + // XXX + //qwsDisplay()->grabKeyboard(this, false); + keyboardGrb = 0; + } +} + +QWidget *QWidget::mouseGrabber() +{ + if (qt_mouseGrb) + return qt_mouseGrb; + return qt_pressGrab; +} + +QWidget *QWidget::keyboardGrabber() +{ + return keyboardGrb; +} + +void QWidget::activateWindow() +{ + // XXX +// qDebug() << "QWidget::activateWindow" << this; + QApplication::setActiveWindow(this); //##### +} + +void QWidgetPrivate::show_sys() +{ + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped); + if (q->testAttribute(Qt::WA_DontShowOnScreen)) { + invalidateBuffer(q->rect()); + return; + } + + QApplication::postEvent(q, new QUpdateLaterEvent(q->rect())); + + if (!q->isWindow()) + return; + + if (QWindowSurface *surface = q->windowSurface()) { + const QRect geomRect = q->geometry(); + if (surface->geometry() != geomRect) + surface->setGeometry(geomRect); + surface->setVisible(true); + } + + if (q->windowType() != Qt::Popup) + q->activateWindow(); //### +} + + +void QWidgetPrivate::hide_sys() +{ + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped, false); + if (!q->isWindow()) { + QWidget *p = q->parentWidget(); + if (p &&p->isVisible()) { + invalidateBuffer(q->rect()); + } + return; + } + if (QWindowSurface *surface = q->windowSurface()) { + surface->setVisible(false); + } + + //### we don't yet have proper focus event handling + if (q == QApplicationPrivate::active_window) + QApplication::setActiveWindow(0); + +} + +void QWidgetPrivate::setMaxWindowState_helper() +{ + // XXX +} + +void QWidgetPrivate::setFullScreenSize_helper() +{ + // XXX +} + +static Qt::WindowStates effectiveState(Qt::WindowStates state) + { + if (state & Qt::WindowMinimized) + return Qt::WindowMinimized; + else if (state & Qt::WindowFullScreen) + return Qt::WindowFullScreen; + else if (state & Qt::WindowMaximized) + return Qt::WindowMaximized; + return Qt::WindowNoState; + } + +void QWidget::setWindowState(Qt::WindowStates newstate) +{ + Q_D(QWidget); + Qt::WindowStates oldstate = windowState(); + if (oldstate == newstate) + return; + if (isWindow() && !testAttribute(Qt::WA_WState_Created)) + create(); + + data->window_state = newstate; + data->in_set_window_state = 1; + bool needShow = false; + Qt::WindowStates newEffectiveState = effectiveState(newstate); + Qt::WindowStates oldEffectiveState = effectiveState(oldstate); + if (isWindow() && newEffectiveState != oldEffectiveState) { + d->createTLExtra(); + if (oldEffectiveState == Qt::WindowNoState) { //normal + d->topData()->normalGeometry = geometry(); + } else if (oldEffectiveState == Qt::WindowFullScreen) { + setParent(0, d->topData()->savedFlags); + needShow = true; + } else if (oldEffectiveState == Qt::WindowMinimized) { + needShow = true; + } + + if (newEffectiveState == Qt::WindowMinimized) { + //### not ideal... + hide(); + needShow = false; + } else if (newEffectiveState == Qt::WindowFullScreen) { + d->topData()->savedFlags = windowFlags(); + setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint)); + d->setFullScreenSize_helper(); + raise(); + needShow = true; + } else if (newEffectiveState == Qt::WindowMaximized) { + createWinId(); + d->setMaxWindowState_helper(); + } else { //normal + QRect r = d->topData()->normalGeometry; + if (r.width() >= 0) { + d->topData()->normalGeometry = QRect(0,0,-1,-1); + setGeometry(r); + } + } + } + data->in_set_window_state = 0; + + if (needShow) + show(); + + if (newstate & Qt::WindowActive) + activateWindow(); + + QWindowStateChangeEvent e(oldstate); + QApplication::sendEvent(this, &e); +} + +void QWidgetPrivate::setFocus_sys() +{ + +} + +void QWidgetPrivate::raise_sys() +{ + // XXX +} + +void QWidgetPrivate::lower_sys() +{ + // XXX +} + +void QWidgetPrivate::stackUnder_sys(QWidget*) +{ + // XXX +} + +void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) +{ + Q_Q(QWidget); + if (extra) { // any size restrictions? + w = qMin(w,extra->maxw); + h = qMin(h,extra->maxh); + w = qMax(w,extra->minw); + h = qMax(h,extra->minh); + } + + QPoint oldp = q->geometry().topLeft(); + QSize olds = q->size(); + QRect r(x, y, w, h); + + bool isResize = olds != r.size(); + isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter? + + + // We only care about stuff that changes the geometry, or may + // cause the window manager to change its state + if (r.size() == olds && oldp == r.topLeft()) + return; + + if (!data.in_set_window_state) { + q->data->window_state &= ~Qt::WindowMaximized; + q->data->window_state &= ~Qt::WindowFullScreen; + if (q->isWindow()) + topData()->normalGeometry = QRect(0, 0, -1, -1); + } + + QPoint oldPos = q->pos(); + data.crect = r; + + if (q->isVisible()) { + + if (q->isWindow()) { + const QWidgetBackingStore *bs = maybeBackingStore(); + if (bs->windowSurface) + bs->windowSurface->setGeometry(q->frameGeometry()); + } else { + if (isMove && !isResize) + moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y()); + else + invalidateBuffer_resizeHelper(oldPos, olds); + } + + if (isMove) { + QMoveEvent e(q->pos(), oldPos); + QApplication::sendEvent(q, &e); + } + if (isResize) { + QResizeEvent e(r.size(), olds); + QApplication::sendEvent(q, &e); + } + } else { // not visible + if (isMove && q->pos() != oldPos) + q->setAttribute(Qt::WA_PendingMoveEvent, true); + if (isResize) + q->setAttribute(Qt::WA_PendingResizeEvent, true); + } + +} + +void QWidgetPrivate::setConstraints_sys() +{ +} + +void QWidgetPrivate::scroll_sys(int dx, int dy) +{ + Q_Q(QWidget); + scrollChildren(dx, dy); + scrollRect(q->rect(), dx, dy); +} + +void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) +{ + scrollRect(r, dx, dy); +} + +static QGraphicsSystemScreen *qt_screenForWidget(const QWidget *w) +{ + if (!w) + return 0; + QRect frame = w->frameGeometry(); + if (!w->isWindow()) + frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); + const QPoint p = (frame.topLeft() + frame.bottomRight()) / 2; + + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) { + qWarning("qt_screenForWidget: no graphics system"); + return 0; + } + QList<QGraphicsSystemScreen *> screens = gs->screens(); + + for (int i = 0; i < screens.size(); ++i) { + if (screens[i]->geometry().contains(p)) + return screens[i]; + } + + // Assume screen zero if we have it. + if (!screens.isEmpty()) + return screens[0]; + else + qWarning("qt_screenForWidget: no screens"); + + return 0; +} + +int QWidget::metric(PaintDeviceMetric m) const +{ + Q_D(const QWidget); + + QGraphicsSystemScreen *screen = qt_screenForWidget(this); + if (!screen) { + if (m == PdmDpiX || m == PdmDpiY) + return 72; + return QPaintDevice::metric(m); + } + int val; + if (m == PdmWidth) { + val = data->crect.width(); + } else if (m == PdmWidthMM) { + val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width(); + } else if (m == PdmHeight) { + val = data->crect.height(); + } else if (m == PdmHeightMM) { + val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height(); + } else if (m == PdmDepth) { + return screen->depth(); + } else if (m == PdmDpiX || m == PdmPhysicalDpiX) { + if (d->extra && d->extra->customDpiX) + return d->extra->customDpiX; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + return qRound(screen->geometry().width() / double(screen->physicalSize().width() / 25.4)); + } else if (m == PdmDpiY || m == PdmPhysicalDpiY) { + if (d->extra && d->extra->customDpiY) + return d->extra->customDpiY; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + return qRound(screen->geometry().height() / double(screen->physicalSize().height() / 25.4)); + } else { + val = QPaintDevice::metric(m);// XXX + } + return val; +} + +void QWidgetPrivate::createSysExtra() +{ +} + +void QWidgetPrivate::deleteSysExtra() +{ +} + +void QWidgetPrivate::createTLSysExtra() +{ +} + +void QWidgetPrivate::deleteTLSysExtra() +{ +} + +void QWidgetPrivate::registerDropSite(bool on) +{ + Q_UNUSED(on); +} + +void QWidgetPrivate::setMask_sys(const QRegion ®ion) +{ + Q_UNUSED(region); + // XXX +} + +void QWidgetPrivate::updateFrameStrut() +{ + // XXX +} + +void QWidgetPrivate::setWindowOpacity_sys(qreal level) +{ + Q_UNUSED(level); + // XXX +} + +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) +{ + Q_UNUSED(dontShow); + Q_UNUSED(oldRect); + // XXX +} + +QPaintEngine *QWidget::paintEngine() const +{ + qWarning("QWidget::paintEngine: Should no longer be called"); + return 0; //##### @@@ +} + +QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() +{ + Q_Q(QWidget); + if (q->windowType() == Qt::Desktop) + return 0; + q->ensurePolished(); + + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) + return 0; + + return gs->createWindowSurface(q); +} + +void QWidgetPrivate::setModal_sys() +{ +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index f69c3a7..3636ffb 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -681,6 +681,12 @@ public: void updateCursor() const; #endif QScreen* getScreen() const; +#elif defined(Q_WS_LITE) + void setMaxWindowState_helper(); + void setFullScreenSize_helper(); +#ifndef QT_NO_CURSOR + void updateCursor() const; +#endif #elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN static QWidget *mouseGrabber; static QWidget *keyboardGrabber; diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h index da3425d..a114bb1 100644 --- a/src/gui/kernel/qwindowdefs.h +++ b/src/gui/kernel/qwindowdefs.h @@ -131,6 +131,12 @@ QT_END_HEADER #endif // Q_WS_QWS +#if defined(Q_WS_LITE) + +typedef unsigned long WId; + +#endif // Q_WS_LITE + #if defined(Q_OS_SYMBIAN) class CCoeControl; typedef CCoeControl * WId; diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 5abac2f..1f2076c 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -136,7 +136,7 @@ unix:x11 { painting/qpaintengine_x11.cpp } -!embedded:!x11:mac { +!embedded:!embedded_lite:!x11:mac { HEADERS += \ painting/qpaintengine_mac_p.h \ painting/qgraphicssystem_mac_p.h \ @@ -152,14 +152,14 @@ unix:x11 { painting/qprintengine_mac.mm \ } -unix:!mac:!symbian { +unix:!mac:!symbian|embedded_lite { HEADERS += \ painting/qprinterinfo_unix_p.h SOURCES += \ painting/qprinterinfo_unix.cpp } -win32|x11|mac|embedded|symbian { +win32|x11|mac|embedded|embedded_lite|symbian { SOURCES += painting/qbackingstore.cpp HEADERS += painting/qbackingstore_p.h } @@ -176,13 +176,19 @@ embedded { painting/qpaintdevice_qws.cpp } +embedded_lite { + SOURCES += \ + painting/qcolormap_lite.cpp \ + painting/qpaintdevice_lite.cpp +} + symbian { SOURCES += \ painting/qregion_s60.cpp \ painting/qcolormap_s60.cpp } -x11|embedded { +x11|embedded|embedded_lite { contains(QT_CONFIG,qtopia) { DEFINES += QT_NO_CUPS QT_NO_LPR } else { @@ -348,7 +354,7 @@ x11 { SOURCES += painting/qwindowsurface_x11.cpp } -mac { +!embedded:!embedded_lite:mac { HEADERS += painting/qwindowsurface_mac_p.h SOURCES += painting/qwindowsurface_mac.cpp } diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index e82f36e..d1ead97 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -691,9 +691,12 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion ®ion, QWidget *widg } // Alien widgets. - if (!widget->internalWinId()) { - QWidget *nativeParent = widget->nativeParentWidget(); - // Alien widgets with the top-level as the native parent (common case). + if (!widget->internalWinId() && !widget->isWindow()) { //### LITEHACK we need winid support!!! +#ifdef Q_WS_LITE + QWidget *nativeParent = widget->window(); //### LITEHACK so far only toplevels are native +#else + QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case). +#endif if (nativeParent == tlw) { if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) dirtyOnScreen += region.translated(topLevelOffset); diff --git a/src/gui/painting/qcolormap_lite.cpp b/src/gui/painting/qcolormap_lite.cpp new file mode 100644 index 0000000..b8ae1af --- /dev/null +++ b/src/gui/painting/qcolormap_lite.cpp @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qcolormap.h" +#include "qcolor.h" +#include "qpaintdevice.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" + +QT_BEGIN_NAMESPACE + +class QColormapPrivate +{ +public: + inline QColormapPrivate() + : ref(1), mode(QColormap::Direct), depth(0), numcolors(0) + { } + + QAtomicInt ref; + + QColormap::Mode mode; + int depth; + int numcolors; +}; + +static QColormapPrivate *screenMap = 0; + +void QColormap::initialize() +{ + screenMap = new QColormapPrivate; + + QGraphicsSystem *gs = QApplicationPrivate::graphicsSystem(); + if (!gs) + return; + QList<QGraphicsSystemScreen *> screens = gs->screens(); + if (screens.isEmpty()) + return; + + screenMap->depth = screens[0]->depth(); + if (screenMap->depth < 8) { + screenMap->mode = QColormap::Indexed; + screenMap->numcolors = 256; + } else { + screenMap->mode = QColormap::Direct; + screenMap->numcolors = -1; + } +} + +void QColormap::cleanup() +{ + delete screenMap; + screenMap = 0; +} + +QColormap QColormap::instance(int /*screen*/) +{ + return QColormap(); +} + +QColormap::QColormap() + : d(screenMap) +{ d->ref.ref(); } + +QColormap::QColormap(const QColormap &colormap) + :d (colormap.d) +{ d->ref.ref(); } + +QColormap::~QColormap() +{ + if (!d->ref.deref()) + delete d; +} + +QColormap::Mode QColormap::mode() const +{ return d->mode; } + + +int QColormap::depth() const +{ return d->depth; } + + +int QColormap::size() const +{ + return d->numcolors; +} + +#ifndef QT_QWS_DEPTH16_RGB +#define QT_QWS_DEPTH16_RGB 565 +#endif +static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100); +static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10); +static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10); +static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); +static const int qt_green_shift = qt_bbits-(8-qt_gbits); +static const int qt_neg_blue_shift = 8-qt_bbits; +static const int qt_blue_mask = (1<<qt_bbits)-1; +static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits); +static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); + +static const int qt_red_rounding_shift = qt_red_shift + qt_rbits; +static const int qt_green_rounding_shift = qt_green_shift + qt_gbits; +static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift; + +inline ushort qt_convRgbTo16(QRgb c) +{ + const int tr = qRed(c) << qt_red_shift; + const int tg = qGreen(c) << qt_green_shift; + const int tb = qBlue(c) >> qt_neg_blue_shift; + + return (tb & qt_blue_mask) | (tg & qt_green_mask) | (tr & qt_red_mask); +} + +inline QRgb qt_conv16ToRgb(ushort c) +{ + const int r=(c & qt_red_mask); + const int g=(c & qt_green_mask); + const int b=(c & qt_blue_mask); + const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift; + const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift; + const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift; + + return qRgb(tr,tg,tb); +} + +uint QColormap::pixel(const QColor &color) const +{ + QRgb rgb = color.rgba(); + if (d->mode == QColormap::Direct) { + switch(d->depth) { + case 16: + return qt_convRgbTo16(rgb); + case 24: + case 32: + { + const int r = qRed(rgb); + const int g = qGreen(rgb); + const int b = qBlue(rgb); + const int red_shift = 16; + const int green_shift = 8; + const int red_mask = 0xff0000; + const int green_mask = 0x00ff00; + const int blue_mask = 0x0000ff; + const int tg = g << green_shift; +#ifdef QT_QWS_DEPTH_32_BGR + if (qt_screen->pixelType() == QScreen::BGRPixel) { + const int tb = b << red_shift; + return 0xff000000 | (r & blue_mask) | (tg & green_mask) | (tb & red_mask); + } +#endif + const int tr = r << red_shift; + return 0xff000000 | (b & blue_mask) | (tg & green_mask) | (tr & red_mask); + } + } + } + //XXX + //return qt_screen->alloc(qRed(rgb), qGreen(rgb), qBlue(rgb)); + return 0; +} + +const QColor QColormap::colorAt(uint pixel) const +{ + if (d->mode == Direct) { + if (d->depth == 16) { + pixel = qt_conv16ToRgb(pixel); + } + const int red_shift = 16; + const int green_shift = 8; + const int red_mask = 0xff0000; + const int green_mask = 0x00ff00; + const int blue_mask = 0x0000ff; +#ifdef QT_QWS_DEPTH_32_BGR + if (qt_screen->pixelType() == QScreen::BGRPixel) { + return QColor((pixel & blue_mask), + (pixel & green_mask) >> green_shift, + (pixel & red_mask) >> red_shift); + } +#endif + return QColor((pixel & red_mask) >> red_shift, + (pixel & green_mask) >> green_shift, + (pixel & blue_mask)); + } +#if 0 // XXX + Q_ASSERT_X(int(pixel) < qt_screen->numCols(), "QColormap::colorAt", "pixel out of bounds of palette"); + return QColor(qt_screen->clut()[pixel]); +#endif + return QColor(); +} + +const QVector<QColor> QColormap::colormap() const +{ + return QVector<QColor>(); +} + +QColormap &QColormap::operator=(const QColormap &colormap) +{ qAtomicAssign(d, colormap.d); return *this; } + +QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index a7f5efb..ce8e500 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -50,6 +50,9 @@ #ifdef Q_WS_MAC # include <private/qpixmap_mac_p.h> #endif +#ifdef Q_WS_LITE +# include <private/qpixmap_raster_p.h> +#endif QT_BEGIN_NAMESPACE @@ -68,11 +71,26 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); +#elif defined(Q_WS_LITE) + return new QRasterPixmapData(type); #elif !defined(Q_WS_QWS) #error QGraphicsSystem::createDefaultPixmapData() not implemented #endif return 0; } +QList<QGraphicsSystemScreen *> QGraphicsSystem::screens() const +{ + return QList<QGraphicsSystemScreen *>(); +} + +QGraphicsSystemScreen::~QGraphicsSystemScreen() +{ +} + +QRect QGraphicsSystemScreen::availableGeometry() const +{ + return geometry(); +} QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h index c4f87f7..7e1ef67 100644 --- a/src/gui/painting/qgraphicssystem_p.h +++ b/src/gui/painting/qgraphicssystem_p.h @@ -60,6 +60,18 @@ QT_BEGIN_NAMESPACE class QPixmapFilter; +class Q_GUI_EXPORT QGraphicsSystemScreen +{ +public: + virtual ~QGraphicsSystemScreen(); + + virtual QRect geometry() const = 0; + virtual QRect availableGeometry() const; + virtual int depth() const = 0; + virtual QImage::Format format() const = 0; + virtual QSize physicalSize() const = 0; +}; + class Q_GUI_EXPORT QGraphicsSystem { public: @@ -68,6 +80,8 @@ public: virtual ~QGraphicsSystem() = 0; + virtual QList<QGraphicsSystemScreen *> screens() const; + //### Remove this & change qpixmap.cpp & qbitmap.cpp once every platform is gaurenteed // to have a graphics system. static QPixmapData *createDefaultPixmapData(QPixmapData::PixelType type); diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp index 7ee0818..b6bd40c 100644 --- a/src/gui/painting/qpaintdevice.cpp +++ b/src/gui/painting/qpaintdevice.cpp @@ -59,10 +59,12 @@ QPaintDevice::~QPaintDevice() } +#ifndef Q_WS_LITE int QPaintDevice::metric(PaintDeviceMetric) const { qWarning("QPaintDevice::metrics: Device has no metric information"); return 0; } +#endif QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintdevice_lite.cpp b/src/gui/painting/qpaintdevice_lite.cpp new file mode 100644 index 0000000..2560bf5 --- /dev/null +++ b/src/gui/painting/qpaintdevice_lite.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + +#include "qpaintdevice.h" +#include "qpainter.h" +#include "qwidget.h" +#include "qbitmap.h" +#include "qapplication.h" + +QT_BEGIN_NAMESPACE + +extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp + +int QPaintDevice::metric(PaintDeviceMetric m) const +{ + qWarning("QPaintDevice::metrics: Device has no metric information"); + if (m == PdmDpiX) { + return 72; + } else if (m == PdmDpiY) { + return 72; + } else if (m == PdmNumColors) { + // FIXME: does this need to be a real value? + return 256; + } else { + qDebug("Unrecognised metric %d!",m); + return 0; + } +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index 921db4f..6da0a2f 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -270,6 +270,9 @@ private: friend class QtopiaPrintEnginePrivate; friend class QProxyFontEngine; #endif +#ifdef Q_WS_LITE + friend class QProxyFontEngine; +#endif friend class QPainter; friend class QPainterPrivate; friend class QWidget; diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index d138663..3e3e8b9 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -1627,7 +1627,7 @@ QT_END_INCLUDE_NAMESPACE QT_BEGIN_INCLUDE_NAMESPACE # include "qregion_win.cpp" QT_END_INCLUDE_NAMESPACE -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_LITE) static QRegionPrivate qrp; QRegion::QRegionData QRegion::shared_empty = {Q_BASIC_ATOMIC_INITIALIZER(1), &qrp}; #endif @@ -4233,7 +4233,7 @@ QRect QRegion::boundingRect() const Returns true if \a rect is guaranteed to be fully contained in \a region. A false return value does not guarantee the opposite. */ -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) Q_GUI_EXPORT #endif bool qt_region_strictContains(const QRegion ®ion, const QRect &rect) diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index 226e3fa..786283c 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -59,7 +59,7 @@ QT_MODULE(Gui) template <class T> class QVector; class QVariant; -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) struct QRegionPrivate; #endif @@ -160,7 +160,7 @@ public: #endif HIMutableShapeRef toHIMutableShape() const; static QRegion fromHIShapeRef(HIShapeRef shape); -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_LITE) inline void *handle() const { return d->qt_rgn; } #endif #endif @@ -200,7 +200,7 @@ private: #elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove. #endif -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) QRegionPrivate *qt_rgn; #endif }; diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp index 1bd343d..c750a05 100644 --- a/src/gui/painting/qwindowsurface.cpp +++ b/src/gui/painting/qwindowsurface.cpp @@ -349,4 +349,35 @@ void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) } } + +#ifdef Q_WS_LITE +/*! +Requests setting the window flags of this surface to \a type. Returns the actual flags set. +*/ +Qt::WindowFlags QWindowSurface::setWindowFlags(Qt::WindowFlags type) +{ + Q_UNUSED(type); + qDebug() << "QWindowSurface::setWindowFlags" << hex << type; + return Qt::Window; +} + +/*! + Returns the effective window flags for this surface. +*/ +Qt::WindowFlags QWindowSurface::windowFlags() const +{ + return Qt::Window; +} + +/*! +Reimplemented in subclasses to show the surface if \a visible is \c true, and hide it if \a visible is \c false. +*/ + +void QWindowSurface::setVisible(bool visible) +{ + Q_UNUSED(visible); +} + +#endif + QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_p.h b/src/gui/painting/qwindowsurface_p.h index 502e10d..06d3dad 100644 --- a/src/gui/painting/qwindowsurface_p.h +++ b/src/gui/painting/qwindowsurface_p.h @@ -89,6 +89,11 @@ public: virtual QPoint offset(const QWidget *widget) const; inline QRect rect(const QWidget *widget) const; +#ifdef Q_WS_LITE + virtual void setVisible(bool visible); + virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags type); + virtual Qt::WindowFlags windowFlags() const; +#endif bool hasStaticContentsSupport() const; void setStaticContents(const QRegion ®ion); diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri index 767ade0..78d0359 100644 --- a/src/gui/styles/styles.pri +++ b/src/gui/styles/styles.pri @@ -33,7 +33,7 @@ contains( styles, all ) { styles = mac windows windowsxp windowsvista } -x11|embedded|!macx-*:styles -= mac +x11|embedded|embedded_lite|!macx-*:styles -= mac x11{ QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 03f69db..b9ce238 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -172,6 +172,8 @@ Q_GUI_EXPORT int qt_defaultDpiX() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4))); +#elif defined(Q_WS_LITE) + dpi = 72; #elif defined(Q_OS_SYMBIAN) dpi = S60->defaultDpiX; #endif // Q_WS_X11 @@ -200,6 +202,8 @@ Q_GUI_EXPORT int qt_defaultDpiY() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4))); +#elif defined(Q_WS_LITE) + dpi = 72; #elif defined(Q_OS_SYMBIAN) dpi = S60->defaultDpiY; #endif // Q_WS_X11 diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 9fe660a..33aa4c4 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -46,7 +46,7 @@ #include <QtCore/qstring.h> #include <QtCore/qsharedpointer.h> -#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_LITE) typedef struct FT_FaceRec_* FT_Face; #endif @@ -232,7 +232,7 @@ public: #ifdef Q_WS_MAC quint32 macFontID() const; #endif -#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_LITE) FT_Face freetypeFace() const; #endif diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 78847ef..98d848f 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -56,7 +56,7 @@ #include <stdlib.h> #include <limits.h> -#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) # include <ft2build.h> # include FT_TRUETYPE_TABLES_H #endif @@ -153,10 +153,11 @@ struct QtFontSize QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0, uint yres = 0, uint avgwidth = 0, bool add = false); #endif // Q_WS_X11 -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) + +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) QByteArray fileName; int fileIndex; -#endif // defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#endif // defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) }; @@ -230,14 +231,14 @@ struct QtFontStyle delete [] weightName; delete [] setwidthName; #endif -#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) while (count) { // bitfield count-- in while condition does not work correctly in mwccsym2 count--; #ifdef Q_WS_X11 free(pixelSizes[count].encodings); #endif -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) pixelSizes[count].fileName.~QByteArray(); #endif } @@ -255,7 +256,7 @@ struct QtFontStyle const char *weightName; const char *setwidthName; #endif // Q_WS_X11 -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) bool antialiased; #endif @@ -296,7 +297,7 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add) pixelSizes[count].count = 0; pixelSizes[count].encodings = 0; #endif -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) new (&pixelSizes[count].fileName) QByteArray; pixelSizes[count].fileIndex = 0; #endif @@ -382,7 +383,7 @@ struct QtFontFamily fixedPitchComputed(false), #endif name(n), count(0), foundries(0) -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) , bogusWritingSystems(false) #endif { @@ -422,7 +423,7 @@ struct QtFontFamily int count; QtFontFoundry **foundries; -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) bool bogusWritingSystems; QStringList fallbackFamilies; #endif @@ -469,7 +470,8 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) // ### copied to tools/makeqpf/qpf2.cpp -#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)) +#if ((defined(Q_WS_QWS) || defined(Q_WS_LITE)) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)) + // see the Unicode subset bitfields in the MSDN docs static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { // Any, @@ -604,7 +606,7 @@ class QFontDatabasePrivate public: QFontDatabasePrivate() : count(0), families(0), reregisterAppFonts(false) -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) , stream(0) #endif #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) @@ -652,11 +654,11 @@ public: void invalidate(); -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) bool loadFromCache(const QString &fontPath); void addQPF2File(const QByteArray &file); #endif // Q_WS_QWS -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, @@ -665,7 +667,7 @@ public: QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray()); #endif // QT_NO_FREETYPE #endif -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined (Q_WS_LITE) QDataStream *stream; QStringList fallbackFamilies; #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) @@ -719,7 +721,7 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) return families[pos]; } -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, const QList<QFontDatabase::WritingSystem> &writingSystems) @@ -750,7 +752,7 @@ void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundr size->fileName = file; size->fileIndex = fileIndex; -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) if (stream) { *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize << file << fileIndex << quint8(antialiased); @@ -765,7 +767,7 @@ void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundr } #endif -#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_QWS) || defined (Q_WS_LITE) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData) { QStringList families; @@ -877,7 +879,7 @@ static const int scriptForWritingSystem[] = { }; -#if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN) +#if defined Q_WS_QWS || defined(Q_WS_LITE) || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN) static inline bool requiresOpenType(int writingSystem) { return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) @@ -951,7 +953,7 @@ static void match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>()); -#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_LITE) static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef) { fontDef->family = desc.family->name; @@ -1039,7 +1041,7 @@ QT_BEGIN_INCLUDE_NAMESPACE # include "qfontdatabase_mac.cpp" #elif defined(Q_WS_WIN) # include "qfontdatabase_win.cpp" -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_LITE) # include "qfontdatabase_qws.cpp" #elif defined(Q_OS_SYMBIAN) # include "qfontdatabase_s60.cpp" diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index e62bb31..9b92c57 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -151,7 +151,7 @@ public: private: static void createDatabase(); static void parseFontName(const QString &name, QString &foundry, QString &family); -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request); #endif static void load(const QFontPrivate *d, int script); diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp index 0a9630f..62c67a3 100644 --- a/src/gui/text/qfontdatabase_qws.cpp +++ b/src/gui/text/qfontdatabase_qws.cpp @@ -40,8 +40,10 @@ ****************************************************************************/ #include "qdir.h" +#if defined(Q_WS_QWS) #include "qscreen_qws.h" //so we can check for rotation #include "qwindowsystem_qws.h" +#endif #include "qlibraryinfo.h" #include "qabstractfileengine.h" #include <QtCore/qsettings.h> @@ -153,7 +155,11 @@ extern QString qws_fontCacheDir(); #ifndef QT_FONTS_ARE_RESOURCES bool QFontDatabasePrivate::loadFromCache(const QString &fontPath) { +#ifdef Q_WS_QWS const bool weAreTheServer = QWSServer::instance(); +#else + const bool weAreTheServer = true; // assume single-process +#endif QString fontDirFile = fontPath + QLatin1String("/fontdir"); @@ -687,6 +693,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, { QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry, style, size)); +#ifndef QT_NO_QWS_QPF if (!engine.isNull() && script == QUnicodeTables::Common && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) { @@ -700,6 +707,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, engine.take(); engine.reset(fe); } +#endif return engine.take(); } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 7a3b3e1..74d72c4 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -816,7 +816,7 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(QFontEngineGlyphCache::Type key, return 0; } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs) { uint left_right = (left << 16) + right; @@ -1182,7 +1182,7 @@ glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout &glyphs) return overall; } -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti) { if (!ti.glyphs.numGlyphs) diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 4cc5c5e..9e10eab 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -256,7 +256,7 @@ public: QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix); bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render); -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {} #endif diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index d654215..dc17c83 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -234,7 +234,7 @@ public: bool symbol; mutable HB_FontRec hbFont; mutable HB_Face hbFace; -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_LITE) || defined(Q_OS_SYMBIAN) struct KernPair { uint left_right; QFixed adjust; diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index b28ecd7..2375f08 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -85,7 +85,7 @@ unix:x11 { text/qfontengine_ft.cpp } -!embedded:!x11:mac { +!embedded:!embedded_lite:!x11:mac { SOURCES += \ text/qfont_mac.cpp OBJECTIVE_SOURCES += text/qfontengine_mac.mm @@ -106,6 +106,19 @@ embedded { DEFINES += QT_NO_FONTCONFIG } +embedded_lite { + SOURCES += \ + text/qfont_qws.cpp \ + text/qfontengine_ft.cpp \ + text/qfontengine_qpf.cpp \ + text/qabstractfontengine_qws.cpp + HEADERS += \ + text/qfontengine_ft_p.h \ + text/qabstractfontengine_qws.h \ + text/qabstractfontengine_p.h + DEFINES += QT_NO_FONTCONFIG +} + symbian { SOURCES += \ text/qfont_s60.cpp diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 76f583d..da4de73 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -45,7 +45,7 @@ #include <qdebug.h> -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_LITE) #include "qdesktopservices_qws.cpp" #elif defined(Q_WS_X11) #include "qdesktopservices_x11.cpp" diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri index cdbb7cc..e718c7b 100644 --- a/src/gui/util/util.pri +++ b/src/gui/util/util.pri @@ -30,12 +30,12 @@ unix:x11 { util/qsystemtrayicon_x11.cpp } -embedded { +embedded|embedded_lite { SOURCES += \ util/qsystemtrayicon_qws.cpp } -!embedded:!x11:mac { +!embedded:!embedded_lite:!x11:mac { OBJECTIVE_SOURCES += util/qsystemtrayicon_mac.mm } diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index da18f86..db6a572 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -112,7 +112,7 @@ void QLineControl::updateDisplayText() Copies the currently selected text into the clipboard using the given \a mode. - + \note If the echo mode is set to a mode other than Normal then copy will not work. This is to prevent using copy as a method of bypassing password features of the line control. @@ -479,7 +479,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) /*! \internal - Draws the display text for the line control using the given + Draws the display text for the line control using the given \a painter, \a clip, and \a offset. Which aspects of the display text are drawn is specified by the given \a flags. diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri index 4567902..5ee693c 100644 --- a/src/gui/widgets/widgets.pri +++ b/src/gui/widgets/widgets.pri @@ -146,7 +146,7 @@ SOURCES += \ widgets/qprintpreviewwidget.cpp \ widgets/qactiontokeyeventmapper.cpp -!embedded:mac { +!embedded:!embedded_lite:mac { HEADERS += widgets/qmacnativewidget_mac.h \ widgets/qmaccocoaviewcontainer_mac.h OBJECTIVE_HEADERS += widgets/qcocoatoolbardelegate_mac_p.h \ diff --git a/src/plugins/generic/linuxinput/linuxinput.pro b/src/plugins/generic/linuxinput/linuxinput.pro new file mode 100644 index 0000000..ad9f6a9 --- /dev/null +++ b/src/plugins/generic/linuxinput/linuxinput.pro @@ -0,0 +1,18 @@ +TARGET = qlinuxinputplugin +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/generic +target.path = $$[QT_INSTALL_PLUGINS]/generic +INSTALLS += target + +DEFINES += QT_QWS_KBD_LINUXINPUT + +HEADERS = qlinuxinput.h + +SOURCES = main.cpp \ + qlinuxinput.cpp + +HEADERS += $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws.h \ + $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws_p.h + +SOURCES += $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws.cpp diff --git a/src/plugins/generic/linuxinput/main.cpp b/src/plugins/generic/linuxinput/main.cpp new file mode 100644 index 0000000..21209b8 --- /dev/null +++ b/src/plugins/generic/linuxinput/main.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 <qgenericplugin_lite.h> +#include "qlinuxinput.h" + +QT_BEGIN_NAMESPACE + +class QLinuxInputPlugin : public QGenericPlugin +{ +public: + QLinuxInputPlugin(); + + QStringList keys() const; + QObject* create(const QString &key, const QString &specification); +}; + +QLinuxInputPlugin::QLinuxInputPlugin() + : QGenericPlugin() +{ +} + +QStringList QLinuxInputPlugin::keys() const +{ + return (QStringList() + << QLatin1String("LinuxInputMouse") + << QLatin1String("LinuxInputKeyboard")); +} + +QObject* QLinuxInputPlugin::create(const QString &key, + const QString &specification) +{ + if (!key.compare(QLatin1String("LinuxInputMouse"), Qt::CaseInsensitive)) + return new QLinuxInputMouseHandler(key, specification); + if (!key.compare(QLatin1String("LinuxInputKeyboard"), Qt::CaseInsensitive)) + return new QLinuxInputKeyboardHandler(key, specification); + return 0; + } + +Q_EXPORT_PLUGIN2(qlinuxinputplugin, QLinuxInputPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/generic/linuxinput/qlinuxinput.cpp b/src/plugins/generic/linuxinput/qlinuxinput.cpp new file mode 100644 index 0000000..2ce687d --- /dev/null +++ b/src/plugins/generic/linuxinput/qlinuxinput.cpp @@ -0,0 +1,371 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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$ +** +****************************************************************************/ + + +#include "qlinuxinput.h" + + +#include <QSocketNotifier> +#include <QStringList> +#include <QPoint> +#include <QMouseEvent> +#include <private/qapplication_p.h> + +#include <qkbd_qws.h> + + +#include <qplatformdefs.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN + +#include <errno.h> +#include <termios.h> + +#include <linux/kd.h> +#include <linux/input.h> + +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +QLinuxInputMouseHandler::QLinuxInputMouseHandler(const QString &key, + const QString &specification) + : m_notify(0), m_x(0), m_y(0), m_buttons(0) +{ + qDebug() << "QLinuxInputMouseHandler" << key << specification; + + + setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler")); + + QString dev = QLatin1String("/dev/input/event0"); + if (specification.startsWith(QLatin1String("/dev/"))) + dev = specification; + + m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); + if (m_fd >= 0) { + m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); + } else { + qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno)); + return; + } + +} + + +QLinuxInputMouseHandler::~QLinuxInputMouseHandler() +{ + if (m_fd >= 0) + QT_CLOSE(m_fd); +} + +void QLinuxInputMouseHandler::readMouseData() +{ + struct ::input_event buffer[32]; + int n = 0; + + forever { + n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); + + if (n == 0) { + qWarning("Got EOF from the input device."); + return; + } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) { + qWarning("Could not read from input device: %s", strerror(errno)); + return; + } else if (n % sizeof(buffer[0]) == 0) { + break; + } + } + + n /= sizeof(buffer[0]); + + for (int i = 0; i < n; ++i) { + struct ::input_event *data = &buffer[i]; + + bool unknown = false; + if (data->type == EV_ABS) { + if (data->code == ABS_X) { + m_x = data->value; + } else if (data->code == ABS_Y) { + m_y = data->value; + } else { + unknown = true; + } + } else if (data->type == EV_REL) { + if (data->code == REL_X) { + m_x += data->value; + } else if (data->code == REL_Y) { + m_y += data->value; + } else { + unknown = true; + } + } else if (data->type == EV_KEY && data->code == BTN_TOUCH) { + m_buttons = data->value ? Qt::LeftButton : Qt::NoButton; + } else if (data->type == EV_KEY) { + Qt::MouseButton button = Qt::NoButton; + switch (data->code) { + case BTN_LEFT: button = Qt::LeftButton; break; + case BTN_MIDDLE: button = Qt::MidButton; break; + case BTN_RIGHT: button = Qt::RightButton; break; + } + if (data->value) + m_buttons |= button; + else + m_buttons &= ~button; + + Qt::KeyboardModifiers modifiers = Qt::NoModifier; //### + QMouseEvent m(data->value ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease, + QPoint(m_x, m_y), QPoint(m_x, m_y), button, m_buttons, modifiers); + QApplicationPrivate::handleMouseEvent(0, m); + } else if (data->type == EV_SYN && data->code == SYN_REPORT) { + QPoint pos(m_x, m_y); + + Qt::KeyboardModifiers modifiers = Qt::NoModifier; //### + QMouseEvent m(QEvent::MouseMove, QPoint(m_x, m_y), QPoint(m_x, m_y), + Qt::NoButton, m_buttons, modifiers); + QApplicationPrivate::handleMouseEvent(0, m); + + // pos = m_handler->transform(pos); + //m_handler->limitToScreen(pos); + //m_handler->mouseChanged(pos, m_buttons); + + } else if (data->type == EV_MSC && data->code == MSC_SCAN) { + // kernel encountered an unmapped key - just ignore it + continue; + } else { + unknown = true; + } + if (unknown) { + qWarning("unknown mouse event type=%x, code=%x, value=%x", data->type, data->code, data->value); + } + } +} + + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//Keyboard handler + + + + +class QWSLinuxInputKeyboardHandler : public QWSKeyboardHandler +{ +public: + QWSLinuxInputKeyboardHandler(const QString&); + ~QWSLinuxInputKeyboardHandler(); + + virtual bool filterInputEvent(quint16 &input_code, qint32 &input_value); + +//private: +// QWSLinuxInputKbPrivate *d; +}; + + +QWSLinuxInputKeyboardHandler::QWSLinuxInputKeyboardHandler(const QString &device) + : QWSKeyboardHandler(device) +{ +} + +QWSLinuxInputKeyboardHandler::~QWSLinuxInputKeyboardHandler() +{ +} + +bool QWSLinuxInputKeyboardHandler::filterInputEvent(quint16 &, qint32 &) +{ + return false; +} + + +QLinuxInputKeyboardHandler::QLinuxInputKeyboardHandler(const QString &key, const QString &specification) + : m_handler(0), m_fd(-1), m_tty_fd(-1), m_orig_kbmode(K_XLATE) +{ + setObjectName(QLatin1String("LinuxInputSubsystem Keyboard Handler")); + + QString dev = QLatin1String("/dev/input/event1"); + int repeat_delay = -1; + int repeat_rate = -1; + + QStringList args = specification.split(QLatin1Char(':')); + foreach (const QString &arg, args) { + if (arg.startsWith(QLatin1String("repeat-delay="))) + repeat_delay = arg.mid(13).toInt(); + else if (arg.startsWith(QLatin1String("repeat-rate="))) + repeat_rate = arg.mid(12).toInt(); + else if (arg.startsWith(QLatin1String("/dev/"))) + dev = arg; + } + + m_handler = new QWSLinuxInputKeyboardHandler(dev); //This is a hack to avoid copying all the QWS code + + m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0); + if (m_fd >= 0) { + if (repeat_delay > 0 && repeat_rate > 0) { + int kbdrep[2] = { repeat_delay, repeat_rate }; + ::ioctl(m_fd, EVIOCSREP, kbdrep); + } + + QSocketNotifier *notifier; + notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode())); + + // play nice in case we are started from a shell (e.g. for debugging) + m_tty_fd = isatty(0) ? 0 : -1; + + if (m_tty_fd >= 0) { + // save tty config for restore. + tcgetattr(m_tty_fd, &m_tty_attr); + + struct ::termios termdata; + tcgetattr(m_tty_fd, &termdata); + + // record the original mode so we can restore it again in the destructor. + ::ioctl(m_tty_fd, KDGKBMODE, &m_orig_kbmode); + + // setting this tranlation mode is even needed in INPUT mode to prevent + // the shell from also interpreting codes, if the process has a tty + // attached: e.g. Ctrl+C wouldn't copy, but kill the application. + ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW); + + // set the tty layer to pass-through + termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + termdata.c_oflag = 0; + termdata.c_cflag = CREAD | CS8; + termdata.c_lflag = 0; + termdata.c_cc[VTIME]=0; + termdata.c_cc[VMIN]=1; + cfsetispeed(&termdata, 9600); + cfsetospeed(&termdata, 9600); + tcsetattr(m_tty_fd, TCSANOW, &termdata); + } + } else { + qWarning("Cannot open keyboard input device '%s': %s", qPrintable(dev), strerror(errno)); + return; + } +} + +QLinuxInputKeyboardHandler::~QLinuxInputKeyboardHandler() +{ + if (m_tty_fd >= 0) { + ::ioctl(m_tty_fd, KDSKBMODE, m_orig_kbmode); + tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr); + } + if (m_fd >= 0) + QT_CLOSE(m_fd); + delete m_handler; +} + +void QLinuxInputKeyboardHandler::switchLed(int led, bool state) +{ + struct ::input_event led_ie; + ::gettimeofday(&led_ie.time, 0); + led_ie.type = EV_LED; + led_ie.code = led; + led_ie.value = state; + + QT_WRITE(m_fd, &led_ie, sizeof(led_ie)); +} + + + +void QLinuxInputKeyboardHandler::readKeycode() +{ + struct ::input_event buffer[32]; + int n = 0; + + forever { + n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); + + if (n == 0) { + qWarning("Got EOF from the input device."); + return; + } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) { + qWarning("Could not read from input device: %s", strerror(errno)); + return; + } else if (n % sizeof(buffer[0]) == 0) { + break; + } + } + + n /= sizeof(buffer[0]); + + for (int i = 0; i < n; ++i) { + if (buffer[i].type != EV_KEY) + continue; + + quint16 code = buffer[i].code; + qint32 value = buffer[i].value; + + if (m_handler->filterInputEvent(code, value)) + continue; + + QWSKeyboardHandler::KeycodeAction ka; + ka = m_handler->processKeycode(code, value != 0, value == 2); + + switch (ka) { + case QWSKeyboardHandler::CapsLockOn: + case QWSKeyboardHandler::CapsLockOff: + switchLed(LED_CAPSL, ka == QWSKeyboardHandler::CapsLockOn); + break; + + case QWSKeyboardHandler::NumLockOn: + case QWSKeyboardHandler::NumLockOff: + switchLed(LED_NUML, ka == QWSKeyboardHandler::NumLockOn); + break; + + case QWSKeyboardHandler::ScrollLockOn: + case QWSKeyboardHandler::ScrollLockOff: + switchLed(LED_SCROLLL, ka == QWSKeyboardHandler::ScrollLockOn); + break; + + default: + // ignore console switching and reboot + break; + } + } +} + + + + + +QT_END_NAMESPACE diff --git a/src/plugins/generic/linuxinput/qlinuxinput.h b/src/plugins/generic/linuxinput/qlinuxinput.h new file mode 100644 index 0000000..5a90c8f --- /dev/null +++ b/src/plugins/generic/linuxinput/qlinuxinput.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QLINUXINPUT_H +#define QLINUXINPUT_H + +#include <qobject.h> +#include <Qt> +#include <termios.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class QLinuxInputMouseHandler : public QObject +{ + Q_OBJECT +public: + QLinuxInputMouseHandler(const QString &key, const QString &specification); + ~QLinuxInputMouseHandler(); + +private slots: + void readMouseData(); + +private: + QSocketNotifier * m_notify; + int m_fd; + int m_x, m_y; + Qt::MouseButtons m_buttons; +}; + + +class QWSLinuxInputKeyboardHandler; + +class QLinuxInputKeyboardHandler : public QObject +{ + Q_OBJECT +public: + QLinuxInputKeyboardHandler(const QString &key, const QString &specification); + ~QLinuxInputKeyboardHandler(); + + +private: + void switchLed(int, bool); + +private slots: + void readKeycode(); + +private: + QWSLinuxInputKeyboardHandler *m_handler; + int m_fd; + int m_tty_fd; + struct termios m_tty_attr; + int m_orig_kbmode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLINUXINPUT_H diff --git a/src/plugins/graphicssystems/graphicssystems.pro b/src/plugins/graphicssystems/graphicssystems.pro index 14e3cfc..12b2c51 100644 --- a/src/plugins/graphicssystems/graphicssystems.pro +++ b/src/plugins/graphicssystems/graphicssystems.pro @@ -1,9 +1,23 @@ TEMPLATE = subdirs SUBDIRS += trace contains(QT_CONFIG, opengl):SUBDIRS += opengl -contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl):SUBDIRS += openvg +contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl) { + embedded_lite { + SUBDIRS += openvglite + } else { + SUBDIRS += openvg + } +} contains(QT_CONFIG, shivavg) { # Only works under X11 at present !win32:!embedded:!mac:SUBDIRS += shivavg } + +embedded_lite: { + SUBDIRS += minimal +} + +embedded_lite:x11 { + SUBDIRS += linuxfb +}
\ No newline at end of file diff --git a/src/plugins/graphicssystems/linuxfb/linuxfb.pro b/src/plugins/graphicssystems/linuxfb/linuxfb.pro new file mode 100644 index 0000000..1251d2f --- /dev/null +++ b/src/plugins/graphicssystems/linuxfb/linuxfb.pro @@ -0,0 +1,10 @@ +TARGET = qlinuxfbgraphicssystem +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_linuxfb.cpp qwindowsurface_linuxfb.cpp +HEADERS = qgraphicssystem_linuxfb.h qwindowsurface_linuxfb.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/graphicssystems/linuxfb/main.cpp b/src/plugins/graphicssystems/linuxfb/main.cpp new file mode 100644 index 0000000..ef6234d --- /dev/null +++ b/src/plugins/graphicssystems/linuxfb/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_linuxfb.h" + +QT_BEGIN_NAMESPACE + +class QLinuxFbGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QLinuxFbGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "LinuxFb"; + return list; +} + +QGraphicsSystem* QLinuxFbGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "linuxfb") + return new QLinuxFbGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(linuxfb, QLinuxFbGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/linuxfb/qgraphicssystem_linuxfb.cpp b/src/plugins/graphicssystems/linuxfb/qgraphicssystem_linuxfb.cpp new file mode 100644 index 0000000..cd0ced2 --- /dev/null +++ b/src/plugins/graphicssystems/linuxfb/qgraphicssystem_linuxfb.cpp @@ -0,0 +1,797 @@ +/**************************************************************************** +** +** 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_linuxfb.h" +#include "qwindowsurface_linuxfb.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN + +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/kd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <limits.h> +#include <signal.h> + +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_FREEBSD) +#include <linux/fb.h> + +#ifdef __i386__ +#include <asm/mtrr.h> +#endif +#endif + +QT_BEGIN_NAMESPACE + +class QLinuxFbGraphicsSystemPrivate +{ +public: + QLinuxFbGraphicsSystemPrivate(); + ~QLinuxFbGraphicsSystemPrivate(); + + void openTty(); + void closeTty(); + + int fd; + int startupw; + int startuph; + int startupd; + bool blank; + + bool doGraphicsMode; +#ifdef QT_QWS_DEPTH_GENERIC + bool doGenericColors; +#endif + int ttyfd; + long oldKdMode; + QString ttyDevice; + QString displaySpec; +}; + +QLinuxFbGraphicsSystemPrivate::QLinuxFbGraphicsSystemPrivate() + : fd(-1), blank(true), doGraphicsMode(true), +#ifdef QT_QWS_DEPTH_GENERIC + doGenericColors(false), +#endif + ttyfd(-1), oldKdMode(KD_TEXT) +{ +} + +QLinuxFbGraphicsSystemPrivate::~QLinuxFbGraphicsSystemPrivate() +{ + closeTty(); +} + +void QLinuxFbGraphicsSystemPrivate::openTty() +{ + const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0}; + + if (ttyDevice.isEmpty()) { + for (const char * const *dev = devs; *dev; ++dev) { + ttyfd = QT_OPEN(*dev, O_RDWR); + if (ttyfd != -1) + break; + } + } else { + ttyfd = QT_OPEN(ttyDevice.toAscii().constData(), O_RDWR); + } + + if (ttyfd == -1) + return; + + if (doGraphicsMode) { + ioctl(ttyfd, KDGETMODE, &oldKdMode); + if (oldKdMode != KD_GRAPHICS) { + int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS); + if (ret == -1) + doGraphicsMode = false; + } + } + + // No blankin' screen, no blinkin' cursor!, no cursor! + const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c"; + QT_WRITE(ttyfd, termctl, sizeof(termctl)); +} + +void QLinuxFbGraphicsSystemPrivate::closeTty() +{ + if (ttyfd == -1) + return; + + if (doGraphicsMode) + ioctl(ttyfd, KDSETMODE, oldKdMode); + + // Blankin' screen, blinkin' cursor! + const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c"; + QT_WRITE(ttyfd, termctl, sizeof(termctl)); + + QT_CLOSE(ttyfd); + ttyfd = -1; +} + +QLinuxFbGraphicsSystem::QLinuxFbGraphicsSystem() +{ + d_ptr = new QLinuxFbGraphicsSystemPrivate(); + + // XXX + QString displaySpec = QString::fromLatin1(qgetenv("QWS_DISPLAY")); + + if (!connect(displaySpec)) + qFatal("QLinuxFbGraphicsSystem: could not initialize screen"); + + mPrimaryScreen = new QLinuxFbGraphicsSystemScreen(); + mPrimaryScreen->mGeometry = QRect(0, 0, w, h); + mPrimaryScreen->mDepth = d; + mPrimaryScreen->mFormat = screenFormat; + mPrimaryScreen->mPhysicalSize = QSize(physWidth, physHeight); + + // Create a QImage directly on the screen's framebuffer. + // This is the blit target for copying windows to the screen. + mPrimaryScreen->mScreenImage = new QImage(data, w, h, lstep, screenFormat); + + mScreens.append(mPrimaryScreen); +} + +QLinuxFbGraphicsSystem::~QLinuxFbGraphicsSystem() +{ + delete mPrimaryScreen; + delete d_ptr; +} + +bool QLinuxFbGraphicsSystem::connect(const QString &displaySpec) +{ + const QStringList args = displaySpec.split(QLatin1Char(':')); + + if (args.contains(QLatin1String("nographicsmodeswitch"))) + d_ptr->doGraphicsMode = false; + +#ifdef QT_QWS_DEPTH_GENERIC + if (args.contains(QLatin1String("genericcolors"))) + d_ptr->doGenericColors = true; +#endif + + QRegExp ttyRegExp(QLatin1String("tty=(.*)")); + if (args.indexOf(ttyRegExp) != -1) + d_ptr->ttyDevice = ttyRegExp.cap(1); + +#if 0 +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN + if (args.contains(QLatin1String("littleendian"))) +#endif + QScreen::setFrameBufferLittleEndian(true); +#endif +#endif + + // Check for explicitly specified device + const int len = 8; // "/dev/fbx" + int m = displaySpec.indexOf(QLatin1String("/dev/fb")); + + QString dev; + if (m > 0) + dev = displaySpec.mid(m, len); + else + dev = QLatin1String("/dev/fb0"); + + if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0) + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR); + if (d_ptr->fd == -1) { + if (access(dev.toLatin1().constData(), R_OK) == 0) + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY); + if (d_ptr->fd == 1) { + qWarning("Error opening framebuffer device %s", qPrintable(dev)); + return false; + } + } + + fb_fix_screeninfo finfo; + fb_var_screeninfo vinfo; + //####################### + // Shut up Valgrind + memset(&vinfo, 0, sizeof(vinfo)); + memset(&finfo, 0, sizeof(finfo)); + //####################### + + /* Get fixed screen information */ + if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) { + perror("QLinuxFbGraphicsSystem::connect"); + qWarning("Error reading fixed information"); + return false; + } + + if (finfo.type == FB_TYPE_VGA_PLANES) { + qWarning("VGA16 video mode not supported"); + return false; + } + + /* Get variable screen information */ + if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("QLinuxFbGraphicsSystem::connect"); + qWarning("Error reading variable information"); + return false; + } + + grayscale = vinfo.grayscale; + d = vinfo.bits_per_pixel; + if (d == 24) { + d = vinfo.red.length + vinfo.green.length + vinfo.blue.length; + if (d <= 0) + d = 24; // reset if color component lengths are not reported + } else if (d == 16) { + d = vinfo.red.length + vinfo.green.length + vinfo.blue.length; + if (d <= 0) + d = 16; + } + lstep = finfo.line_length; + + int xoff = vinfo.xoffset; + int yoff = vinfo.yoffset; + const char* qwssize; + if((qwssize=::getenv("QWS_SIZE")) && sscanf(qwssize,"%dx%d",&w,&h)==2) { + if (d_ptr->fd != -1) { + if ((uint)w > vinfo.xres) w = vinfo.xres; + if ((uint)h > vinfo.yres) h = vinfo.yres; + } + dw=w; + dh=h; + int xxoff, yyoff; + if (sscanf(qwssize, "%*dx%*d+%d+%d", &xxoff, &yyoff) == 2) { + if (xxoff < 0 || xxoff + w > (int)(vinfo.xres)) + xxoff = vinfo.xres - w; + if (yyoff < 0 || yyoff + h > (int)(vinfo.yres)) + yyoff = vinfo.yres - h; + xoff += xxoff; + yoff += yyoff; + } else { + xoff += (vinfo.xres - w)/2; + yoff += (vinfo.yres - h)/2; + } + } else { + dw=w=vinfo.xres; + dh=h=vinfo.yres; + } + + if (w == 0 || h == 0) { + qWarning("QLinuxFbGraphicsSystem::connect(): Unable to find screen geometry, " + "will use 320x240."); + dw = w = 320; + dh = h = 240; + } + + setPixelFormat(vinfo); + + // Handle display physical size spec. + QStringList displayArgs = displaySpec.split(QLatin1Char(':')); + QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); + int dimIdxW = displayArgs.indexOf(mmWidthRx); + QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); + int dimIdxH = displayArgs.indexOf(mmHeightRx); + if (dimIdxW >= 0) { + mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); + physWidth = mmWidthRx.cap(1).toInt(); + if (dimIdxH < 0) + physHeight = dh*physWidth/dw; + } + if (dimIdxH >= 0) { + mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); + physHeight = mmHeightRx.cap(1).toInt(); + if (dimIdxW < 0) + physWidth = dw*physHeight/dh; + } + if (dimIdxW < 0 && dimIdxH < 0) { + if (vinfo.width != 0 && vinfo.height != 0 + && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) { + physWidth = vinfo.width; + physHeight = vinfo.height; + } else { + const int dpi = 72; + physWidth = qRound(dw * 25.4 / dpi); + physHeight = qRound(dh * 25.4 / dpi); + } + } + + dataoffset = yoff * lstep + xoff * d / 8; + //qDebug("Using %dx%dx%d screen",w,h,d); + + /* Figure out the size of the screen in bytes */ + size = h * lstep; + + mapsize = finfo.smem_len; + + data = (unsigned char *)-1; + if (d_ptr->fd != -1) + data = (unsigned char *)mmap(0, mapsize, PROT_READ | PROT_WRITE, + MAP_SHARED, d_ptr->fd, 0); + + if ((long)data == -1) { + perror("QLinuxFbGraphicsSystem::connect"); + qWarning("Error: failed to map framebuffer device to memory."); + return false; + } else { + data += dataoffset; + } + +#if 0 + canaccel = useOffscreen(); + if(canaccel) + setupOffScreen(); +#endif + canaccel = false; + + // Now read in palette + if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) { + screencols= (vinfo.bits_per_pixel==8) ? 256 : 16; + int loopc; + fb_cmap startcmap; + startcmap.start=0; + startcmap.len=screencols; + startcmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + if (d_ptr->fd == -1 || ioctl(d_ptr->fd, FBIOGETCMAP, &startcmap)) { + perror("QLinuxFbGraphicsSystem::connect"); + qWarning("Error reading palette from framebuffer, using default palette"); + createPalette(startcmap, vinfo, finfo); + } + int bits_used = 0; + for(loopc=0;loopc<screencols;loopc++) { + screenclut[loopc]=qRgb(startcmap.red[loopc] >> 8, + startcmap.green[loopc] >> 8, + startcmap.blue[loopc] >> 8); + bits_used |= startcmap.red[loopc] + | startcmap.green[loopc] + | startcmap.blue[loopc]; + } + // WORKAROUND: Some framebuffer drivers only return 8 bit + // color values, so we need to not bit shift them.. + if ((bits_used & 0x00ff) && !(bits_used & 0xff00)) { + for(loopc=0;loopc<screencols;loopc++) { + screenclut[loopc] = qRgb(startcmap.red[loopc], + startcmap.green[loopc], + startcmap.blue[loopc]); + } + qWarning("8 bits cmap returned due to faulty FB driver, colors corrected"); + } + free(startcmap.red); + free(startcmap.green); + free(startcmap.blue); + free(startcmap.transp); + } else { + screencols=0; + } + + return true; +} + +bool QLinuxFbGraphicsSystem::initDevice() +{ + d_ptr->openTty(); + + // Grab current mode so we can reset it + fb_var_screeninfo vinfo; + fb_fix_screeninfo finfo; + //####################### + // Shut up Valgrind + memset(&vinfo, 0, sizeof(vinfo)); + memset(&finfo, 0, sizeof(finfo)); + //####################### + + if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("QLinuxFbScreen::initDevice"); + qFatal("Error reading variable information in card init"); + return false; + } + +#ifdef DEBUG_VINFO + qDebug("Greyscale %d",vinfo.grayscale); + qDebug("Nonstd %d",vinfo.nonstd); + qDebug("Red %d %d %d",vinfo.red.offset,vinfo.red.length, + vinfo.red.msb_right); + qDebug("Green %d %d %d",vinfo.green.offset,vinfo.green.length, + vinfo.green.msb_right); + qDebug("Blue %d %d %d",vinfo.blue.offset,vinfo.blue.length, + vinfo.blue.msb_right); + qDebug("Transparent %d %d %d",vinfo.transp.offset,vinfo.transp.length, + vinfo.transp.msb_right); +#endif + + d_ptr->startupw=vinfo.xres; + d_ptr->startuph=vinfo.yres; + d_ptr->startupd=vinfo.bits_per_pixel; + grayscale = vinfo.grayscale; + + if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) { + perror("QLinuxFbScreen::initDevice"); + qCritical("Error reading fixed information in card init"); + // It's not an /error/ as such, though definitely a bad sign + // so we return true + return true; + } + +#ifdef __i386__ + // Now init mtrr + if(!::getenv("QWS_NOMTRR")) { + int mfd=QT_OPEN("/proc/mtrr",O_WRONLY,0); + // MTRR entry goes away when file is closed - i.e. + // hopefully when QWS is killed + if(mfd != -1) { + mtrr_sentry sentry; + sentry.base=(unsigned long int)finfo.smem_start; + //qDebug("Physical framebuffer address %p",(void*)finfo.smem_start); + // Size needs to be in 4k chunks, but that's not always + // what we get thanks to graphics card registers. Write combining + // these is Not Good, so we write combine what we can + // (which is not much - 4 megs on an 8 meg card, it seems) + unsigned int size=finfo.smem_len; + size=size >> 22; + size=size << 22; + sentry.size=size; + sentry.type=MTRR_TYPE_WRCOMB; + if(ioctl(mfd,MTRRIOC_ADD_ENTRY,&sentry)==-1) { + //printf("Couldn't add mtrr entry for %lx %lx, %s\n", + //sentry.base,sentry.size,strerror(errno)); + } + } + + // Should we close mfd here? + //QT_CLOSE(mfd); + } +#endif + if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR)) + { + fb_cmap cmap; + createPalette(cmap, vinfo, finfo); + if (ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap)) { + perror("QLinuxFbScreen::initDevice"); + qWarning("Error writing palette to framebuffer"); + } + free(cmap.red); + free(cmap.green); + free(cmap.blue); + free(cmap.transp); + } + +#if 0 + if (canaccel) { + *entryp=0; + *lowest = mapsize; + insert_entry(*entryp, *lowest, *lowest); // dummy entry to mark start + } + + shared->fifocount = 0; + shared->buffer_offset = 0xffffffff; // 0 would be a sensible offset (screen) + shared->linestep = 0; + shared->cliptop = 0xffffffff; + shared->clipleft = 0xffffffff; + shared->clipright = 0xffffffff; + shared->clipbottom = 0xffffffff; + shared->rop = 0xffffffff; +#endif + +#ifdef QT_QWS_DEPTH_GENERIC + if (pixelFormat() == QImage::Format_Invalid && screencols == 0 + && d_ptr->doGenericColors) + { + qt_set_generic_blit(this, vinfo.bits_per_pixel, + vinfo.red.length, vinfo.green.length, + vinfo.blue.length, vinfo.transp.length, + vinfo.red.offset, vinfo.green.offset, + vinfo.blue.offset, vinfo.transp.offset); + } +#endif + +#if 0 +#ifndef QT_NO_QWS_CURSOR + QScreenCursor::initSoftwareCursor(); +#endif +#endif + blank(false); + + return true; +} + +void QLinuxFbGraphicsSystem::setPixelFormat(struct fb_var_screeninfo info) +{ + const fb_bitfield rgba[4] = { info.red, info.green, + info.blue, info.transp }; + + QImage::Format format = QImage::Format_Invalid; + + switch (d) { + case 32: { + const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0}, + {0, 8, 0}, {24, 8, 0}}; + const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0}, + {16, 8, 0}, {24, 8, 0}}; + if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_ARGB32; + } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB32; + } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB32; + pixeltype = BGRPixel; + } + break; + } + case 24: { + const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0}, + {0, 8, 0}, {0, 0, 0}}; + const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0}, + {16, 8, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB888; + } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB888; + pixeltype = BGRPixel; + } + break; + } + case 18: { + const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0}, + {0, 6, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0) + format = QImage::Format_RGB666; + break; + } + case 16: { + const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0}, + {0, 5, 0}, {0, 0, 0}}; + const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0}, + {11, 5, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB16; + } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB16; + pixeltype = BGRPixel; + } + break; + } + case 15: { + const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0}, + {0, 5, 0}, {15, 1, 0}}; + const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0}, + {10, 5, 0}, {15, 1, 0}}; + if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB555; + } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB555; + pixeltype = BGRPixel; + } + break; + } + case 12: { + const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0}, + {0, 4, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0) + format = QImage::Format_RGB444; + break; + } + case 8: + break; + case 1: + format = QImage::Format_Mono; //###: LSB??? + break; + default: + break; + } + + screenFormat = format; +} + +void QLinuxFbGraphicsSystem::createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo) +{ + if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) { + screencols= (vinfo.bits_per_pixel==8) ? 256 : 16; + cmap.start=0; + cmap.len=screencols; + cmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + + if (screencols==16) { + if (finfo.type == FB_TYPE_PACKED_PIXELS) { + // We'll setup a grayscale cmap for 4bpp linear + int val = 0; + for (int idx = 0; idx < 16; ++idx, val += 17) { + cmap.red[idx] = (val<<8)|val; + cmap.green[idx] = (val<<8)|val; + cmap.blue[idx] = (val<<8)|val; + screenclut[idx]=qRgb(val, val, val); + } + } else { + // Default 16 colour palette + // Green is now trolltech green so certain images look nicer + // black d_gray l_gray white red green blue cyan magenta yellow + unsigned char reds[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0xFF, 0xA2, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x82 }; + unsigned char greens[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0xC5, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F }; + unsigned char blues[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0x11, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00 }; + + for (int idx = 0; idx < 16; ++idx) { + cmap.red[idx] = ((reds[idx]) << 8)|reds[idx]; + cmap.green[idx] = ((greens[idx]) << 8)|greens[idx]; + cmap.blue[idx] = ((blues[idx]) << 8)|blues[idx]; + cmap.transp[idx] = 0; + screenclut[idx]=qRgb(reds[idx], greens[idx], blues[idx]); + } + } + } else { + if (grayscale) { + // Build grayscale palette + int i; + for(i=0;i<screencols;++i) { + int bval = screencols == 256 ? i : (i << 4); + ushort val = (bval << 8) | bval; + cmap.red[i] = val; + cmap.green[i] = val; + cmap.blue[i] = val; + cmap.transp[i] = 0; + screenclut[i] = qRgb(bval,bval,bval); + } + } 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) { + cmap.red[idx] = (ir << 8)|ir; + cmap.green[idx] = (ig << 8)|ig; + cmap.blue[idx] = (ib << 8)|ib; + cmap.transp[idx] = 0; + screenclut[idx]=qRgb(ir, ig, ib); + ++idx; + } + } + } + // Fill in rest with 0 + for (int loopc=0; loopc<40; ++loopc) { + screenclut[idx]=0; + ++idx; + } + screencols=idx; + } + } + } else if(finfo.visual==FB_VISUAL_DIRECTCOLOR) { + cmap.start=0; + int rbits=0,gbits=0,bbits=0; + switch (vinfo.bits_per_pixel) { + case 8: + rbits=vinfo.red.length; + gbits=vinfo.green.length; + bbits=vinfo.blue.length; + if(rbits==0 && gbits==0 && bbits==0) { + // cyber2000 driver bug hack + rbits=3; + gbits=3; + bbits=2; + } + break; + case 15: + rbits=5; + gbits=5; + bbits=5; + break; + case 16: + rbits=5; + gbits=6; + bbits=5; + break; + case 18: + case 19: + rbits=6; + gbits=6; + bbits=6; + break; + case 24: case 32: + rbits=gbits=bbits=8; + break; + } + screencols=cmap.len=1<<qMax(rbits,qMax(gbits,bbits)); + cmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + for(unsigned int i = 0x0; i < cmap.len; i++) { + cmap.red[i] = i*65535/((1<<rbits)-1); + cmap.green[i] = i*65535/((1<<gbits)-1); + cmap.blue[i] = i*65535/((1<<bbits)-1); + cmap.transp[i] = 0; + } + } +} + +void QLinuxFbGraphicsSystem::blank(bool on) +{ + if (d_ptr->blank == on) + return; + +#if defined(QT_QWS_IPAQ) + if (on) + system("apm -suspend"); +#else + if (d_ptr->fd == -1) + return; +// Some old kernel versions don't have this. These defines should go +// away eventually +#if defined(FBIOBLANK) +#if defined(VESA_POWERDOWN) && defined(VESA_NO_BLANKING) + ioctl(d_ptr->fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING); +#else + ioctl(d_ptr->fd, FBIOBLANK, on ? 1 : 0); +#endif +#endif +#endif + + d_ptr->blank = on; +} + +QPixmapData *QLinuxFbGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QLinuxFbGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + if (widget->windowType() == Qt::Desktop) + return 0; // Don't create an explicit window surface for the destkop. + return new QLinuxFbWindowSurface(mPrimaryScreen, widget); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/linuxfb/qgraphicssystem_linuxfb.h b/src/plugins/graphicssystems/linuxfb/qgraphicssystem_linuxfb.h new file mode 100644 index 0000000..3446008 --- /dev/null +++ b/src/plugins/graphicssystems/linuxfb/qgraphicssystem_linuxfb.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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_LINUXFB_H +#define QGRAPHICSSYSTEM_LINUXFB_H + +#include <QtGui/private/qgraphicssystem_p.h> + +QT_BEGIN_NAMESPACE + +class QLinuxFbGraphicsSystemScreen : public QGraphicsSystemScreen +{ +public: + QLinuxFbGraphicsSystemScreen() + : mDepth(16), mFormat(QImage::Format_RGB16), mScreenImage(0) {} + ~QLinuxFbGraphicsSystemScreen() { delete mScreenImage; } + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + QSize physicalSize() const { return mPhysicalSize; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + QImage *mScreenImage; + +}; + +class QLinuxFbGraphicsSystemPrivate; +struct fb_cmap; +struct fb_var_screeninfo; +struct fb_fix_screeninfo; + +class QLinuxFbGraphicsSystem : public QGraphicsSystem +{ +public: + QLinuxFbGraphicsSystem(); + ~QLinuxFbGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + + QList<QGraphicsSystemScreen *> screens() const { return mScreens; } + +private: + QLinuxFbGraphicsSystemScreen *mPrimaryScreen; + QList<QGraphicsSystemScreen *> mScreens; + QLinuxFbGraphicsSystemPrivate *d_ptr; + + enum PixelType { NormalPixel, BGRPixel }; + + QRgb screenclut[256]; + int screencols; + + uchar * data; + + QImage::Format screenFormat; + int w; + int lstep; + int h; + int d; + PixelType pixeltype; + bool grayscale; + + int dw; + int dh; + + int size; // Screen size + int mapsize; // Total mapped memory + + int displayId; + + int physWidth; + int physHeight; + + bool canaccel; + int dataoffset; + int cacheStart; + + bool connect(const QString &displaySpec); + bool initDevice(); + void setPixelFormat(struct fb_var_screeninfo); + void createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo); + void blank(bool on); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/linuxfb/qwindowsurface_linuxfb.cpp b/src/plugins/graphicssystems/linuxfb/qwindowsurface_linuxfb.cpp new file mode 100644 index 0000000..bfc2f83 --- /dev/null +++ b/src/plugins/graphicssystems/linuxfb/qwindowsurface_linuxfb.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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$ +** +****************************************************************************/ + +#include "qwindowsurface_linuxfb.h" +#include "qgraphicssystem_linuxfb.h" +#include <QtCore/qdebug.h> +#include <QtGui/qpainter.h> +#include <private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +QLinuxFbWindowSurface::QLinuxFbWindowSurface + (QLinuxFbGraphicsSystemScreen *screen, QWidget *window) + : QWindowSurface(window), + mScreen(screen) +{ +} + +QLinuxFbWindowSurface::~QLinuxFbWindowSurface() +{ +} + +QPaintDevice *QLinuxFbWindowSurface::paintDevice() +{ + return &mImage; +} + +void QLinuxFbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + + QRect rect = geometry(); + QPoint topLeft = rect.topLeft(); + + QPainter painter(mScreen->mScreenImage); + if (region.numRects() == 1) { + QRect wrect = region.boundingRect(); + painter.drawImage(wrect.topLeft() + topLeft, mImage, wrect); + } else { + QVector<QRect> rects = region.rects(); + foreach (QRect wrect, rects) + painter.drawImage(wrect.topLeft() + topLeft, mImage, wrect); + } +} + +void QLinuxFbWindowSurface::setGeometry(const QRect &r) +{ +#ifdef QT_LITE_FORCE_FULLSCREEN +// any size you like as long as it's full-screen... + QRect rect(mScreen->availableGeometry()); + QApplicationPrivate::handleGeometryChange(this->window(), rect); +#else + QRect rect(r); +#endif + QWindowSurface::setGeometry(rect); + if (mImage.size() != rect.size()) + mImage = QImage(rect.size(), mScreen->format()); +} + +bool QLinuxFbWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QLinuxFbWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QLinuxFbWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/linuxfb/qwindowsurface_linuxfb.h b/src/plugins/graphicssystems/linuxfb/qwindowsurface_linuxfb.h new file mode 100644 index 0000000..763f362 --- /dev/null +++ b/src/plugins/graphicssystems/linuxfb/qwindowsurface_linuxfb.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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 QWINDOWSURFACE_LINUXFB_H +#define QWINDOWSURFACE_LINUXFB_H + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QLinuxFbGraphicsSystemScreen; + +class QLinuxFbWindowSurface : public QWindowSurface +{ +public: + QLinuxFbWindowSurface + (QLinuxFbGraphicsSystemScreen *screen, QWidget *window); + ~QLinuxFbWindowSurface(); + + 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); + +private: + QLinuxFbGraphicsSystemScreen *mScreen; + QImage mImage; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/minimal/main.cpp b/src/plugins/graphicssystems/minimal/main.cpp new file mode 100644 index 0000000..f7d5eef --- /dev/null +++ b/src/plugins/graphicssystems/minimal/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_minimal.h" + +QT_BEGIN_NAMESPACE + +class QMinimalGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QMinimalGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "Minimal"; + return list; +} + +QGraphicsSystem* QMinimalGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "minimal") + return new QMinimalGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(minimal, QMinimalGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/minimal/minimal.pro b/src/plugins/graphicssystems/minimal/minimal.pro new file mode 100644 index 0000000..11604dd --- /dev/null +++ b/src/plugins/graphicssystems/minimal/minimal.pro @@ -0,0 +1,10 @@ +TARGET = qminimalgraphicssystem +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_minimal.cpp qwindowsurface_minimal.cpp +HEADERS = qgraphicssystem_minimal.h qwindowsurface_minimal.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/graphicssystems/minimal/qgraphicssystem_minimal.cpp b/src/plugins/graphicssystems/minimal/qgraphicssystem_minimal.cpp new file mode 100644 index 0000000..31023fc --- /dev/null +++ b/src/plugins/graphicssystems/minimal/qgraphicssystem_minimal.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 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_minimal.h" +#include "qwindowsurface_minimal.h" +#include <QtGui/private/qpixmap_raster_p.h> + +QT_BEGIN_NAMESPACE + +QMinimalGraphicsSystem::QMinimalGraphicsSystem() +{ + mPrimaryScreen = new QMinimalGraphicsSystemScreen(); + + mPrimaryScreen->mGeometry = QRect(0, 0, 240, 320); + mPrimaryScreen->mDepth = 16; + mPrimaryScreen->mFormat = QImage::Format_RGB16; + mPrimaryScreen->mPhysicalSize = QSize(40, 54); + + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QMinimalGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QMinimalGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + return new QMinimalWindowSurface(mPrimaryScreen, widget); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/minimal/qgraphicssystem_minimal.h b/src/plugins/graphicssystems/minimal/qgraphicssystem_minimal.h new file mode 100644 index 0000000..b15f6f6 --- /dev/null +++ b/src/plugins/graphicssystems/minimal/qgraphicssystem_minimal.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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_MINIMAL_H +#define QGRAPHICSSYSTEM_MINIMAL_H + +#include <QtGui/private/qgraphicssystem_p.h> + +QT_BEGIN_NAMESPACE + +class QMinimalGraphicsSystemScreen : public QGraphicsSystemScreen +{ +public: + QMinimalGraphicsSystemScreen() + : mDepth(16), mFormat(QImage::Format_RGB16) {} + ~QMinimalGraphicsSystemScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + QSize physicalSize() const { return mPhysicalSize; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; +}; + +class QMinimalGraphicsSystem : public QGraphicsSystem +{ +public: + QMinimalGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + + QList<QGraphicsSystemScreen *> screens() const { return mScreens; } + +private: + QMinimalGraphicsSystemScreen *mPrimaryScreen; + QList<QGraphicsSystemScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/minimal/qwindowsurface_minimal.cpp b/src/plugins/graphicssystems/minimal/qwindowsurface_minimal.cpp new file mode 100644 index 0000000..e9d7d69 --- /dev/null +++ b/src/plugins/graphicssystems/minimal/qwindowsurface_minimal.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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$ +** +****************************************************************************/ + +#include "qwindowsurface_minimal.h" +#include "qgraphicssystem_minimal.h" +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +QMinimalWindowSurface::QMinimalWindowSurface + (QMinimalGraphicsSystemScreen *screen, QWidget *window) + : QWindowSurface(window), + mScreen(screen) +{ + //qDebug() << "QMinimalWindowSurface::QMinimalWindowSurface:" << (long)this; +} + +QMinimalWindowSurface::~QMinimalWindowSurface() +{ +} + +QPaintDevice *QMinimalWindowSurface::paintDevice() +{ + //qDebug() << "QMinimalWindowSurface::paintDevice"; + return &mImage; +} + +void QMinimalWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + + static int c = 0; + QString filename = QString("output%1.png").arg(c++, 4, 10, QLatin1Char('0')); + qDebug() << "QMinimalWindowSurface::flush() saving contents to" << filename.toLocal8Bit().constData(); + mImage.save(filename); +} + +void QMinimalWindowSurface::setGeometry(const QRect &rect) +{ + //qDebug() << "QMinimalWindowSurface::setGeometry:" << (long)this << rect; + QWindowSurface::setGeometry(rect); + if (mImage.size() != rect.size()) + mImage = QImage(rect.size(), mScreen->format()); +} + +bool QMinimalWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QMinimalWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QMinimalWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/minimal/qwindowsurface_minimal.h b/src/plugins/graphicssystems/minimal/qwindowsurface_minimal.h new file mode 100644 index 0000000..89dc860 --- /dev/null +++ b/src/plugins/graphicssystems/minimal/qwindowsurface_minimal.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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 QWINDOWSURFACE_MINIMAL_H +#define QWINDOWSURFACE_MINIMAL_H + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QMinimalGraphicsSystemScreen; + +class QMinimalWindowSurface : public QWindowSurface +{ +public: + QMinimalWindowSurface + (QMinimalGraphicsSystemScreen *screen, QWidget *window); + ~QMinimalWindowSurface(); + + 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); + +private: + QMinimalGraphicsSystemScreen *mScreen; + QImage mImage; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/openvglite/main.cpp b/src/plugins/graphicssystems/openvglite/main.cpp new file mode 100644 index 0000000..3a73f5c --- /dev/null +++ b/src/plugins/graphicssystems/openvglite/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_vglite.h" + +QT_BEGIN_NAMESPACE + +class QVGGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QVGGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "OpenVG"; + return list; +} + +QGraphicsSystem* QVGGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "openvg") + return new QVGLiteGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(openvg, QVGGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/openvglite/openvglite.pro b/src/plugins/graphicssystems/openvglite/openvglite.pro new file mode 100644 index 0000000..9d7860a --- /dev/null +++ b/src/plugins/graphicssystems/openvglite/openvglite.pro @@ -0,0 +1,12 @@ +TARGET = qvglitegraphicssystem +include(../../qpluginbase.pri) + +QT += openvg + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_vglite.cpp qwindowsurface_vglite.cpp +HEADERS = qgraphicssystem_vglite.h qwindowsurface_vglite.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/graphicssystems/openvglite/qgraphicssystem_vglite.cpp b/src/plugins/graphicssystems/openvglite/qgraphicssystem_vglite.cpp new file mode 100644 index 0000000..cc5b012 --- /dev/null +++ b/src/plugins/graphicssystems/openvglite/qgraphicssystem_vglite.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** 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_vglite.h" +#include "qwindowsurface_vglite.h" +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#include <QtGui/private/qegl_p.h> +#include <QtCore/qdebug.h> +#ifdef OPENVG_USBHP_INIT +extern "C" { +#include <linuxusbhp.h> +}; +#endif + +QT_BEGIN_NAMESPACE + +QVGLiteGraphicsSystem::QVGLiteGraphicsSystem() + : w(0), h(0), d(0), dw(0), dh(0), physWidth(0), physHeight(0), + surface(0), context(0), rootWindow(0), + screenFormat(QImage::Format_RGB16), preservedSwap(false) +{ +#ifdef OPENVG_USBHP_INIT + initLibrary(); +#endif + + // The graphics system is also the screen definition. + mScreens.append(this); + + QString displaySpec = QString::fromLatin1(qgetenv("QWS_DISPLAY")); + QStringList displayArgs = displaySpec.split(QLatin1Char(':')); + + // Initialize EGL and create the global EGL context. + context = qt_vg_create_context(0); + if (!context) { + qFatal("QVGLiteGraphicsSystem: could not initialize EGL"); + return; + } + + // Get the root window handle to use. Default to zero. + QRegExp winidRx(QLatin1String("winid=?(\\d+)")); + int winidIdx = displayArgs.indexOf(winidRx); + int handle = 0; + if (winidIdx >= 0) { + winidRx.exactMatch(displayArgs.at(winidIdx)); + handle = winidRx.cap(1).toInt(); + } + + // Create a full-screen window based on the native handle. + // If the context is premultiplied, the window should be too. + QEglProperties props; +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + EGLint surfaceType = 0; + if (context->configAttrib(EGL_SURFACE_TYPE, &surfaceType) && + (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0) + props.setValue(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE); +#endif + rootWindow = eglCreateWindowSurface + (context->display(), context->config(), + (EGLNativeWindowType)handle, props.properties()); + if (rootWindow == EGL_NO_SURFACE) { + delete context; + context = 0; + qFatal("QVGLiteGraphicsSystem: could not create full-screen window"); + return; + } + + // Try to turn on preserved swap behaviour on the root window. + // This will allow us to optimize compositing to focus on just + // the screen region that has changed. Otherwise we must + // re-composite the entire screen every frame. +#if !defined(QVG_NO_PRESERVED_SWAP) + eglGetError(); // Clear error state first. + eglSurfaceAttrib(context->display(), rootWindow, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + preservedSwap = (eglGetError() == EGL_SUCCESS); +#else + preservedSwap = false; +#endif + + // Fetch the root window properties. + eglQuerySurface(context->display(), rootWindow, EGL_WIDTH, &w); + eglQuerySurface(context->display(), rootWindow, EGL_HEIGHT, &h); + screenFormat = qt_vg_config_to_image_format(context); + switch (screenFormat) { + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + default: + d = 32; + break; + case QImage::Format_RGB16: + case QImage::Format_ARGB4444_Premultiplied: + d = 16; + break; + } + dw = w; + dh = h; + qDebug("screen size: %dx%dx%d", w, h, d); + + // Handle display physical size spec. From qscreenlinuxfb_qws.cpp. + QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); + int dimIdxW = displayArgs.indexOf(mmWidthRx); + QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); + int dimIdxH = displayArgs.indexOf(mmHeightRx); + if (dimIdxW >= 0) { + mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); + physWidth = mmWidthRx.cap(1).toInt(); + if (dimIdxH < 0) + physHeight = dh*physWidth/dw; + } + if (dimIdxH >= 0) { + mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); + physHeight = mmHeightRx.cap(1).toInt(); + 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); + } +} + +QVGLiteGraphicsSystem::~QVGLiteGraphicsSystem() +{ +} + +QPixmapData *QVGLiteGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ +#if !defined(QVGLite_NO_SINGLE_CONTEXT) && !defined(QVGLite_NO_PIXMAP_DATA) + // Pixmaps can use QVGLitePixmapData; bitmaps must use raster. + if (type == QPixmapData::PixmapType) + return new QVGPixmapData(type); + else + return new QRasterPixmapData(type); +#else + return new QRasterPixmapData(type); +#endif +} + +QWindowSurface *QVGLiteGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + if (widget->windowType() == Qt::Desktop) + return 0; // Don't create an explicit window surface for the destkop. + if (surface) { + qWarning() << "QVGLiteGraphicsSystem: only one window surface " + "is supported at a time"; + return 0; + } + surface = new QVGLiteWindowSurface + (const_cast<QVGLiteGraphicsSystem *>(this), widget); + return surface; +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/openvglite/qgraphicssystem_vglite.h b/src/plugins/graphicssystems/openvglite/qgraphicssystem_vglite.h new file mode 100644 index 0000000..74fc41e --- /dev/null +++ b/src/plugins/graphicssystems/openvglite/qgraphicssystem_vglite.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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_VGLITE_H +#define QGRAPHICSSYSTEM_VGLITE_H + +#include <QtGui/private/qgraphicssystem_p.h> +#include <QtGui/private/qegl_p.h> +#include <QtGui/qimage.h> + +QT_BEGIN_NAMESPACE + +class QVGLiteWindowSurface; + +class QVGLiteGraphicsSystem : public QGraphicsSystem, + public QGraphicsSystemScreen +{ +public: + QVGLiteGraphicsSystem(); + ~QVGLiteGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + QList<QGraphicsSystemScreen *> screens() const { return mScreens; } + + QRect geometry() const { return QRect(0, 0, w, h); } + int depth() const { return d; } + QImage::Format format() const { return screenFormat; } + QSize physicalSize() const { return QSize(physWidth, physHeight); } + +private: + friend class QVGLiteWindowSurface; + + int w; + int h; + int d; + + int dw; + int dh; + + int physWidth; + int physHeight; + + mutable QVGLiteWindowSurface *surface; + QEglContext *context; + EGLSurface rootWindow; + QImage::Format screenFormat; + bool preservedSwap; + + QList<QGraphicsSystemScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/openvglite/qwindowsurface_vglite.cpp b/src/plugins/graphicssystems/openvglite/qwindowsurface_vglite.cpp new file mode 100644 index 0000000..d250a8e --- /dev/null +++ b/src/plugins/graphicssystems/openvglite/qwindowsurface_vglite.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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$ +** +****************************************************************************/ + +#include "qwindowsurface_vglite.h" +#include "qgraphicssystem_vglite.h" +#include <QtOpenVG/qvg.h> +#include <QtOpenVG/private/qvg_p.h> +#include <QtOpenVG/private/qpaintengine_vg_p.h> + +QT_BEGIN_NAMESPACE + +QVGLiteWindowSurface::QVGLiteWindowSurface + (QVGLiteGraphicsSystem *gs, QWidget *window) + : QWindowSurface(window), graphicsSystem(gs), + isPaintingActive(false), engine(0) +{ +} + +QVGLiteWindowSurface::~QVGLiteWindowSurface() +{ + graphicsSystem->surface = 0; + if (engine) + qt_vg_destroy_paint_engine(engine); +} + +QPaintDevice *QVGLiteWindowSurface::paintDevice() +{ + qt_vg_make_current(graphicsSystem->context, graphicsSystem->rootWindow); + isPaintingActive = true; + // TODO: clear the parts of the back buffer that are not + // covered by the window surface to black. + return this; +} + +void QVGLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + QEglContext *context = graphicsSystem->context; + if (context) { + if (!isPaintingActive) + qt_vg_make_current(context, graphicsSystem->rootWindow); + context->swapBuffers(); + qt_vg_done_current(context); + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } +} + +void QVGLiteWindowSurface::setGeometry(const QRect &rect) +{ + QWindowSurface::setGeometry(rect); +} + +bool QVGLiteWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QVGLiteWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QVGLiteWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QPaintEngine *QVGLiteWindowSurface::paintEngine() const +{ + if (!engine) + engine = qt_vg_create_paint_engine(); + return engine; +} + +// We need to get access to QWidget::metric() from QVGLiteWindowSurface::metric, +// but it is not a friend of QWidget. To get around this, we create a +// fake QX11PaintEngine class, which is a friend. +class QX11PaintEngine +{ +public: + static int metric(const QWidget *widget, QPaintDevice::PaintDeviceMetric met) + { + return widget->metric(met); + } +}; + +int QVGLiteWindowSurface::metric(PaintDeviceMetric met) const +{ + return QX11PaintEngine::metric(window(), met); +} diff --git a/src/plugins/graphicssystems/openvglite/qwindowsurface_vglite.h b/src/plugins/graphicssystems/openvglite/qwindowsurface_vglite.h new file mode 100644 index 0000000..c1ae02e --- /dev/null +++ b/src/plugins/graphicssystems/openvglite/qwindowsurface_vglite.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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 QWINDOWSURFACE_VGLITE_H +#define QWINDOWSURFACE_VGLITE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qwindowsurface_p.h> +#include <QtGui/private/qegl_p.h> + +QT_BEGIN_NAMESPACE + +class QVGLiteGraphicsSystem; +class QVGPaintEngine; + +class Q_OPENVG_EXPORT QVGLiteWindowSurface : public QWindowSurface, public QPaintDevice +{ +public: + QVGLiteWindowSurface(QVGLiteGraphicsSystem *gs, QWidget *window); + ~QVGLiteWindowSurface(); + + 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); + + QPaintEngine *paintEngine() const; + +protected: + int metric(PaintDeviceMetric metric) const; + +private: + QVGLiteGraphicsSystem *graphicsSystem; + bool isPaintingActive; + mutable QVGPaintEngine *engine; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSURFACE_VGLITE_H diff --git a/src/plugins/graphicssystems/testlite/main.cpp b/src/plugins/graphicssystems/testlite/main.cpp new file mode 100644 index 0000000..6271829 --- /dev/null +++ b/src/plugins/graphicssystems/testlite/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_testlite.h" + +QT_BEGIN_NAMESPACE + +class QTestLiteGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QTestLiteGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "TestLite"; + return list; +} + +QGraphicsSystem* QTestLiteGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "testlite") + return new QTestLiteGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(testlite, QTestLiteGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/testlite/qgraphicssystem_testlite.cpp b/src/plugins/graphicssystems/testlite/qgraphicssystem_testlite.cpp new file mode 100644 index 0000000..b1948b9 --- /dev/null +++ b/src/plugins/graphicssystems/testlite/qgraphicssystem_testlite.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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_testlite.h" +#include "qwindowsurface_testlite.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> + +#include "x11util.h" + +QT_BEGIN_NAMESPACE + +QTestLiteGraphicsSystem::QTestLiteGraphicsSystem() +{ + xd = new MyDisplay; + + mPrimaryScreen = new QTestLiteGraphicsSystemScreen(); + + mPrimaryScreen->mGeometry = QRect + (0, 0, xd->width, xd->height); + mPrimaryScreen->mDepth = 32; + mPrimaryScreen->mFormat = QImage::Format_RGB32; + mPrimaryScreen->mPhysicalSize = + QSize(xd->physicalWidth, xd->physicalHeight); + + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QTestLiteGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QTestLiteGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + if (widget->windowType() == Qt::Desktop) + return 0; // Don't create an explicit window surface for the destkop. + return new QTestLiteWindowSurface + (const_cast<QTestLiteGraphicsSystem *>(this), mPrimaryScreen, widget); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/testlite/qgraphicssystem_testlite.h b/src/plugins/graphicssystems/testlite/qgraphicssystem_testlite.h new file mode 100644 index 0000000..cb88ee8 --- /dev/null +++ b/src/plugins/graphicssystems/testlite/qgraphicssystem_testlite.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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_TESTLITE_H +#define QGRAPHICSSYSTEM_TESTLITE_H + +#include <QtGui/private/qgraphicssystem_p.h> + +QT_BEGIN_NAMESPACE + +class MyDisplay; + +class QTestLiteGraphicsSystemScreen : public QGraphicsSystemScreen +{ +public: + QTestLiteGraphicsSystemScreen() + : mDepth(16), mFormat(QImage::Format_RGB16) {} + ~QTestLiteGraphicsSystemScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + QSize physicalSize() const { return mPhysicalSize; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; +}; + +class QTestLiteGraphicsSystem : public QGraphicsSystem +{ +public: + QTestLiteGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + + QList<QGraphicsSystemScreen *> screens() const { return mScreens; } + + MyDisplay *xd; + +private: + QTestLiteGraphicsSystemScreen *mPrimaryScreen; + QList<QGraphicsSystemScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/testlite/qwindowsurface_testlite.cpp b/src/plugins/graphicssystems/testlite/qwindowsurface_testlite.cpp new file mode 100644 index 0000000..6996809 --- /dev/null +++ b/src/plugins/graphicssystems/testlite/qwindowsurface_testlite.cpp @@ -0,0 +1,528 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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$ +** +****************************************************************************/ + +#include "qwindowsurface_testlite.h" +#include "qgraphicssystem_testlite.h" + +#include <QtCore/qdebug.h> +#include <private/qapplication_p.h> + +#include "x11util.h" + +QT_BEGIN_NAMESPACE + +QTestLiteWindowSurface::QTestLiteWindowSurface + (QTestLiteGraphicsSystem *graphicsSystem, + QTestLiteGraphicsSystemScreen *screen, QWidget *window) + : QWindowSurface(window), + mGraphicsSystem(graphicsSystem), + mScreen(screen), + xw(0) +{ + + + xw = new MyWindow(graphicsSystem->xd, 0,0,300,300); + xw->windowSurface = this; + + qDebug() << "QTestLiteWindowSurface::QTestLiteWindowSurface:" << xw->window; + + setWindowFlags(window->windowFlags()); //##### This should not be the plugin's responsibility +} + +QTestLiteWindowSurface::~QTestLiteWindowSurface() +{ + qDebug() << "~QTestLiteWindowSurface" << xw->window; + delete xw; +} + +QPaintDevice *QTestLiteWindowSurface::paintDevice() +{ + return &xw->img; +} + +void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + + // qDebug() << "QTestLiteWindowSurface::flush:" << (long)this; + + xw->paintEvent(); +} + +void QTestLiteWindowSurface::setGeometry(const QRect &rect) +{ + //qDebug() << "QTestLiteWindowSurface::setGeometry:" << rect << xw->window; + QWindowSurface::setGeometry(rect); + + if (xw->img.size() != rect.size()) + xw->img = QImage(rect.size(), mScreen->format()); + + //if unchanged ### +// xw->setSize(rect.width(), rect.height()); + xw->setGeometry(rect.x(), rect.y(), rect.width(), rect.height()); +} + +bool QTestLiteWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QTestLiteWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QTestLiteWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Mouse event stuff + + + + +static Qt::MouseButtons translateMouseButtons(int s) +{ + Qt::MouseButtons ret = 0; + if (s & Button1Mask) + ret |= Qt::LeftButton; + if (s & Button2Mask) + ret |= Qt::MidButton; + if (s & Button3Mask) + ret |= Qt::RightButton; + return ret; +} + + +static Qt::KeyboardModifiers translateModifiers(int s) +{ + const uchar qt_alt_mask = Mod1Mask; + const uchar qt_meta_mask = Mod4Mask; + + + Qt::KeyboardModifiers ret = 0; + if (s & ShiftMask) + ret |= Qt::ShiftModifier; + if (s & ControlMask) + ret |= Qt::ControlModifier; + if (s & qt_alt_mask) + ret |= Qt::AltModifier; + if (s & qt_meta_mask) + ret |= Qt::MetaModifier; +#if 0 + if (s & qt_mode_switch_mask) + ret |= Qt::GroupSwitchModifier; +#endif + return ret; +} + +void QTestLiteWindowSurface::handleMouseEvent(QEvent::Type type, void *ev) +{ + static QPoint mousePoint; + + XButtonEvent *e = static_cast<XButtonEvent*>(ev); + + Qt::MouseButton button = Qt::NoButton; + Qt::MouseButtons buttons = translateMouseButtons(e->state); + Qt::KeyboardModifiers modifiers = translateModifiers(e->state); + if (type != QEvent::MouseMove) { + switch (e->button) { + case Button1: button = Qt::LeftButton; break; + case Button2: button = Qt::MidButton; break; + case Button3: button = Qt::RightButton; break; + default: break; + } + } + + if (type == QEvent::MouseButtonPress && mousePoint != QPoint(e->x_root, e->y_root)) { + //we've missed a mouse move event somewhere (maybe because we + //haven't implemented mouse tracking yet); let's synthesize it. + QMouseEvent me(QEvent::MouseMove, QPoint(e->x, e->y), QPoint(e->x_root, e->y_root), + Qt::NoButton, buttons, modifiers); + QApplicationPrivate::handleMouseEvent(window(), me); + } + + buttons ^= button; // X event uses state *before*, Qt uses state *after* + + QMouseEvent me(type, QPoint(e->x, e->y), QPoint(e->x_root, e->y_root), button, buttons, modifiers); + QApplicationPrivate::handleMouseEvent(window(), me); + mousePoint = QPoint(e->x_root, e->y_root); +} + +void QTestLiteWindowSurface::handleGeometryChange(int x, int y, int w, int h) +{ + QApplicationPrivate::handleGeometryChange(window(), QRect(x,y,w,h)); +} + + + + + + + + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Key event stuff -- not pretty either +// +// What we want to do is to port Robert's keytable code properly + + + + + + + +// keyboard mapping table +static const unsigned int keyTbl[] = { + + // misc keys + + XK_Escape, Qt::Key_Escape, + XK_Tab, Qt::Key_Tab, + XK_ISO_Left_Tab, Qt::Key_Backtab, + XK_BackSpace, Qt::Key_Backspace, + XK_Return, Qt::Key_Return, + XK_Insert, Qt::Key_Insert, + XK_Delete, Qt::Key_Delete, + XK_Clear, Qt::Key_Delete, + XK_Pause, Qt::Key_Pause, + XK_Print, Qt::Key_Print, + 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq + 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq + + // cursor movement + + XK_Home, Qt::Key_Home, + XK_End, Qt::Key_End, + XK_Left, Qt::Key_Left, + XK_Up, Qt::Key_Up, + XK_Right, Qt::Key_Right, + XK_Down, Qt::Key_Down, + XK_Prior, Qt::Key_PageUp, + XK_Next, Qt::Key_PageDown, + + // modifiers + + XK_Shift_L, Qt::Key_Shift, + XK_Shift_R, Qt::Key_Shift, + XK_Shift_Lock, Qt::Key_Shift, + XK_Control_L, Qt::Key_Control, + XK_Control_R, Qt::Key_Control, + XK_Meta_L, Qt::Key_Meta, + XK_Meta_R, Qt::Key_Meta, + XK_Alt_L, Qt::Key_Alt, + XK_Alt_R, Qt::Key_Alt, + XK_Caps_Lock, Qt::Key_CapsLock, + XK_Num_Lock, Qt::Key_NumLock, + XK_Scroll_Lock, Qt::Key_ScrollLock, + XK_Super_L, Qt::Key_Super_L, + XK_Super_R, Qt::Key_Super_R, + XK_Menu, Qt::Key_Menu, + XK_Hyper_L, Qt::Key_Hyper_L, + XK_Hyper_R, Qt::Key_Hyper_R, + XK_Help, Qt::Key_Help, + 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab + 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) + 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) + + // numeric and function keypad keys + + XK_KP_Space, Qt::Key_Space, + XK_KP_Tab, Qt::Key_Tab, + XK_KP_Enter, Qt::Key_Enter, + //XK_KP_F1, Qt::Key_F1, + //XK_KP_F2, Qt::Key_F2, + //XK_KP_F3, Qt::Key_F3, + //XK_KP_F4, Qt::Key_F4, + XK_KP_Home, Qt::Key_Home, + XK_KP_Left, Qt::Key_Left, + XK_KP_Up, Qt::Key_Up, + XK_KP_Right, Qt::Key_Right, + XK_KP_Down, Qt::Key_Down, + XK_KP_Prior, Qt::Key_PageUp, + XK_KP_Next, Qt::Key_PageDown, + XK_KP_End, Qt::Key_End, + XK_KP_Begin, Qt::Key_Clear, + XK_KP_Insert, Qt::Key_Insert, + XK_KP_Delete, Qt::Key_Delete, + XK_KP_Equal, Qt::Key_Equal, + XK_KP_Multiply, Qt::Key_Asterisk, + XK_KP_Add, Qt::Key_Plus, + XK_KP_Separator, Qt::Key_Comma, + XK_KP_Subtract, Qt::Key_Minus, + XK_KP_Decimal, Qt::Key_Period, + XK_KP_Divide, Qt::Key_Slash, + + // International input method support keys + + // International & multi-key character composition + XK_ISO_Level3_Shift, Qt::Key_AltGr, + XK_Multi_key, Qt::Key_Multi_key, + XK_Codeinput, Qt::Key_Codeinput, + XK_SingleCandidate, Qt::Key_SingleCandidate, + XK_MultipleCandidate, Qt::Key_MultipleCandidate, + XK_PreviousCandidate, Qt::Key_PreviousCandidate, + + // Misc Functions + XK_Mode_switch, Qt::Key_Mode_switch, + XK_script_switch, Qt::Key_Mode_switch, + + // Japanese keyboard support + XK_Kanji, Qt::Key_Kanji, + XK_Muhenkan, Qt::Key_Muhenkan, + //XK_Henkan_Mode, Qt::Key_Henkan_Mode, + XK_Henkan_Mode, Qt::Key_Henkan, + XK_Henkan, Qt::Key_Henkan, + XK_Romaji, Qt::Key_Romaji, + XK_Hiragana, Qt::Key_Hiragana, + XK_Katakana, Qt::Key_Katakana, + XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, + XK_Zenkaku, Qt::Key_Zenkaku, + XK_Hankaku, Qt::Key_Hankaku, + XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, + XK_Touroku, Qt::Key_Touroku, + XK_Massyo, Qt::Key_Massyo, + XK_Kana_Lock, Qt::Key_Kana_Lock, + XK_Kana_Shift, Qt::Key_Kana_Shift, + XK_Eisu_Shift, Qt::Key_Eisu_Shift, + XK_Eisu_toggle, Qt::Key_Eisu_toggle, + //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, + //XK_Zen_Koho, Qt::Key_Zen_Koho, + //XK_Mae_Koho, Qt::Key_Mae_Koho, + XK_Kanji_Bangou, Qt::Key_Codeinput, + XK_Zen_Koho, Qt::Key_MultipleCandidate, + XK_Mae_Koho, Qt::Key_PreviousCandidate, + +#ifdef XK_KOREAN + // Korean keyboard support + XK_Hangul, Qt::Key_Hangul, + XK_Hangul_Start, Qt::Key_Hangul_Start, + XK_Hangul_End, Qt::Key_Hangul_End, + XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, + XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, + XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, + //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, + XK_Hangul_Codeinput, Qt::Key_Codeinput, + XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, + XK_Hangul_Banja, Qt::Key_Hangul_Banja, + XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, + XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, + //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, + //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, + //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, + XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, + XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, + XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, + XK_Hangul_Special, Qt::Key_Hangul_Special, + //XK_Hangul_switch, Qt::Key_Hangul_switch, + XK_Hangul_switch, Qt::Key_Mode_switch, +#endif // XK_KOREAN + + // dead keys + XK_dead_grave, Qt::Key_Dead_Grave, + XK_dead_acute, Qt::Key_Dead_Acute, + XK_dead_circumflex, Qt::Key_Dead_Circumflex, + XK_dead_tilde, Qt::Key_Dead_Tilde, + XK_dead_macron, Qt::Key_Dead_Macron, + XK_dead_breve, Qt::Key_Dead_Breve, + XK_dead_abovedot, Qt::Key_Dead_Abovedot, + XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, + XK_dead_abovering, Qt::Key_Dead_Abovering, + XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, + XK_dead_caron, Qt::Key_Dead_Caron, + XK_dead_cedilla, Qt::Key_Dead_Cedilla, + XK_dead_ogonek, Qt::Key_Dead_Ogonek, + XK_dead_iota, Qt::Key_Dead_Iota, + XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, + XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, + XK_dead_belowdot, Qt::Key_Dead_Belowdot, + XK_dead_hook, Qt::Key_Dead_Hook, + XK_dead_horn, Qt::Key_Dead_Horn, + +#if 0 + // Special multimedia keys + // currently only tested with MS internet keyboard + + // browsing keys + XF86XK_Back, Qt::Key_Back, + XF86XK_Forward, Qt::Key_Forward, + XF86XK_Stop, Qt::Key_Stop, + XF86XK_Refresh, Qt::Key_Refresh, + XF86XK_Favorites, Qt::Key_Favorites, + XF86XK_AudioMedia, Qt::Key_LaunchMedia, + XF86XK_OpenURL, Qt::Key_OpenUrl, + XF86XK_HomePage, Qt::Key_HomePage, + XF86XK_Search, Qt::Key_Search, + + // media keys + XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, + XF86XK_AudioMute, Qt::Key_VolumeMute, + XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, + XF86XK_AudioPlay, Qt::Key_MediaPlay, + XF86XK_AudioStop, Qt::Key_MediaStop, + XF86XK_AudioPrev, Qt::Key_MediaPrevious, + XF86XK_AudioNext, Qt::Key_MediaNext, + XF86XK_AudioRecord, Qt::Key_MediaRecord, + + // launch keys + XF86XK_Mail, Qt::Key_LaunchMail, + XF86XK_MyComputer, Qt::Key_Launch0, + XF86XK_Calculator, Qt::Key_Launch1, + XF86XK_Standby, Qt::Key_Standby, + + XF86XK_Launch0, Qt::Key_Launch2, + XF86XK_Launch1, Qt::Key_Launch3, + XF86XK_Launch2, Qt::Key_Launch4, + XF86XK_Launch3, Qt::Key_Launch5, + XF86XK_Launch4, Qt::Key_Launch6, + XF86XK_Launch5, Qt::Key_Launch7, + XF86XK_Launch6, Qt::Key_Launch8, + XF86XK_Launch7, Qt::Key_Launch9, + XF86XK_Launch8, Qt::Key_LaunchA, + XF86XK_Launch9, Qt::Key_LaunchB, + XF86XK_LaunchA, Qt::Key_LaunchC, + XF86XK_LaunchB, Qt::Key_LaunchD, + XF86XK_LaunchC, Qt::Key_LaunchE, + XF86XK_LaunchD, Qt::Key_LaunchF, +#endif + +#if 0 + // Qtopia keys + QTOPIAXK_Select, Qt::Key_Select, + QTOPIAXK_Yes, Qt::Key_Yes, + QTOPIAXK_No, Qt::Key_No, + QTOPIAXK_Cancel, Qt::Key_Cancel, + QTOPIAXK_Printer, Qt::Key_Printer, + QTOPIAXK_Execute, Qt::Key_Execute, + QTOPIAXK_Sleep, Qt::Key_Sleep, + QTOPIAXK_Play, Qt::Key_Play, + QTOPIAXK_Zoom, Qt::Key_Zoom, + QTOPIAXK_Context1, Qt::Key_Context1, + QTOPIAXK_Context2, Qt::Key_Context2, + QTOPIAXK_Context3, Qt::Key_Context3, + QTOPIAXK_Context4, Qt::Key_Context4, + QTOPIAXK_Call, Qt::Key_Call, + QTOPIAXK_Hangup, Qt::Key_Hangup, + QTOPIAXK_Flip, Qt::Key_Flip, +#endif + 0, 0 +}; + + +static int lookupCode(unsigned int xkeycode) +{ + const unsigned int *p = keyTbl; + while (*p) { + if (*p == xkeycode) + return *++p; + p += 2; + } + + return 0; +} + + +void QTestLiteWindowSurface::handleKeyEvent(QEvent::Type type, void *ev) +{ + XKeyEvent *e = static_cast<XKeyEvent*>(ev); + + KeySym keySym; + QByteArray chars; + chars.resize(513); + + int count = XLookupString(e, chars.data(), chars.size(), &keySym, 0); + +// qDebug() << "QTLWS::handleKeyEvent" << count << hex << "XKeysym:" << keySym; +// if (count) +// qDebug() << hex << int(chars[0]) << "String:" << chars; + + Qt::KeyboardModifiers modifiers = translateModifiers(e->state); + + int qtcode = lookupCode(keySym); +// qDebug() << "lookup: " << hex << keySym << qtcode; + + if (qtcode) { + QKeyEvent keyEvent(type, qtcode, modifiers); + QApplicationPrivate::handleKeyEvent(window(), &keyEvent); + } else if (chars[0]) { + int qtcode = chars.toUpper()[0]; //Not exactly right... + QKeyEvent keyEvent(type, qtcode, modifiers, QString::fromLatin1(chars)); + QApplicationPrivate::handleKeyEvent(window(), &keyEvent); + } else { + qWarning() << "unknown X keycode" << hex << e->keycode << keySym; + } +} + + + +Qt::WindowFlags QTestLiteWindowSurface::setWindowFlags(Qt::WindowFlags flags) +{ + Q_ASSERT(flags & Qt::Window); + + window_flags = flags; + + xw->setWindowFlags(flags); + + return window_flags; + +} + +Qt::WindowFlags QTestLiteWindowSurface::windowFlags() const +{ + return window_flags; +} + +void QTestLiteWindowSurface::setVisible(bool visible) +{ + //qDebug() << "QTestLiteWindowSurface::setVisible" << visible << xw->window; + xw->setVisible(visible); +} + + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/testlite/qwindowsurface_testlite.h b/src/plugins/graphicssystems/testlite/qwindowsurface_testlite.h new file mode 100644 index 0000000..33b55e9 --- /dev/null +++ b/src/plugins/graphicssystems/testlite/qwindowsurface_testlite.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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 QWINDOWSURFACE_TESTLITE_H +#define QWINDOWSURFACE_TESTLITE_H + +#include <QtGui/private/qwindowsurface_p.h> +#include <qevent.h> + +QT_BEGIN_NAMESPACE + +class MyWindow; +class QTestLiteGraphicsSystem; +class QTestLiteGraphicsSystemScreen; + +class QTestLiteWindowSurface : public QWindowSurface +{ +public: + QTestLiteWindowSurface + (QTestLiteGraphicsSystem *graphicsSystem, + QTestLiteGraphicsSystemScreen *screen, QWidget *window); + ~QTestLiteWindowSurface(); + + 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); + + void handleMouseEvent(QEvent::Type, void *); //forwarding X types is apparently impossible :( + void handleKeyEvent(QEvent::Type, void *); + void handleGeometryChange(int x, int y, int w, int h); + + + Qt::WindowFlags setWindowFlags(Qt::WindowFlags type); + Qt::WindowFlags windowFlags() const; + void setVisible(bool visible); + +private: + QTestLiteGraphicsSystem *mGraphicsSystem; + QTestLiteGraphicsSystemScreen *mScreen; + Qt::WindowFlags window_flags; + MyWindow *xw; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/testlite/testlite.pro b/src/plugins/graphicssystems/testlite/testlite.pro new file mode 100644 index 0000000..af8a437 --- /dev/null +++ b/src/plugins/graphicssystems/testlite/testlite.pro @@ -0,0 +1,17 @@ +TARGET = qtestlitegraphicssystem +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_testlite.cpp qwindowsurface_testlite.cpp +HEADERS = qgraphicssystem_testlite.h qwindowsurface_testlite.h + + +HEADERS += x11util.h +SOURCES += x11util.cpp + +LIBS += -lX11 + + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/graphicssystems/testlite/x11util.cpp b/src/plugins/graphicssystems/testlite/x11util.cpp new file mode 100644 index 0000000..f77356a --- /dev/null +++ b/src/plugins/graphicssystems/testlite/x11util.cpp @@ -0,0 +1,684 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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$ +** +****************************************************************************/ + +#include <QImage> +#include <QSocketNotifier> + +#include <qdebug.h> +#include <QTimer> + +#include "x11util.h" +#include "qwindowsurface_testlite.h" + +#include <stdio.h> +#include <stdlib.h> + + +#include <X11/Xatom.h> + + + +//### remove stuff we don't want from qt_x11_p.h +#undef ATOM +#undef X11 + + + + + +static int (*original_x_errhandler)(Display *dpy, XErrorEvent *); +static bool seen_badwindow; + + +//### copied from qapplication_x11.cpp + +static int qt_x_errhandler(Display *dpy, XErrorEvent *err) +{ + +qDebug() << "qt_x_errhandler" << err->error_code; + + switch (err->error_code) { + case BadAtom: +#if 0 + if (err->request_code == 20 /* X_GetProperty */ + && (err->resourceid == XA_RESOURCE_MANAGER + || err->resourceid == XA_RGB_DEFAULT_MAP + || err->resourceid == ATOM(_NET_SUPPORTED) + || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK) + || err->resourceid == ATOM(KDE_FULL_SESSION) + || err->resourceid == ATOM(KWIN_RUNNING) + || err->resourceid == ATOM(XdndProxy) + || err->resourceid == ATOM(XdndAware)) + + + ) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } +#endif + qDebug() << "BadAtom"; + break; + + case BadWindow: + if (err->request_code == 2 /* X_ChangeWindowAttributes */ + || err->request_code == 38 /* X_QueryPointer */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } + } + seen_badwindow = true; + if (err->request_code == 25 /* X_SendEvent */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } +#if 0 + if (X11->xdndHandleBadwindow()) { + qDebug("xdndHandleBadwindow returned true"); + return 0; + } +#endif + } +#if 0 + if (X11->ignore_badwindow) + return 0; +#endif + break; + + case BadMatch: + if (err->request_code == 42 /* X_SetInputFocus */) + return 0; + break; + + default: +#if 0 //!defined(QT_NO_XINPUT) + if (err->request_code == X11->xinput_major + && err->error_code == (X11->xinput_errorbase + XI_BadDevice) + && err->minor_code == 3 /* X_OpenDevice */) { + return 0; + } +#endif + break; + } + + char errstr[256]; + XGetErrorText( dpy, err->error_code, errstr, 256 ); + char buffer[256]; + char request_str[256]; + qsnprintf(buffer, 256, "%d", err->request_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256); + if (err->request_code < 128) { + // X error for a normal protocol request + qWarning( "X Error: %s %d\n" + " Major opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + request_str, + err->resourceid ); + } else { + // X error for an extension request + const char *extensionName = 0; +#if 0 + if (err->request_code == X11->xrender_major) + extensionName = "RENDER"; + else if (err->request_code == X11->xrandr_major) + extensionName = "RANDR"; + else if (err->request_code == X11->xinput_major) + extensionName = "XInputExtension"; + else if (err->request_code == X11->mitshm_major) + extensionName = "MIT-SHM"; +#endif + char minor_str[256]; + if (extensionName) { + qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256); + } else { + extensionName = "Uknown extension"; + qsnprintf(minor_str, 256, "Unknown request"); + } + qWarning( "X Error: %s %d\n" + " Extension: %d (%s)\n" + " Minor opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + extensionName, + err->minor_code, + minor_str, + err->resourceid ); + } + + // ### we really should distinguish between severe, non-severe and + // ### application specific errors + + return 0; +} + + + + + + + + + +bool MyDisplay::handleEvent(XEvent *xe) +{ + //qDebug() << "handleEvent" << xe->xany.type << xe->xany.window; + int quit = false; + MyWindow *xw = 0; + foreach (MyWindow *w, windowList) { + if (w->window == xe->xany.window) { + xw = w; + break; + } + } + if (!xw) { + qWarning() << "Unknown window" << xe->xany.window << "received event" << hex << xe->type; + return quit; + } + + switch (xe->type) { + case Expose: + if (xw) + if (xe->xexpose.count == 0) + xw->paintEvent(); + break; + case ConfigureNotify: + if (xw) + xw->resizeEvent(&xe->xconfigure); + break; +#if 1 + + case ButtonPress: + xw->mousePressEvent(&xe->xbutton); + break; + + case ButtonRelease: + xw->mouseReleaseEvent(&xe->xbutton); + break; + + case MotionNotify: + xw->mouseMoveEvent(&xe->xbutton); + break; + + case XKeyPress: + xw->keyPressEvent(&xe->xkey); + break; + + case XKeyRelease: + xw->keyReleaseEvent(&xe->xkey); + break; +#endif + + default: + qDebug() << "Other X event" << hex << xe->type; + break; + } + return quit; +}; + + +MyDisplay::MyDisplay() +{ + char *display_name = getenv("DISPLAY"); + display = XOpenDisplay(display_name); + if (!display) { + fprintf(stderr, "Cannot connect to X server: %s\n", + display_name); + exit(1); + } + + original_x_errhandler = XSetErrorHandler(qt_x_errhandler); + + if (qgetenv("DO_X_SYNCHRONIZE").toInt()) + XSynchronize(display, true); + + + screen = DefaultScreen(display); + width = DisplayWidth(display, screen); + height = DisplayHeight(display, screen); + physicalWidth = DisplayWidthMM(display, screen); + physicalHeight = DisplayHeightMM(display, screen); + + int xSocketNumber = XConnectionNumber(display); + qDebug() << "X socket:"<< xSocketNumber; + + QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this); + connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); +} + + +MyDisplay::~MyDisplay() +{ + XCloseDisplay(display); +} + + +void MyDisplay::eventDispatcher() +{ +// qDebug() << "eventDispatcher"; + + + ulong marker = XNextRequest(display); +// int i = 0; + while (XPending(display)) { + XEvent event; + XNextEvent(display, &event); + /* done = */ + handleEvent(&event); + + if (event.xany.serial >= marker) { + qDebug() << "potential livelock averted"; +#if 0 + if (XEventsQueued(display, QueuedAfterFlush)) { + qDebug() << " with events queued"; + QTimer::singleShot(0, this, SLOT(eventDispatcher())); + } +#endif + break; + } + } +} + + +MyWindow::MyWindow(MyDisplay *display, int x, int y, int w, int h) +{ + xd = display; + + xd->windowList.append(this); + + qDebug() << "MyWindow::MyWindow"; + + window = XCreateSimpleWindow(xd->display, xd->rootWindow(), + x, y, w, h, 0 /*border_width*/, + xd->blackPixel(), xd->whitePixel()); + + width = -1; + height = -1; + xpos = -1; + ypos = -1; + + XSetWindowBackgroundPixmap(xd->display, window, XNone); + + XSelectInput(xd->display, window, ExposureMask | KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | StructureNotifyMask); + + gc = createGC(); +} + +MyWindow::~MyWindow() +{ + XFreeGC(xd->display, gc); + XDestroyWindow(xd->display, window); + + xd->windowList.removeAll(this); +} + +GC MyWindow::createGC() +{ + GC gc; + + gc = XCreateGC(xd->display, window, 0, 0); + if (gc < 0) { + qWarning("MyWindow::createGC() could not create GC"); + } + return gc; +} + + + +void MyWindow::paintEvent() +{ + Visual *visual = DefaultVisual(xd->display, xd->screen); + + if (!img.isNull()) { + QImage image = img.convertToFormat(QImage::Format_RGB32); + XImage *xi = XCreateImage(xd->display, visual, 24, ZPixmap, + 0, (char *) image.scanLine(0), image.width(), image.height(), + 32, image.bytesPerLine()); + + int x = 0; + int y = 0; + + /*int r =*/ XPutImage(xd->display, window, gc, xi, 0, 0, x, y, image.width(), image.height()); + + xi->data = 0; // QImage owns these bits + XDestroyImage(xi); + } +} + +void MyWindow::resizeEvent(XConfigureEvent *e) +{ + + if ((e->width != width || e->height != height) && e->x == 0 && e->y == 0) { + //qDebug() << "resize with bogus pos" << e->x << e->y << e->width << e->height << "window"<< hex << window; + } else { + //qDebug() << "geometry change" << e->x << e->y << e->width << e->height << "window"<< hex << window; + xpos = e->x; + ypos = e->y; + } + width = e->width; + height = e->height; + + windowSurface->handleGeometryChange(xpos, ypos, width, height); +} + + +void MyWindow::setSize(int w, int h) +{ + XResizeWindow(xd->display, window, w, h); +} + +void MyWindow::setGeometry(int x, int y, int w, int h) +{ + XMoveResizeWindow(xd->display, window, x, y, w, h); +} + + +void MyWindow::mousePressEvent(XButtonEvent *e) +{ + windowSurface->handleMouseEvent(QEvent::MouseButtonPress, e); +} + +void MyWindow::mouseReleaseEvent(XButtonEvent *e) +{ + windowSurface->handleMouseEvent(QEvent::MouseButtonRelease, e); +} + +void MyWindow::mouseMoveEvent(XButtonEvent *e) +{ + windowSurface->handleMouseEvent(QEvent::MouseMove, e); +} + +#ifdef KeyPress +#undef KeyPress +#endif + +void MyWindow::keyPressEvent(XKeyEvent *e) +{ + windowSurface->handleKeyEvent(QEvent::KeyPress, e); +} + +#ifdef KeyRelease +#undef KeyRelease +#endif + +void MyWindow::keyReleaseEvent(XKeyEvent *e) +{ + windowSurface->handleKeyEvent(QEvent::KeyRelease, e); +} + + +// WindowFlag stuff, lots of copied code from qwidget_x11.cpp... + +//We're hacking here... + + +// MWM support +struct QtMWMHints { + ulong flags, functions, decorations; + long input_mode; + ulong status; +}; + +enum { + MWM_HINTS_FUNCTIONS = (1L << 0), + + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), + + MWM_HINTS_DECORATIONS = (1L << 1), + + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), + + MWM_HINTS_INPUT_MODE = (1L << 2), + + MWM_INPUT_MODELESS = 0L, + MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, + MWM_INPUT_FULL_APPLICATION_MODAL = 3L +}; + +static Atom mwm_hint_atom = XNone; + +static QtMWMHints GetMWMHints(Display *display, Window window) +{ + QtMWMHints mwmhints; + + Atom type; + int format; + ulong nitems, bytesLeft; + uchar *data = 0; + if ((XGetWindowProperty(display, window, mwm_hint_atom, 0, 5, false, + mwm_hint_atom, &type, &format, &nitems, &bytesLeft, + &data) == Success) + && (type == mwm_hint_atom + && format == 32 + && nitems >= 5)) { + mwmhints = *(reinterpret_cast<QtMWMHints *>(data)); + } else { + mwmhints.flags = 0L; + mwmhints.functions = MWM_FUNC_ALL; + mwmhints.decorations = MWM_DECOR_ALL; + mwmhints.input_mode = 0L; + mwmhints.status = 0L; + } + + if (data) + XFree(data); + + return mwmhints; +} + +static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints) +{ + if (mwmhints.flags != 0l) { + XChangeProperty(display, window, mwm_hint_atom, mwm_hint_atom, 32, + PropModeReplace, (unsigned char *) &mwmhints, 5); + } else { + XDeleteProperty(display, window, mwm_hint_atom); + } +} + +// Returns true if we should set WM_TRANSIENT_FOR on \a w +static inline bool isTransient(const QWidget *w) +{ + return ((w->windowType() == Qt::Dialog + || w->windowType() == Qt::Sheet + || w->windowType() == Qt::Tool + || w->windowType() == Qt::SplashScreen + || w->windowType() == Qt::ToolTip + || w->windowType() == Qt::Drawer + || w->windowType() == Qt::Popup) + && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); +} + + + +Qt::WindowFlags MyWindow::setWindowFlags(Qt::WindowFlags flags) +{ + + if (mwm_hint_atom == XNone) { + mwm_hint_atom = XInternAtom(xd->display, "_MOTIF_WM_HINTS\0", False); + } + + qDebug() << "MyWindow::setWindowFlags" << hex << mwm_hint_atom << "flags" << flags; + + Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); + + if (type == Qt::ToolTip) + flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; + if (type == Qt::Popup) + flags |= Qt::X11BypassWindowManagerHint; + + bool topLevel = (flags & Qt::Window); + bool popup = (type == Qt::Popup); + bool dialog = (type == Qt::Dialog + || type == Qt::Sheet); + bool desktop = (type == Qt::Desktop); + bool tool = (type == Qt::Tool || type == Qt::SplashScreen + || type == Qt::ToolTip || type == Qt::Drawer); + + + XSetWindowAttributes wsa; + + QtMWMHints mwmhints; + mwmhints.flags = 0L; + mwmhints.functions = 0L; + mwmhints.decorations = 0; + mwmhints.input_mode = 0L; + mwmhints.status = 0L; + + + ulong wsa_mask = 0; + if (type != Qt::SplashScreen) { // && customize) { + mwmhints.flags |= MWM_HINTS_DECORATIONS; + + bool customize = flags & Qt::CustomizeWindowHint; + if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { + mwmhints.decorations |= MWM_DECOR_BORDER; + mwmhints.decorations |= MWM_DECOR_RESIZEH; + + if (flags & Qt::WindowTitleHint) + mwmhints.decorations |= MWM_DECOR_TITLE; + + if (flags & Qt::WindowSystemMenuHint) + mwmhints.decorations |= MWM_DECOR_MENU; + + if (flags & Qt::WindowMinimizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MINIMIZE; + mwmhints.functions |= MWM_FUNC_MINIMIZE; + } + + if (flags & Qt::WindowMaximizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MAXIMIZE; + mwmhints.functions |= MWM_FUNC_MAXIMIZE; + } + + if (flags & Qt::WindowCloseButtonHint) + mwmhints.functions |= MWM_FUNC_CLOSE; + } + } else { + // if type == Qt::SplashScreen + mwmhints.decorations = MWM_DECOR_ALL; + } + + if (tool) { + wsa.save_under = True; + wsa_mask |= CWSaveUnder; + } + + if (flags & Qt::X11BypassWindowManagerHint) { + wsa.override_redirect = True; + wsa_mask |= CWOverrideRedirect; + } +#if 0 + if (wsa_mask && initializeWindow) { + Q_ASSERT(id); + XChangeWindowAttributes(dpy, id, wsa_mask, &wsa); + } +#endif + if (mwmhints.functions != 0) { + mwmhints.flags |= MWM_HINTS_FUNCTIONS; + mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + } else { + mwmhints.functions = MWM_FUNC_ALL; + } + + if (!(flags & Qt::FramelessWindowHint) + && flags & Qt::CustomizeWindowHint + && flags & Qt::WindowTitleHint + && !(flags & + (Qt::WindowMinimizeButtonHint + | Qt::WindowMaximizeButtonHint + | Qt::WindowCloseButtonHint))) { + // a special case - only the titlebar without any button + mwmhints.flags = MWM_HINTS_FUNCTIONS; + mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + mwmhints.decorations = 0; + } + + SetMWMHints(xd->display, window, mwmhints); + +//##### only if initializeWindow??? + + if (popup) { // popup widget + qDebug() << "Doing XChangeWindowAttributes for popup" << wsa.override_redirect; + // set EWMH window types + // setNetWmWindowTypes(); + + wsa.override_redirect = True; + wsa.save_under = True; + XChangeWindowAttributes(xd->display, window, CWOverrideRedirect | CWSaveUnder, + &wsa); + } else { + + qDebug() << "Doing XChangeWindowAttributes for non-popup"; + + } + + return flags; +} + +void MyWindow::setVisible(bool visible) +{ +// qDebug() << "MyWindow::setVisible" << visible << hex << window; + if (visible) + XMapWindow(xd->display, window); + else + XUnmapWindow(xd->display, window); +} diff --git a/src/plugins/graphicssystems/testlite/x11util.h b/src/plugins/graphicssystems/testlite/x11util.h new file mode 100644 index 0000000..3d813c0 --- /dev/null +++ b/src/plugins/graphicssystems/testlite/x11util.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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 MYX11UTIL_H +#define MYX11UTIL_H + +#include <QObject> +#include <QImage> + +#include <private/qt_x11_p.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> + + +class MyWindow; + +class MyDisplay : public QObject +{ + Q_OBJECT; +public: + MyDisplay(); + ~MyDisplay(); + + Window rootWindow() { return RootWindow(display, screen); } + unsigned long blackPixel() { return BlackPixel(display, screen); } + unsigned long whitePixel() { return WhitePixel(display, screen); } + + bool handleEvent(XEvent *xe); + +public slots: + void eventDispatcher(); + +public: //### + Display * display; + int screen; + int width, height; + int physicalWidth; + int physicalHeight; + + QList<MyWindow*> windowList; +}; + +class QTestLiteWindowSurface; //### abstract callback interface, anyone? + +class MyWindow : public QObject +{ + Q_OBJECT; +public: + MyWindow(MyDisplay *xd, int x, int y, int w, int h); + ~MyWindow(); + + + void mousePressEvent(XButtonEvent*); + void mouseReleaseEvent(XButtonEvent*); + void mouseMoveEvent(XButtonEvent*); + + void keyPressEvent(XKeyEvent*); + void keyReleaseEvent(XKeyEvent*); + + + void paintEvent(); + void resizeEvent(XConfigureEvent *configure_event); + void setSize(int w, int h); + void setGeometry(int x, int y, int w, int h); + + GC createGC(); + + Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + void setVisible(bool visible); + +public: //### + + int xpos, ypos; + int width, height; + QImage img; + Window window; + MyDisplay *xd; + GC gc; + + QTestLiteWindowSurface *windowSurface; +}; + + + + + +#endif // MYX11UTIL_H diff --git a/src/plugins/graphicssystems/vnc/main.cpp b/src/plugins/graphicssystems/vnc/main.cpp new file mode 100644 index 0000000..7deb91a --- /dev/null +++ b/src/plugins/graphicssystems/vnc/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_vnc.h" +#include <qstringlist.h> + +QT_BEGIN_NAMESPACE + +class QVNCGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QVNCGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "VNC"; + return list; +} + +QGraphicsSystem* QVNCGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "vnc") + return new QVNCGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(vnc, QVNCGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/vnc/qgraphicssystem_vnc.cpp b/src/plugins/graphicssystems/vnc/qgraphicssystem_vnc.cpp new file mode 100644 index 0000000..4890e09 --- /dev/null +++ b/src/plugins/graphicssystems/vnc/qgraphicssystem_vnc.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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_vnc.h" +#include "qwindowsurface_vnc.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> + +#include <qvncserver.h> + + + + +QVNCGraphicsSystemScreen::QVNCGraphicsSystemScreen() + : mDepth(16), mFormat(QImage::Format_RGB16), mScreenImage(0) +{ + mGeometry = QRect(0,0,800, 600); + + mDepth = 32; + mFormat = QImage::Format_RGB32; + mPhysicalSize = (mGeometry.size()*254)/720; + + + mScreenImage = new QImage(mGeometry.size(), mFormat); + d_ptr = new QVNCGraphicsSystemScreenPrivate(this); +} + + +QVNCGraphicsSystemScreen::~QVNCGraphicsSystemScreen() +{ + delete mScreenImage; +} + +QVNCDirtyMap *QVNCGraphicsSystemScreen::dirtyMap() +{ + return d_ptr->dirty; +} + + +void QVNCGraphicsSystemScreen::setDirty(const QRect &rect) +{ + d_ptr->setDirty(rect); +} + + +QVNCGraphicsSystem::QVNCGraphicsSystem() +{ +//////// xd = new MyDisplay; + + mPrimaryScreen = new QVNCGraphicsSystemScreen(); + + + int dw = mPrimaryScreen->geometry().width(); + int dh = mPrimaryScreen->geometry().height(); + + + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QVNCGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QVNCGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + if (widget->windowType() == Qt::Desktop) + return 0; // Don't create an explicit window surface for the destkop. + return new QVNCWindowSurface + (const_cast<QVNCGraphicsSystem *>(this), mPrimaryScreen, widget); +} diff --git a/src/plugins/graphicssystems/vnc/qgraphicssystem_vnc.h b/src/plugins/graphicssystems/vnc/qgraphicssystem_vnc.h new file mode 100644 index 0000000..d9b4375 --- /dev/null +++ b/src/plugins/graphicssystems/vnc/qgraphicssystem_vnc.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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_VNC_H +#define QGRAPHICSSYSTEM_VNC_H + +#include <QtGui/private/qgraphicssystem_p.h> + +QT_BEGIN_NAMESPACE + +class QVNCServer; +class QVNCDirtyMap; + + +class QVNCGraphicsSystemScreenPrivate; + +class QVNCGraphicsSystemScreen : public QGraphicsSystemScreen +{ +public: + QVNCGraphicsSystemScreen(); + ~QVNCGraphicsSystemScreen(); + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + QSize physicalSize() const { return mPhysicalSize; } + int linestep() const { return mScreenImage ? mScreenImage->bytesPerLine() : 0; } + uchar *base() const { return mScreenImage ? mScreenImage->bits() : 0; } + QVNCDirtyMap *dirtyMap(); + + void setDirty(const QRect &rect); + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + QImage *mScreenImage; + QVNCServer *server; + + QVNCGraphicsSystemScreenPrivate *d_ptr; +}; + +class QVNCGraphicsSystemPrivate; + + +class QVNCGraphicsSystem : public QGraphicsSystem +{ +public: + QVNCGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + + QList<QGraphicsSystemScreen *> screens() const { return mScreens; } + +private: + QVNCGraphicsSystemScreen *mPrimaryScreen; + QList<QGraphicsSystemScreen *> mScreens; +}; + + + +QT_END_NAMESPACE + +#endif //QGRAPHICSSYSTEM_VNC_H + diff --git a/src/plugins/graphicssystems/vnc/qvncserver.cpp b/src/plugins/graphicssystems/vnc/qvncserver.cpp new file mode 100644 index 0000000..c3677a0 --- /dev/null +++ b/src/plugins/graphicssystems/vnc/qvncserver.cpp @@ -0,0 +1,1912 @@ +/**************************************************************************** +** +** 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 "qvncserver.h" + +#include <QtCore/qtimer.h> +#include <QtCore/qregexp.h> +#include <QtGui/qwidget.h> +#include <QtGui/qpolygon.h> +#include <QtGui/qpainter.h> + +#include <QtGui/qevent.h> +#include <private/qapplication_p.h> + +#include <qplatformdefs.h> + +#include <qdebug.h> + +#include <stdlib.h> + + +#define QT_QWS_VNC_DEBUG +#define QT_NO_QWS_CURSOR //### + + +QT_BEGIN_NAMESPACE + + + +//copied from qscreen_qws.h +#ifndef QT_QWS_DEPTH16_RGB +#define QT_QWS_DEPTH16_RGB 565 +#endif +static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100); +static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10); +static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10); +static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); +static const int qt_green_shift = qt_bbits-(8-qt_gbits); +static const int qt_neg_blue_shift = 8-qt_bbits; +static const int qt_blue_mask = (1<<qt_bbits)-1; +static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits); +static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); + +static const int qt_red_rounding_shift = qt_red_shift + qt_rbits; +static const int qt_green_rounding_shift = qt_green_shift + qt_gbits; +static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift; + + +inline QRgb qt_conv16ToRgb(ushort c) +{ + const int r=(c & qt_red_mask); + const int g=(c & qt_green_mask); + const int b=(c & qt_blue_mask); + const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift; + const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift; + const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift; + + return qRgb(tr,tg,tb); +} + + + +//=========================================================================== + +static const struct { + int keysym; + int keycode; +} keyMap[] = { + { 0xff08, Qt::Key_Backspace }, + { 0xff09, Qt::Key_Tab }, + { 0xff0d, Qt::Key_Return }, + { 0xff1b, Qt::Key_Escape }, + { 0xff63, Qt::Key_Insert }, + { 0xffff, Qt::Key_Delete }, + { 0xff50, Qt::Key_Home }, + { 0xff57, Qt::Key_End }, + { 0xff55, Qt::Key_PageUp }, + { 0xff56, Qt::Key_PageDown }, + { 0xff51, Qt::Key_Left }, + { 0xff52, Qt::Key_Up }, + { 0xff53, Qt::Key_Right }, + { 0xff54, Qt::Key_Down }, + { 0xffbe, Qt::Key_F1 }, + { 0xffbf, Qt::Key_F2 }, + { 0xffc0, Qt::Key_F3 }, + { 0xffc1, Qt::Key_F4 }, + { 0xffc2, Qt::Key_F5 }, + { 0xffc3, Qt::Key_F6 }, + { 0xffc4, Qt::Key_F7 }, + { 0xffc5, Qt::Key_F8 }, + { 0xffc6, Qt::Key_F9 }, + { 0xffc7, Qt::Key_F10 }, + { 0xffc8, Qt::Key_F11 }, + { 0xffc9, Qt::Key_F12 }, + { 0xffe1, Qt::Key_Shift }, + { 0xffe2, Qt::Key_Shift }, + { 0xffe3, Qt::Key_Control }, + { 0xffe4, Qt::Key_Control }, + { 0xffe7, Qt::Key_Meta }, + { 0xffe8, Qt::Key_Meta }, + { 0xffe9, Qt::Key_Alt }, + { 0xffea, Qt::Key_Alt }, + { 0, 0 } +}; + +void QRfbRect::read(QTcpSocket *s) +{ + quint16 buf[4]; + s->read((char*)buf, 8); + x = ntohs(buf[0]); + y = ntohs(buf[1]); + w = ntohs(buf[2]); + h = ntohs(buf[3]); +} + +void QRfbRect::write(QTcpSocket *s) const +{ + quint16 buf[4]; + buf[0] = htons(x); + buf[1] = htons(y); + buf[2] = htons(w); + buf[3] = htons(h); + s->write((char*)buf, 8); +} + +void QRfbPixelFormat::read(QTcpSocket *s) +{ + char buf[16]; + s->read(buf, 16); + bitsPerPixel = buf[0]; + depth = buf[1]; + bigEndian = buf[2]; + trueColor = buf[3]; + + quint16 a = ntohs(*(quint16 *)(buf + 4)); + redBits = 0; + while (a) { a >>= 1; redBits++; } + + a = ntohs(*(quint16 *)(buf + 6)); + greenBits = 0; + while (a) { a >>= 1; greenBits++; } + + a = ntohs(*(quint16 *)(buf + 8)); + blueBits = 0; + while (a) { a >>= 1; blueBits++; } + + redShift = buf[10]; + greenShift = buf[11]; + blueShift = buf[12]; +} + +void QRfbPixelFormat::write(QTcpSocket *s) +{ + char buf[16]; + buf[0] = bitsPerPixel; + buf[1] = depth; + buf[2] = bigEndian; + buf[3] = trueColor; + + quint16 a = 0; + for (int i = 0; i < redBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 4) = htons(a); + + a = 0; + for (int i = 0; i < greenBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 6) = htons(a); + + a = 0; + for (int i = 0; i < blueBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 8) = htons(a); + + buf[10] = redShift; + buf[11] = greenShift; + buf[12] = blueShift; + s->write(buf, 16); +} + + +void QRfbServerInit::setName(const char *n) +{ + delete[] name; + name = new char [strlen(n) + 1]; + strcpy(name, n); +} + +void QRfbServerInit::read(QTcpSocket *s) +{ + s->read((char *)&width, 2); + width = ntohs(width); + s->read((char *)&height, 2); + height = ntohs(height); + format.read(s); + + quint32 len; + s->read((char *)&len, 4); + len = ntohl(len); + + name = new char [len + 1]; + s->read(name, len); + name[len] = '\0'; +} + +void QRfbServerInit::write(QTcpSocket *s) +{ + quint16 t = htons(width); + s->write((char *)&t, 2); + t = htons(height); + s->write((char *)&t, 2); + format.write(s); + quint32 len = strlen(name); + len = htonl(len); + s->write((char *)&len, 4); + s->write(name, strlen(name)); +} + +bool QRfbSetEncodings::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 3) + return false; + + char tmp; + s->read(&tmp, 1); // padding + s->read((char *)&count, 2); + count = ntohs(count); + + return true; +} + +bool QRfbFrameBufferUpdateRequest::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 9) + return false; + + s->read(&incremental, 1); + rect.read(s); + + return true; +} + +bool QRfbKeyEvent::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 7) + return false; + + s->read(&down, 1); + quint16 tmp; + s->read((char *)&tmp, 2); // padding + + quint32 key; + s->read((char *)&key, 4); + key = ntohl(key); + + unicode = 0; + keycode = 0; + int i = 0; + while (keyMap[i].keysym && !keycode) { + if (keyMap[i].keysym == (int)key) + keycode = keyMap[i].keycode; + i++; + } + if (!keycode) { + if (key <= 0xff) { + unicode = key; + if (key >= 'a' && key <= 'z') + keycode = Qt::Key_A + key - 'a'; + else if (key >= ' ' && key <= '~') + keycode = Qt::Key_Space + key - ' '; + } + } + + return true; +} + +bool QRfbPointerEvent::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 5) + return false; + + char buttonMask; + s->read(&buttonMask, 1); + buttons = Qt::NoButton; + if (buttonMask & 1) + buttons |= Qt::LeftButton; + if (buttonMask & 2) + buttons |= Qt::MidButton; + if (buttonMask & 4) + buttons |= Qt::RightButton; + + quint16 tmp; + s->read((char *)&tmp, 2); + x = ntohs(tmp); + s->read((char *)&tmp, 2); + y = ntohs(tmp); + + return true; +} + +bool QRfbClientCutText::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 7) + return false; + + char tmp[3]; + s->read(tmp, 3); // padding + s->read((char *)&length, 4); + length = ntohl(length); + + return true; +} + +//=========================================================================== + +QVNCServer::QVNCServer(QVNCGraphicsSystemScreen *screen) + : qvnc_screen(screen) +{ + init(5900); +} + +QVNCServer::QVNCServer(QVNCGraphicsSystemScreen *screen, int id) + : qvnc_screen(screen) +{ + init(5900 + id); +} + +void QVNCServer::init(uint port) +{ + qDebug() << "QVNCServer::init" << port; + + handleMsg = false; + client = 0; + encodingsPending = 0; + cutTextPending = 0; + keymod = 0; + state = Unconnected; + dirtyCursor = false; + + refreshRate = 25; + timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + + serverSocket = new QTcpServer(this); + if (!serverSocket->listen(QHostAddress::Any, port)) + qDebug() << "QVNCServer could not connect:" << serverSocket->errorString(); + else + qDebug("QVNCServer created on port %d", port); + + connect(serverSocket, SIGNAL(newConnection()), this, SLOT(newConnection())); + +#ifndef QT_NO_QWS_CURSOR + qvnc_cursor = 0; +#endif + encoder = 0; +} + +QVNCServer::~QVNCServer() +{ + delete encoder; + encoder = 0; + delete client; + client = 0; +#ifndef QT_NO_QWS_CURSOR + delete qvnc_cursor; + qvnc_cursor = 0; +#endif +} + +void QVNCServer::setDirty() +{ + if (state == Connected && !timer->isActive() && + ((dirtyMap()->numDirty > 0) || dirtyCursor)) { + timer->start(); + } +} + +void QVNCServer::newConnection() +{ + if (client) + delete client; + + client = serverSocket->nextPendingConnection(); + connect(client,SIGNAL(readyRead()),this,SLOT(readClient())); + connect(client,SIGNAL(disconnected()),this,SLOT(discardClient())); + handleMsg = false; + encodingsPending = 0; + cutTextPending = 0; + supportHextile = false; + wantUpdate = false; + + timer->start(1000 / refreshRate); + dirtyMap()->reset(); + + // send protocol version + const char *proto = "RFB 003.003\n"; + client->write(proto, 12); + state = Protocol; + +// if (!qvnc_screen->screen()) +// QWSServer::instance()->enablePainting(true); +} + +void QVNCServer::readClient() +{ + switch (state) { + case Protocol: + if (client->bytesAvailable() >= 12) { + char proto[13]; + client->read(proto, 12); + proto[12] = '\0'; + qDebug("Client protocol version %s", proto); + // No authentication + quint32 auth = htonl(1); + client->write((char *) &auth, sizeof(auth)); + state = Init; + } + break; + + case Init: + if (client->bytesAvailable() >= 1) { + quint8 shared; + client->read((char *) &shared, 1); + + // Server Init msg + QRfbServerInit sim; + QRfbPixelFormat &format = sim.format; + switch (qvnc_screen->depth()) { + case 32: + format.bitsPerPixel = 32; + format.depth = 32; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 8; + format.greenBits = 8; + format.blueBits = 8; + format.redShift = 16; + format.greenShift = 8; + format.blueShift = 0; + break; + + case 24: + format.bitsPerPixel = 24; + format.depth = 24; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 8; + format.greenBits = 8; + format.blueBits = 8; + format.redShift = 16; + format.greenShift = 8; + format.blueShift = 0; + break; + + case 18: + format.bitsPerPixel = 24; + format.depth = 18; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 6; + format.greenBits = 6; + format.blueBits = 6; + format.redShift = 12; + format.greenShift = 6; + format.blueShift = 0; + break; + + case 16: + format.bitsPerPixel = 16; + format.depth = 16; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 5; + format.greenBits = 6; + format.blueBits = 5; + format.redShift = 11; + format.greenShift = 5; + format.blueShift = 0; + break; + + case 15: + format.bitsPerPixel = 16; + format.depth = 15; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 5; + format.greenBits = 5; + format.blueBits = 5; + format.redShift = 10; + format.greenShift = 5; + format.blueShift = 0; + break; + + case 12: + format.bitsPerPixel = 16; + format.depth = 12; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 4; + format.greenBits = 4; + format.blueBits = 4; + format.redShift = 8; + format.greenShift = 4; + format.blueShift = 0; + break; + + case 8: + case 4: + format.bitsPerPixel = 8; + format.depth = 8; + format.bigEndian = 0; + format.trueColor = false; + format.redBits = 0; + format.greenBits = 0; + format.blueBits = 0; + format.redShift = 0; + format.greenShift = 0; + format.blueShift = 0; + break; + + default: + qDebug("QVNC cannot drive depth %d", qvnc_screen->depth()); + discardClient(); + return; + } + sim.width = qvnc_screen->geometry().width(); + sim.height = qvnc_screen->geometry().height(); + sim.setName("Qt for Embedded Linux VNC Server"); + sim.write(client); + state = Connected; + } + break; + + case Connected: + do { + if (!handleMsg) { + client->read((char *)&msgType, 1); + handleMsg = true; + } + if (handleMsg) { + switch (msgType ) { + case SetPixelFormat: + setPixelFormat(); + break; + case FixColourMapEntries: + qDebug("Not supported: FixColourMapEntries"); + handleMsg = false; + break; + case SetEncodings: + setEncodings(); + break; + case FramebufferUpdateRequest: + frameBufferUpdateRequest(); + break; + case KeyEvent: + keyEvent(); + break; + case PointerEvent: + pointerEvent(); + break; + case ClientCutText: + clientCutText(); + break; + default: + qDebug("Unknown message type: %d", (int)msgType); + handleMsg = false; + } + } + } while (!handleMsg && client->bytesAvailable()); + break; + default: + break; + } +} + +#if 0//Q_BYTE_ORDER == Q_BIG_ENDIAN +bool QVNCGraphicsSystemScreen::swapBytes() const +{ + if (depth() != 16) + return false; + + if (screen()) + return screen()->frameBufferLittleEndian(); + return frameBufferLittleEndian(); +} +#endif + +void QVNCServer::setPixelFormat() +{ + if (client->bytesAvailable() >= 19) { + char buf[3]; + client->read(buf, 3); // just padding + pixelFormat.read(client); +#ifdef QT_QWS_VNC_DEBUG + qDebug("Want format: %d %d %d %d %d %d %d %d %d %d", + int(pixelFormat.bitsPerPixel), + int(pixelFormat.depth), + int(pixelFormat.bigEndian), + int(pixelFormat.trueColor), + int(pixelFormat.redBits), + int(pixelFormat.greenBits), + int(pixelFormat.blueBits), + int(pixelFormat.redShift), + int(pixelFormat.greenShift), + int(pixelFormat.blueShift)); +#endif + if (!pixelFormat.trueColor) { + qDebug("Can only handle true color clients"); + discardClient(); + } + handleMsg = false; + sameEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) == !!pixelFormat.bigEndian; + needConversion = pixelConversionNeeded(); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + swapBytes = qvnc_screen->swapBytes(); +#endif + } +} + +void QVNCServer::setEncodings() +{ + QRfbSetEncodings enc; + + if (!encodingsPending && enc.read(client)) { + encodingsPending = enc.count; + if (!encodingsPending) + handleMsg = false; + } + + if (encoder) { + delete encoder; + encoder = 0; + } + + enum Encodings { + Raw = 0, + CopyRect = 1, + RRE = 2, + CoRRE = 4, + Hextile = 5, + ZRLE = 16, + Cursor = -239, + DesktopSize = -223 + }; + + if (encodingsPending && (unsigned)client->bytesAvailable() >= + encodingsPending * sizeof(quint32)) { + for (int i = 0; i < encodingsPending; ++i) { + qint32 enc; + client->read((char *)&enc, sizeof(qint32)); + enc = ntohl(enc); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: %d", enc); +#endif + switch (enc) { + case Raw: + if (!encoder) { + encoder = new QRfbRawEncoder(this); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: using raw"); +#endif + } + break; + case CopyRect: + supportCopyRect = true; + break; + case RRE: + supportRRE = true; + break; + case CoRRE: + supportCoRRE = true; + break; + case Hextile: + supportHextile = true; + if (encoder) + break; + switch (qvnc_screen->depth()) { +#ifdef QT_QWS_DEPTH_8 + case 8: + encoder = new QRfbHextileEncoder<quint8>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_12 + case 12: + encoder = new QRfbHextileEncoder<qrgb444>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_15 + case 15: + encoder = new QRfbHextileEncoder<qrgb555>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_16 + case 16: + encoder = new QRfbHextileEncoder<quint16>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_18 + case 18: + encoder = new QRfbHextileEncoder<qrgb666>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_24 + case 24: + encoder = new QRfbHextileEncoder<qrgb888>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_32 + case 32: + encoder = new QRfbHextileEncoder<quint32>(this); + break; +#endif + default: + break; + } +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: using hextile"); +#endif + break; + case ZRLE: + supportZRLE = true; + break; + case Cursor: + supportCursor = true; +#ifndef QT_NO_QWS_CURSOR + if (!qvnc_screen->screen() || qt_screencursor->isAccelerated()) { + delete qvnc_cursor; + qvnc_cursor = new QVNCClientCursor(this); + } +#endif + break; + case DesktopSize: + supportDesktopSize = true; + break; + default: + break; + } + } + handleMsg = false; + encodingsPending = 0; + } + + if (!encoder) { + encoder = new QRfbRawEncoder(this); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: fallback using raw"); +#endif + } +} + +void QVNCServer::frameBufferUpdateRequest() +{ + QRfbFrameBufferUpdateRequest ev; + + if (ev.read(client)) { + if (!ev.incremental) { + QRect r(ev.rect.x, ev.rect.y, ev.rect.w, ev.rect.h); +////### r.translate(qvnc_screen->offset()); + qvnc_screen->d_ptr->setDirty(r, true); + } + wantUpdate = true; + checkUpdate(); + handleMsg = false; + } +} + +static bool buttonChange(Qt::MouseButtons before, Qt::MouseButtons after, Qt::MouseButton *button, bool *isPress) +{ + if (before == after) + return false; + for (int b = Qt::LeftButton; b <= Qt::MidButton; b<<=1) { + if ((before & b) != (after & b)) { + *button = static_cast<Qt::MouseButton>(b); + *isPress = (after & b); + return true; + } + } + return false; +} + +void QVNCServer::pointerEvent() +{ + QRfbPointerEvent ev; + if (ev.read(client)) { +// const QPoint offset = qvnc_screen->offset(); +// QWSServer::sendMouseEvent(offset + QPoint(ev.x, ev.y), ev.buttons); + + + //qDebug() << "pointerEvent" << ev.x << ev.y << hex << ev.buttons; + + QEvent::Type type = QEvent::MouseMove; + Qt::MouseButton button = Qt::NoButton; + bool isPress; + if (buttonChange(buttons, ev.buttons, &button, &isPress)) + type = isPress ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + QMouseEvent me(type, QPoint(ev.x, ev.y), QPoint(ev.x, ev.y), button, ev.buttons, keymod); + QApplicationPrivate::handleMouseEvent(0, me); + buttons = ev.buttons; + handleMsg = false; + } +} + +void QVNCServer::keyEvent() +{ + QRfbKeyEvent ev; + + if (ev.read(client)) { + if (ev.keycode == Qt::Key_Shift) + keymod = ev.down ? keymod | Qt::ShiftModifier : + keymod & ~Qt::ShiftModifier; + else if (ev.keycode == Qt::Key_Control) + keymod = ev.down ? keymod | Qt::ControlModifier : + keymod & ~Qt::ControlModifier; + else if (ev.keycode == Qt::Key_Alt) + keymod = ev.down ? keymod | Qt::AltModifier : + keymod & ~Qt::AltModifier; + if (ev.unicode || ev.keycode) { +// qDebug() << "keyEvent" << hex << ev.unicode << ev.keycode << keymod << ev.down; + QEvent::Type type = ev.down ? QEvent::KeyPress : QEvent::KeyRelease; + QString str; + if (ev.unicode && ev.unicode != 0xffff) + str = QString(ev.unicode); + QKeyEvent keyEvent(type, ev.keycode, keymod, str); + QApplicationPrivate::handleKeyEvent(0, &keyEvent); + } + handleMsg = false; + } +} + +void QVNCServer::clientCutText() +{ + QRfbClientCutText ev; + + if (ev.read(client)) { + cutTextPending = ev.length; + if (!cutTextPending) + handleMsg = false; + } + + if (cutTextPending && client->bytesAvailable() >= cutTextPending) { + char *text = new char [cutTextPending+1]; + client->read(text, cutTextPending); + delete [] text; + cutTextPending = 0; + handleMsg = false; + } +} + +// stride in bytes +template <class SRC> +bool QRfbSingleColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const int depth = encoder->server->screen()->depth(); + if (width % (depth / 8)) // hw: should rather fallback to simple loop + return false; + + static int alwaysFalse = qgetenv("QT_VNC_NOCHECKFILL").toInt(); + if (alwaysFalse) + return false; + + switch (depth) { + case 4: { + const quint8 *data8 = reinterpret_cast<const quint8*>(data); + if ((data8[0] & 0xf) != (data8[0] >> 4)) + return false; + width /= 2; + } // fallthrough + case 8: { + const quint8 *data8 = reinterpret_cast<const quint8*>(data); + if (data8[0] != data8[1]) + return false; + width /= 2; + } // fallthrough + case 12: + case 15: + case 16: { + const quint16 *data16 = reinterpret_cast<const quint16*>(data); + if (data16[0] != data16[1]) + return false; + width /= 2; + } // fallthrough + case 18: + case 24: + case 32: { + const quint32 *data32 = reinterpret_cast<const quint32*>(data); + const quint32 first = data32[0]; + const int linestep = (stride / sizeof(quint32)) - width; + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (*(data32++) != first) + return false; + } + data32 += linestep; + } + break; + } + default: + return false; + } + + SRC color = reinterpret_cast<const SRC*>(data)[0]; + encoder->newBg |= (color != encoder->bg); + encoder->bg = color; + return true; +} + +template <class SRC> +void QRfbSingleColorHextile<SRC>::write(QTcpSocket *socket) const +{ + if (true || encoder->newBg) { + const int bpp = encoder->server->clientBytesPerPixel(); + const int padding = 3; + QVarLengthArray<char> buffer(padding + 1 + bpp); + buffer[padding] = 2; // BackgroundSpecified + encoder->server->convertPixels(buffer.data() + padding + 1, + reinterpret_cast<char*>(&encoder->bg), + 1); + socket->write(buffer.data() + padding, bpp + 1); +// encoder->newBg = false; + } else { + char subenc = 0; + socket->write(&subenc, 1); + } +} + +template <class SRC> +bool QRfbDualColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const SRC *ptr = reinterpret_cast<const SRC*>(data); + const int linestep = (stride / sizeof(SRC)) - width; + + SRC c1; + SRC c2 = 0; + int n1 = 0; + int n2 = 0; + int x = 0; + int y = 0; + + c1 = *ptr; + + // find second color + while (y < height) { + while (x < width) { + if (*ptr == c1) { + ++n1; + } else { + c2 = *ptr; + goto found_second_color; + } + ++ptr; + ++x; + } + x = 0; + ptr += linestep; + ++y; + } + +found_second_color: + // finish counting + while (y < height) { + while (x < width) { + if (*ptr == c1) { + ++n1; + } else if (*ptr == c2) { + ++n2; + } else { + return false; + } + ++ptr; + ++x; + } + x = 0; + ptr += linestep; + ++y; + } + + if (n2 > n1) { + const quint32 tmpC = c1; + c1 = c2; + c2 = tmpC; + } + + encoder->newBg |= (c1 != encoder->bg); + encoder->newFg |= (c2 != encoder->fg); + + encoder->bg = c1; + encoder->fg = c2; + + // create map + bool inRect = false; + numRects = 0; + ptr = reinterpret_cast<const SRC*>(data); + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (inRect && *ptr == encoder->bg) { + // rect finished + setWidth(x - lastx()); + next(); + inRect = false; + } else if (!inRect && *ptr == encoder->fg) { + // rect start + setX(x); + setY(y); + setHeight(1); + inRect = true; + } + ++ptr; + } + if (inRect) { + // finish rect + setWidth(width - lastx()); + next(); + inRect = false; + } + ptr += linestep; + } + + return true; +} + +template <class SRC> +void QRfbDualColorHextile<SRC>::write(QTcpSocket *socket) const +{ + const int bpp = encoder->server->clientBytesPerPixel(); + const int padding = 3; + QVarLengthArray<char> buffer(padding + 2 * bpp + sizeof(char) + sizeof(numRects)); + char &subenc = buffer[padding]; + int n = padding + sizeof(subenc); + + subenc = 0x8; // AnySubrects + + if (encoder->newBg) { + subenc |= 0x2; // Background + encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->bg, 1); + n += bpp; +// encoder->newBg = false; + } + + if (encoder->newFg) { + subenc |= 0x4; // Foreground + encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->fg, 1); + n += bpp; +// encoder->newFg = false; + } + buffer[n] = numRects; + n += sizeof(numRects); + + socket->write(buffer.data() + padding, n - padding); + socket->write((char*)rects, numRects * sizeof(Rect)); +} + +template <class SRC> +void QRfbDualColorHextile<SRC>::next() +{ + for (int r = numRects - 1; r >= 0; --r) { + if (recty(r) == lasty()) + continue; + if (recty(r) < lasty() - 1) // only search previous scanline + break; + if (rectx(r) == lastx() && width(r) == width(numRects)) { + ++rects[r].wh; + return; + } + } + ++numRects; +} + +template <class SRC> +inline void QRfbMultiColorHextile<SRC>::setColor(SRC color) +{ + encoder->server->convertPixels(reinterpret_cast<char*>(rect(numRects)), + (const char*)&color, 1); +} + +template <class SRC> +inline bool QRfbMultiColorHextile<SRC>::beginRect() +{ + if ((rects.size() + bpp + 2) > maxRectsSize) + return false; + rects.resize(rects.size() + bpp + 2); + return true; +} + +template <class SRC> +inline void QRfbMultiColorHextile<SRC>::endRect() +{ + setHeight(numRects, 1); + ++numRects; +} + +template <class SRC> +bool QRfbMultiColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const SRC *ptr = reinterpret_cast<const SRC*>(data); + const int linestep = (stride / sizeof(SRC)) - width; + + bpp = encoder->server->clientBytesPerPixel(); + + if (encoder->newBg) + encoder->bg = ptr[0]; + + const SRC bg = encoder->bg; + SRC color = bg; + bool inRect = false; + + numRects = 0; + rects.clear(); + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (inRect && *ptr != color) { // end rect + setWidth(numRects, x - rectx(numRects)); + endRect(); + inRect = false; + } + + if (!inRect && *ptr != bg) { // begin rect + if (!beginRect()) + return false; + inRect = true; + color = *ptr; + setColor(color); + setX(numRects, x); + setY(numRects, y); + } + ++ptr; + } + if (inRect) { // end rect + setWidth(numRects, width - rectx(numRects)); + endRect(); + inRect = false; + } + ptr += linestep; + } + + return true; +} + +template <class SRC> +void QRfbMultiColorHextile<SRC>::write(QTcpSocket *socket) const +{ + const int padding = 3; + QVarLengthArray<quint8> buffer(bpp + padding + sizeof(quint8) + sizeof(numRects)); + + quint8 &subenc = buffer[padding]; + int n = padding + sizeof(quint8); + + subenc = 8 | 16; // AnySubrects | SubrectsColoured + + if (encoder->newBg) { + subenc |= 0x2; // Background + encoder->server->convertPixels(reinterpret_cast<char*>(buffer.data() + n), + reinterpret_cast<const char*>(&encoder->bg), + 1); + n += bpp; +// encoder->newBg = false; + } + + buffer[n] = numRects; + n += sizeof(numRects); + + socket->write(reinterpret_cast<const char*>(buffer.data() + padding), + n - padding); + socket->write(reinterpret_cast<const char*>(rects.constData()), + rects.size()); +} + +bool QVNCServer::pixelConversionNeeded() const +{ + if (!sameEndian) + return true; + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (qvnc_screen->swapBytes()) + return true; +#endif + + const int screendepth = qvnc_screen->depth(); + if (screendepth != pixelFormat.bitsPerPixel) + return true; + + switch (screendepth) { + case 32: + case 24: + return false; + case 18: + return (pixelFormat.redBits == 6 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 6); + case 16: + return (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 5); + case 15: + return (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 5 + && pixelFormat.blueBits == 5); + case 12: + return (pixelFormat.redBits == 4 + && pixelFormat.greenBits == 4 + && pixelFormat.blueBits == 4); + } + return true; +} + +// count: number of pixels +void QVNCServer::convertPixels(char *dst, const char *src, int count) const +{ + const int screendepth = qvnc_screen->depth(); + const bool isBgr = false; //### qvnc_screen->pixelType() == QScreen::BGRPixel; + + // cutoffs +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (!swapBytes) +#endif + if (sameEndian) { + if (screendepth == pixelFormat.bitsPerPixel) { // memcpy cutoffs + + switch (screendepth) { + case 32: + memcpy(dst, src, count * sizeof(quint32)); + return; + case 16: + if (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 5) + { + memcpy(dst, src, count * sizeof(quint16)); + return; + } + } + } else if (screendepth == 16 && pixelFormat.bitsPerPixel == 32) { +#if defined(__i386__) // Currently fails on ARM if dst is not 4 byte aligned + const quint32 *src32 = reinterpret_cast<const quint32*>(src); + quint32 *dst32 = reinterpret_cast<quint32*>(dst); + int count32 = count * sizeof(quint16) / sizeof(quint32); + while (count32--) { + const quint32 s = *src32++; + quint32 result1; + quint32 result2; + + // red + result1 = ((s & 0xf8000000) | ((s & 0xe0000000) >> 5)) >> 8; + result2 = ((s & 0x0000f800) | ((s & 0x0000e000) >> 5)) << 8; + + // green + result1 |= ((s & 0x07e00000) | ((s & 0x06000000) >> 6)) >> 11; + result2 |= ((s & 0x000007e0) | ((s & 0x00000600) >> 6)) << 5; + + // blue + result1 |= ((s & 0x001f0000) | ((s & 0x001c0000) >> 5)) >> 13; + result2 |= ((s & 0x0000001f) | ((s & 0x0000001c) >> 5)) << 3; + + *dst32++ = result2; + *dst32++ = result1; + } + if (count & 0x1) { + const quint16 *src16 = reinterpret_cast<const quint16*>(src); + dst32[count - 1] = qt_conv16ToRgb(src16[count - 1]); + } + return; +#endif + } + } + + const int bytesPerPixel = (pixelFormat.bitsPerPixel + 7) / 8; + +// nibble = 0; + + for (int i = 0; i < count; ++i) { + int r, g, b; + + switch (screendepth) { +#if 0 + case 4: { + if (!nibble) { + r = ((*src) & 0x0f) << 4; + } else { + r = (*src) & 0xf0; + src++; + } + nibble = !nibble; + g = b = r; + break; + } +#endif +#if 0 + case 8: { + QRgb rgb = qvnc_screen->clut()[int(*src)]; + r = qRed(rgb); + g = qGreen(rgb); + b = qBlue(rgb); + src++; + break; + } +#endif +#ifdef QT_QWS_DEPTH_12 + case 12: { + quint32 p = quint32(*reinterpret_cast<const qrgb444*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb444); + break; + } +#endif +#ifdef QT_QWS_DEPTH_15 + case 15: { + quint32 p = quint32(*reinterpret_cast<const qrgb555*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb555); + break; + } +#endif + case 16: { + quint16 p = *reinterpret_cast<const quint16*>(src); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (swapBytes) + p = ((p & 0xff) << 8) | ((p & 0xff00) >> 8); +#endif + r = (p >> 11) & 0x1f; + g = (p >> 5) & 0x3f; + b = p & 0x1f; + r <<= 3; + g <<= 2; + b <<= 3; + src += sizeof(quint16); + break; + } +#ifdef QT_QWS_DEPTH_18 + case 18: { + quint32 p = quint32(*reinterpret_cast<const qrgb666*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb666); + break; + } +#endif +#ifdef QT_QWS_DEPTH_24 + case 24: { + quint32 p = quint32(*reinterpret_cast<const qrgb888*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb888); + break; + } +#endif + case 32: { + quint32 p = *reinterpret_cast<const quint32*>(src); + r = (p >> 16) & 0xff; + g = (p >> 8) & 0xff; + b = p & 0xff; + src += sizeof(quint32); + break; + } + default: { + r = g = b = 0; + qDebug("QVNCServer: don't support %dbpp display", screendepth); + return; + } + } + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (swapBytes ^ isBgr) +#else + if (isBgr) +#endif + qSwap(r, b); + + r >>= (8 - pixelFormat.redBits); + g >>= (8 - pixelFormat.greenBits); + b >>= (8 - pixelFormat.blueBits); + + int pixel = (r << pixelFormat.redShift) | + (g << pixelFormat.greenShift) | + (b << pixelFormat.blueShift); + + if (sameEndian || pixelFormat.bitsPerPixel == 8) { + memcpy(dst, &pixel, bytesPerPixel); // XXX: do a simple for-loop instead? + dst += bytesPerPixel; + continue; + } + + + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + switch (pixelFormat.bitsPerPixel) { + case 16: + pixel = (((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + case 32: + pixel = (((pixel & 0xff000000) >> 24) | + ((pixel & 0x00ff0000) >> 8) | + ((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + default: + qDebug("Cannot handle %d bpp client", pixelFormat.bitsPerPixel); + } + } else { // QSysInfo::ByteOrder == QSysInfo::LittleEndian + switch (pixelFormat.bitsPerPixel) { + case 16: + pixel = (((pixel & 0xff000000) >> 8) | + ((pixel & 0x00ff0000) << 8)); + break; + case 32: + pixel = (((pixel & 0xff000000) >> 24) | + ((pixel & 0x00ff0000) >> 8) | + ((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + default: + qDebug("Cannot handle %d bpp client", + pixelFormat.bitsPerPixel); + break; + } + } + memcpy(dst, &pixel, bytesPerPixel); // XXX: simple for-loop instead? + dst += bytesPerPixel; + } +} + +#ifndef QT_NO_QWS_CURSOR +static void blendCursor(QImage &image, const QRect &imageRect) +{ + const QRect cursorRect = qt_screencursor->boundingRect(); + const QRect intersection = (cursorRect & imageRect); + const QRect destRect = intersection.translated(-imageRect.topLeft()); + const QRect srcRect = intersection.translated(-cursorRect.topLeft()); + + QPainter painter(&image); + painter.drawImage(destRect, qt_screencursor->image(), srcRect); + painter.end(); +} +#endif // QT_NO_QWS_CURSOR + +QVNCDirtyMap::QVNCDirtyMap(QVNCGraphicsSystemScreen *s) + : bytesPerPixel(0), numDirty(0), screen(s) +{ + bytesPerPixel = (screen->depth() + 7) / 8; + QSize screenSize = screen->geometry().size(); + bufferWidth = screenSize.width(); + bufferHeight = screenSize.height(); + bufferStride = bufferWidth * bytesPerPixel; + buffer = new uchar[bufferHeight * bufferStride]; + + mapWidth = (bufferWidth + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; + mapHeight = (bufferHeight + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; + numTiles = mapWidth * mapHeight; + map = new uchar[numTiles]; +} + +QVNCDirtyMap::~QVNCDirtyMap() +{ + delete[] map; + delete[] buffer; +} + +void QVNCDirtyMap::reset() +{ + memset(map, 1, numTiles); + memset(buffer, 0, bufferHeight * bufferStride); + numDirty = numTiles; +} + +inline bool QVNCDirtyMap::dirty(int x, int y) const +{ + return map[y * mapWidth + x]; +} + +inline void QVNCDirtyMap::setClean(int x, int y) +{ + map[y * mapWidth + x] = 0; + --numDirty; +} + +template <class T> +void QVNCDirtyMapOptimized<T>::setDirty(int tileX, int tileY, bool force) +{ + static bool alwaysForce = qgetenv("QT_VNC_NO_COMPAREBUFFER").toInt(); + if (alwaysForce) + force = true; + + bool changed = false; + + if (!force) { + const int lstep = screen->linestep(); + const int startX = tileX * MAP_TILE_SIZE; + const int startY = tileY * MAP_TILE_SIZE; + const uchar *scrn = screen->base() + + startY * lstep + startX * bytesPerPixel; + uchar *old = buffer + startY * bufferStride + startX * sizeof(T); + + const int tileHeight = (startY + MAP_TILE_SIZE > bufferHeight ? + bufferHeight - startY : MAP_TILE_SIZE); + const int tileWidth = (startX + MAP_TILE_SIZE > bufferWidth ? + bufferWidth - startX : MAP_TILE_SIZE); + const bool doInlines = (tileWidth == MAP_TILE_SIZE); + + int y = tileHeight; + + if (doInlines) { // hw: memcmp/memcpy is inlined when using constants + while (y) { + if (memcmp(old, scrn, sizeof(T) * MAP_TILE_SIZE)) { + changed = true; + break; + } + scrn += lstep; + old += bufferStride; + --y; + } + + while (y) { + memcpy(old, scrn, sizeof(T) * MAP_TILE_SIZE); + scrn += lstep; + old += bufferStride; + --y; + } + } else { + while (y) { + if (memcmp(old, scrn, sizeof(T) * tileWidth)) { + changed = true; + break; + } + scrn += lstep; + old += bufferStride; + --y; + } + + while (y) { + memcpy(old, scrn, sizeof(T) * tileWidth); + scrn += lstep; + old += bufferStride; + --y; + } + } + } + + const int mapIndex = tileY * mapWidth + tileX; + if ((force || changed) && !map[mapIndex]) { + map[mapIndex] = 1; + ++numDirty; + } +} + +template <class SRC> +QRfbHextileEncoder<SRC>::QRfbHextileEncoder(QVNCServer *s) + : QRfbEncoder(s), + singleColorHextile(this), dualColorHextile(this), multiColorHextile(this) +{ +} + +/* + \internal + Send dirty rects using hextile encoding. +*/ +template <class SRC> +void QRfbHextileEncoder<SRC>::write() +{ +// QWSDisplay::grab(true); + + QVNCDirtyMap *map = server->dirtyMap(); + QTcpSocket *socket = server->clientSocket(); + + const quint32 encoding = htonl(5); // hextile encoding + const int bytesPerPixel = server->clientBytesPerPixel(); + + { + const char tmp[2] = { 0, 0 }; // msg type, padding + socket->write(tmp, sizeof(tmp)); + } + { + const quint16 count = htons(map->numDirty); + socket->write((char *)&count, sizeof(count)); + } + + if (map->numDirty <= 0) { +// QWSDisplay::ungrab(); + return; + } + + newBg = true; + newFg = true; + + const QImage screenImage = server->screenImage(); + QRfbRect rect(0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE); + + QSize screenSize = server->screen()->geometry().size(); + + for (int y = 0; y < map->mapHeight; ++y) { + if (rect.y + MAP_TILE_SIZE > screenSize.height()) + rect.h = screenSize.height() - rect.y; + rect.w = MAP_TILE_SIZE; + for (int x = 0; x < map->mapWidth; ++x) { + if (!map->dirty(x, y)) + continue; + map->setClean(x, y); + + rect.x = x * MAP_TILE_SIZE; + if (rect.x + MAP_TILE_SIZE > screenSize.width()) //###deviceWidth ??? + rect.w = screenSize.width() - rect.x; + rect.write(socket); + + socket->write((char *)&encoding, sizeof(encoding)); + + const uchar *screendata = screenImage.scanLine(rect.y) + + rect.x * screenImage.depth() / 8; + int linestep = screenImage.bytesPerLine(); + +#ifndef QT_NO_QWS_CURSOR + // hardware cursors must be blended with the screen memory + const bool doBlendCursor = qt_screencursor + && !server->hasClientCursor() + && qt_screencursor->isAccelerated(); + QImage tileImage; + if (doBlendCursor) { + const QRect tileRect(rect.x, rect.y, rect.w, rect.h); + const QRect cursorRect = qt_screencursor->boundingRect() + .translated(-server->screen()->offset()); + if (tileRect.intersects(cursorRect)) { + tileImage = screenImage.copy(tileRect); + blendCursor(tileImage, + tileRect.translated(server->screen()->offset())); + screendata = tileImage.bits(); + linestep = tileImage.bytesPerLine(); + } + } +#endif // QT_NO_QWS_CURSOR + + if (singleColorHextile.read(screendata, rect.w, rect.h, linestep)) { + singleColorHextile.write(socket); + } else if (dualColorHextile.read(screendata, rect.w, rect.h, linestep)) { + dualColorHextile.write(socket); + } else if (multiColorHextile.read(screendata, rect.w, rect.h, linestep)) { + multiColorHextile.write(socket); + } else if (server->doPixelConversion()) { + const int bufferSize = rect.w * rect.h * bytesPerPixel + 1; + const int padding = sizeof(quint32) - sizeof(char); + buffer.resize(bufferSize + padding); + + buffer[padding] = 1; // Raw subencoding + + // convert pixels + char *b = buffer.data() + padding + 1; + const int bstep = rect.w * bytesPerPixel; + for (int i = 0; i < rect.h; ++i) { + server->convertPixels(b, (const char*)screendata, rect.w); + screendata += linestep; + b += bstep; + } + socket->write(buffer.constData() + padding, bufferSize); + } else { + quint8 subenc = 1; // Raw subencoding + socket->write((char *)&subenc, 1); + + // send pixels + for (int i = 0; i < rect.h; ++i) { + socket->write((const char*)screendata, + rect.w * bytesPerPixel); + screendata += linestep; + } + } + } + if (socket->state() == QAbstractSocket::UnconnectedState) + break; + rect.y += MAP_TILE_SIZE; + } + socket->flush(); + Q_ASSERT(map->numDirty == 0); + +// QWSDisplay::ungrab(); +} + +void QRfbRawEncoder::write() +{ +// QWSDisplay::grab(false); + + QVNCDirtyMap *map = server->dirtyMap(); + QTcpSocket *socket = server->clientSocket(); + + const int bytesPerPixel = server->clientBytesPerPixel(); + QSize screenSize = server->screen()->geometry().size(); + + // create a region from the dirty rects and send the region's merged rects. + QRegion rgn; + if (map) { + for (int y = 0; y < map->mapHeight; ++y) { + for (int x = 0; x < map->mapWidth; ++x) { + if (!map->dirty(x, y)) + continue; + rgn += QRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, + MAP_TILE_SIZE, MAP_TILE_SIZE); + map->setClean(x, y); + } + } + + rgn &= QRect(0, 0, screenSize.width(), + screenSize.height()); + } + const QVector<QRect> rects = rgn.rects(); + + { + const char tmp[2] = { 0, 0 }; // msg type, padding + socket->write(tmp, sizeof(tmp)); + } + + { + const quint16 count = htons(rects.size()); + socket->write((char *)&count, sizeof(count)); + } + + if (rects.size() <= 0) { +// QWSDisplay::ungrab(); + return; + } + + const QImage *screenImage = server->screenImage(); + + for (int i = 0; i < rects.size(); ++i) { + const QRect tileRect = rects.at(i); + const QRfbRect rect(tileRect.x(), tileRect.y(), + tileRect.width(), tileRect.height()); + rect.write(socket); + + const quint32 encoding = htonl(0); // raw encoding + socket->write((char *)&encoding, sizeof(encoding)); + + int linestep = screenImage->bytesPerLine(); + const uchar *screendata = screenImage->scanLine(rect.y) + + rect.x * screenImage->depth() / 8; + +#ifndef QT_NO_QWS_CURSOR + // hardware cursors must be blended with the screen memory + const bool doBlendCursor = qt_screencursor + && !server->hasClientCursor() + && qt_screencursor->isAccelerated(); + QImage tileImage; + if (doBlendCursor) { + const QRect cursorRect = qt_screencursor->boundingRect() + .translated(-server->screen()->offset()); + if (tileRect.intersects(cursorRect)) { + tileImage = screenImage->copy(tileRect); + blendCursor(tileImage, + tileRect.translated(server->screen()->offset())); + screendata = tileImage.bits(); + linestep = tileImage.bytesPerLine(); + } + } +#endif // QT_NO_QWS_CURSOR + + if (server->doPixelConversion()) { + const int bufferSize = rect.w * rect.h * bytesPerPixel; + if (bufferSize > buffer.size()) + buffer.resize(bufferSize); + + // convert pixels + char *b = buffer.data(); + const int bstep = rect.w * bytesPerPixel; + for (int i = 0; i < rect.h; ++i) { + server->convertPixels(b, (const char*)screendata, rect.w); + screendata += linestep; + b += bstep; + } + socket->write(buffer.constData(), bufferSize); + } else { + for (int i = 0; i < rect.h; ++i) { + socket->write((const char*)screendata, rect.w * bytesPerPixel); + screendata += linestep; + } + } + if (socket->state() == QAbstractSocket::UnconnectedState) + break; + } + socket->flush(); + +// QWSDisplay::ungrab(); +} + +inline QImage *QVNCServer::screenImage() const +{ + return qvnc_screen->mScreenImage; +} + +void QVNCServer::checkUpdate() +{ + if (!wantUpdate) + return; + + if (dirtyCursor) { +#ifndef QT_NO_QWS_CURSOR + Q_ASSERT(qvnc_cursor); + qvnc_cursor->write(); +#endif + dirtyCursor = false; + wantUpdate = false; + return; + } + + if (dirtyMap()->numDirty > 0) { + if (encoder) + encoder->write(); + wantUpdate = false; + } +} + +void QVNCServer::discardClient() +{ + timer->stop(); + state = Unconnected; + delete encoder; + encoder = 0; +#ifndef QT_NO_QWS_CURSOR + delete qvnc_cursor; + qvnc_cursor = 0; +#endif +// if (!qvnc_screen->screen()) +// QWSServer::instance()->enablePainting(false); +} + + + +QVNCGraphicsSystemScreenPrivate::QVNCGraphicsSystemScreenPrivate(QVNCGraphicsSystemScreen *parent) + : dpiX(72), dpiY(72), doOnScreenSurface(false), refreshRate(25), + vncServer(0), q_ptr(parent) +{ +#if 0//ndef QT_NO_QWS_SIGNALHANDLER + QWSSignalHandler::instance()->addObject(this); +#endif + + vncServer = new QVNCServer(q_ptr); + vncServer->setRefreshRate(refreshRate); + + + Q_ASSERT(q_ptr->depth() == 32); + + dirty = new QVNCDirtyMapOptimized<quint32>(q_ptr); +} + +QVNCGraphicsSystemScreenPrivate::~QVNCGraphicsSystemScreenPrivate() +{ +} + + +void QVNCGraphicsSystemScreenPrivate::setDirty(const QRect& rect, bool force) +{ + if (rect.isEmpty()) + return; + +// if (q_ptr->screen()) +// q_ptr->screen()->setDirty(rect); + + if (!vncServer || !vncServer->isConnected()) { +// qDebug() << "QVNCGraphicsSystemScreenPrivate::setDirty() - Not connected"; + return; + } + const QRect r = rect; // .translated(-q_ptr->offset()); + const int x1 = r.x() / MAP_TILE_SIZE; + int y = r.y() / MAP_TILE_SIZE; + for (; (y <= r.bottom() / MAP_TILE_SIZE) && y < dirty->mapHeight; y++) + for (int x = x1; (x <= r.right() / MAP_TILE_SIZE) && x < dirty->mapWidth; x++) + dirty->setDirty(x, y, force); + + vncServer->setDirty(); +} + + + + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/vnc/qvncserver.h b/src/plugins/graphicssystems/vnc/qvncserver.h new file mode 100644 index 0000000..e7eb531 --- /dev/null +++ b/src/plugins/graphicssystems/vnc/qvncserver.h @@ -0,0 +1,524 @@ +/**************************************************************************** +** +** 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 QSCREENVNC_P_H +#define QSCREENVNC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicssystem_vnc.h" +#define QT_NO_QWS_CURSOR + +#ifndef QT_NO_QWS_VNC + +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qsharedmemory.h> +#include <QtNetwork/qtcpsocket.h> +#include <QtNetwork/qtcpserver.h> + +QT_BEGIN_NAMESPACE + +class QVNCServer; + +#ifndef QT_NO_QWS_CURSOR +class QVNCCursor : public QProxyScreenCursor +{ +public: + QVNCCursor(QVNCGraphicsSystemScreen *s); + ~QVNCCursor(); + + void hide(); + void show(); + void set(const QImage &image, int hotx, int hoty); + void move(int x, int y); + +private: + void setDirty(const QRect &r) const; + QVNCGraphicsSystemScreen *screen; +}; + +class QVNCClientCursor : public QProxyScreenCursor +{ +public: + QVNCClientCursor(QVNCServer *s); + ~QVNCClientCursor(); + + void set(const QImage &image, int hotx, int hoty); + void write() const; + +private: + QVNCServer *server; +}; +#endif // QT_NO_QWS_CURSOR + +#define MAP_TILE_SIZE 16 +#define MAP_WIDTH 1280 / MAP_TILE_SIZE +#define MAP_HEIGHT 1024 / MAP_TILE_SIZE + +class QVNCDirtyMap +{ +public: + QVNCDirtyMap(QVNCGraphicsSystemScreen *screen); + virtual ~QVNCDirtyMap(); + + void reset(); + bool dirty(int x, int y) const; + virtual void setDirty(int x, int y, bool force = false) = 0; + void setClean(int x, int y); + + int bytesPerPixel; + + int numDirty; + int mapWidth; + int mapHeight; + +protected: + uchar *map; + QVNCGraphicsSystemScreen *screen; + uchar *buffer; + int bufferWidth; + int bufferHeight; + int bufferStride; + int numTiles; +}; + +template <class T> +class QVNCDirtyMapOptimized : public QVNCDirtyMap +{ +public: + QVNCDirtyMapOptimized(QVNCGraphicsSystemScreen *screen) : QVNCDirtyMap(screen) {} + ~QVNCDirtyMapOptimized() {} + + void setDirty(int x, int y, bool force = false); +}; + +class QRfbRect +{ +public: + QRfbRect() {} + QRfbRect(quint16 _x, quint16 _y, quint16 _w, quint16 _h) { + x = _x; y = _y; w = _w; h = _h; + } + + void read(QTcpSocket *s); + void write(QTcpSocket *s) const; + + quint16 x; + quint16 y; + quint16 w; + quint16 h; +}; + +class QRfbPixelFormat +{ +public: + static int size() { return 16; } + + void read(QTcpSocket *s); + void write(QTcpSocket *s); + + int bitsPerPixel; + int depth; + bool bigEndian; + bool trueColor; + int redBits; + int greenBits; + int blueBits; + int redShift; + int greenShift; + int blueShift; +}; + +class QRfbServerInit +{ +public: + QRfbServerInit() { name = 0; } + ~QRfbServerInit() { delete[] name; } + + int size() const { return QRfbPixelFormat::size() + 8 + strlen(name); } + void setName(const char *n); + + void read(QTcpSocket *s); + void write(QTcpSocket *s); + + quint16 width; + quint16 height; + QRfbPixelFormat format; + char *name; +}; + +class QRfbSetEncodings +{ +public: + bool read(QTcpSocket *s); + + quint16 count; +}; + +class QRfbFrameBufferUpdateRequest +{ +public: + bool read(QTcpSocket *s); + + char incremental; + QRfbRect rect; +}; + +class QRfbKeyEvent +{ +public: + bool read(QTcpSocket *s); + + char down; + int keycode; + int unicode; +}; + +class QRfbPointerEvent +{ +public: + bool read(QTcpSocket *s); + + Qt::MouseButtons buttons; + quint16 x; + quint16 y; +}; + +class QRfbClientCutText +{ +public: + bool read(QTcpSocket *s); + + quint32 length; +}; + +class QVNCGraphicsSystemScreenPrivate : public QObject +{ +public: + QVNCGraphicsSystemScreenPrivate(QVNCGraphicsSystemScreen *parent); + ~QVNCGraphicsSystemScreenPrivate(); + + void setDirty(const QRect &rect, bool force = false); + void configure(); + + qreal dpiX; + qreal dpiY; + bool doOnScreenSurface; + QVNCDirtyMap *dirty; + int refreshRate; + QVNCServer *vncServer; + +#if !defined(QT_NO_QWS_MULTIPROCESS) && !defined(QT_NO_SHAREDMEMORY) + QSharedMemory shm; +#endif + + QVNCGraphicsSystemScreen *q_ptr; +}; + +class QRfbEncoder +{ +public: + QRfbEncoder(QVNCServer *s) : server(s) {} + virtual ~QRfbEncoder() {} + + virtual void write() = 0; + +protected: + QVNCServer *server; +}; + +class QRfbRawEncoder : public QRfbEncoder +{ +public: + QRfbRawEncoder(QVNCServer *s) : QRfbEncoder(s) {} + + void write(); + +private: + QByteArray buffer; +}; + +template <class SRC> class QRfbHextileEncoder; + +template <class SRC> +class QRfbSingleColorHextile +{ +public: + QRfbSingleColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + QRfbHextileEncoder<SRC> *encoder; +}; + +template <class SRC> +class QRfbDualColorHextile +{ +public: + QRfbDualColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + struct Rect { + quint8 xy; + quint8 wh; + } Q_PACKED rects[8 * 16]; + + quint8 numRects; + QRfbHextileEncoder<SRC> *encoder; + +private: + inline int lastx() const { return rectx(numRects); } + inline int lasty() const { return recty(numRects); } + inline int rectx(int r) const { return rects[r].xy >> 4; } + inline int recty(int r) const { return rects[r].xy & 0x0f; } + inline int width(int r) const { return (rects[r].wh >> 4) + 1; } + inline int height(int r) const { return (rects[r].wh & 0x0f) + 1; } + + inline void setX(int r, int x) { + rects[r].xy = (x << 4) | (rects[r].xy & 0x0f); + } + inline void setY(int r, int y) { + rects[r].xy = (rects[r].xy & 0xf0) | y; + } + inline void setWidth(int r, int width) { + rects[r].wh = ((width - 1) << 4) | (rects[r].wh & 0x0f); + } + inline void setHeight(int r, int height) { + rects[r].wh = (rects[r].wh & 0xf0) | (height - 1); + } + + inline void setWidth(int width) { setWidth(numRects, width); } + inline void setHeight(int height) { setHeight(numRects, height); } + inline void setX(int x) { setX(numRects, x); } + inline void setY(int y) { setY(numRects, y); } + void next(); +}; + +template <class SRC> +class QRfbMultiColorHextile +{ +public: + QRfbMultiColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + inline quint8* rect(int r) { + return rects.data() + r * (bpp + 2); + } + inline const quint8* rect(int r) const { + return rects.constData() + r * (bpp + 2); + } + inline void setX(int r, int x) { + quint8 *ptr = rect(r) + bpp; + *ptr = (x << 4) | (*ptr & 0x0f); + } + inline void setY(int r, int y) { + quint8 *ptr = rect(r) + bpp; + *ptr = (*ptr & 0xf0) | y; + } + void setColor(SRC color); + inline int rectx(int r) const { + const quint8 *ptr = rect(r) + bpp; + return *ptr >> 4; + } + inline int recty(int r) const { + const quint8 *ptr = rect(r) + bpp; + return *ptr & 0x0f; + } + inline void setWidth(int r, int width) { + quint8 *ptr = rect(r) + bpp + 1; + *ptr = ((width - 1) << 4) | (*ptr & 0x0f); + } + inline void setHeight(int r, int height) { + quint8 *ptr = rect(r) + bpp + 1; + *ptr = (*ptr & 0xf0) | (height - 1); + } + + bool beginRect(); + void endRect(); + + static const int maxRectsSize = 16 * 16; + QVarLengthArray<quint8, maxRectsSize> rects; + + quint8 bpp; + quint8 numRects; + QRfbHextileEncoder<SRC> *encoder; +}; + +template <class SRC> +class QRfbHextileEncoder : public QRfbEncoder +{ +public: + QRfbHextileEncoder(QVNCServer *s); + void write(); + +private: + enum SubEncoding { + Raw = 1, + BackgroundSpecified = 2, + ForegroundSpecified = 4, + AnySubrects = 8, + SubrectsColoured = 16 + }; + + QByteArray buffer; + QRfbSingleColorHextile<SRC> singleColorHextile; + QRfbDualColorHextile<SRC> dualColorHextile; + QRfbMultiColorHextile<SRC> multiColorHextile; + + SRC bg; + SRC fg; + bool newBg; + bool newFg; + + friend class QRfbSingleColorHextile<SRC>; + friend class QRfbDualColorHextile<SRC>; + friend class QRfbMultiColorHextile<SRC>; +}; + +class QVNCServer : public QObject +{ + Q_OBJECT +public: + QVNCServer(QVNCGraphicsSystemScreen *screen); + QVNCServer(QVNCGraphicsSystemScreen *screen, int id); + ~QVNCServer(); + + void setDirty(); + void setDirtyCursor() { dirtyCursor = true; setDirty(); } + inline bool isConnected() const { return state == Connected; } + inline void setRefreshRate(int rate) { refreshRate = rate; } + + enum ClientMsg { SetPixelFormat = 0, + FixColourMapEntries = 1, + SetEncodings = 2, + FramebufferUpdateRequest = 3, + KeyEvent = 4, + PointerEvent = 5, + ClientCutText = 6 }; + + enum ServerMsg { FramebufferUpdate = 0, + SetColourMapEntries = 1 }; + + void convertPixels(char *dst, const char *src, int count) const; + + inline int clientBytesPerPixel() const { + return pixelFormat.bitsPerPixel / 8; + } + + inline QVNCGraphicsSystemScreen* screen() const { return qvnc_screen; } + inline QVNCDirtyMap* dirtyMap() const { return qvnc_screen->dirtyMap(); } + inline QTcpSocket* clientSocket() const { return client; } + QImage *screenImage() const; + inline bool doPixelConversion() const { return needConversion; } +#ifndef QT_NO_QWS_CURSOR + inline bool hasClientCursor() const { return qvnc_cursor != 0; } +#endif + +private: + void setPixelFormat(); + void setEncodings(); + void frameBufferUpdateRequest(); + void pointerEvent(); + void keyEvent(); + void clientCutText(); + bool pixelConversionNeeded() const; + +private slots: + void newConnection(); + void readClient(); + void checkUpdate(); + void discardClient(); + +private: + void init(uint port); + enum ClientState { Unconnected, Protocol, Init, Connected }; + QTimer *timer; + QTcpServer *serverSocket; + QTcpSocket *client; + ClientState state; + quint8 msgType; + bool handleMsg; + QRfbPixelFormat pixelFormat; + Qt::KeyboardModifiers keymod; + Qt::MouseButtons buttons; + int encodingsPending; + int cutTextPending; + uint supportCopyRect : 1; + uint supportRRE : 1; + uint supportCoRRE : 1; + uint supportHextile : 1; + uint supportZRLE : 1; + uint supportCursor : 1; + uint supportDesktopSize : 1; + bool wantUpdate; + bool sameEndian; + bool needConversion; +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + bool swapBytes; +#endif + bool dirtyCursor; + int refreshRate; + QVNCGraphicsSystemScreen *qvnc_screen; +#ifndef QT_NO_QWS_CURSOR + QVNCClientCursor *qvnc_cursor; +#endif + + QRfbEncoder *encoder; +}; + + +QT_END_NAMESPACE +#endif // QT_NO_QWS_VNC +#endif // QSCREENVNC_P_H diff --git a/src/plugins/graphicssystems/vnc/qwindowsurface_vnc.cpp b/src/plugins/graphicssystems/vnc/qwindowsurface_vnc.cpp new file mode 100644 index 0000000..9429eb2 --- /dev/null +++ b/src/plugins/graphicssystems/vnc/qwindowsurface_vnc.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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$ +** +****************************************************************************/ + + +#include "qwindowsurface_vnc.h" +#include "qgraphicssystem_vnc.h" +#include <QtCore/qdebug.h> +#include <QtGui/qpainter.h> +#include <private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +QVNCWindowSurface::QVNCWindowSurface(QVNCGraphicsSystem *graphicsSystem, + QVNCGraphicsSystemScreen *screen, QWidget *window) + : QWindowSurface(window), + mScreen(screen) +{ +} + +QVNCWindowSurface::~QVNCWindowSurface() +{ +} + +QPaintDevice *QVNCWindowSurface::paintDevice() +{ + return mScreen->mScreenImage; +} + +void QVNCWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + + QRect rect = geometry(); + QPoint topLeft = rect.topLeft(); + + mScreen->setDirty(region.boundingRect()); + // server->flush(region); + +} + +void QVNCWindowSurface::setGeometry(const QRect &) +{ + +// any size you like as long as it's full-screen... + + QRect rect(mScreen->availableGeometry()); + QApplicationPrivate::handleGeometryChange(this->window(), rect); + + QWindowSurface::setGeometry(rect); +} + +bool QVNCWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QVNCWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QVNCWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/vnc/qwindowsurface_vnc.h b/src/plugins/graphicssystems/vnc/qwindowsurface_vnc.h new file mode 100644 index 0000000..3a85db3 --- /dev/null +++ b/src/plugins/graphicssystems/vnc/qwindowsurface_vnc.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG 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 QWINDOWSURFACE_TESTLITE_H +#define QWINDOWSURFACE_TESTLITE_H + +#include <QtGui/private/qwindowsurface_p.h> +#include <qevent.h> + +QT_BEGIN_NAMESPACE + +class MyWindow; +class QVNCGraphicsSystem; +class QVNCGraphicsSystemScreen; + +class QVNCWindowSurface : public QWindowSurface +{ +public: + QVNCWindowSurface(QVNCGraphicsSystem *graphicsSystem, + QVNCGraphicsSystemScreen *screen, QWidget *window); + ~QVNCWindowSurface(); + + 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); + +private: + QVNCGraphicsSystem *mGraphicsSystem; + QVNCGraphicsSystemScreen *mScreen; + MyWindow *xw; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/vnc/vnc.pro b/src/plugins/graphicssystems/vnc/vnc.pro new file mode 100644 index 0000000..20e48ad --- /dev/null +++ b/src/plugins/graphicssystems/vnc/vnc.pro @@ -0,0 +1,16 @@ +TARGET = qvncgraphicssystem +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + + + +SOURCES = main.cpp qgraphicssystem_vnc.cpp qwindowsurface_vnc.cpp +HEADERS = qgraphicssystem_vnc.h qwindowsurface_vnc.h + +HEADERS += qvncserver.h +SOURCES += qvncserver.cpp + + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target |